diff --git a/README.md b/README.md index 14805d23..c19917b8 100644 --- a/README.md +++ b/README.md @@ -199,7 +199,7 @@ You can find all default templates in [templates folder](https://github.com/smoo ## Node API usage -SVGR can also be used programmatically: +### `svgr(code, config, state)` ```js import svgr from '@svgr/core' @@ -218,6 +218,8 @@ svgr(svgCode, { icon: true }, { componentName: 'MyComponent' }).then(jsCode => { }) ``` +Use `svgr.sync(code, config, state)` if you would like to use sync version. + ## [Webpack loader](https://github.com/smooth-code/svgr/blob/master/packages/webpack) ## [Rollup plugin](https://github.com/smooth-code/svgr/blob/master/packages/rollup) diff --git a/packages/core/README.md b/packages/core/README.md index 408bc90b..05bf7897 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -28,6 +28,8 @@ svgr(svgCode, { icon: true }, { componentName: 'MyComponent' }).then(jsCode => { }) ``` +Use `svgr.sync(code, config, state)` if you would like to use sync version. + ## License MIT diff --git a/packages/core/src/__snapshots__/config.test.js.snap b/packages/core/src/__snapshots__/config.test.js.snap new file mode 100644 index 00000000..b496b556 --- /dev/null +++ b/packages/core/src/__snapshots__/config.test.js.snap @@ -0,0 +1,199 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`svgo async #loadConfig [async] should load config using filePath 1`] = ` +Object { + "dimensions": true, + "expandProps": "end", + "h2xConfig": null, + "icon": true, + "native": false, + "noSemi": true, + "prettier": true, + "prettierConfig": null, + "ref": false, + "replaceAttrValues": Array [ + Array [ + "#063855", + "currentColor", + ], + ], + "runtimeConfig": true, + "svgProps": null, + "svgo": true, + "svgoConfig": null, + "template": null, + "titleProp": false, +} +`; + +exports[`svgo async #loadConfig [async] should not load config with "runtimeConfig: false 1`] = ` +Object { + "dimensions": true, + "expandProps": "end", + "h2xConfig": null, + "icon": true, + "native": false, + "noSemi": true, + "prettier": true, + "prettierConfig": null, + "ref": false, + "replaceAttrValues": Array [ + Array [ + "#063855", + "currentColor", + ], + ], + "runtimeConfig": true, + "svgProps": null, + "svgo": true, + "svgoConfig": null, + "template": null, + "titleProp": false, + "useRuntimeConfig": false, +} +`; + +exports[`svgo async #loadConfig [async] should use default config without state.filePath 1`] = ` +Object { + "dimensions": false, + "expandProps": "end", + "h2xConfig": null, + "icon": false, + "native": false, + "prettier": true, + "prettierConfig": null, + "ref": false, + "replaceAttrValues": null, + "runtimeConfig": true, + "svgProps": null, + "svgo": true, + "svgoConfig": null, + "template": null, + "titleProp": false, +} +`; + +exports[`svgo async #loadConfig [async] should work with custom config path 1`] = ` +Object { + "dimensions": true, + "expandProps": "end", + "h2xConfig": null, + "icon": true, + "native": false, + "noSemi": true, + "prettier": true, + "prettierConfig": null, + "ref": false, + "replaceAttrValues": Array [ + Array [ + "#063855", + "currentColor", + ], + ], + "runtimeConfig": true, + "svgProps": null, + "svgo": true, + "svgoConfig": null, + "template": null, + "titleProp": false, +} +`; + +exports[`svgo sync #loadConfig [sync] should load config using filePath 1`] = ` +Object { + "dimensions": true, + "expandProps": "end", + "h2xConfig": null, + "icon": true, + "native": false, + "noSemi": true, + "prettier": true, + "prettierConfig": null, + "ref": false, + "replaceAttrValues": Array [ + Array [ + "#063855", + "currentColor", + ], + ], + "runtimeConfig": true, + "svgProps": null, + "svgo": true, + "svgoConfig": null, + "template": null, + "titleProp": false, +} +`; + +exports[`svgo sync #loadConfig [sync] should not load config with "runtimeConfig: false 1`] = ` +Object { + "dimensions": true, + "expandProps": "end", + "h2xConfig": null, + "icon": true, + "native": false, + "noSemi": true, + "prettier": true, + "prettierConfig": null, + "ref": false, + "replaceAttrValues": Array [ + Array [ + "#063855", + "currentColor", + ], + ], + "runtimeConfig": true, + "svgProps": null, + "svgo": true, + "svgoConfig": null, + "template": null, + "titleProp": false, + "useRuntimeConfig": false, +} +`; + +exports[`svgo sync #loadConfig [sync] should use default config without state.filePath 1`] = ` +Object { + "dimensions": false, + "expandProps": "end", + "h2xConfig": null, + "icon": false, + "native": false, + "prettier": true, + "prettierConfig": null, + "ref": false, + "replaceAttrValues": null, + "runtimeConfig": true, + "svgProps": null, + "svgo": true, + "svgoConfig": null, + "template": null, + "titleProp": false, +} +`; + +exports[`svgo sync #loadConfig [sync] should work with custom config path 1`] = ` +Object { + "dimensions": true, + "expandProps": "end", + "h2xConfig": null, + "icon": true, + "native": false, + "noSemi": true, + "prettier": true, + "prettierConfig": null, + "ref": false, + "replaceAttrValues": Array [ + Array [ + "#063855", + "currentColor", + ], + ], + "runtimeConfig": true, + "svgProps": null, + "svgo": true, + "svgoConfig": null, + "template": null, + "titleProp": false, +} +`; diff --git a/packages/core/src/config.js b/packages/core/src/config.js index 439e325f..c7e9ebfd 100644 --- a/packages/core/src/config.js +++ b/packages/core/src/config.js @@ -33,11 +33,25 @@ export async function resolveConfig(searchFrom, configFile) { return result ? result.config : null } +resolveConfig.sync = (searchFrom, configFile) => { + if (configFile == null) { + const result = explorer.searchSync(searchFrom) + return result ? result.config : null + } + const result = explorer.loadSync(configFile) + return result ? result.config : null +} + export async function resolveConfigFile(filePath) { const result = await explorer.search(filePath) return result ? result.filepath : null } +resolveConfigFile.sync = filePath => { + const result = explorer.searchSync(filePath) + return result ? result.filepath : null +} + export async function loadConfig({ configFile, ...baseConfig }, state = {}) { const rcConfig = state.filePath && baseConfig.runtimeConfig !== false @@ -45,3 +59,11 @@ export async function loadConfig({ configFile, ...baseConfig }, state = {}) { : {} return { ...DEFAULT_CONFIG, ...rcConfig, ...baseConfig } } + +loadConfig.sync = ({ configFile, ...baseConfig }, state = {}) => { + const rcConfig = + state.filePath && baseConfig.runtimeConfig !== false + ? resolveConfig.sync(state.filePath, configFile) + : {} + return { ...DEFAULT_CONFIG, ...rcConfig, ...baseConfig } +} diff --git a/packages/core/src/config.test.js b/packages/core/src/config.test.js index 89c64c40..11379a0d 100644 --- a/packages/core/src/config.test.js +++ b/packages/core/src/config.test.js @@ -1,158 +1,71 @@ import path from 'path' import { resolveConfig, resolveConfigFile, loadConfig } from './config' -describe('config', () => { - describe('#resolveConfig', () => { - it('should return null if no config found', async () => { - const config = await resolveConfig('/tmp') - expect(config).toBe(null) - }) +const getMethod = (method, mode) => (mode === 'sync' ? method.sync : method) - it('should return config if found', async () => { - const config = await resolveConfig( - path.join(__dirname, '__fixtures__/svgr'), - ) - expect(config).toEqual({ - icon: true, - noSemi: true, - replaceAttrValues: [['#063855', 'currentColor']], +describe('svgo', () => { + describe.each([['sync'], ['async']])('%s', mode => { + describe(`#resolveConfig [${mode}]`, () => { + it('should return null if no config found', async () => { + const config = await getMethod(resolveConfig, mode)('/tmp') + expect(config).toBe(null) }) - }) - }) - describe('#resolveConfigFile', () => { - it('should return null if no config found', async () => { - const config = await resolveConfigFile('/tmp') - expect(config).toBe(null) + it('should return config if found', async () => { + const config = await getMethod(resolveConfig, mode)( + path.join(__dirname, '__fixtures__/svgr'), + ) + expect(config).toEqual({ + icon: true, + noSemi: true, + replaceAttrValues: [['#063855', 'currentColor']], + }) + }) }) - it('should return config path if found', async () => { - const config = await resolveConfigFile( - path.join(__dirname, '__fixtures__/svgr'), - ) - expect(config).toMatch(/__fixtures__(\/|\\)svgr(\/|\\)\.svgrrc$/) - }) - }) + describe(`#resolveConfigFile [${mode}]`, () => { + it('should return null if no config found', async () => { + const config = await getMethod(resolveConfigFile, mode)('/tmp') + expect(config).toBe(null) + }) - describe('#loadConfig', () => { - it('should use default config without state.filePath', async () => { - const config = await loadConfig({ dimensions: false }) - expect(config).toMatchInlineSnapshot(` -Object { - "dimensions": false, - "expandProps": "end", - "h2xConfig": null, - "icon": false, - "native": false, - "prettier": true, - "prettierConfig": null, - "ref": false, - "replaceAttrValues": null, - "runtimeConfig": true, - "svgProps": null, - "svgo": true, - "svgoConfig": null, - "template": null, - "titleProp": false, -} -`) + it('should return config path if found', async () => { + const config = await getMethod(resolveConfigFile, mode)( + path.join(__dirname, '__fixtures__/svgr'), + ) + expect(config).toMatch(/__fixtures__(\/|\\)svgr(\/|\\)\.svgrrc$/) + }) }) - it('should load config using filePath', async () => { - const config = await loadConfig( - {}, - { filePath: path.join(__dirname, '__fixtures__/svgr/icon.svg') }, - ) - expect(config).toMatchInlineSnapshot(` -Object { - "dimensions": true, - "expandProps": "end", - "h2xConfig": null, - "icon": true, - "native": false, - "noSemi": true, - "prettier": true, - "prettierConfig": null, - "ref": false, - "replaceAttrValues": Array [ - Array [ - "#063855", - "currentColor", - ], - ], - "runtimeConfig": true, - "svgProps": null, - "svgo": true, - "svgoConfig": null, - "template": null, - "titleProp": false, -} -`) - }) + describe(`#loadConfig [${mode}]`, () => { + it('should use default config without state.filePath', async () => { + const config = await getMethod(loadConfig, mode)({ dimensions: false }) + expect(config).toMatchSnapshot() + }) - it('should not load config with "runtimeConfig: false', async () => { - const config = await loadConfig( - { useRuntimeConfig: false }, - { filePath: path.join(__dirname, '__fixtures__/svgr/icon.svg') }, - ) - expect(config).toMatchInlineSnapshot(` -Object { - "dimensions": true, - "expandProps": "end", - "h2xConfig": null, - "icon": true, - "native": false, - "noSemi": true, - "prettier": true, - "prettierConfig": null, - "ref": false, - "replaceAttrValues": Array [ - Array [ - "#063855", - "currentColor", - ], - ], - "runtimeConfig": true, - "svgProps": null, - "svgo": true, - "svgoConfig": null, - "template": null, - "titleProp": false, - "useRuntimeConfig": false, -} -`) - }) + it('should load config using filePath', async () => { + const config = await getMethod(loadConfig, mode)( + {}, + { filePath: path.join(__dirname, '__fixtures__/svgr/icon.svg') }, + ) + expect(config).toMatchSnapshot() + }) - it('should work with custom config path', async () => { - const config = await loadConfig( - { configFile: path.join(__dirname, '__fixtures__/svgr/.svgrrc') }, - { filePath: __dirname }, - ) - expect(config).toMatchInlineSnapshot(` -Object { - "dimensions": true, - "expandProps": "end", - "h2xConfig": null, - "icon": true, - "native": false, - "noSemi": true, - "prettier": true, - "prettierConfig": null, - "ref": false, - "replaceAttrValues": Array [ - Array [ - "#063855", - "currentColor", - ], - ], - "runtimeConfig": true, - "svgProps": null, - "svgo": true, - "svgoConfig": null, - "template": null, - "titleProp": false, -} -`) + it('should not load config with "runtimeConfig: false', async () => { + const config = await getMethod(loadConfig, mode)( + { useRuntimeConfig: false }, + { filePath: path.join(__dirname, '__fixtures__/svgr/icon.svg') }, + ) + expect(config).toMatchSnapshot() + }) + + it('should work with custom config path', async () => { + const config = await getMethod(loadConfig, mode)( + { configFile: path.join(__dirname, '__fixtures__/svgr/.svgrrc') }, + { filePath: __dirname }, + ) + expect(config).toMatchSnapshot() + }) }) }) }) diff --git a/packages/core/src/convert.js b/packages/core/src/convert.js index 79b3cd8b..fa6d6b94 100644 --- a/packages/core/src/convert.js +++ b/packages/core/src/convert.js @@ -5,17 +5,26 @@ import transform from './plugins/transform' import { expandState } from './util' import { loadConfig } from './config' -async function convert(code, baseConfig = {}, baseState = {}) { - const state = expandState(baseState) - const config = await loadConfig(baseConfig, baseState) +function applyPlugins(code, config, state) { + state = expandState(state) let result = code // Remove null-byte character (copy/paste from Illustrator) result = String(result).replace('\0', '') - result = await svgo(result, config, state) - result = await h2x(result, config, state) - result = await transform(result, config, state) - result = await prettier(result, config, state) + result = svgo(result, config, state) + result = h2x(result, config, state) + result = transform(result, config, state) + result = prettier(result, config, state) return result } +async function convert(code, config = {}, state = {}) { + config = await loadConfig(config, state) + return applyPlugins(code, config, state) +} + +convert.sync = (code, config = {}, state = {}) => { + config = loadConfig.sync(config, state) + return applyPlugins(code, config, state) +} + export default convert diff --git a/packages/core/src/convert.test.js b/packages/core/src/convert.test.js index 8cc732c4..490e7c5c 100644 --- a/packages/core/src/convert.test.js +++ b/packages/core/src/convert.test.js @@ -22,6 +22,12 @@ describe('convert', () => { expect(result).toMatchSnapshot() }) + it('should work synchronously', async () => { + const syncResult = convert.sync(svgBaseCode) + const asyncResult = await convert(svgBaseCode) + expect(syncResult).toEqual(asyncResult) + }) + it('should remove style tags', async () => { const result = await convert( ` diff --git a/packages/core/src/plugins/__snapshots__/svgo.test.js.snap b/packages/core/src/plugins/__snapshots__/svgo.test.js.snap index c419fd57..c9488274 100644 --- a/packages/core/src/plugins/__snapshots__/svgo.test.js.snap +++ b/packages/core/src/plugins/__snapshots__/svgo.test.js.snap @@ -1,5 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`svgo should not load runtime configuration with \`runtimeConfig: false\` 1`] = `""`; + exports[`svgo should not remove viewBox with icon option 1`] = ` " @@ -18,6 +20,8 @@ exports[`svgo should not remove viewBox with icon option 1`] = ` exports[`svgo should optimize svg 1`] = `""`; -exports[`svgo should support config.svgoConfig 1`] = `"Created with Sketch."`; +exports[`svgo should support config.svgoConfig 1`] = `""`; + +exports[`svgo should support icon with config.svgoConfig svgos 1`] = `""`; -exports[`svgo should support icon with config.svgoConfig plugins 1`] = `"Created with Sketch."`; +exports[`svgo should use state.filePath to detect configuration 1`] = `"Created with Sketch."`; diff --git a/packages/core/src/plugins/prettier.js b/packages/core/src/plugins/prettier.js index e548da1e..1c36c242 100644 --- a/packages/core/src/plugins/prettier.js +++ b/packages/core/src/plugins/prettier.js @@ -1,11 +1,11 @@ import prettier from 'prettier' import mergeDeep from 'merge-deep' -export default async (code, config = {}, state = {}) => { +export default (code, config = {}, state = {}) => { if (!config.prettier) return code const filePath = state.filePath || process.cwd() const prettierRcConfig = config.runtimeConfig - ? await prettier.resolveConfig(filePath, { + ? prettier.resolveConfig.sync(filePath, { editorconfig: true, }) : {} diff --git a/packages/core/src/plugins/prettier.test.js b/packages/core/src/plugins/prettier.test.js index 84038195..77a8253f 100644 --- a/packages/core/src/plugins/prettier.test.js +++ b/packages/core/src/plugins/prettier.test.js @@ -1,16 +1,16 @@ import prettier from './prettier' describe('prettier', () => { - it('should prettify code', async () => { - const result = await prettier(`const foo =
`, { + it('should prettify code', () => { + const result = prettier(`const foo =
`, { prettier: true, runtimeConfig: true, }) expect(result).toBe('const foo =
\n') }) - it('should support config.prettierConfig', async () => { - const result = await prettier(`const foo =
`, { + it('should support config.prettierConfig', () => { + const result = prettier(`const foo =
`, { prettier: true, runtimeConfig: true, prettierConfig: { semi: true }, @@ -18,8 +18,8 @@ describe('prettier', () => { expect(result).toBe('const foo =
;\n') }) - it('should use state.filePath to detect configuration', async () => { - const result = await prettier( + it('should use state.filePath to detect configuration', () => { + const result = prettier( `const foo =
`, { prettier: true, runtimeConfig: true }, { filePath: '/tmp' }, @@ -27,7 +27,7 @@ describe('prettier', () => { expect(result).toBe('const foo =
;\n') }) - it('should resolve the prettier config with the editorconfig option', async () => { + it('should resolve the prettier config with the editorconfig option', () => { jest.resetModules() jest.doMock('prettier') /* eslint-disable global-require */ @@ -35,16 +35,16 @@ describe('prettier', () => { const { resolveConfig } = require('prettier') /* eslint-enable global-require */ - await prettierPlugin(`const foo =
`, { + prettierPlugin(`const foo =
`, { prettier: true, runtimeConfig: true, }) - expect(resolveConfig).toHaveBeenCalledWith(expect.any(String), { + expect(resolveConfig.sync).toHaveBeenCalledWith(expect.any(String), { editorconfig: true, }) }) - it('should not load runtime configuration with `runtimeConfig: false`', async () => { + it('should not load runtime configuration with `runtimeConfig: false`', () => { jest.resetModules() jest.doMock('prettier') /* eslint-disable global-require */ @@ -52,10 +52,10 @@ describe('prettier', () => { const { resolveConfig } = require('prettier') /* eslint-enable global-require */ - await prettierPlugin(`const foo =
`, { + prettierPlugin(`const foo =
`, { prettier: true, runtimeConfig: false, }) - expect(resolveConfig).not.toHaveBeenCalled() + expect(resolveConfig.sync).not.toHaveBeenCalled() }) }) diff --git a/packages/core/src/plugins/svgo.js b/packages/core/src/plugins/svgo.js index 86eaab8e..f1fb107e 100644 --- a/packages/core/src/plugins/svgo.js +++ b/packages/core/src/plugins/svgo.js @@ -1,3 +1,4 @@ +/* eslint-disable no-underscore-dangle */ import SVGO from 'svgo' import cosmiconfig from 'cosmiconfig' import mergeDeep from 'merge-deep' @@ -15,24 +16,99 @@ const explorer = cosmiconfig('svgo', { transform: result => result && result.config, }) +function encodeSVGDatauri(str, type) { + let prefix = 'data:image/svg+xml' + + // base64 + if (!type || type === 'base64') { + prefix += ';base64,' + + if (Buffer.from) { + str = prefix + Buffer.from(str).toString('base64') + } else { + // eslint-disable-next-line + str = prefix + new Buffer(str).toString('base64') + } + + // URI encoded + } else if (type === 'enc') { + str = `${prefix},${encodeURIComponent(str)}` + + // unencoded + } else if (type === 'unenc') { + str = `${prefix},${str}` + } + + return str +} + +// See https://github.com/svg/svgo/blob/master/lib/svgo.js#L24 +// _optimizeOnce is synchronous internally +function optimizeSync(svgstr, info) { + const { config } = this + + if (config.error) { + throw config.error + } + + const maxPassCount = config.multipass ? 10 : 1 + let counter = 0 + let prevResultSize = Number.POSITIVE_INFINITY + + let result + + const optimizeOnceCallback = svgjs => { + if (svgjs.error) { + throw svgjs.error + } + + // eslint-disable-next-line no-plusplus + if (++counter < maxPassCount && svgjs.data.length < prevResultSize) { + prevResultSize = svgjs.data.length + this._optimizeOnce(svgjs.data, info, optimizeOnceCallback) + } else { + if (config.datauri) { + svgjs.data = encodeSVGDatauri(svgjs.data, config.datauri) + } + if (info.path) { + svgjs.path = info.path + } + + result = svgjs + } + } + + this._optimizeOnce(svgstr, info, optimizeOnceCallback) + return result +} + function getBaseSvgoConfig(config) { const baseSvgoConfig = { plugins: [] } if (config.icon) baseSvgoConfig.plugins.push({ removeViewBox: false }) return baseSvgoConfig } -export default async (code, config = {}, state = {}) => { - if (!config.svgo) return code - const filePath = state.filePath || process.cwd() - const svgoRcConfig = config.runtimeConfig - ? await explorer.search(filePath) - : {} - const svgo = new SVGO( - mergeDeep(getBaseSvgoConfig(config), svgoRcConfig, config.svgoConfig), +function getFilePath(state) { + return state.filePath || process.cwd() +} + +function createSvgo(config, rcConfig) { + return new SVGO( + mergeDeep(getBaseSvgoConfig(config), rcConfig, config.svgoConfig), ) - const info = state.filePath +} + +function getInfo(state) { + return state.filePath ? { input: 'file', path: state.filePath } : { input: 'string' } - const { data } = await svgo.optimize(code, info) +} + +export default (code, config = {}, state = {}) => { + if (!config.svgo) return code + const filePath = getFilePath(state) + const svgoRcConfig = config.runtimeConfig ? explorer.searchSync(filePath) : {} + const svgo = createSvgo(config, svgoRcConfig) + const { data } = optimizeSync.call(svgo, code, getInfo(state)) return data } diff --git a/packages/core/src/plugins/svgo.test.js b/packages/core/src/plugins/svgo.test.js index 3043bd24..7e89cfec 100644 --- a/packages/core/src/plugins/svgo.test.js +++ b/packages/core/src/plugins/svgo.test.js @@ -16,61 +16,54 @@ const baseSvg = ` ` describe('svgo', () => { - it('should optimize svg', async () => { - const result = await svgo(baseSvg, { svgo: true, runtimeConfig: true }) - + it('should optimize svg', () => { + const result = svgo(baseSvg, { svgo: true, runtimeConfig: true }) expect(result).toMatchSnapshot() }) - it('should support config.svgoConfig', async () => { - const result = await svgo(baseSvg, { + it('should support config.svgoConfig', () => { + const result = svgo(baseSvg, { svgo: true, runtimeConfig: true, - svgoConfig: { plugins: [{ removeDesc: false }] }, + svgoConfig: { svgos: [{ removeDesc: false }] }, }) expect(result).toMatchSnapshot() }) - it('should support icon with config.svgoConfig plugins', async () => { - const result = await svgo(baseSvg, { + it('should support icon with config.svgoConfig svgos', () => { + const result = svgo(baseSvg, { svgo: true, icon: true, runtimeConfig: true, - svgoConfig: { plugins: [{ removeDesc: false }] }, + svgoConfig: { svgos: [{ removeDesc: false }] }, }) expect(result).toMatchSnapshot() }) - it('should use state.filePath to detect configuration', async () => { - const result = await svgo( + it('should use state.filePath to detect configuration', () => { + const result = svgo( baseSvg, { svgo: true, runtimeConfig: true }, { filePath: path.join(__dirname, '../__fixtures__/svgo') }, ) - // Desc should appear - expect(result).toMatchInlineSnapshot( - `"Created with Sketch."`, - ) + expect(result).toMatchSnapshot() }) - it('should not load runtime configuration with `runtimeConfig: false`', async () => { - const result = await svgo( + it('should not load runtime configuration with `runtimeConfig: false`', () => { + const result = svgo( baseSvg, { svgo: true, runtimeConfig: false }, { filePath: path.join(__dirname, '../__fixtures__/svgo') }, ) - // Desc should not appear - expect(result).toMatchInlineSnapshot( - `""`, - ) + expect(result).toMatchSnapshot() }) - it('should not remove viewBox with icon option', async () => { - const result = await svgo( + it('should not remove viewBox with icon option', () => { + const result = svgo( baseSvg, { icon: true, runtimeConfig: true }, { filePath: path.join(__dirname, '../__fixtures__/svgo') },