Skip to content

Commit

Permalink
feat(gatsby-remark-images): Add flag to suppress css background-image…
Browse files Browse the repository at this point in the history
… to prevent FOUB (#17154)
  • Loading branch information
kimbaudi authored and wardpeet committed Sep 10, 2019
1 parent 491d662 commit 125fd01
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,67 +70,15 @@ Object {
}
`;

exports[`gatsby-plugin-sharp queueImageResizing should process immediately when asked 1`] = `
[MockFunction] {
"calls": Array [
Array [
Object {
"args": Object {
"base64": true,
"duotone": false,
"grayscale": false,
"jpegProgressive": true,
"maxWidth": 800,
"pathPrefix": "",
"pngCompressionLevel": 9,
"pngCompressionSpeed": 4,
"quality": 50,
"sizeByPixelDensity": false,
"toFormat": "png",
"width": 3,
},
"inputPath": "<PROJECT_ROOT>/packages/gatsby-plugin-sharp/src/__tests__/images/144-density.png",
"outputPath": "<PROJECT_ROOT>/public/static/1234/39ca0/test.png",
},
Object {
"addThirdPartySchema": [Function],
"createJob": [Function],
"createNode": [Function],
"createNodeField": [Function],
"createPage": [Function],
"createPageDependency": [Function],
"createParentChildLink": [Function],
"createRedirect": [Function],
"deleteComponentsDependencies": [Function],
"deleteNode": [Function],
"deleteNodes": [Function],
"deletePage": [Function],
"endJob": [Function],
"replaceComponentQuery": [Function],
"replaceStaticQuery": [Function],
"replaceWebpackConfig": [Function],
"setBabelOptions": [Function],
"setBabelPlugin": [Function],
"setBabelPreset": [Function],
"setJob": [Function],
"setPluginStatus": [Function],
"setWebpackConfig": [Function],
"touchNode": [Function],
},
Object {
"defaultQuality": 50,
"lazyImageGeneration": true,
"stripMetadata": true,
"useMozJpeg": false,
},
],
],
"results": Array [
Object {
"type": "return",
"value": Promise {},
},
],
exports[`gatsby-plugin-sharp stats determines if the image is transparent, based on the presence and use of alpha channel 1`] = `
Object {
"isTransparent": false,
}
`;

exports[`gatsby-plugin-sharp stats determines if the image is transparent, based on the presence and use of alpha channel 2`] = `
Object {
"isTransparent": true,
}
`;

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions packages/gatsby-plugin-sharp/src/__tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const {
fixed,
queueImageResizing,
getImageSize,
stats,
} = require(`../`)
const { scheduleJob } = require(`../scheduler`)
scheduleJob.mockResolvedValue(Promise.resolve())
Expand Down Expand Up @@ -391,6 +392,21 @@ describe(`gatsby-plugin-sharp`, () => {
expect(result).toMatchSnapshot()
})
})

describe(`stats`, () => {
it(`determines if the image is transparent, based on the presence and use of alpha channel`, async () => {
const result = await stats({ file, args })
expect(result).toMatchSnapshot()
expect(result.isTransparent).toEqual(false)

const alphaResult = await stats({
file: getFileObject(path.join(__dirname, `images/alphatest.png`)),
args,
})
expect(alphaResult).toMatchSnapshot()
expect(alphaResult.isTransparent).toEqual(true)
})
})
})

