Skip to content

Commit

Permalink
fix(gatsby-remark-images): allow tracedSVG to accept object with sett…
Browse files Browse the repository at this point in the history
…ings (#28242)

* fix(gatsby-remark-images): allow tracedSVG to accept object with settings

* fix test setup that was testing same thing twice
  • Loading branch information
pieh authored Dec 9, 2020
1 parent da04f3c commit 23ecf2d
Show file tree
Hide file tree
Showing 2 changed files with 247 additions and 2 deletions.
209 changes: 208 additions & 1 deletion packages/gatsby-remark-images/src/__tests__/gatsby-node.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { testPluginOptionsSchema } from "gatsby-plugin-utils"
import { pluginOptionsSchema } from "../gatsby-node"
import { Potrace } from "potrace"

describe(`pluginOptionsSchema`, () => {
it(`should provide meaningful errors when fields are invalid`, async () => {
Expand All @@ -13,7 +14,7 @@ describe(`pluginOptionsSchema`, () => {
`"backgroundColor" must be a string`,
`"quality" must be a number`,
`"withWebp" must be one of [object, boolean]`,
`"tracedSVG" must be a boolean`,
`"tracedSVG" must be one of [boolean, object]`,
`"loading" must be one of [lazy, eager, auto]`,
`"disableBgImageOnAlpha" must be a boolean`,
`"disableBgImage" must be a boolean`,
Expand Down Expand Up @@ -102,4 +103,210 @@ describe(`pluginOptionsSchema`, () => {
expect(isValid).toBe(false)
})
})

describe(`allow different variants of "tracedSVG" option`, () => {
describe(`supports boolean variant`, () => {
it.each([
[`true`, true],
[`false`, false],
])(`%s`, async (_title, booleanValue) => {
const { isValid } = await testPluginOptionsSchema(pluginOptionsSchema, {
tracedSVG: booleanValue,
})

expect(isValid).toBe(true)
})
})

describe(`supports object notation`, () => {
it(`should validate when all fields are set`, async () => {
const { isValid } = await testPluginOptionsSchema(pluginOptionsSchema, {
tracedSVG: {
turnPolicy: Potrace.TURNPOLICY_RIGHT,
turdSize: 50,
alphaMax: 0.5,
optCurve: false,
optTolerance: 0.9,
threshold: 230,
blackOnWhite: false,
color: `red`,
background: `green`,
},
})

expect(isValid).toBe(true)
})

it(`should validate when some fields are set`, async () => {
const { isValid } = await testPluginOptionsSchema(pluginOptionsSchema, {
tracedSVG: {
turnPolicy: Potrace.TURNPOLICY_RIGHT,
turdSize: 50,
// alphaMax: 0.5,
// optCurve: 0.2,
// optTolerance: 0.9,
// threshold: 230,
// blackOnWhite: false,
color: `red`,
background: `green`,
},
})

expect(isValid).toBe(true)
})

it(`should fail validation when unknown fields are set`, async () => {
const { isValid, errors } = await testPluginOptionsSchema(
pluginOptionsSchema,
{
tracedSVG: {
foo: `bar`,
},
}
)

expect(isValid).toBe(false)
expect(errors).toMatchInlineSnapshot(`
Array [
"\\"tracedSVG.foo\\" is not allowed",
]
`)
})

describe(`turnPolicy variants`, () => {
it.each([
`TURNPOLICY_BLACK`,
`TURNPOLICY_WHITE`,
`TURNPOLICY_LEFT`,
`TURNPOLICY_RIGHT`,
`TURNPOLICY_MINORITY`,
`TURNPOLICY_MAJORITY`,
])(`supports setting by policy name (%s)`, async name => {
const { isValid } = await testPluginOptionsSchema(
pluginOptionsSchema,
{
tracedSVG: { turnPolicy: name },
}
)

expect(isValid).toBe(true)
})

it.each([
Potrace.TURNPOLICY_BLACK,
Potrace.TURNPOLICY_WHITE,
Potrace.TURNPOLICY_LEFT,
Potrace.TURNPOLICY_RIGHT,
Potrace.TURNPOLICY_MINORITY,
Potrace.TURNPOLICY_MAJORITY,
])(`supports setting by policy value (%s)`, async value => {
const { isValid } = await testPluginOptionsSchema(
pluginOptionsSchema,
{
tracedSVG: { turnPolicy: value },
}
)

expect(isValid).toBe(true)
})

it(`Doesn't support arbitrary string values`, async () => {
const { isValid, errors } = await testPluginOptionsSchema(
pluginOptionsSchema,
{
tracedSVG: { turnPolicy: `foo` },
}
)

expect(isValid).toBe(false)
expect(errors).toMatchInlineSnapshot(`
Array [
"\\"tracedSVG.turnPolicy\\" must be one of [TURNPOLICY_BLACK, TURNPOLICY_WHITE, TURNPOLICY_LEFT, TURNPOLICY_RIGHT, TURNPOLICY_MINORITY, TURNPOLICY_MAJORITY, black, white, left, right, minority, majority]",
]
`)
})
})

describe(`threshold`, () => {
// valid settings
it.each([
[
`THRESHOLD_AUTO`,
{
value: Potrace.THRESHOLD_AUTO,
expectedIsValid: true,
},
],
[
0,
{
expectedIsValid: true,
},
],
[
128,
{
expectedIsValid: true,
},
],
[
255,
{
expectedIsValid: true,
},
],
])(`Allow setting %s`, async (titleAndMaybeValue, { value }) => {
if (typeof value === `undefined`) {
// if value wasn't explicitly set use title
value = titleAndMaybeValue
}

const { isValid } = await testPluginOptionsSchema(
pluginOptionsSchema,
{
tracedSVG: { threshold: value },
}
)

expect(isValid).toBe(true)
})

// invalid settings
it.each([
[
-5,
{
expectedIsValid: false,
errorMessage: `"tracedSVG.threshold" must be greater than or equal to 0`,
},
],
[
256,
{
expectedIsValid: false,
errorMessage: `"tracedSVG.threshold" must be less than or equal to 255`,
},
],
])(
`Doesn't allow setting %s`,
async (titleAndMaybeValue, { value, errorMessage }) => {
if (typeof value === `undefined`) {
// if value wasn't explicitly set use title
value = titleAndMaybeValue
}

const { isValid, errors } = await testPluginOptionsSchema(
pluginOptionsSchema,
{
tracedSVG: { threshold: value },
}
)

expect(isValid).toBe(false)
expect(errors[0]).toEqual(errorMessage)
}
)
})
})
})
})
40 changes: 39 additions & 1 deletion packages/gatsby-remark-images/src/gatsby-node.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
const { Potrace } = require(`potrace`)

exports.pluginOptionsSchema = function ({ Joi }) {
return Joi.object({
maxWidth: Joi.number()
Expand Down Expand Up @@ -52,7 +54,43 @@ exports.pluginOptionsSchema = function ({ Joi }) {
.description(
`Additionally generate WebP versions alongside your chosen file format. They are added as a srcset with the appropriate mimetype and will be loaded in browsers that support the format. Pass true for default support, or an object of options to specifically override those for the WebP files. For example, pass { quality: 80 } to have the WebP images be at quality level 80.`
),
tracedSVG: Joi.boolean()
tracedSVG: Joi.alternatives()
.try(
Joi.boolean(),
Joi.object({
turnPolicy: Joi.string()
.valid(
// this plugin also allow to use key names and not exact values
`TURNPOLICY_BLACK`,
`TURNPOLICY_WHITE`,
`TURNPOLICY_LEFT`,
`TURNPOLICY_RIGHT`,
`TURNPOLICY_MINORITY`,
`TURNPOLICY_MAJORITY`,
// it also allow using actual policy values
Potrace.TURNPOLICY_BLACK,
Potrace.TURNPOLICY_WHITE,
Potrace.TURNPOLICY_LEFT,
Potrace.TURNPOLICY_RIGHT,
Potrace.TURNPOLICY_MINORITY,
Potrace.TURNPOLICY_MAJORITY
)
.default(Potrace.TURNPOLICY_MAJORITY),
turdSize: Joi.number().default(100),
alphaMax: Joi.number(),
optCurve: Joi.boolean().default(true),
optTolerance: Joi.number().default(0.4),
threshold: Joi.alternatives()
.try(
Joi.number().min(0).max(255),
Joi.number().valid(Potrace.THRESHOLD_AUTO)
)
.default(Potrace.THRESHOLD_AUTO),
blackOnWhite: Joi.boolean().default(true),
color: Joi.string().default(`lightgray`),
background: Joi.string().default(`transparent`),
})
)
.default(false)
.description(
`Use traced SVGs for placeholder images instead of the “blur up” effect. Pass true for traced SVGs with the default settings (seen here), or an object of options to override the default. For example, pass { color: "#F00", turnPolicy: "TURNPOLICY_MAJORITY" } to change the color of the trace to red and the turn policy to TURNPOLICY_MAJORITY. See node-potrace parameter documentation for a full listing and explanation of the available options.`
Expand Down

0 comments on commit 23ecf2d

Please sign in to comment.