-
Notifications
You must be signed in to change notification settings - Fork 10.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Ready 4 Review] SQIP - Vectorized primitive image previews #4205
Changes from 1 commit
033faad
7660c4e
5781b9c
f7f05da
b72921b
b6cdeab
d571ba8
423ed1a
d11370b
4550f94
19c33d0
a386a12
64a6dd2
6e8f3a4
84ebf42
f2ffe45
5c11f36
48006eb
f058965
365f36c
36fc041
f8b4caa
a439dee
3fdca72
fb22bcb
b551857
df6c807
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,20 +2,77 @@ const crypto = require(`crypto`) | |
const { createWriteStream } = require(`fs`) | ||
const { extname, join, resolve } = require(`path`) | ||
|
||
const axios = require(`axios`) | ||
const { | ||
GraphQLString, | ||
GraphQLInt, | ||
} = require(`graphql`) | ||
const fs = require(`fs-extra`) | ||
const sqip = require(`sqip`) | ||
const { schemes: { ImageResizingBehavior, ImageCropFocusType } } = require(`gatsby-source-contentful`) | ||
|
||
module.exports = async ({ type, store, cache }) => { | ||
module.exports = async (args) => { | ||
const { type: { name } } = args | ||
|
||
if (name === `ImageSharp`) { | ||
return sqipSharp(args) | ||
} | ||
|
||
if (name === `ContentfulAsset`) { | ||
return sqipContentful(args) | ||
} | ||
|
||
return {} | ||
} | ||
|
||
async function sqipSharp ({ type, cache }) { | ||
if (type.name !== `ImageSharp`) { | ||
return {} | ||
} | ||
|
||
return { | ||
sqip: { | ||
type: GraphQLString, | ||
args: { | ||
blur: { | ||
type: GraphQLInt, | ||
defaultValue: 1, | ||
}, | ||
numberOfPrimitives: { | ||
type: GraphQLInt, | ||
defaultValue: 10, | ||
}, | ||
mode: { | ||
type: GraphQLInt, | ||
defaultValue: 0, | ||
}, | ||
}, | ||
async resolve(image, fieldArgs, context) { | ||
const { blur, numberOfPrimitives, mode } = fieldArgs | ||
// not everything is available at this point of time, maybe conflicts with extend node type from gatsby-transform-sharp, so lets hack it for now... | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
should do the trick
|
||
// const { original: { src }, internal: { contentDigest } } = image | ||
// const absolutePath = join( | ||
// process.cwd(), | ||
// `public`, | ||
// src | ||
// ) | ||
|
||
const { id, internal: { contentDigest } } = image | ||
const absolutePath = id.replace(` absPath of file >> ImageSharp`, ``) | ||
|
||
return generateSqip({ cache, contentDigest, absolutePath, numberOfPrimitives, blur, mode }) | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
async function sqipContentful ({ type, store, cache }) { | ||
if (type.name !== `ContentfulAsset`) { | ||
return {} | ||
} | ||
|
||
const fs = require(`fs-extra`) | ||
const axios = require(`axios`) | ||
|
||
const { schemes: { ImageResizingBehavior, ImageCropFocusType } } = require(`gatsby-source-contentful`) | ||
|
||
const cacheDir = join( | ||
store.getState().program.directory, | ||
`.cache`, | ||
|
@@ -127,38 +184,46 @@ module.exports = async ({ type, store, cache }) => { | |
}) | ||
} | ||
|
||
const sqipOptions = { | ||
filename: absolutePath, | ||
numberOfPrimitives, | ||
blur, | ||
mode, | ||
} | ||
return generateSqip({ cache, contentDigest, absolutePath, numberOfPrimitives, blur, mode }) | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
const optionsHash = crypto | ||
.createHash(`md5`) | ||
.update(JSON.stringify(sqipOptions)) | ||
.digest(`hex`) | ||
async function generateSqip (options) { | ||
const { cache, contentDigest, absolutePath, numberOfPrimitives, blur, mode } = options | ||
|
||
const cacheKey = `sqip-${contentDigest}-${optionsHash}` | ||
// @todo add check if file actually exists | ||
|
||
let svgThumbnail = await cache.get(cacheKey) | ||
const sqipOptions = { | ||
filename: absolutePath, | ||
numberOfPrimitives, | ||
blur, | ||
mode, | ||
} | ||
|
||
if (!svgThumbnail) { | ||
console.log(`Calculating low quality svg thumbnail: ${url}`) | ||
const result = sqip(sqipOptions) | ||
// @todo make blur setting in sqip via PR | ||
svgThumbnail = result.final_svg.replace(new RegExp(`<feGaussianBlur stdDeviation="[0-9]+"\\s*/>`), `<feGaussianBlur stdDeviation="${sqipOptions.blur}" />`) | ||
const optionsHash = crypto | ||
.createHash(`md5`) | ||
.update(JSON.stringify(sqipOptions)) | ||
.digest(`hex`) | ||
|
||
await cache.set(cacheKey, svgThumbnail) | ||
console.log(`done calculating primitive ${url}`) | ||
} | ||
const cacheKey = `sqip-${contentDigest}-${optionsHash}` | ||
|
||
const dataURI = encodeOptimizedSVGDataUri(svgThumbnail) | ||
let svgThumbnail = await cache.get(cacheKey) | ||
|
||
return dataURI | ||
}, | ||
}, | ||
if (!svgThumbnail) { | ||
console.log(`Calculating low quality svg thumbnail: ${absolutePath}`) | ||
const result = sqip(sqipOptions) | ||
// @todo make blur setting in sqip via PR | ||
svgThumbnail = result.final_svg.replace(new RegExp(`<feGaussianBlur stdDeviation="[0-9]+"\\s*/>`), `<feGaussianBlur stdDeviation="${sqipOptions.blur}" />`) | ||
|
||
await cache.set(cacheKey, svgThumbnail) | ||
console.log(`done calculating primitive ${absolutePath}`) | ||
} | ||
|
||
const dataURI = encodeOptimizedSVGDataUri(svgThumbnail) | ||
|
||
return dataURI | ||
} | ||
|
||
// https://codepen.io/tigt/post/optimizing-svgs-in-data-uris | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a copy of the sharp plugin. Should be exported, though. |
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note to myself: set to
^current version