diff --git a/e2e-tests/contentful/cypress/integration/gatsby-image.js b/e2e-tests/contentful/cypress/integration/gatsby-image.js
index 2b47919a5fa67..e192cc2f06557 100644
--- a/e2e-tests/contentful/cypress/integration/gatsby-image.js
+++ b/e2e-tests/contentful/cypress/integration/gatsby-image.js
@@ -52,7 +52,9 @@ describe(`gatsby-image`, () => {
it(`fluid`, testConfig, () => testGatsbyImage(`fluid`, hasBase64Placeholder))
it(`fixed`, testConfig, () => testGatsbyImage(`fixed`, hasBase64Placeholder))
it(`webp`, testConfig, () => testGatsbyImage(`webp`, hasBase64Placeholder))
- it(`traced`, testConfig, () => testGatsbyImage(`traced`, hasSVGPlaceholder))
+ it(`traced`, testConfig, () =>
+ testGatsbyImage(`traced`, hasBase64Placeholder)
+ )
it(`sqip`, testConfig, () => testGatsbyImage(`sqip`, hasSVGPlaceholder))
it(`english`, testConfig, () => {
diff --git a/e2e-tests/contentful/cypress/integration/gatsby-plugin-image.js b/e2e-tests/contentful/cypress/integration/gatsby-plugin-image.js
index 98ae486d7f9e8..ec27c6c0660fc 100644
--- a/e2e-tests/contentful/cypress/integration/gatsby-plugin-image.js
+++ b/e2e-tests/contentful/cypress/integration/gatsby-plugin-image.js
@@ -74,7 +74,7 @@ describe(`gatsby-plugin-image`, () => {
testGatsbyPluginImage(`dominant-color`, hasColorPlaceholder)
)
it(`traced`, testConfig, () =>
- testGatsbyPluginImage(`traced`, hasSVGPlaceholder)
+ testGatsbyPluginImage(`traced`, hasColorPlaceholder)
)
it(`blurred`, testConfig, () =>
testGatsbyPluginImage(`blurred`, hasBase64Placeholder)
diff --git a/e2e-tests/contentful/cypress/integration/tags.js b/e2e-tests/contentful/cypress/integration/tags.js
index bb5b50b45e113..7e41f1d39f25e 100644
--- a/e2e-tests/contentful/cypress/integration/tags.js
+++ b/e2e-tests/contentful/cypress/integration/tags.js
@@ -19,7 +19,7 @@ describe(`tags`, () => {
"have.text",
"numberInteger"
)
- cy.get('[data-cy-id^="tag-"]').should("have.length", 2)
+ cy.get('[data-cy-id^="tag-"]').should("have.length", 5)
})
it(`Filtered Entries`, () => {
cy.get('[data-cy-integers] [data-cy-id="number-integer"]').should(
diff --git a/e2e-tests/contentful/src/pages/gatsby-plugin-image.js b/e2e-tests/contentful/src/pages/gatsby-plugin-image.js
index 38f11874aa32f..6034696e46512 100644
--- a/e2e-tests/contentful/src/pages/gatsby-plugin-image.js
+++ b/e2e-tests/contentful/src/pages/gatsby-plugin-image.js
@@ -85,7 +85,9 @@ const GatsbyPluginImagePage = ({ data }) => {
))}
-
gatsby-plugin-image: Traced SVG Placeholder
+
+ gatsby-plugin-image: Traced SVG Placeholder (fallback to DOMINANT_COLOR)
+
{data.default.nodes.map(node => (
diff --git a/e2e-tests/gatsby-static-image/cypress/integration/traced.js b/e2e-tests/gatsby-static-image/cypress/integration/traced.js
index 1ae2902980036..b57574cfb16db 100644
--- a/e2e-tests/gatsby-static-image/cypress/integration/traced.js
+++ b/e2e-tests/gatsby-static-image/cypress/integration/traced.js
@@ -5,12 +5,14 @@ describe(`fixed`, () => {
cy.visit(`/traced`).waitForRouteChange()
})
- it(`renders a traced svg`, () => {
+ it(`traced svg (falls back to DOMINANT_COLOR)`, () => {
cy.getTestElement(tracedTestId)
- .find(`.gatsby-image-wrapper > img`)
- .should(`have.attr`, `src`)
- .and(src => {
- ;[`data:image/svg+xml`].forEach(part => expect(src).to.include(part))
+ .find(`.gatsby-image-wrapper > [data-placeholder-image]`)
+ .first()
+ .should($el => {
+ // traced falls
+ expect($el.prop("tagName")).to.be.equal("DIV")
+ expect($el).to.be.empty
})
})
diff --git a/examples/using-contentful/package.json b/examples/using-contentful/package.json
index bee4a0c26c41c..838a1bf31d704 100644
--- a/examples/using-contentful/package.json
+++ b/examples/using-contentful/package.json
@@ -30,6 +30,7 @@
"scripts": {
"develop": "gatsby develop",
"build": "gatsby build",
+ "clean": "gatsby clean",
"start": "gatsby serve"
}
}
diff --git a/integration-tests/gatsby-cli/__tests__/new.js b/integration-tests/gatsby-cli/__tests__/new.js
index 6cf61330aff15..b4e10b2d1ff69 100644
--- a/integration-tests/gatsby-cli/__tests__/new.js
+++ b/integration-tests/gatsby-cli/__tests__/new.js
@@ -29,7 +29,11 @@ describe(`gatsby new`, () => {
})
it(`creates a gatsby site with the default starter`, () => {
- const [code, logs] = GatsbyCLI.from(cwd).invoke([`new`, `gatsby-default`])
+ const [code, logs] = GatsbyCLI.from(cwd).invoke([
+ `new`,
+ `gatsby-default`,
+ `gatsbyjs/gatsby-starter-default#v3`,
+ ])
logs.should.contain(
`info Creating new site from git: https://github.com/gatsbyjs/gatsby-starter-default.git`
@@ -48,7 +52,7 @@ describe(`gatsby new`, () => {
const [code, logs] = GatsbyCLI.from(cwd).invoke([
`new`,
`gatsby-blog`,
- `gatsbyjs/gatsby-starter-blog`,
+ `gatsbyjs/gatsby-starter-blog#v3`,
])
logs.should.contain(
diff --git a/packages/gatsby-cli/src/structured-errors/error-schema.ts b/packages/gatsby-cli/src/structured-errors/error-schema.ts
index 306da6d31bdee..ec7dcdbb0e89c 100644
--- a/packages/gatsby-cli/src/structured-errors/error-schema.ts
+++ b/packages/gatsby-cli/src/structured-errors/error-schema.ts
@@ -1,10 +1,12 @@
import Joi from "joi"
import { ILocationPosition, IStructuredError } from "./types"
-export const Position: Joi.ObjectSchema
= Joi.object().keys({
- line: Joi.number(),
- column: Joi.number(),
-})
+export const Position: Joi.ObjectSchema = Joi.object()
+ .keys({
+ line: Joi.number(),
+ column: Joi.number(),
+ })
+ .unknown()
export const errorSchema: Joi.ObjectSchema =
Joi.object().keys({
@@ -27,7 +29,7 @@ export const errorSchema: Joi.ObjectSchema =
location: Joi.object({
start: Position.required(),
end: Position,
- }),
+ }).unknown(),
docsUrl: Joi.string().uri({
allowRelative: false,
relativeOnly: false,
diff --git a/packages/gatsby-plugin-image/src/resolver-utils.ts b/packages/gatsby-plugin-image/src/resolver-utils.ts
index b21a3ab991ff2..a0bac3ff2c8d2 100644
--- a/packages/gatsby-plugin-image/src/resolver-utils.ts
+++ b/packages/gatsby-plugin-image/src/resolver-utils.ts
@@ -201,9 +201,9 @@ export function getGatsbyImageFieldConfig(
type: ImagePlaceholderType.name,
description: stripIndent`
Format of generated placeholder image, displayed while the main image loads.
- BLURRED: a blurred, low resolution image, encoded as a base64 data URI (default)
- DOMINANT_COLOR: a solid color, calculated from the dominant color of the image.
- TRACED_SVG: a low-resolution traced SVG of the image.
+ BLURRED: a blurred, low resolution image, encoded as a base64 data URI.
+ DOMINANT_COLOR: a solid color, calculated from the dominant color of the image (default).
+ TRACED_SVG: deprecated. Will use DOMINANT_COLOR.
NONE: no placeholder. Set the argument "backgroundColor" to use a fixed background color.`,
},
formats: {
diff --git a/packages/gatsby-plugin-sharp/package.json b/packages/gatsby-plugin-sharp/package.json
index 41fea2eb19a18..b82a9d1509bf0 100644
--- a/packages/gatsby-plugin-sharp/package.json
+++ b/packages/gatsby-plugin-sharp/package.json
@@ -17,13 +17,10 @@
"gatsby-telemetry": "^2.14.0",
"got": "^11.8.2",
"lodash": "^4.17.21",
- "mini-svg-data-uri": "^1.3.3",
- "potrace": "^2.1.8",
"probe-image-size": "^6.0.0",
"progress": "^2.0.3",
"semver": "^7.3.5",
"sharp": "^0.29.0",
- "svgo": "1.3.2",
"uuid": "3.4.0"
},
"devDependencies": {
diff --git a/packages/gatsby-plugin-sharp/src/__tests__/__snapshots__/index.js.snap b/packages/gatsby-plugin-sharp/src/__tests__/__snapshots__/index.js.snap
index ad86535eea532..79b914277c34f 100644
--- a/packages/gatsby-plugin-sharp/src/__tests__/__snapshots__/index.js.snap
+++ b/packages/gatsby-plugin-sharp/src/__tests__/__snapshots__/index.js.snap
@@ -1604,7 +1604,7 @@ Object {
}
`;
-exports[`gatsby-plugin-sharp tracedSVG runs on demand 1`] = `
+exports[`gatsby-plugin-sharp tracedSVG runs on demand (and falls back to blurred): fixed 1`] = `
Object {
"aspectRatio": 1,
"base64": undefined,
@@ -1612,12 +1612,12 @@ Object {
"originalName": "test.png",
"src": "/static/1234/7e516/test.png",
"srcSet": "/static/1234/7e516/test.png 1x",
- "tracedSVG": "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='100'%20height='100'%20viewBox='0%200%20100%20100'%20preserveAspectRatio='none'%3e%3cpath%20d='M41%2024c-18%207-24%2029-11%2043%2015%2017%2044%208%2046-15%201-19-17-34-35-28'%20fill='red'%20fill-rule='evenodd'/%3e%3c/svg%3e",
+ "tracedSVG": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsTAAALEwEAmpwYAAABP0lEQVQ4y2P4r8ZANmKgvuZ/agy/VaHojyopmv+CNf/XQCCoCEHNf1VBqv+oM5yVY1giwbBakuG2AkjknzoW/eh2/tdgOCPHYM7OwMDAwAgiGFgYGMJ5GF4og43ApRmuk58JqpMJRjIwMBizMbxTZviPaj8ihCD6rThAStkgljJATWEHc3P5wT5SxdD8B2ztERmQIiYGdAAxSpaF4T2q5TDN4HCaLgZSxMyAE1yQgwY+Fs1zxQloviSPTTMktM7JgVzIiKEH4hElFoavKogAQgltiJA3F0gdOyPC58yw8GsUwhFgUMvVGR4oMqiwogQbhOHLxfBLDcVabIlEneGxEkMMLwMvTLc4M0OdEMN3VfRIxp48/6mDnPdCieGkHCiRflRh+K+JPXljz1IQJ0AzhjrRGQPZC5As+ZeuhQGRmgHU8mT34D0STQAAAABJRU5ErkJggg==",
"width": 100,
}
`;
-exports[`gatsby-plugin-sharp tracedSVG runs on demand 2`] = `
+exports[`gatsby-plugin-sharp tracedSVG runs on demand (and falls back to blurred): fluid 1`] = `
Object {
"aspectRatio": 1,
"base64": undefined,
@@ -1632,6 +1632,6 @@ Object {
/static/1234/a1812/test.png 50w,
/static/1234/7e516/test.png 100w",
"srcSetType": "image/png",
- "tracedSVG": "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='100'%20height='100'%20viewBox='0%200%20100%20100'%20preserveAspectRatio='none'%3e%3cpath%20d='M41%2024c-18%207-24%2029-11%2043%2015%2017%2044%208%2046-15%201-19-17-34-35-28'%20fill='red'%20fill-rule='evenodd'/%3e%3c/svg%3e",
+ "tracedSVG": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsTAAALEwEAmpwYAAABP0lEQVQ4y2P4r8ZANmKgvuZ/agy/VaHojyopmv+CNf/XQCCoCEHNf1VBqv+oM5yVY1giwbBakuG2AkjknzoW/eh2/tdgOCPHYM7OwMDAwAgiGFgYGMJ5GF4og43ApRmuk58JqpMJRjIwMBizMbxTZviPaj8ihCD6rThAStkgljJATWEHc3P5wT5SxdD8B2ztERmQIiYGdAAxSpaF4T2q5TDN4HCaLgZSxMyAE1yQgwY+Fs1zxQloviSPTTMktM7JgVzIiKEH4hElFoavKogAQgltiJA3F0gdOyPC58yw8GsUwhFgUMvVGR4oMqiwogQbhOHLxfBLDcVabIlEneGxEkMMLwMvTLc4M0OdEMN3VfRIxp48/6mDnPdCieGkHCiRflRh+K+JPXljz1IQJ0AzhjrRGQPZC5As+ZeuhQGRmgHU8mT34D0STQAAAABJRU5ErkJggg==",
}
`;
diff --git a/packages/gatsby-plugin-sharp/src/__tests__/index.js b/packages/gatsby-plugin-sharp/src/__tests__/index.js
index dd8bbb209b32a..4e55c971fa258 100644
--- a/packages/gatsby-plugin-sharp/src/__tests__/index.js
+++ b/packages/gatsby-plugin-sharp/src/__tests__/index.js
@@ -651,7 +651,7 @@ describe(`gatsby-plugin-sharp`, () => {
expect(result.tracedSVG).toBeUndefined()
})
- it(`runs on demand`, async () => {
+ it(`runs on demand (and falls back to blurred)`, async () => {
const args = {
maxWidth: 100,
width: 100,
@@ -665,14 +665,20 @@ describe(`gatsby-plugin-sharp`, () => {
args,
})
- expect(fixedSvg).toMatchSnapshot()
+ expect(fixedSvg).toMatchSnapshot(`fixed`)
+
+ expect(fixedSvg.tracedSVG).toMatch(`data:image/png;base64`)
+ expect(fixedSvg.tracedSVG).not.toMatch(`data:image/svg+xml`)
const fluidSvg = await fluid({
file,
args,
})
- expect(fluidSvg).toMatchSnapshot()
+ expect(fluidSvg).toMatchSnapshot(`fluid`)
+
+ expect(fluidSvg.tracedSVG).toMatch(`data:image/png;base64`)
+ expect(fluidSvg.tracedSVG).not.toMatch(`data:image/svg+xml`)
})
})
diff --git a/packages/gatsby-plugin-sharp/src/__tests__/trace-svg.js b/packages/gatsby-plugin-sharp/src/__tests__/trace-svg.js
deleted file mode 100644
index ddb790fa5b049..0000000000000
--- a/packages/gatsby-plugin-sharp/src/__tests__/trace-svg.js
+++ /dev/null
@@ -1,236 +0,0 @@
-jest.mock(`sharp`, () => {
- const sharp = path => {
- const pipeline = {
- rotate: () => pipeline,
- resize: () => pipeline,
- png: () => pipeline,
- jpeg: () => pipeline,
- toFile: (_, cb) => cb(),
- on: () => pipeline,
- once: () => pipeline,
- write: () => pipeline,
- end: () => pipeline,
- emit: () => pipeline,
- }
- return pipeline
- }
-
- sharp.simd = jest.fn()
- sharp.concurrency = jest.fn()
-
- return sharp
-})
-
-jest.mock(`fs-extra`, () => {
- return {
- ...jest.requireActual(`fs-extra`),
- createReadStream: () => {
- const stream = {
- pipe: () => stream,
- }
- return stream
- },
- }
-})
-
-jest.mock(`potrace`, () => {
- const circleSvgString = ``
- return {
- trace: (_, _2, cb) => cb(null, circleSvgString),
- Potrace: {
- TURNPOLICY_MAJORITY: `wat`,
- },
- }
-})
-
-const path = require(`path`)
-
-const traceSVGHelpers = require(`../trace-svg`)
-
-const notMemoizedtraceSVG = jest.spyOn(traceSVGHelpers, `notMemoizedtraceSVG`)
-const notMemoizedPrepareTraceSVGInputFile = jest.spyOn(
- traceSVGHelpers,
- `notMemoizedPrepareTraceSVGInputFile`
-)
-// note that we started spying on not memoized functions first
-// now we recreate memoized functions that will use function we just started
-// spying on
-traceSVGHelpers.createMemoizedFunctions()
-const memoizedTraceSVG = jest.spyOn(traceSVGHelpers, `memoizedTraceSVG`)
-const memoizedPrepareTraceSVGInputFile = jest.spyOn(
- traceSVGHelpers,
- `memoizedPrepareTraceSVGInputFile`
-)
-
-const { traceSVG } = require(`../`)
-
-function getFileObject(absolutePath, name = path.parse(absolutePath).name) {
- return {
- id: `${absolutePath} absPath of file`,
- name: name,
- absolutePath,
- extension: `png`,
- internal: {
- contentDigest: `1234`,
- },
- }
-}
-
-describe(`traceSVG memoization`, () => {
- const file = getFileObject(path.join(__dirname, `images/test.png`))
- const copyOfFile = getFileObject(path.join(__dirname, `images/test-copy.png`))
- const differentFile = getFileObject(
- path.join(__dirname, `images/different.png`)
- )
- differentFile.internal.contentDigest = `4321`
-
- beforeEach(() => {
- traceSVGHelpers.clearMemoizeCaches()
- memoizedTraceSVG.mockClear()
- notMemoizedtraceSVG.mockClear()
- memoizedPrepareTraceSVGInputFile.mockClear()
- notMemoizedPrepareTraceSVGInputFile.mockClear()
- })
-
- it(`Baseline`, async () => {
- await traceSVG({
- file,
- })
-
- expect(memoizedTraceSVG).toBeCalledTimes(1)
- expect(notMemoizedtraceSVG).toBeCalledTimes(1)
- expect(memoizedPrepareTraceSVGInputFile).toBeCalledTimes(1)
- expect(notMemoizedPrepareTraceSVGInputFile).toBeCalledTimes(1)
- })
-
- it(`Is memoizing results for same args`, async () => {
- await traceSVG({
- file,
- })
-
- await traceSVG({
- file,
- })
-
- expect(memoizedTraceSVG).toBeCalledTimes(2)
- expect(notMemoizedtraceSVG).toBeCalledTimes(1)
- expect(memoizedPrepareTraceSVGInputFile).toBeCalledTimes(1)
- expect(notMemoizedPrepareTraceSVGInputFile).toBeCalledTimes(1)
- })
-
- it(`Is calling functions with same input file when params change`, async () => {
- await traceSVG({
- file,
- args: {
- color: `red`,
- },
- fileArgs: {
- width: 400,
- },
- })
- await traceSVG({
- file,
- args: {
- color: `blue`,
- },
- fileArgs: {
- width: 400,
- },
- })
- await traceSVG({
- file,
- args: {
- color: `red`,
- },
- fileArgs: {
- width: 200,
- },
- })
- await traceSVG({
- file,
- args: {
- color: `blue`,
- },
- fileArgs: {
- width: 200,
- },
- })
- await traceSVG({
- file: differentFile,
- args: {
- color: `red`,
- },
- fileArgs: {
- width: 400,
- },
- })
-
- expect(memoizedTraceSVG).toBeCalledTimes(5)
- expect(notMemoizedtraceSVG).toBeCalledTimes(5)
- expect(memoizedPrepareTraceSVGInputFile).toBeCalledTimes(5)
- // trace svg should be actually created just 3 times
- // because it's affected just by `fileArgs`, and not `args`
- // this makes sure we don't try to write to same input file multiple times
- expect(notMemoizedPrepareTraceSVGInputFile).toBeCalledTimes(3)
- expect(notMemoizedPrepareTraceSVGInputFile).toHaveBeenNthCalledWith(
- 1,
- expect.objectContaining({
- file,
- options: expect.objectContaining({
- width: 400,
- }),
- })
- )
- expect(notMemoizedPrepareTraceSVGInputFile).toHaveBeenNthCalledWith(
- 2,
- expect.objectContaining({
- file,
- options: expect.objectContaining({
- width: 200,
- }),
- })
- )
- expect(notMemoizedPrepareTraceSVGInputFile).toHaveBeenNthCalledWith(
- 3,
- expect.objectContaining({
- file: differentFile,
- options: expect.objectContaining({
- width: 400,
- }),
- })
- )
-
- const usedTmpFilePaths = notMemoizedPrepareTraceSVGInputFile.mock.calls.map(
- args => args[0].tmpFilePath
- )
-
- // tmpFilePath was always unique
- expect(usedTmpFilePaths.length).toBe(new Set(usedTmpFilePaths).size)
- })
-
- it(`Use memoized results for file copies`, async () => {
- await traceSVG({
- file,
- args: {
- color: `red`,
- },
- fileArgs: {
- width: 400,
- },
- })
- await traceSVG({
- file: copyOfFile,
- args: {
- color: `red`,
- },
- fileArgs: {
- width: 400,
- },
- })
-
- expect(memoizedTraceSVG).toBeCalledTimes(2)
- expect(notMemoizedtraceSVG).toBeCalledTimes(1)
- expect(memoizedPrepareTraceSVGInputFile).toBeCalledTimes(1)
- expect(notMemoizedPrepareTraceSVGInputFile).toBeCalledTimes(1)
- })
-})
diff --git a/packages/gatsby-plugin-sharp/src/image-data.ts b/packages/gatsby-plugin-sharp/src/image-data.ts
index bd48443bed063..4cc87340c38af 100644
--- a/packages/gatsby-plugin-sharp/src/image-data.ts
+++ b/packages/gatsby-plugin-sharp/src/image-data.ts
@@ -89,6 +89,7 @@ function normalizeFormat(format: string): ImageFormat {
return format as ImageFormat
}
+let didShowTraceSVGRemovalWarning = false
export async function generateImageData({
file,
args,
@@ -98,7 +99,7 @@ export async function generateImageData({
}: IImageDataArgs): Promise {
args = mergeDefaults(args)
- const {
+ let {
layout = `constrained`,
placeholder = `dominantColor`,
tracedSVGOptions = {},
@@ -115,6 +116,16 @@ export async function generateImageData({
: DEFAULT_BREAKPOINTS
}
+ if (placeholder === `tracedSVG`) {
+ if (!didShowTraceSVGRemovalWarning) {
+ console.warn(
+ `"TRACED_SVG" placeholder argument value is no longer supported (used in gatsbyImageData processing), falling back to "DOMINANT_COLOR". See https://gatsby.dev/tracesvg-removal/`
+ )
+ didShowTraceSVGRemovalWarning = true
+ }
+ placeholder = `dominantColor`
+ }
+
const {
fit = `cover`,
cropFocus = sharp.strategy.attention,
diff --git a/packages/gatsby-plugin-sharp/src/index.js b/packages/gatsby-plugin-sharp/src/index.js
index 0d701feff6ad3..ac738c04abe31 100644
--- a/packages/gatsby-plugin-sharp/src/index.js
+++ b/packages/gatsby-plugin-sharp/src/index.js
@@ -16,7 +16,6 @@ const {
createTransformObject,
removeDefaultValues,
} = require(`./plugin-options`)
-const { memoizedTraceSVG, notMemoizedtraceSVG } = require(`./trace-svg`)
const duotone = require(`./duotone`)
const { IMAGE_PROCESSING_JOB_NAME } = require(`./gatsby-worker`)
const { getDimensionsAndAspectRatio } = require(`./utils`)
@@ -387,26 +386,17 @@ async function base64(arg) {
return await memoizedBase64(arg)
}
+let didShowTraceSVGRemovalWarning = false
async function traceSVG(args) {
- if (args.cache) {
- // Not all transformer plugins are going to provide cache
- return await cachifiedProcess(args, generateCacheKey, notMemoizedtraceSVG)
+ if (!didShowTraceSVGRemovalWarning) {
+ console.warn(
+ `traceSVG placeholder generation is no longer supported, falling back to blurred. See https://gatsby.dev/tracesvg-removal/`
+ )
+ didShowTraceSVGRemovalWarning = true
}
- return await memoizedTraceSVG(args)
-}
-async function getTracedSVG({ file, options, cache, reporter }) {
- if (options.generateTracedSVG && options.tracedSVG) {
- const tracedSVG = await traceSVG({
- args: options.tracedSVG,
- fileArgs: options,
- file,
- cache,
- reporter,
- })
- return tracedSVG
- }
- return undefined
+ const { src } = await base64(args)
+ return src
}
async function stats({ file, reporter }) {
@@ -430,6 +420,7 @@ async function stats({ file, reporter }) {
}
}
+let didShowTraceSVGRemovalWarningFluid = false
async function fluid({ file, args = {}, reporter, cache }) {
const options = healOptions(getPluginOptions(), args, file.extension)
if (options.sizeByPixelDensity) {
@@ -564,8 +555,17 @@ async function fluid({ file, args = {}, reporter, cache }) {
reporter,
})
+ if (options.generateTracedSVG && options.tracedSVG) {
+ if (!didShowTraceSVGRemovalWarningFluid) {
+ console.warn(
+ `tracedSVG placeholder generation for fluid images is no longer supported, falling back to blurred. See https://gatsby.dev/tracesvg-removal/`
+ )
+ didShowTraceSVGRemovalWarningFluid = true
+ }
+ }
+
let base64Image
- if (options.base64) {
+ if (options.base64 || (options.generateTracedSVG && options.tracedSVG)) {
const base64Width = options.base64Width
const base64Height = Math.max(
1,
@@ -588,8 +588,6 @@ async function fluid({ file, args = {}, reporter, cache }) {
base64Image = await base64({ file, args: base64Args, reporter, cache })
}
- const tracedSVG = await getTracedSVG({ options, file, cache, reporter })
-
// Construct src and srcSet strings.
const originalImg = _.maxBy(images, image => image.width).src
const fallbackSrc = _.minBy(images, image =>
@@ -636,7 +634,7 @@ async function fluid({ file, args = {}, reporter, cache }) {
`(max-width: ${presentationWidth}px) 100vw, ${presentationWidth}px`
return {
- base64: base64Image && base64Image.src,
+ base64: (options.base64 && base64Image && base64Image.src) || undefined,
aspectRatio: images[0].aspectRatio,
src: fallbackSrc,
srcSet,
@@ -647,10 +645,16 @@ async function fluid({ file, args = {}, reporter, cache }) {
density,
presentationWidth,
presentationHeight,
- tracedSVG,
+ tracedSVG:
+ (options.generateTracedSVG &&
+ options.tracedSVG &&
+ base64Image &&
+ base64Image.src) ||
+ undefined,
}
}
+let didShowTraceSVGRemovalWarningFixed = false
async function fixed({ file, args = {}, reporter, cache }) {
const options = healOptions(getPluginOptions(), args, file.extension)
@@ -703,8 +707,17 @@ async function fixed({ file, args = {}, reporter, cache }) {
reporter,
})
+ if (options.generateTracedSVG && options.tracedSVG) {
+ if (!didShowTraceSVGRemovalWarningFixed) {
+ console.warn(
+ `tracedSVG placeholder generation for fixed images is no longer supported, falling back to blurred. See https://gatsby.dev/tracesvg-removal/`
+ )
+ didShowTraceSVGRemovalWarningFixed = true
+ }
+ }
+
let base64Image
- if (options.base64) {
+ if (options.base64 || (options.generateTracedSVG && options.tracedSVG)) {
const base64Width = options.base64Width
const base64Height = Math.max(
1,
@@ -732,8 +745,6 @@ async function fixed({ file, args = {}, reporter, cache }) {
})
}
- const tracedSVG = await getTracedSVG({ options, file, reporter, cache })
-
const fallbackSrc = images[0].src
const srcSet = images
.map((image, i) => {
@@ -757,14 +768,19 @@ async function fixed({ file, args = {}, reporter, cache }) {
const originalName = file.base
return {
- base64: base64Image && base64Image.src,
+ base64: (options.base64 && base64Image && base64Image.src) || undefined,
aspectRatio: images[0].aspectRatio,
width: images[0].width,
height: images[0].height,
src: fallbackSrc,
srcSet,
originalName: originalName,
- tracedSVG,
+ tracedSVG:
+ (options.generateTracedSVG &&
+ options.tracedSVG &&
+ base64Image &&
+ base64Image.src) ||
+ undefined,
}
}
diff --git a/packages/gatsby-plugin-sharp/src/trace-svg.js b/packages/gatsby-plugin-sharp/src/trace-svg.js
deleted file mode 100644
index b9a894d9f66d3..0000000000000
--- a/packages/gatsby-plugin-sharp/src/trace-svg.js
+++ /dev/null
@@ -1,179 +0,0 @@
-const { promisify } = require(`bluebird`)
-const fs = require(`fs-extra`)
-const _ = require(`lodash`)
-const tmpDir = require(`os`).tmpdir()
-const path = require(`path`)
-const sharp = require(`./safe-sharp`)
-const filenamify = require(`filenamify`)
-const duotone = require(`./duotone`)
-const { getPluginOptions, healOptions } = require(`./plugin-options`)
-const { reportError } = require(`./report-error`)
-const { createContentDigest } = require(`gatsby-core-utils`)
-
-exports.notMemoizedPrepareTraceSVGInputFile = async ({
- file,
- options,
- tmpFilePath,
- reporter,
-}) => {
- let pipeline
- try {
- pipeline = sharp()
-
- if (!options.rotate) {
- pipeline.rotate()
- }
- fs.createReadStream(file.absolutePath).pipe(pipeline)
- } catch (err) {
- reportError(`Failed to process image ${file.absolutePath}`, err, reporter)
- return
- }
-
- pipeline
- .resize(options.width, options.height, {
- position: options.cropFocus,
- })
- .png({
- compressionLevel: options.pngCompressionLevel,
- adaptiveFiltering: false,
- force: options.toFormat === `png`,
- })
- .jpeg({
- quality: options.quality,
- progressive: options.jpegProgressive,
- force: options.toFormat === `jpg`,
- })
-
- // grayscale
- if (options.grayscale) {
- pipeline = pipeline.grayscale()
- }
-
- // rotate
- if (options.rotate && options.rotate !== 0) {
- pipeline = pipeline.rotate(options.rotate)
- }
-
- // duotone
- if (options.duotone) {
- pipeline = await duotone(options.duotone, options.toFormat, pipeline)
- }
-
- await new Promise((resolve, reject) =>
- pipeline.toFile(tmpFilePath, err => {
- if (err) {
- return reject(err)
- }
- return resolve()
- })
- )
-}
-
-const optimize = svg => {
- const SVGO = require(`svgo`)
- const svgo = new SVGO({
- multipass: true,
- floatPrecision: 0,
- plugins: [
- {
- removeViewBox: false,
- },
- {
- addAttributesToSVGElement: {
- attributes: [
- {
- preserveAspectRatio: `none`,
- },
- ],
- },
- },
- ],
- })
- return svgo.optimize(svg).then(({ data }) => data)
-}
-
-exports.notMemoizedtraceSVG = async ({ file, args, fileArgs, reporter }) => {
- const options = healOptions(
- getPluginOptions(),
- {
- // use maxWidth/maxHeight as width/height if available
- // if width/height is used in fileArgs, the maxWidth/maxHeight
- // values will be overritten
- ...(fileArgs && fileArgs.maxWidth && fileArgs.maxHeight
- ? {
- height: fileArgs.maxHeight,
- width: fileArgs.maxWidth,
- }
- : {}),
- ...fileArgs,
- },
- file.extension
- )
-
- const optionsHash = createContentDigest(options)
-
- const tmpFilePath = path.join(
- tmpDir,
- filenamify(
- `${file.internal.contentDigest}-${file.name}-${optionsHash}.${file.extension}`
- )
- )
-
- await exports.memoizedPrepareTraceSVGInputFile({
- tmpFilePath,
- file,
- options,
- reporter,
- })
-
- const svgToMiniDataURI = require(`mini-svg-data-uri`)
- const potrace = require(`potrace`)
- const trace = promisify(potrace.trace)
-
- const defaultArgs = {
- color: `lightgray`,
- optTolerance: 0.4,
- turdSize: 100,
- turnPolicy: potrace.Potrace.TURNPOLICY_MAJORITY,
- }
-
- const optionsSVG = _.defaults({}, args, defaultArgs)
-
- // `srcset` attribute rejects URIs with literal spaces
- const encodeSpaces = str => str.replace(/ /gi, `%20`)
-
- return trace(tmpFilePath, optionsSVG)
- .then(optimize)
- .then(svgToMiniDataURI)
- .then(encodeSpaces)
-}
-
-let memoizedPrepareTraceSVGInputFile
-let memoizedTraceSVG
-const createMemoizedFunctions = () => {
- exports.memoizedPrepareTraceSVGInputFile = memoizedPrepareTraceSVGInputFile =
- _.memoize(
- exports.notMemoizedPrepareTraceSVGInputFile,
- ({ tmpFilePath }) => tmpFilePath
- )
-
- exports.memoizedTraceSVG = memoizedTraceSVG = _.memoize(
- exports.notMemoizedtraceSVG,
- ({ file, args, fileArgs }) =>
- `${file.internal.contentDigest}${JSON.stringify(args)}${JSON.stringify(
- fileArgs
- )}`
- )
-}
-
-// This is very hacky, but memoized function are pretty tricky to spy on
-// in tests ;(
-createMemoizedFunctions()
-exports.createMemoizedFunctions = () => {
- createMemoizedFunctions()
-}
-
-exports.clearMemoizeCaches = () => {
- memoizedTraceSVG.cache.clear()
- memoizedPrepareTraceSVGInputFile.cache.clear()
-}
diff --git a/packages/gatsby-recipes/src/providers/npm/__snapshots__/package.test.js.snap b/packages/gatsby-recipes/src/providers/npm/__snapshots__/package.test.js.snap
index 86fe29313d72f..029c6414cc4cc 100644
--- a/packages/gatsby-recipes/src/providers/npm/__snapshots__/package.test.js.snap
+++ b/packages/gatsby-recipes/src/providers/npm/__snapshots__/package.test.js.snap
@@ -48,11 +48,11 @@ Object {
exports[`npm package resource installs 2 resources, one prod & one dev 1`] = `
Object {
- "_message": "Installed NPM package div@2.0.1",
+ "_message": "Installed NPM package div@2.0.2",
"description": "<Div row> Use flexbox with ease in React! </Div>",
"id": "div",
"name": "div",
- "version": "2.0.1",
+ "version": "2.0.2",
}
`;
diff --git a/packages/gatsby-recipes/src/providers/npm/package.js b/packages/gatsby-recipes/src/providers/npm/package.js
index 6e8ce2bd0b5d1..3361a87715e95 100644
--- a/packages/gatsby-recipes/src/providers/npm/package.js
+++ b/packages/gatsby-recipes/src/providers/npm/package.js
@@ -170,9 +170,15 @@ const destroy = async ({ root }, resource) => {
return undefined
}
- await execa(`yarn`, [`remove`, resource.name, `-W`], {
- cwd: root,
- })
+ if (PACKAGE_MANGER === `yarn`) {
+ await execa(`yarn`, [`remove`, resource.name, `-W`], {
+ cwd: root,
+ })
+ } else {
+ await execa(`npm`, [`uninstall`, resource.name], {
+ cwd: root,
+ })
+ }
return readResource
}
diff --git a/packages/gatsby-remark-images/package.json b/packages/gatsby-remark-images/package.json
index 3c9eb482ddb8d..1a17ccbd15fb6 100644
--- a/packages/gatsby-remark-images/package.json
+++ b/packages/gatsby-remark-images/package.json
@@ -14,7 +14,6 @@
"is-relative-url": "^3.0.0",
"lodash": "^4.17.21",
"mdast-util-definitions": "^4.0.0",
- "potrace": "^2.1.8",
"query-string": "^6.13.3",
"unist-util-select": "^3.0.4",
"unist-util-visit-parents": "^3.1.1"
diff --git a/packages/gatsby-remark-images/src/__tests__/__snapshots__/index.js.snap b/packages/gatsby-remark-images/src/__tests__/__snapshots__/index.js.snap
index ea64aca0a8481..a8e2f2f1bd19b 100644
--- a/packages/gatsby-remark-images/src/__tests__/__snapshots__/index.js.snap
+++ b/packages/gatsby-remark-images/src/__tests__/__snapshots__/index.js.snap
@@ -124,6 +124,37 @@ exports[`disableBgImageOnAlpha does not disable background image on transparent
"
`;
+exports[`it doesn't use tracedSVG placeholder (deprecated and fallback to base64) 1`] = `
+"
+
+
+
+
+ "
+`;
+
exports[`it handles goofy nesting properly 1`] = `
""
`;
-exports[`it uses tracedSVG placeholder when enabled 1`] = `
-"
-
-
-
-
- "
-`;
-
exports[`markdownCaptions display title in markdown as caption when showCaptions === true && markdownCaptions === true 1`] = `
"