From 07f8d606e0aee1b37d869994815f351a284ee2a0 Mon Sep 17 00:00:00 2001 From: Bogdan Chadkin Date: Fri, 13 Aug 2021 19:07:08 +0300 Subject: [PATCH] Implement preset-default plugin (#1513) I saw complaints about `extendDefaultPlugins` api - it cannot be used when svgo is installed globally - it requires svgo to be installed when using svgo-loader or svgo-jsx - it prevents using serializable config formats like json In this diff I introduced the new plugin which is a bundle of all default plugins. ```js module.exports = { plugins: [ 'preset_default', // or { name: 'preset_default', floatPrecision: 4, overrides: { convertPathData: { applyTransforms: false } } } ] } ``` --- README.md | 307 ++++++++++------------ lib/svgo.js | 12 +- lib/svgo.test.js | 122 +++++++++ lib/svgo/config.js | 25 +- lib/svgo/plugins.js | 113 ++++---- plugins/addAttributesToSVGElement.js | 2 + plugins/addClassesToSVGElement.js | 2 + plugins/cleanupAttrs.js | 1 + plugins/cleanupEnableBackground.js | 2 + plugins/cleanupIDs.js | 2 + plugins/cleanupListOfValues.js | 2 + plugins/cleanupNumericValues.js | 2 + plugins/collapseGroups.js | 2 + plugins/convertColors.js | 2 + plugins/convertEllipseToCircle.js | 1 + plugins/convertPathData.js | 1 + plugins/convertShapeToPath.js | 1 + plugins/convertStyleToAttrs.js | 2 + plugins/convertTransform.js | 2 + plugins/inlineStyles.js | 2 + plugins/mergePaths.js | 1 + plugins/mergeStyles.js | 1 + plugins/minifyStyles.js | 2 + plugins/moveElemsAttrsToGroup.js | 2 + plugins/moveGroupAttrsToElems.js | 2 + plugins/plugins.js | 4 + plugins/prefixIds.js | 2 + plugins/preset-default.js | 80 ++++++ plugins/removeAttributesBySelector.js | 2 + plugins/removeAttrs.js | 2 + plugins/removeComments.js | 1 + plugins/removeDesc.js | 1 + plugins/removeDimensions.js | 2 + plugins/removeDoctype.js | 1 + plugins/removeEditorsNSData.js | 2 + plugins/removeElementsByAttr.js | 2 + plugins/removeEmptyAttrs.js | 2 + plugins/removeEmptyContainers.js | 2 + plugins/removeEmptyText.js | 1 + plugins/removeHiddenElems.js | 1 + plugins/removeMetadata.js | 1 + plugins/removeNonInheritableGroupAttrs.js | 2 + plugins/removeOffCanvasPaths.js | 2 + plugins/removeRasterImages.js | 1 + plugins/removeScriptElement.js | 1 + plugins/removeStyleElement.js | 1 + plugins/removeTitle.js | 1 + plugins/removeUnknownsAndDefaults.js | 2 + plugins/removeUnusedNS.js | 2 + plugins/removeUselessDefs.js | 2 + plugins/removeUselessStrokeAndFill.js | 2 + plugins/removeViewBox.js | 2 + plugins/removeXMLNS.js | 2 + plugins/removeXMLProcInst.js | 1 + plugins/reusePaths.js | 2 + plugins/sortAttrs.js | 2 + plugins/sortDefsChildren.js | 2 + test/config/_index.test.js | 39 +-- test/svgo/_index.test.js | 8 +- tsconfig.json | 17 +- 60 files changed, 522 insertions(+), 288 deletions(-) create mode 100644 lib/svgo.test.js create mode 100644 plugins/preset-default.js diff --git a/README.md b/README.md index c45b5fd6..24d073ac 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ SVGO logo - ## SVGO [![npm version](https://img.shields.io/npm/v/svgo)](https://npmjs.org/package/svgo) [![Discord](https://img.shields.io/discord/815166721315831868)](https://discord.gg/z8jX8NYxrE) **SVG O**ptimizer is a Node.js-based tool for optimizing SVG vector graphics files. @@ -53,8 +52,8 @@ module.exports = { js2svg: { indent: 2, // string with spaces or number of spaces. 4 by default pretty: true, // boolean, false by default - } -} + }, +}; ``` SVGO has a plugin-based architecture, so almost every optimization is a separate plugin. @@ -67,97 +66,83 @@ module.exports = { 'builtinPluginName', // or by expanded version { - name: 'builtinPluginName' + name: 'builtinPluginName', }, // some plugins allow/require to pass options { name: 'builtinPluginName', params: { - optionName: 'optionValue' - } - } - ] -} + optionName: 'optionValue', + }, + }, + ], +}; ``` -The default list is fully overridden if the `plugins` field is specified. To extend the default -list use the `extendDefaultPlugins` utility: - -```js -const { extendDefaultPlugins } = require('svgo'); -module.exports = { - plugins: extendDefaultPlugins([ - { - name: 'builtinPluginName', - params: { - optionName: 'optionValue' - } - } - ]) -} -``` - -To disable one of the default plugins use the `active` field: - -```js -const { extendDefaultPlugins } = require('svgo'); -module.exports = { - plugins: extendDefaultPlugins([ - { - name: 'builtinPluginName', - active: false - } - ]) -} -``` - -See the list of the default plugins: +The default preset of plugins is fully overridden if the `plugins` field is specified. +Use `preset-default` plugin to customize plugins options. ```js module.exports = { plugins: [ - 'removeDoctype', - 'removeXMLProcInst', - 'removeComments', - 'removeMetadata', - 'removeEditorsNSData', - 'cleanupAttrs', - 'mergeStyles', - 'inlineStyles', - 'minifyStyles', - 'cleanupIDs', - 'removeUselessDefs', - 'cleanupNumericValues', - 'convertColors', - 'removeUnknownsAndDefaults', - 'removeNonInheritableGroupAttrs', - 'removeUselessStrokeAndFill', - 'removeViewBox', - 'cleanupEnableBackground', - 'removeHiddenElems', - 'removeEmptyText', - 'convertShapeToPath', - 'convertEllipseToCircle', - 'moveElemsAttrsToGroup', - 'moveGroupAttrsToElems', - 'collapseGroups', - 'convertPathData', - 'convertTransform', - 'removeEmptyAttrs', - 'removeEmptyContainers', - 'mergePaths', - 'removeUnusedNS', - 'sortDefsChildren', - 'removeTitle', - 'removeDesc' - ] -} + { + name: 'preset-default', + params: { + overrides: { + // customize options + builtinPluginName: { + optionName: 'optionValue', + }, + // or disable plugins + anotherBuiltinPlugin: false, + }, + }, + }, + ], +}; ``` +Default preset includes the following list of plugins: + +- removeDoctype +- removeXMLProcInst +- removeComments +- removeMetadata +- removeEditorsNSData +- cleanupAttrs +- mergeStyles +- inlineStyles +- minifyStyles +- cleanupIDs +- removeUselessDefs +- cleanupNumericValues +- convertColors +- removeUnknownsAndDefaults +- removeNonInheritableGroupAttrs +- removeUselessStrokeAndFill +- removeViewBox +- cleanupEnableBackground +- removeHiddenElems +- removeEmptyText +- convertShapeToPath +- convertEllipseToCircle +- moveElemsAttrsToGroup +- moveGroupAttrsToElems +- collapseGroups +- convertPathData +- convertTransform +- removeEmptyAttrs +- removeEmptyContainers +- mergePaths +- removeUnusedNS +- sortDefsChildren +- removeTitle +- removeDesc + It's also possible to specify a custom plugin: ```js -const anotherCustomPlugin = require('./another-custom-plugin.js') +const anotherCustomPlugin = require('./another-custom-plugin.js'); module.exports = { plugins: [ { @@ -166,11 +151,11 @@ module.exports = { params: { optionName: 'optionValue', }, - fn: (ast, params, info) => {} + fn: (ast, params, info) => {}, }, - anotherCustomPlugin - ] -} + anotherCustomPlugin, + ], +}; ``` ## API usage @@ -187,9 +172,9 @@ const result = optimize(svgString, { // optional but recommended field path: 'path-to.svg', // all config fields are also available here - multipass: true -}) -const optimizedSvgString = result.data + multipass: true, +}); +const optimizedSvgString = result.data; ``` ### loadConfig @@ -198,95 +183,95 @@ If you write a tool on top of SVGO you might need a way to load SVGO config. ```js const { loadConfig } = require('svgo'); -const config = await loadConfig() +const config = await loadConfig(); // you can also specify a relative or absolute path and customize the current working directory -const config = await loadConfig(configFile, cwd) +const config = await loadConfig(configFile, cwd); ``` ## Built-in plugins -| Plugin | Description | Default | -| ------ | ----------- | ------- | -| [cleanupAttrs](https://github.com/svg/svgo/blob/master/plugins/cleanupAttrs.js) | cleanup attributes from newlines, trailing, and repeating spaces | `enabled` | -| [mergeStyles](https://github.com/svg/svgo/blob/master/plugins/mergeStyles.js) | merge multiple style elements into one | `enabled` | -| [inlineStyles](https://github.com/svg/svgo/blob/master/plugins/inlineStyles.js) | move and merge styles from `