function getFileObject(absolutePath, name = `test`) {
Expand Down
19 changes: 19 additions & 0 deletions packages/gatsby-plugin-sharp/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,24 @@ async function getTracedSVG({ file, options, cache, reporter }) {
return undefined
}

async function stats({ file, reporter }) {
let imgStats
try {
imgStats = await sharp(file.absolutePath).stats()
} catch (err) {
reportError(
`Failed to get stats for image ${file.absolutePath}`,
err,
reporter
)
return null
}

return {
isTransparent: !imgStats.isOpaque,
}
}

async function fluid({ file, args = {}, reporter, cache }) {
const options = healOptions(getPluginOptions(), args, file.extension)

Expand Down Expand Up @@ -572,3 +590,4 @@ exports.resolutions = fixed
exports.fluid = fluid
exports.fixed = fixed
exports.getImageSize = getImageSize
exports.stats = stats
27 changes: 14 additions & 13 deletions packages/gatsby-remark-images/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,5 +1,63 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`disableBgImageOnAlpha disables background image on transparent images when disableBgImageOnAlpha === true 1`] = `
"<span
class=\\"gatsby-resp-image-wrapper\\"
style=\\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 300px;\\"
>
<a
class=\\"gatsby-resp-image-link\\"
href=\\"not-a-real-dir/images/my-image.jpeg\\"
style=\\"display: block\\"
target=\\"_blank\\"
rel=\\"noopener\\"
>
<span
class=\\"gatsby-resp-image-background-image\\"
style=\\"padding-bottom: 133.33333333333331%; position: relative; bottom: 0; left: 0; display: block;\\"
></span>
<img
class=\\"gatsby-resp-image-image\\"
alt=\\"some alt\\"
title=\\"some title\\"
src=\\"not-a-real-dir/images/my-image.jpeg\\"
srcset=\\"not-a-real-dir/images/my-image.jpeg, not-a-real-dir/images/my-image.jpeg\\"
sizes=\\"(max-width: 650px) 100vw, 650px\\"
loading=\\"lazy\\"
/>
</a>
</span>"
`;

exports[`disableBgImageOnAlpha does not disable background image on transparent images when disableBgImageOnAlpha === false 1`] = `
"<span
class=\\"gatsby-resp-image-wrapper\\"
style=\\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 300px;\\"
>
<a
class=\\"gatsby-resp-image-link\\"
href=\\"not-a-real-dir/images/my-image.jpeg\\"
style=\\"display: block\\"
target=\\"_blank\\"
rel=\\"noopener\\"
>
<span
class=\\"gatsby-resp-image-background-image\\"
style=\\"padding-bottom: 133.33333333333331%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw'); background-size: cover; display: block;\\"
></span>
<img
class=\\"gatsby-resp-image-image\\"
alt=\\"some alt\\"
title=\\"some title\\"
src=\\"not-a-real-dir/images/my-image.jpeg\\"
srcset=\\"not-a-real-dir/images/my-image.jpeg, not-a-real-dir/images/my-image.jpeg\\"
sizes=\\"(max-width: 650px) 100vw, 650px\\"
loading=\\"lazy\\"
/>
</a>
</span>"
`;

exports[`it handles goofy nesting properly 1`] = `
"<span
class=\\"gatsby-resp-image-wrapper\\"
Expand Down
35 changes: 35 additions & 0 deletions packages/gatsby-remark-images/src/__tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ jest.mock(`gatsby-plugin-sharp`, () => {
})
},
traceSVG: mockTraceSVG,
stats() {
return Promise.resolve({
isTransparent: true,
})
},
}
})

Expand Down Expand Up @@ -587,3 +592,33 @@ describe(`markdownCaptions`, () => {
expect($(`figcaption`).length).toBe(0)
})
})

describe(`disableBgImageOnAlpha`, () => {
it(`does not disable background image on transparent images when disableBgImageOnAlpha === false`, async () => {
const imagePath = `images/my-image.jpeg`
const content = `![some alt](./${imagePath} "some title")`

const nodes = await plugin(createPluginOptions(content, imagePath), {
disableBgImageOnAlpha: false,
})
expect(nodes.length).toBe(1)

const node = nodes.pop()
expect(node.type).toBe(`html`)
expect(node.value).toMatchSnapshot()
})

it(`disables background image on transparent images when disableBgImageOnAlpha === true`, async () => {
const imagePath = `images/my-image.jpeg`
const content = `![some alt](./${imagePath} "some title")`

const nodes = await plugin(createPluginOptions(content, imagePath), {
disableBgImageOnAlpha: true,
})
expect(nodes.length).toBe(1)

const node = nodes.pop()
expect(node.type).toBe(`html`)
expect(node.value).toMatchSnapshot()
})
})
1 change: 1 addition & 0 deletions packages/gatsby-remark-images/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ exports.DEFAULT_OPTIONS = {
withWebp: false,
tracedSVG: false,
loading: `lazy`,
disableBgImageOnAlpha: false,
}

exports.imageClass = `gatsby-resp-image-image`
Expand Down
14 changes: 12 additions & 2 deletions packages/gatsby-remark-images/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const path = require(`path`)
const queryString = require(`query-string`)
const isRelativeUrl = require(`is-relative-url`)
const _ = require(`lodash`)
const { fluid, traceSVG } = require(`gatsby-plugin-sharp`)
const { fluid, stats, traceSVG } = require(`gatsby-plugin-sharp`)
const Promise = require(`bluebird`)
const cheerio = require(`cheerio`)
const slash = require(`slash`)
Expand Down Expand Up @@ -282,10 +282,20 @@ module.exports = (
const imageCaption =
options.showCaptions && getImageCaption(node, overWrites)

let removeBgImage = false
if (options.disableBgImageOnAlpha) {
const imageStats = await stats({ file: imageNode, reporter })
if (imageStats && imageStats.isTransparent) removeBgImage = true
}

const bgImage = removeBgImage
? ``
: ` background-image: url('${placeholderImageData}'); background-size: cover;`

let rawHTML = `
<span
class="${imageBackgroundClass}"
style="padding-bottom: ${ratio}; position: relative; bottom: 0; left: 0; background-image: url('${placeholderImageData}'); background-size: cover; display: block;"
style="padding-bottom: ${ratio}; position: relative; bottom: 0; left: 0;${bgImage} display: block;"
></span>
${imageTag}
`.trim()
Expand Down

0 comments on commit 125fd01

Please sign in to comment.