Skip to content

Commit a2f1624

Browse files
authored
Merge branch 'master' into gatsby-plugin-compression
2 parents 3f00c69 + 3ce505c commit a2f1624

File tree

7 files changed

+202
-32
lines changed

7 files changed

+202
-32
lines changed

docs/docs/adding-images-fonts-files.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ This mechanism provides a number of benefits:
5353

5454
However there is an **escape hatch** that you can use to add an asset outside of the module system.
5555

56-
If you put a file into the `static` folder, it will **not** be processed by Webpack. Instead it will be copied into the public folder untouched. E.g. if you add a file named `sun.jpg` to the static folder, it'll be copied to `public/sun.jpg`. To reference assets in the `static` folder, you need to use a special variable called `__PATH_PREFIX__`. You will need to make sure you set `pathPrefix` in your gatsby-config.js for this to work (set it to `/` if you don't have a path prefix).
57-
58-
In JavaScript code, you can use `__PATH_PREFIX__` for similar purposes:
56+
If you put a file into the `static` folder, it will **not** be processed by Webpack. Instead it will be copied into the public folder untouched. E.g. if you add a file named `sun.jpg` to the static folder, it'll be copied to `public/sun.jpg`. To reference assets in the `static` folder, you'll need to [import a helper function from `gatsby-link` named `withPrefix`](/packages/gatsby-link/#prefixed-paths-helper). You will need to make sure [you set `pathPrefix` in your gatsby-config.js for this to work](/docs/path-prefix/).
5957

6058
```js
59+
import { withPrefix } from 'gatsby-link'
60+
6161
render() {
6262
// Note: this is an escape hatch and should be used sparingly!
6363
// Normally we recommend using `import` for getting asset URLs

examples/image-processing/package.json

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,20 @@
55
"version": "1.0.0",
66
"author": "Florian Kissling <[email protected]>",
77
"dependencies": {
8-
"gatsby": "^1.9.52",
9-
"gatsby-image": "^1.0.5",
10-
"gatsby-link": "^1.6.20",
11-
"gatsby-plugin-google-analytics": "^1.0.8",
8+
"gatsby": "^1.9.112",
9+
"gatsby-image": "^1.0.24",
10+
"gatsby-link": "^1.6.27",
11+
"gatsby-plugin-google-analytics": "^1.0.12",
1212
"gatsby-plugin-offline": "latest",
13-
"gatsby-plugin-sharp": "^1.6.8",
13+
"gatsby-plugin-sharp": "^1.6.20",
1414
"gatsby-source-drupal": "^1.3.7",
15-
"gatsby-source-filesystem": "^1.5.2",
16-
"gatsby-transformer-sharp": "^1.6.8",
15+
"gatsby-source-filesystem": "^1.5.8",
16+
"gatsby-transformer-sharp": "^1.6.13",
1717
"react-typography": "^0.15.0",
1818
"typography": "^0.15.8",
1919
"typography-theme-bootstrap": "^0.15.10"
2020
},
21-
"keywords": [
22-
"gatsby",
23-
"sharp"
24-
],
21+
"keywords": ["gatsby", "sharp"],
2522
"license": "MIT",
2623
"main": "n/a",
2724
"scripts": {

examples/image-processing/src/pages/index.js

Lines changed: 119 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ class Index extends React.Component {
1212
const cropBottomLeft = this.props.data.cropBottomLeft.resize
1313
const cropEntropy = this.props.data.cropEntropy.resize
1414
const cropCenter = this.props.data.cropCenter.resize
15+
const sizesDuotoneOriginal = this.props.data.sizesDuotoneOriginal.sizes
16+
const sizesDuotone25 = this.props.data.sizesDuotone25.sizes
17+
const sizesDuotone50 = this.props.data.sizesDuotone50.sizes
18+
const sizesDuotone75 = this.props.data.sizesDuotone75.sizes
19+
const sizesDuotone = this.props.data.sizesDuotone.sizes
1520

1621
return (
1722
<div>
@@ -83,9 +88,9 @@ class Index extends React.Component {
8388
</code>
8489
</h3>
8590

86-
<ul style={styles.ul}>
91+
<ul style={{ ...styles.ul, ...styles.row }}>
8792
{images.map(image => (
88-
<li style={styles.thumbnail} key={image.node.resize.src}>
93+
<li style={styles.column20} key={image.node.resize.src}>
8994
<img src={image.node.resize.src} />
9095
</li>
9196
))}
@@ -114,27 +119,27 @@ class Index extends React.Component {
114119
see Mr. Gatsby toasting to us in the first thumbnail:
115120
</p>
116121

117-
<ul style={styles.ul}>
118-
<li style={styles.thumbnail}>
122+
<ul style={{ ...styles.ul, ...styles.row }}>
123+
<li style={styles.column25}>
119124
<img src={cropDefault.src} />
120125
</li>
121-
<li style={styles.thumbnail}>
126+
<li style={styles.column25}>
122127
<img src={cropBottomLeft.src} />
123128
<p>
124129
<small>
125130
<code>cropFocus: SOUTHWEST</code>
126131
</small>
127132
</p>
128133
</li>
129-
<li style={styles.thumbnail}>
134+
<li style={styles.column25}>
130135
<img src={cropEntropy.src} />
131136
<p>
132137
<small>
133138
<code>cropFocus: ENTROPY</code>
134139
</small>
135140
</p>
136141
</li>
137-
<li style={styles.thumbnail}>
142+
<li style={styles.column25}>
138143
<img src={cropCenter.src} />
139144
<p>
140145
<small>
@@ -231,7 +236,44 @@ class Index extends React.Component {
231236
highlight: "#f00e2e", shadow: "#192550" {`}`}, toFormat: PNG)
232237
</small>
233238
</h3>
239+
234240
<Img sizes={sizes} />
241+
242+
<h3 style={{ marginTop: rhythm(2) }}>
243+
<small>
244+
sizes(duotone:
245+
{` `}
246+
{`{ `}
247+
highlight: "#0ec4f1", shadow: "#192550", opacity: 50 {`}`})
248+
</small>
249+
</h3>
250+
251+
<div style={styles.row}>
252+
<div style={styles.column20}>
253+
<Img sizes={sizesDuotoneOriginal} />
254+
</div>
255+
<div style={styles.column20}>
256+
<Img sizes={sizesDuotone25} />
257+
</div>
258+
<div style={styles.column20}>
259+
<Img sizes={sizesDuotone50} />
260+
</div>
261+
<div style={styles.column20}>
262+
<Img sizes={sizesDuotone75} />
263+
</div>
264+
<div style={styles.column20}>
265+
<Img sizes={sizesDuotone} />
266+
</div>
267+
</div>
268+
269+
<p>
270+
By setting an optional third parameter{` `}
271+
<code>opacity</code> for <code>duotone</code>, a semi-transparent
272+
version of the duotone{`'`}d image will be composited over the
273+
original allowing the original image and its colors to partially {`"`}shine
274+
through{`"`}.
275+
</p>
276+
235277
<h2
236278
style={{
237279
paddingTop: rhythm(2),
@@ -273,19 +315,33 @@ class Index extends React.Component {
273315

274316
const styles = {}
275317

318+
styles.row = {
319+
display: `flex`,
320+
flexWrap: `wrap`,
321+
margin: `8px -4px 1rem`,
322+
}
323+
276324
styles.ul = {
277-
marginLeft: rhythm(-3 / 4),
278-
marginRight: rhythm(-3 / 4),
279325
padding: `0`,
280326
listStyle: `none`,
281327
}
282328

283-
styles.thumbnail = {
329+
styles.column20 = {
330+
flexShrink: 0,
331+
flexGrow: 0,
332+
color: `#999`,
333+
width: `20%`,
334+
padding: `0 4px`,
335+
margin: 0,
336+
}
337+
338+
styles.column25 = {
339+
flexShrink: 0,
340+
flexGrow: 0,
284341
color: `#999`,
285-
float: `left`,
286-
marginLeft: rhythm(3 / 4),
287-
marginRight: rhythm(3 / 4),
288-
marginBottom: rhythm(6 / 4),
342+
width: `25%`,
343+
padding: `0 4px`,
344+
margin: 0,
289345
}
290346

291347
export default Index
@@ -316,6 +372,55 @@ export const pageQuery = graphql`
316372
...GatsbyImageSharpSizes_tracedSVG
317373
}
318374
}
375+
sizesDuotone: imageSharp(id: { regex: "/fecolormatrix-kanye-west.jpg/" }) {
376+
sizes(
377+
maxWidth: 120
378+
duotone: { highlight: "#0ec4f1", shadow: "#192550" }
379+
traceSVG: { color: "#1E2151" }
380+
) {
381+
...GatsbyImageSharpSizes_tracedSVG
382+
}
383+
}
384+
sizesDuotone50: imageSharp(
385+
id: { regex: "/fecolormatrix-kanye-west.jpg/" }
386+
) {
387+
sizes(
388+
maxWidth: 120
389+
duotone: { highlight: "#0ec4f1", shadow: "#192550", opacity: 50 }
390+
traceSVG: { color: "#A7DEF6" }
391+
) {
392+
...GatsbyImageSharpSizes_tracedSVG
393+
}
394+
}
395+
sizesDuotone75: imageSharp(
396+
id: { regex: "/fecolormatrix-kanye-west.jpg/" }
397+
) {
398+
sizes(
399+
maxWidth: 120
400+
duotone: { highlight: "#0ec4f1", shadow: "#192550", opacity: 75 }
401+
traceSVG: { color: "#0ec4f1" }
402+
) {
403+
...GatsbyImageSharpSizes_tracedSVG
404+
}
405+
}
406+
sizesDuotone25: imageSharp(
407+
id: { regex: "/fecolormatrix-kanye-west.jpg/" }
408+
) {
409+
sizes(
410+
maxWidth: 120
411+
traceSVG: { color: "#D1EFFB" }
412+
duotone: { highlight: "#0ec4f1", shadow: "#192550", opacity: 25 }
413+
) {
414+
...GatsbyImageSharpSizes_tracedSVG
415+
}
416+
}
417+
sizesDuotoneOriginal: imageSharp(
418+
id: { regex: "/fecolormatrix-kanye-west.jpg/" }
419+
) {
420+
sizes(maxWidth: 120, traceSVG: { color: "#e7f7fe" }, toFormat: PNG) {
421+
...GatsbyImageSharpSizes_tracedSVG
422+
}
423+
}
319424
resolution: imageSharp(id: { regex: "/lol.jpg/" }) {
320425
resolutions(grayscale: true, width: 500) {
321426
...GatsbyImageSharpResolutions_withWebp

packages/gatsby-link/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ Gatsby allows you to [automatically prefix links](/docs/path-prefix/) for sites
5959

6060
This can create problems during development as pathnames won't be prefixed. To handle both, gatsby-link exports a helper function `withPrefix` that prepends the prefix during production but doesn't in development.
6161

62+
This is only for pathnames you're constructing manually. The `<Link>` component handles prefixing automatically.
63+
6264
```jsx
6365
import { withPrefix } from "gatsby-link"
6466

packages/gatsby-plugin-sharp/README.md

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,8 @@ allImageSharp {
143143
#### duotone
144144

145145
Applys a "duotone" effect (see [I][1], [II][2], [III][3]) to the source image if
146-
given two hex colors `shadow` and `highlight` defining start and end color of
147-
the duotone gradient, e.g.
146+
given two hex colors `shadow` and `highlight` defining start and end color of
147+
the duotone gradient, e.g.
148148

149149
```javascript
150150
responsiveResolution(
@@ -161,9 +161,36 @@ responsiveResolution(
161161
```
162162

163163
the source image colors will be converted to match a gradient color chosen based
164-
on each pixel's [relative luminance][4].
164+
on each pixel's [relative luminance][4].
165165
Logic is borrowed from [react-duotone][5].
166166

167+
You can pass a third optional parameter, `opacity`:
168+
169+
```javascript
170+
responsiveResolution(
171+
width: 800,
172+
duotone: {
173+
highlight: "#f00e2e",
174+
shadow: "#192550",
175+
opacity: 50
176+
}
177+
) {
178+
src
179+
srcSet
180+
base64
181+
}
182+
```
183+
184+
If set, a semi-transparent version of duotone'd image will be composited over
185+
the original image, allowing the original image and its colors to partially
186+
"shine through". _Heads up_: If the original image contains an alpha
187+
channel it will be [flattened][15] before creating the composite.
188+
189+
This works by adding an alpha channel to the duotone'd image - then we let Sharp
190+
do its magic via [`overlayWith`](http://sharp.dimens.io/en/stable/api-composite/#overlaywith); quoting the Sharp documentation:
191+
192+
> If the overlay image contains an alpha channel then composition with <a href="https://en.wikipedia.org/wiki/Alpha_compositing">premultiplication</a> will occur.
193+
167194
#### tracedSVG
168195

169196
Generates a traced SVG of the image (see [the original GitHub issue][9]) and
@@ -214,3 +241,4 @@ responsiveResolution(
214241
[12]: https://github.com/svg/svgo
215242
[13]: https://github.com/tooolbox/node-potrace#parameters
216243
[14]: https://github.com/oliver-moran/jimp
244+
[15]: http://sharp.dimens.io/en/stable/api-operation/#flatten

packages/gatsby-plugin-sharp/src/duotone.js

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module.exports = async function duotone(duotone, format, clonedPipeline) {
1313
format = `jpeg`
1414
}
1515

16-
return await clonedPipeline
16+
const duotoneImage = await clonedPipeline
1717
.raw()
1818
.toBuffer({ resolveWithObject: true })
1919
.then(({ data, info }) => {
@@ -34,6 +34,12 @@ module.exports = async function duotone(duotone, format, clonedPipeline) {
3434
raw: info,
3535
}).toFormat(format)
3636
})
37+
38+
if (duotone.opacity) {
39+
return overlayDuotone(duotoneImage, clonedPipeline, duotone, format)
40+
} else {
41+
return duotoneImage
42+
}
3743
}
3844

3945
// @see https://github.com/nagelflorian/react-duotone/blob/master/src/hex-to-rgb.js
@@ -69,3 +75,34 @@ function createDuotoneGradient(primaryColorRGB, secondaryColorRGB) {
6975

7076
return duotoneGradient
7177
}
78+
79+
async function overlayDuotone(duotoneImage, originalImage, duotone, format) {
80+
const info = await duotoneImage
81+
.flatten()
82+
.metadata()
83+
.then(info => info)
84+
// see https://github.com/lovell/sharp/issues/859#issuecomment-311319149
85+
const percentGrey = Math.round(duotone.opacity / 100 * 255)
86+
const percentTransparency = Buffer.alloc(
87+
info.width * info.height,
88+
percentGrey
89+
)
90+
91+
const duotoneWithTransparency = await duotoneImage
92+
.joinChannel(percentTransparency, {
93+
raw: { width: info.width, height: info.height, channels: 1 },
94+
})
95+
.raw()
96+
.toBuffer()
97+
98+
return await originalImage
99+
.overlayWith(duotoneWithTransparency, {
100+
raw: { width: info.width, height: info.height, channels: 4 },
101+
})
102+
.toBuffer({ resolveWithObject: true })
103+
.then(({ data, info }) =>
104+
sharp(data, {
105+
raw: info,
106+
}).toFormat(format)
107+
)
108+
}

packages/gatsby-transformer-sharp/src/extend-node-type.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const DuotoneGradientType = new GraphQLInputObjectType({
5555
return {
5656
highlight: { type: GraphQLString },
5757
shadow: { type: GraphQLString },
58+
opacity: { type: GraphQLInt },
5859
}
5960
},
6061
})

0 commit comments

Comments
 (0)