1
0
mirror of https://github.com/svg/svgo.git synced 2025-08-09 02:22:08 +03:00

chore: convert project to us ECMAScript modules (preserving CJS compatibility) (#1905)

This commit is contained in:
Jon Dufresne
2024-01-03 08:17:37 -08:00
committed by GitHub
parent 252b28c4bf
commit 2442f74239
103 changed files with 1147 additions and 1058 deletions

View File

@@ -1,6 +1,7 @@
{ {
"parserOptions": { "parserOptions": {
"ecmaVersion": 2021 "ecmaVersion": 2021,
"sourceType": "module"
}, },
"env": { "env": {
"node": true, "node": true,
@@ -8,12 +9,6 @@
}, },
"extends": ["eslint:recommended"], "extends": ["eslint:recommended"],
"overrides": [ "overrides": [
{
"files": ["rollup.config.js", "**/*.mjs"],
"parserOptions": {
"sourceType": "module"
}
},
{ {
"files": ["**/*.cjs"], "files": ["**/*.cjs"],
"parserOptions": { "parserOptions": {

View File

@@ -47,7 +47,6 @@ jobs:
- 20 - 20
- 18 - 18
- 16 - 16
- 14
os: os:
- ubuntu-latest - ubuntu-latest
- windows-latest - windows-latest
@@ -61,4 +60,4 @@ jobs:
- run: yarn install - run: yarn install
- run: yarn playwright install --with-deps chromium - run: yarn playwright install --with-deps chromium
- run: yarn test - run: yarn test
- run: yarn test-browser - run: yarn test-bundles

View File

@@ -54,7 +54,7 @@ SVGO reads the configuration from `svgo.config.js` or the `--config path/to/conf
**`svgo.config.js`** **`svgo.config.js`**
```js ```js
module.exports = { export default {
multipass: false, // boolean multipass: false, // boolean
datauri: 'base64', // 'base64'|'enc'|'unenc' datauri: 'base64', // 'base64'|'enc'|'unenc'
js2svg: { js2svg: {
@@ -83,7 +83,7 @@ Instead of configuring SVGO from scratch, you can tweak the default preset to su
**`svgo.config.js`** **`svgo.config.js`**
```js ```js
module.exports = { export default {
plugins: [ plugins: [
{ {
name: 'preset-default', name: 'preset-default',
@@ -112,9 +112,9 @@ You can also specify custom plugins:
**`svgo.config.js`** **`svgo.config.js`**
```js ```js
const importedPlugin = require('./imported-plugin'); import importedPlugin from './imported-plugin';
module.exports = { export default {
plugins: [ plugins: [
// plugin imported from another JavaScript file // plugin imported from another JavaScript file
importedPlugin, importedPlugin,
@@ -140,7 +140,7 @@ SVGO provides a few low level utilities.
The core of SVGO is `optimize` function. The core of SVGO is `optimize` function.
```js ```js
const { optimize } = require('svgo'); import { optimize } from 'svgo';
const result = optimize(svgString, { const result = optimize(svgString, {
path: 'path-to.svg', // recommended path: 'path-to.svg', // recommended
@@ -155,7 +155,7 @@ const optimizedSvgString = result.data;
If you write a tool on top of SVGO you may want to resolve the `svgo.config.js` file. If you write a tool on top of SVGO you may want to resolve the `svgo.config.js` file.
```js ```js
const { loadConfig } = require('svgo'); import { loadConfig } from 'svgo';
const config = await loadConfig(); const config = await loadConfig();
``` ```

View File

@@ -1,8 +1,8 @@
#!/usr/bin/env node #!/usr/bin/env node
const colors = require('picocolors'); import colors from 'picocolors';
const { program } = require('commander'); import { program } from 'commander';
const makeProgram = require('../lib/svgo/coa'); import makeProgram from '../lib/svgo/coa.js';
makeProgram(program); makeProgram(program);
program.parseAsync(process.argv).catch((error) => { program.parseAsync(process.argv).catch((error) => {
console.error(colors.red(error.stack)); console.error(colors.red(error.stack));

View File

@@ -1,57 +1,109 @@
'use strict'; import presetDefault from '../plugins/preset-default.js';
import * as addAttributesToSVGElement from '../plugins/addAttributesToSVGElement.js';
import * as addClassesToSVGElement from '../plugins/addClassesToSVGElement.js';
import * as cleanupAttrs from '../plugins/cleanupAttrs.js';
import * as cleanupEnableBackground from '../plugins/cleanupEnableBackground.js';
import * as cleanupIds from '../plugins/cleanupIds.js';
import * as cleanupListOfValues from '../plugins/cleanupListOfValues.js';
import * as cleanupNumericValues from '../plugins/cleanupNumericValues.js';
import * as collapseGroups from '../plugins/collapseGroups.js';
import * as convertColors from '../plugins/convertColors.js';
import * as convertEllipseToCircle from '../plugins/convertEllipseToCircle.js';
import * as convertOneStopGradients from '../plugins/convertOneStopGradients.js';
import * as convertPathData from '../plugins/convertPathData.js';
import * as convertShapeToPath from '../plugins/convertShapeToPath.js';
import * as convertStyleToAttrs from '../plugins/convertStyleToAttrs.js';
import * as convertTransform from '../plugins/convertTransform.js';
import * as mergeStyles from '../plugins/mergeStyles.js';
import * as inlineStyles from '../plugins/inlineStyles.js';
import * as mergePaths from '../plugins/mergePaths.js';
import * as minifyStyles from '../plugins/minifyStyles.js';
import * as moveElemsAttrsToGroup from '../plugins/moveElemsAttrsToGroup.js';
import * as moveGroupAttrsToElems from '../plugins/moveGroupAttrsToElems.js';
import * as prefixIds from '../plugins/prefixIds.js';
import * as removeAttributesBySelector from '../plugins/removeAttributesBySelector.js';
import * as removeAttrs from '../plugins/removeAttrs.js';
import * as removeComments from '../plugins/removeComments.js';
import * as removeDesc from '../plugins/removeDesc.js';
import * as removeDimensions from '../plugins/removeDimensions.js';
import * as removeDoctype from '../plugins/removeDoctype.js';
import * as removeEditorsNSData from '../plugins/removeEditorsNSData.js';
import * as removeElementsByAttr from '../plugins/removeElementsByAttr.js';
import * as removeEmptyAttrs from '../plugins/removeEmptyAttrs.js';
import * as removeEmptyContainers from '../plugins/removeEmptyContainers.js';
import * as removeEmptyText from '../plugins/removeEmptyText.js';
import * as removeHiddenElems from '../plugins/removeHiddenElems.js';
import * as removeMetadata from '../plugins/removeMetadata.js';
import * as removeNonInheritableGroupAttrs from '../plugins/removeNonInheritableGroupAttrs.js';
import * as removeOffCanvasPaths from '../plugins/removeOffCanvasPaths.js';
import * as removeRasterImages from '../plugins/removeRasterImages.js';
import * as removeScriptElement from '../plugins/removeScriptElement.js';
import * as removeStyleElement from '../plugins/removeStyleElement.js';
import * as removeTitle from '../plugins/removeTitle.js';
import * as removeUnknownsAndDefaults from '../plugins/removeUnknownsAndDefaults.js';
import * as removeUnusedNS from '../plugins/removeUnusedNS.js';
import * as removeUselessDefs from '../plugins/removeUselessDefs.js';
import * as removeUselessStrokeAndFill from '../plugins/removeUselessStrokeAndFill.js';
import * as removeViewBox from '../plugins/removeViewBox.js';
import * as removeXlink from '../plugins/removeXlink.js';
import * as removeXMLNS from '../plugins/removeXMLNS.js';
import * as removeXMLProcInst from '../plugins/removeXMLProcInst.js';
import * as reusePaths from '../plugins/reusePaths.js';
import * as sortAttrs from '../plugins/sortAttrs.js';
import * as sortDefsChildren from '../plugins/sortDefsChildren.js';
exports.builtin = [ export const builtin = [
require('../plugins/preset-default.js'), presetDefault,
require('../plugins/addAttributesToSVGElement.js'), addAttributesToSVGElement,
require('../plugins/addClassesToSVGElement.js'), addClassesToSVGElement,
require('../plugins/cleanupAttrs.js'), cleanupAttrs,
require('../plugins/cleanupEnableBackground.js'), cleanupEnableBackground,
require('../plugins/cleanupIds.js'), cleanupIds,
require('../plugins/cleanupListOfValues.js'), cleanupListOfValues,
require('../plugins/cleanupNumericValues.js'), cleanupNumericValues,
require('../plugins/collapseGroups.js'), collapseGroups,
require('../plugins/convertColors.js'), convertColors,
require('../plugins/convertEllipseToCircle.js'), convertEllipseToCircle,
require('../plugins/convertOneStopGradients.js'), convertOneStopGradients,
require('../plugins/convertPathData.js'), convertPathData,
require('../plugins/convertShapeToPath.js'), convertShapeToPath,
require('../plugins/convertStyleToAttrs.js'), convertStyleToAttrs,
require('../plugins/convertTransform.js'), convertTransform,
require('../plugins/mergeStyles.js'), mergeStyles,
require('../plugins/inlineStyles.js'), inlineStyles,
require('../plugins/mergePaths.js'), mergePaths,
require('../plugins/minifyStyles.js'), minifyStyles,
require('../plugins/moveElemsAttrsToGroup.js'), moveElemsAttrsToGroup,
require('../plugins/moveGroupAttrsToElems.js'), moveGroupAttrsToElems,
require('../plugins/prefixIds.js'), prefixIds,
require('../plugins/removeAttributesBySelector.js'), removeAttributesBySelector,
require('../plugins/removeAttrs.js'), removeAttrs,
require('../plugins/removeComments.js'), removeComments,
require('../plugins/removeDesc.js'), removeDesc,
require('../plugins/removeDimensions.js'), removeDimensions,
require('../plugins/removeDoctype.js'), removeDoctype,
require('../plugins/removeEditorsNSData.js'), removeEditorsNSData,
require('../plugins/removeElementsByAttr.js'), removeElementsByAttr,
require('../plugins/removeEmptyAttrs.js'), removeEmptyAttrs,
require('../plugins/removeEmptyContainers.js'), removeEmptyContainers,
require('../plugins/removeEmptyText.js'), removeEmptyText,
require('../plugins/removeHiddenElems.js'), removeHiddenElems,
require('../plugins/removeMetadata.js'), removeMetadata,
require('../plugins/removeNonInheritableGroupAttrs.js'), removeNonInheritableGroupAttrs,
require('../plugins/removeOffCanvasPaths.js'), removeOffCanvasPaths,
require('../plugins/removeRasterImages.js'), removeRasterImages,
require('../plugins/removeScriptElement.js'), removeScriptElement,
require('../plugins/removeStyleElement.js'), removeStyleElement,
require('../plugins/removeTitle.js'), removeTitle,
require('../plugins/removeUnknownsAndDefaults.js'), removeUnknownsAndDefaults,
require('../plugins/removeUnusedNS.js'), removeUnusedNS,
require('../plugins/removeUselessDefs.js'), removeUselessDefs,
require('../plugins/removeUselessStrokeAndFill.js'), removeUselessStrokeAndFill,
require('../plugins/removeViewBox.js'), removeViewBox,
require('../plugins/removeXlink.js'), removeXlink,
require('../plugins/removeXMLNS.js'), removeXMLNS,
require('../plugins/removeXMLProcInst.js'), removeXMLProcInst,
require('../plugins/reusePaths.js'), reusePaths,
require('../plugins/sortAttrs.js'), sortAttrs,
require('../plugins/sortDefsChildren.js'), sortDefsChildren,
]; ];

View File

@@ -1,21 +1,19 @@
'use strict';
/** /**
* @typedef {import('./types').XastNode} XastNode * @typedef {import('./types.js').XastNode} XastNode
* @typedef {import('./types').XastInstruction} XastInstruction * @typedef {import('./types.js').XastInstruction} XastInstruction
* @typedef {import('./types').XastDoctype} XastDoctype * @typedef {import('./types.js').XastDoctype} XastDoctype
* @typedef {import('./types').XastComment} XastComment * @typedef {import('./types.js').XastComment} XastComment
* @typedef {import('./types').XastRoot} XastRoot * @typedef {import('./types.js').XastRoot} XastRoot
* @typedef {import('./types').XastElement} XastElement * @typedef {import('./types.js').XastElement} XastElement
* @typedef {import('./types').XastCdata} XastCdata * @typedef {import('./types.js').XastCdata} XastCdata
* @typedef {import('./types').XastText} XastText * @typedef {import('./types.js').XastText} XastText
* @typedef {import('./types').XastParent} XastParent * @typedef {import('./types.js').XastParent} XastParent
* @typedef {import('./types').XastChild} XastChild * @typedef {import('./types.js').XastChild} XastChild
*/ */
// @ts-ignore sax will be replaced with something else later // @ts-ignore sax will be replaced with something else later
const SAX = require('@trysound/sax'); import SAX from '@trysound/sax';
const { textElems } = require('../plugins/_collections'); import { textElems } from '../plugins/_collections.js';
class SvgoParserError extends Error { class SvgoParserError extends Error {
/** /**
@@ -89,7 +87,7 @@ const config = {
* *
* @type {(data: string, from?: string) => XastRoot} * @type {(data: string, from?: string) => XastRoot}
*/ */
const parseSvg = (data, from) => { export const parseSvg = (data, from) => {
const sax = SAX.parser(config.strict, config); const sax = SAX.parser(config.strict, config);
/** /**
* @type {XastRoot} * @type {XastRoot}
@@ -259,4 +257,3 @@ const parseSvg = (data, from) => {
sax.write(data).close(); sax.write(data).close();
return root; return root;
}; };
exports.parseSvg = parseSvg;

View File

@@ -1,10 +1,8 @@
'use strict'; import { removeLeadingZero, toFixed } from './svgo/tools.js';
const { removeLeadingZero, toFixed } = require('./svgo/tools');
/** /**
* @typedef {import('./types').PathDataItem} PathDataItem * @typedef {import('./types.js').PathDataItem} PathDataItem
* @typedef {import('./types').PathDataCommand} PathDataCommand * @typedef {import('./types.js').PathDataCommand} PathDataCommand
*/ */
// Based on https://www.w3.org/TR/SVG11/paths.html#PathDataBNF // Based on https://www.w3.org/TR/SVG11/paths.html#PathDataBNF
@@ -137,7 +135,7 @@ const readNumber = (string, cursor) => {
/** /**
* @type {(string: string) => PathDataItem[]} * @type {(string: string) => PathDataItem[]}
*/ */
const parsePathData = (string) => { export const parsePathData = (string) => {
/** /**
* @type {PathDataItem[]} * @type {PathDataItem[]}
*/ */
@@ -240,7 +238,6 @@ const parsePathData = (string) => {
} }
return pathData; return pathData;
}; };
exports.parsePathData = parsePathData;
/** /**
* @type {(number: number, precision?: number) => { * @type {(number: number, precision?: number) => {
@@ -316,7 +313,11 @@ const stringifyArgs = (command, args, precision, disableSpaceAfterFlags) => {
* @param {StringifyPathDataOptions} options * @param {StringifyPathDataOptions} options
* @returns {string} * @returns {string}
*/ */
const stringifyPathData = ({ pathData, precision, disableSpaceAfterFlags }) => { export const stringifyPathData = ({
pathData,
precision,
disableSpaceAfterFlags,
}) => {
if (pathData.length === 1) { if (pathData.length === 1) {
const { command, args } = pathData[0]; const { command, args } = pathData[0];
return ( return (
@@ -377,4 +378,3 @@ const stringifyPathData = ({ pathData, precision, disableSpaceAfterFlags }) => {
return result; return result;
}; };
exports.stringifyPathData = stringifyPathData;

View File

@@ -1,11 +1,9 @@
'use strict'; import { parsePathData, stringifyPathData } from './path.js';
/** /**
* @typedef {import('../lib/types').PathDataItem} PathDataItem * @typedef {import('../lib/types.js').PathDataItem} PathDataItem
*/ */
const { parsePathData, stringifyPathData } = require('./path.js');
describe('parse path data', () => { describe('parse path data', () => {
it('should allow spaces between commands', () => { it('should allow spaces between commands', () => {
expect(parsePathData('M0 10 L \n\r\t20 30')).toStrictEqual([ expect(parsePathData('M0 10 L \n\r\t20 30')).toStrictEqual([

View File

@@ -1,28 +1,20 @@
'use strict'; import { textElems } from '../plugins/_collections.js';
/**
* @typedef {import('./types').XastParent} XastParent
* @typedef {import('./types').XastRoot} XastRoot
* @typedef {import('./types').XastElement} XastElement
* @typedef {import('./types').XastInstruction} XastInstruction
* @typedef {import('./types').XastDoctype} XastDoctype
* @typedef {import('./types').XastText} XastText
* @typedef {import('./types').XastCdata} XastCdata
* @typedef {import('./types').XastComment} XastComment
* @typedef {import('./types').StringifyOptions} StringifyOptions
*/
const { textElems } = require('../plugins/_collections');
/** /**
* @typedef {import('./types.js').XastParent} XastParent
* @typedef {import('./types.js').XastRoot} XastRoot
* @typedef {import('./types.js').XastElement} XastElement
* @typedef {import('./types.js').XastInstruction} XastInstruction
* @typedef {import('./types.js').XastDoctype} XastDoctype
* @typedef {import('./types.js').XastText} XastText
* @typedef {import('./types.js').XastCdata} XastCdata
* @typedef {import('./types.js').XastComment} XastComment
* @typedef {import('./types.js').StringifyOptions} StringifyOptions
* @typedef {{ * @typedef {{
* indent: string, * indent: string,
* textContext: ?XastElement, * textContext: ?XastElement,
* indentLevel: number, * indentLevel: number,
* }} State * }} State
*/
/**
* @typedef {Required<StringifyOptions>} Options * @typedef {Required<StringifyOptions>} Options
*/ */
@@ -77,7 +69,7 @@ const entities = {
* *
* @type {(data: XastRoot, config: StringifyOptions) => string} * @type {(data: XastRoot, config: StringifyOptions) => string}
*/ */
const stringifySvg = (data, userOptions = {}) => { export const stringifySvg = (data, userOptions = {}) => {
/** /**
* @type {Options} * @type {Options}
*/ */
@@ -114,7 +106,6 @@ const stringifySvg = (data, userOptions = {}) => {
} }
return svg; return svg;
}; };
exports.stringifySvg = stringifySvg;
/** /**
* @type {(node: XastParent, config: Options, state: State) => string} * @type {(node: XastParent, config: Options, state: State) => string}

View File

@@ -1,29 +1,25 @@
'use strict'; import * as csstree from 'css-tree';
import * as csswhat from 'css-what';
/** import { syntax } from 'csso';
* @typedef {import('css-tree').Rule} CsstreeRule import { visit, matches } from './xast.js';
* @typedef {import('./types').Specificity} Specificity import {
* @typedef {import('./types').Stylesheet} Stylesheet
* @typedef {import('./types').StylesheetRule} StylesheetRule
* @typedef {import('./types').StylesheetDeclaration} StylesheetDeclaration
* @typedef {import('./types').ComputedStyles} ComputedStyles
* @typedef {import('./types').XastRoot} XastRoot
* @typedef {import('./types').XastElement} XastElement
* @typedef {import('./types').XastParent} XastParent
* @typedef {import('./types').XastChild} XastChild
*/
const csstree = require('css-tree');
const csswhat = require('css-what');
const {
syntax: { specificity },
} = require('csso');
const { visit, matches } = require('./xast.js');
const {
attrsGroups, attrsGroups,
inheritableAttrs, inheritableAttrs,
presentationNonInheritableGroupAttrs, presentationNonInheritableGroupAttrs,
} = require('../plugins/_collections.js'); } from '../plugins/_collections.js';
/**
* @typedef {import('css-tree').Rule} CsstreeRule
* @typedef {import('./types.js').Specificity} Specificity
* @typedef {import('./types.js').Stylesheet} Stylesheet
* @typedef {import('./types.js').StylesheetRule} StylesheetRule
* @typedef {import('./types.js').StylesheetDeclaration} StylesheetDeclaration
* @typedef {import('./types.js').ComputedStyles} ComputedStyles
* @typedef {import('./types.js').XastRoot} XastRoot
* @typedef {import('./types.js').XastElement} XastElement
* @typedef {import('./types.js').XastParent} XastParent
* @typedef {import('./types.js').XastChild} XastChild
*/
// @ts-ignore not defined in @types/csstree // @ts-ignore not defined in @types/csstree
const csstreeWalkSkip = csstree.walk.skip; const csstreeWalkSkip = csstree.walk.skip;
@@ -60,7 +56,7 @@ const parseRule = (ruleNode, dynamic) => {
} }
}); });
rules.push({ rules.push({
specificity: specificity(node), specificity: syntax.specificity(node),
dynamic: hasPseudoClasses || dynamic, dynamic: hasPseudoClasses || dynamic,
// compute specificity from original node to consider pseudo classes // compute specificity from original node to consider pseudo classes
selector: csstree.generate(newNode), selector: csstree.generate(newNode),
@@ -201,7 +197,7 @@ const computeOwnStyle = (stylesheet, node) => {
* @param {Specificity} b * @param {Specificity} b
* @returns {number} * @returns {number}
*/ */
const compareSpecificity = (a, b) => { export const compareSpecificity = (a, b) => {
for (let i = 0; i < 4; i += 1) { for (let i = 0; i < 4; i += 1) {
if (a[i] < b[i]) { if (a[i] < b[i]) {
return -1; return -1;
@@ -212,12 +208,11 @@ const compareSpecificity = (a, b) => {
return 0; return 0;
}; };
exports.compareSpecificity = compareSpecificity;
/** /**
* @type {(root: XastRoot) => Stylesheet} * @type {(root: XastRoot) => Stylesheet}
*/ */
const collectStylesheet = (root) => { export const collectStylesheet = (root) => {
/** @type {StylesheetRule[]} */ /** @type {StylesheetRule[]} */
const rules = []; const rules = [];
/** @type {Map<XastElement, XastParent>} */ /** @type {Map<XastElement, XastParent>} */
@@ -253,14 +248,13 @@ const collectStylesheet = (root) => {
rules.sort((a, b) => compareSpecificity(a.specificity, b.specificity)); rules.sort((a, b) => compareSpecificity(a.specificity, b.specificity));
return { rules, parents }; return { rules, parents };
}; };
exports.collectStylesheet = collectStylesheet;
/** /**
* @param {Stylesheet} stylesheet * @param {Stylesheet} stylesheet
* @param {XastElement} node * @param {XastElement} node
* @returns {ComputedStyles} * @returns {ComputedStyles}
*/ */
const computeStyle = (stylesheet, node) => { export const computeStyle = (stylesheet, node) => {
const { parents } = stylesheet; const { parents } = stylesheet;
const computedStyles = computeOwnStyle(stylesheet, node); const computedStyles = computeOwnStyle(stylesheet, node);
let parent = parents.get(node); let parent = parents.get(node);
@@ -279,7 +273,6 @@ const computeStyle = (stylesheet, node) => {
} }
return computedStyles; return computedStyles;
}; };
exports.computeStyle = computeStyle;
/** /**
* Determines if the CSS selector includes or traverses the given attribute. * Determines if the CSS selector includes or traverses the given attribute.
@@ -294,7 +287,7 @@ exports.computeStyle = computeStyle;
* @param {boolean} traversed * @param {boolean} traversed
* @returns {boolean} * @returns {boolean}
*/ */
const includesAttrSelector = ( export const includesAttrSelector = (
selector, selector,
name, name,
value = null, value = null,
@@ -333,4 +326,3 @@ const includesAttrSelector = (
return false; return false;
}; };
exports.includesAttrSelector = includesAttrSelector;

View File

@@ -1,14 +1,12 @@
'use strict'; import { collectStylesheet, computeStyle } from './style.js';
import { visit } from './xast.js';
import { parseSvg } from './parser.js';
/** /**
* @typedef {import('./types').XastParent} XastParent * @typedef {import('./types.js').XastParent} XastParent
* @typedef {import('./types').XastElement} XastElement * @typedef {import('./types.js').XastElement} XastElement
*/ */
const { collectStylesheet, computeStyle } = require('./style.js');
const { visit } = require('./xast.js');
const { parseSvg } = require('./parser.js');
/** /**
* @type {(node: XastParent, id: string) => XastElement} * @type {(node: XastParent, id: string) => XastElement}
*/ */

View File

@@ -1,24 +1,15 @@
'use strict'; import os from 'os';
import fs from 'fs';
const os = require('os'); import { pathToFileURL } from 'url';
const fs = require('fs'); import path from 'path';
const { pathToFileURL } = require('url'); import { optimize as optimizeAgnostic } from './svgo.js';
const path = require('path');
const { optimize: optimizeAgnostic } = require('./svgo.js');
const importConfig = async (configFile) => { const importConfig = async (configFile) => {
let config; // dynamic import expects file url instead of path and may fail
// at the moment dynamic import may randomly fail with segfault // when windows path is provided
// to workaround this for some users .cjs extension is loaded const imported = await import(pathToFileURL(configFile));
// exclusively with require const config = imported.default;
if (configFile.endsWith('.cjs')) {
config = require(configFile);
} else {
// dynamic import expects file url instead of path and may fail
// when windows path is provided
const { default: imported } = await import(pathToFileURL(configFile));
config = imported;
}
if (config == null || typeof config !== 'object' || Array.isArray(config)) { if (config == null || typeof config !== 'object' || Array.isArray(config)) {
throw Error(`Invalid config file "${configFile}"`); throw Error(`Invalid config file "${configFile}"`);
} }
@@ -34,7 +25,7 @@ const isFile = async (file) => {
} }
}; };
const loadConfig = async (configFile, cwd = process.cwd()) => { export const loadConfig = async (configFile, cwd = process.cwd()) => {
if (configFile != null) { if (configFile != null) {
if (path.isAbsolute(configFile)) { if (path.isAbsolute(configFile)) {
return await importConfig(configFile); return await importConfig(configFile);
@@ -64,9 +55,8 @@ const loadConfig = async (configFile, cwd = process.cwd()) => {
dir = parent; dir = parent;
} }
}; };
exports.loadConfig = loadConfig;
const optimize = (input, config) => { export const optimize = (input, config) => {
if (config == null) { if (config == null) {
config = {}; config = {};
} }
@@ -82,4 +72,3 @@ const optimize = (input, config) => {
}, },
}); });
}; };
exports.optimize = optimize;

View File

@@ -1,13 +1,11 @@
'use strict'; import os from 'os';
import path from 'path';
import { optimize, loadConfig } from './svgo-node.js';
/** /**
* @typedef {import('../lib/types').Plugin} Plugin * @typedef {import('../lib/types.js').Plugin} Plugin
*/ */
const os = require('os');
const path = require('path');
const { optimize, loadConfig } = require('./svgo-node.js');
const describeLF = os.EOL === '\r\n' ? describe.skip : describe; const describeLF = os.EOL === '\r\n' ? describe.skip : describe;
const describeCRLF = os.EOL === '\r\n' ? describe : describe.skip; const describeCRLF = os.EOL === '\r\n' ? describe : describe.skip;

6
lib/svgo.d.ts vendored
View File

@@ -1,12 +1,12 @@
import type { StringifyOptions, DataUri, Plugin as PluginFn } from './types'; import type { StringifyOptions, DataUri, Plugin } from './types.js';
import type { import type {
BuiltinsWithOptionalParams, BuiltinsWithOptionalParams,
BuiltinsWithRequiredParams, BuiltinsWithRequiredParams,
} from '../plugins/plugins-types'; } from '../plugins/plugins-types.js';
type CustomPlugin = { type CustomPlugin = {
name: string; name: string;
fn: PluginFn<void>; fn: Plugin<void>;
}; };
type PluginConfig = type PluginConfig =

View File

@@ -1,10 +1,8 @@
'use strict'; import { parseSvg } from './parser.js';
import { stringifySvg } from './stringifier.js';
const { parseSvg } = require('./parser.js'); import { builtin } from './builtin.js';
const { stringifySvg } = require('./stringifier.js'); import { invokePlugins } from './svgo/plugins.js';
const { builtin } = require('./builtin.js'); import { encodeSVGDatauri } from './svgo/tools.js';
const { invokePlugins } = require('./svgo/plugins.js');
const { encodeSVGDatauri } = require('./svgo/tools.js');
const pluginsMap = {}; const pluginsMap = {};
for (const plugin of builtin) { for (const plugin of builtin) {
@@ -47,7 +45,7 @@ const resolvePluginConfig = (plugin) => {
return null; return null;
}; };
const optimize = (input, config) => { export const optimize = (input, config) => {
if (config == null) { if (config == null) {
config = {}; config = {};
} }
@@ -99,4 +97,3 @@ const optimize = (input, config) => {
data: output, data: output,
}; };
}; };
exports.optimize = optimize;

View File

@@ -1,11 +1,10 @@
'use strict'; import { jest } from '@jest/globals';
import { optimize } from './svgo.js';
/** /**
* @typedef {import('../lib/types').Plugin} Plugin * @typedef {import('../lib/types.js').Plugin} Plugin
*/ */
const { optimize } = require('./svgo.js');
test('allow to setup default preset', () => { test('allow to setup default preset', () => {
const svg = ` const svg = `
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>

View File

@@ -1,12 +1,14 @@
'use strict'; import fs from 'fs';
import path from 'path';
import colors from 'picocolors';
import { fileURLToPath } from 'url';
import { encodeSVGDatauri, decodeSVGDatauri } from './tools.js';
import { loadConfig, optimize } from '../svgo-node.js';
import { builtin } from '../builtin.js';
const fs = require('fs'); const __dirname = path.dirname(fileURLToPath(import.meta.url));
const path = require('path'); const pkgPath = path.join(__dirname, '../../package.json');
const colors = require('picocolors'); const PKG = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
const { loadConfig, optimize } = require('../svgo-node.js');
const { builtin } = require('../builtin.js');
const PKG = require('../../package.json');
const { encodeSVGDatauri, decodeSVGDatauri } = require('./tools.js');
const regSVGFile = /\.svg$/i; const regSVGFile = /\.svg$/i;
@@ -15,7 +17,7 @@ const regSVGFile = /\.svg$/i;
* *
* @param {string} path * @param {string} path
*/ */
function checkIsDir(path) { export function checkIsDir(path) {
try { try {
return fs.lstatSync(path).isDirectory(); return fs.lstatSync(path).isDirectory();
} catch (e) { } catch (e) {
@@ -23,7 +25,7 @@ function checkIsDir(path) {
} }
} }
module.exports = function makeProgram(program) { export default function makeProgram(program) {
program program
.name(PKG.name) .name(PKG.name)
.description(PKG.description, { .description(PKG.description, {
@@ -77,7 +79,7 @@ module.exports = function makeProgram(program) {
// used by picocolors internally // used by picocolors internally
.option('--no-color', 'Output plain text without color') .option('--no-color', 'Output plain text without color')
.action(action); .action(action);
}; }
async function action(args, opts, command) { async function action(args, opts, command) {
var input = opts.input || args; var input = opts.input || args;
@@ -524,5 +526,3 @@ function showAvailablePlugins() {
.join('\n'); .join('\n');
console.log('Currently available plugins:\n' + list); console.log('Currently available plugins:\n' + list);
} }
module.exports.checkIsDir = checkIsDir;

View File

@@ -1,2 +1,2 @@
declare let obj: any; declare let obj: any;
export = obj; export default obj;

View File

@@ -1,5 +1,3 @@
'use strict';
const isTag = (node) => { const isTag = (node) => {
return node.type === 'element'; return node.type === 'element';
}; };
@@ -117,4 +115,4 @@ const svgoCssSelectAdapter = {
findOne, findOne,
}; };
module.exports = svgoCssSelectAdapter; export default svgoCssSelectAdapter;

View File

@@ -1,6 +1,4 @@
'use strict'; import { visit } from '../xast.js';
const { visit } = require('../xast.js');
/** /**
* Plugins engine. * Plugins engine.
@@ -12,7 +10,13 @@ const { visit } = require('../xast.js');
* @param {Array} plugins plugins object from config * @param {Array} plugins plugins object from config
* @return {Object} output ast * @return {Object} output ast
*/ */
const invokePlugins = (ast, info, plugins, overrides, globalOverrides) => { export const invokePlugins = (
ast,
info,
plugins,
overrides,
globalOverrides,
) => {
for (const plugin of plugins) { for (const plugin of plugins) {
const override = overrides?.[plugin.name]; const override = overrides?.[plugin.name];
if (override === false) { if (override === false) {
@@ -26,9 +30,8 @@ const invokePlugins = (ast, info, plugins, overrides, globalOverrides) => {
} }
} }
}; };
exports.invokePlugins = invokePlugins;
const createPreset = ({ name, plugins }) => { export const createPreset = ({ name, plugins }) => {
return { return {
name, name,
fn: (ast, params, info) => { fn: (ast, params, info) => {
@@ -58,4 +61,3 @@ const createPreset = ({ name, plugins }) => {
}, },
}; };
}; };
exports.createPreset = createPreset;

View File

@@ -1,12 +1,10 @@
'use strict';
/** /**
* @typedef {import('../../lib/types').XastElement} XastElement * @typedef {import('../types.js').DataUri} DataUri
* @typedef {import('../types').PathDataCommand} PathDataCommand * @typedef {import('../types.js').PathDataCommand} PathDataCommand
* @typedef {import('../types').DataUri} DataUri * @typedef {import('../../lib/types.js').XastElement} XastElement
*/ */
const { attrsGroups, referencesProps } = require('../../plugins/_collections'); import { attrsGroups, referencesProps } from '../../plugins/_collections.js';
const regReferencesUrl = /\burl\((["'])?#(.+?)\1\)/g; const regReferencesUrl = /\burl\((["'])?#(.+?)\1\)/g;
const regReferencesHref = /^#(.+?)$/; const regReferencesHref = /^#(.+?)$/;
@@ -17,7 +15,7 @@ const regReferencesBegin = /(\w+)\.[a-zA-Z]/;
* *
* @type {(str: string, type?: DataUri) => string} * @type {(str: string, type?: DataUri) => string}
*/ */
exports.encodeSVGDatauri = (str, type) => { export const encodeSVGDatauri = (str, type) => {
var prefix = 'data:image/svg+xml'; var prefix = 'data:image/svg+xml';
if (!type || type === 'base64') { if (!type || type === 'base64') {
// base64 // base64
@@ -38,7 +36,7 @@ exports.encodeSVGDatauri = (str, type) => {
* *
* @type {(str: string) => string} * @type {(str: string) => string}
*/ */
exports.decodeSVGDatauri = (str) => { export const decodeSVGDatauri = (str) => {
var regexp = /data:image\/svg\+xml(;charset=[^;,]*)?(;base64)?,(.*)/; var regexp = /data:image\/svg\+xml(;charset=[^;,]*)?(;base64)?,(.*)/;
var match = regexp.exec(str); var match = regexp.exec(str);
@@ -76,7 +74,7 @@ exports.decodeSVGDatauri = (str) => {
* *
* @type {(data: number[], params: CleanupOutDataParams, command?: PathDataCommand) => string} * @type {(data: number[], params: CleanupOutDataParams, command?: PathDataCommand) => string}
*/ */
exports.cleanupOutData = (data, params, command) => { export const cleanupOutData = (data, params, command) => {
let str = ''; let str = '';
let delimiter; let delimiter;
/** /**
@@ -130,7 +128,7 @@ exports.cleanupOutData = (data, params, command) => {
* 0.5 → .5 * 0.5 → .5
* -0.5 → -.5 * -0.5 → -.5
*/ */
const removeLeadingZero = (value) => { export const removeLeadingZero = (value) => {
const strValue = value.toString(); const strValue = value.toString();
if (0 < value && value < 1 && strValue.startsWith('0')) { if (0 < value && value < 1 && strValue.startsWith('0')) {
@@ -143,7 +141,6 @@ const removeLeadingZero = (value) => {
return strValue; return strValue;
}; };
exports.removeLeadingZero = removeLeadingZero;
/** /**
* If the current node contains any scripts. This does not check parents or * If the current node contains any scripts. This does not check parents or
@@ -152,7 +149,7 @@ exports.removeLeadingZero = removeLeadingZero;
* @param {XastElement} node Current node to check against. * @param {XastElement} node Current node to check against.
* @returns {boolean} If the current node contains scripts. * @returns {boolean} If the current node contains scripts.
*/ */
const hasScripts = (node) => { export const hasScripts = (node) => {
if (node.name === 'script' && node.children.length !== 0) { if (node.name === 'script' && node.children.length !== 0) {
return true; return true;
} }
@@ -180,7 +177,6 @@ const hasScripts = (node) => {
return eventAttrs.some((attr) => node.attributes[attr] != null); return eventAttrs.some((attr) => node.attributes[attr] != null);
}; };
exports.hasScripts = hasScripts;
/** /**
* For example, a string that contains one or more of following would match and * For example, a string that contains one or more of following would match and
@@ -192,17 +188,16 @@ exports.hasScripts = hasScripts;
* @param {string} body * @param {string} body
* @returns {boolean} If the given string includes a URL reference. * @returns {boolean} If the given string includes a URL reference.
*/ */
const includesUrlReference = (body) => { export const includesUrlReference = (body) => {
return new RegExp(regReferencesUrl).test(body); return new RegExp(regReferencesUrl).test(body);
}; };
exports.includesUrlReference = includesUrlReference;
/** /**
* @param {string} attribute * @param {string} attribute
* @param {string} value * @param {string} value
* @returns {string[]} * @returns {string[]}
*/ */
const findReferences = (attribute, value) => { export const findReferences = (attribute, value) => {
const results = []; const results = [];
if (referencesProps.has(attribute)) { if (referencesProps.has(attribute)) {
@@ -228,7 +223,6 @@ const findReferences = (attribute, value) => {
return results.map((body) => decodeURI(body)); return results.map((body) => decodeURI(body));
}; };
exports.findReferences = findReferences;
/** /**
* Does the same as {@link Number.toFixed} but without casting * Does the same as {@link Number.toFixed} but without casting
@@ -238,8 +232,7 @@ exports.findReferences = findReferences;
* @param {number} precision * @param {number} precision
* @returns {number} * @returns {number}
*/ */
const toFixed = (num, precision) => { export const toFixed = (num, precision) => {
const pow = 10 ** precision; const pow = 10 ** precision;
return Math.round(num * pow) / pow; return Math.round(num * pow) / pow;
}; };
exports.toFixed = toFixed;

View File

@@ -1,15 +1,13 @@
'use strict'; import { selectAll, selectOne, is } from 'css-select';
import xastAdaptor from './svgo/css-select-adapter.js';
/** /**
* @typedef {import('./types').XastNode} XastNode * @typedef {import('./types.js').XastNode} XastNode
* @typedef {import('./types').XastChild} XastChild * @typedef {import('./types.js').XastChild} XastChild
* @typedef {import('./types').XastParent} XastParent * @typedef {import('./types.js').XastParent} XastParent
* @typedef {import('./types').Visitor} Visitor * @typedef {import('./types.js').Visitor} Visitor
*/ */
const { selectAll, selectOne, is } = require('css-select');
const xastAdaptor = require('./svgo/css-select-adapter.js');
const cssSelectOptions = { const cssSelectOptions = {
xmlMode: true, xmlMode: true,
adapter: xastAdaptor, adapter: xastAdaptor,
@@ -18,34 +16,30 @@ const cssSelectOptions = {
/** /**
* @type {(node: XastNode, selector: string) => XastChild[]} * @type {(node: XastNode, selector: string) => XastChild[]}
*/ */
const querySelectorAll = (node, selector) => { export const querySelectorAll = (node, selector) => {
return selectAll(selector, node, cssSelectOptions); return selectAll(selector, node, cssSelectOptions);
}; };
exports.querySelectorAll = querySelectorAll;
/** /**
* @type {(node: XastNode, selector: string) => ?XastChild} * @type {(node: XastNode, selector: string) => ?XastChild}
*/ */
const querySelector = (node, selector) => { export const querySelector = (node, selector) => {
return selectOne(selector, node, cssSelectOptions); return selectOne(selector, node, cssSelectOptions);
}; };
exports.querySelector = querySelector;
/** /**
* @type {(node: XastChild, selector: string) => boolean} * @type {(node: XastChild, selector: string) => boolean}
*/ */
const matches = (node, selector) => { export const matches = (node, selector) => {
return is(node, selector, cssSelectOptions); return is(node, selector, cssSelectOptions);
}; };
exports.matches = matches;
const visitSkip = Symbol(); export const visitSkip = Symbol();
exports.visitSkip = visitSkip;
/** /**
* @type {(node: XastNode, visitor: Visitor, parentNode?: any) => void} * @type {(node: XastNode, visitor: Visitor, parentNode?: any) => void}
*/ */
const visit = (node, visitor, parentNode) => { export const visit = (node, visitor, parentNode) => {
const callbacks = visitor[node.type]; const callbacks = visitor[node.type];
if (callbacks && callbacks.enter) { if (callbacks && callbacks.enter) {
// @ts-ignore hard to infer // @ts-ignore hard to infer
@@ -74,14 +68,12 @@ const visit = (node, visitor, parentNode) => {
callbacks.exit(node, parentNode); callbacks.exit(node, parentNode);
} }
}; };
exports.visit = visit;
/** /**
* @param {XastChild} node * @param {XastChild} node
* @param {XastParent} parentNode * @param {XastParent} parentNode
*/ */
const detachNodeFromParent = (node, parentNode) => { export const detachNodeFromParent = (node, parentNode) => {
// avoid splice to not break for loops // avoid splice to not break for loops
parentNode.children = parentNode.children.filter((child) => child !== node); parentNode.children = parentNode.children.filter((child) => child !== node);
}; };
exports.detachNodeFromParent = detachNodeFromParent;

View File

@@ -1,11 +1,9 @@
'use strict';
/** /**
* @typedef {import('./types').XastRoot} XastRoot * @typedef {import('./types.js').XastElement} XastElement
* @typedef {import('./types').XastElement} XastElement * @typedef {import('./types.js').XastRoot} XastRoot
*/ */
const { visit, visitSkip, detachNodeFromParent } = require('./xast.js'); import { visit, visitSkip, detachNodeFromParent } from './xast.js';
/** /**
* @type {(children: XastElement[]) => XastRoot} * @type {(children: XastElement[]) => XastRoot}

View File

@@ -1,9 +1,10 @@
{ {
"packageManager": "yarn@2.4.3", "packageManager": "yarn@2.4.3",
"name": "svgo", "name": "svgo",
"version": "3.2.0", "version": "3.3.0",
"description": "Nodejs-based tool for optimizing SVG vector graphics files", "description": "Nodejs-based tool for optimizing SVG vector graphics files",
"license": "MIT", "license": "MIT",
"type": "module",
"keywords": [ "keywords": [
"svgo", "svgo",
"svg", "svg",
@@ -50,8 +51,12 @@
"url": "https://opencollective.com/svgo" "url": "https://opencollective.com/svgo"
}, },
"main": "./lib/svgo-node.js", "main": "./lib/svgo-node.js",
"bin": "./bin/svgo", "bin": "./bin/svgo.js",
"types": "./lib/svgo.d.ts", "types": "./lib/svgo.d.ts",
"exports": {
"require": "./dist/svgo-node.cjs",
"default": "./lib/svgo-node.js"
},
"files": [ "files": [
"bin", "bin",
"lib", "lib",
@@ -67,10 +72,11 @@
"lint": "eslint --ignore-path .gitignore . && prettier --check . --ignore-path .gitignore", "lint": "eslint --ignore-path .gitignore . && prettier --check . --ignore-path .gitignore",
"fix": "eslint --ignore-path .gitignore --fix . && prettier --write . --ignore-path .gitignore", "fix": "eslint --ignore-path .gitignore --fix . && prettier --write . --ignore-path .gitignore",
"typecheck": "tsc", "typecheck": "tsc",
"test-browser": "rollup -c && node ./test/browser.js", "generate-bundles": "rollup -c",
"test-bundles": "yarn generate-bundles && node ./test/svgo.cjs && node ./test/browser.js",
"test-regression": "node ./test/regression-extract.js && NO_DIFF=1 node ./test/regression.js", "test-regression": "node ./test/regression-extract.js && NO_DIFF=1 node ./test/regression.js",
"prepublishOnly": "rm -rf dist && rollup -c", "prepublishOnly": "rm -rf dist && yarn generate-bundles",
"qa": "yarn lint && yarn typecheck && yarn test && yarn test-browser && yarn test-regression" "qa": "yarn lint && yarn typecheck && yarn test && yarn test-bundles && yarn test-regression"
}, },
"jest": { "jest": {
"coveragePathIgnorePatterns": [ "coveragePathIgnorePatterns": [
@@ -87,8 +93,9 @@
"picocolors": "^1.0.0" "picocolors": "^1.0.0"
}, },
"devDependencies": { "devDependencies": {
"@rollup/plugin-commonjs": "^22.0.2", "@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^14.1.0", "@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-terser": "^0.4.4",
"@types/css-tree": "^2.3.4", "@types/css-tree": "^2.3.4",
"@types/csso": "^5.0.4", "@types/csso": "^5.0.4",
"@types/jest": "^29.5.5", "@types/jest": "^29.5.5",
@@ -100,8 +107,7 @@
"playwright": "^1.40.1", "playwright": "^1.40.1",
"pngjs": "^7.0.0", "pngjs": "^7.0.0",
"prettier": "^3.1.1", "prettier": "^3.1.1",
"rollup": "^2.79.1", "rollup": "^4.9.2",
"rollup-plugin-terser": "^7.0.2",
"tar-stream": "^3.1.6", "tar-stream": "^3.1.6",
"typescript": "^5.3.3" "typescript": "^5.3.3"
} }

View File

@@ -1,11 +1,9 @@
'use strict';
// https://www.w3.org/TR/SVG11/intro.html#Definitions // https://www.w3.org/TR/SVG11/intro.html#Definitions
/** /**
* @type {Record<string, Set<string>>} * @type {Record<string, Set<string>>}
*/ */
exports.elemsGroups = { export const elemsGroups = {
animation: new Set([ animation: new Set([
'animate', 'animate',
'animateColor', 'animateColor',
@@ -107,19 +105,15 @@ exports.elemsGroups = {
* *
* @see https://developer.mozilla.org/docs/Web/HTML/Element/pre * @see https://developer.mozilla.org/docs/Web/HTML/Element/pre
*/ */
exports.textElems = new Set([ export const textElems = new Set([...elemsGroups.textContent, 'pre', 'title']);
...exports.elemsGroups.textContent,
'pre',
'title',
]);
exports.pathElems = new Set(['glyph', 'missing-glyph', 'path']); export const pathElems = new Set(['glyph', 'missing-glyph', 'path']);
/** /**
* @type {Record<string, Set<string>>} * @type {Record<string, Set<string>>}
* @see https://www.w3.org/TR/SVG11/intro.html#Definitions * @see https://www.w3.org/TR/SVG11/intro.html#Definitions
*/ */
exports.attrsGroups = { export const attrsGroups = {
animationAddition: new Set(['additive', 'accumulate']), animationAddition: new Set(['additive', 'accumulate']),
animationAttributeTarget: new Set(['attributeType', 'attributeName']), animationAttributeTarget: new Set(['attributeType', 'attributeName']),
animationEvent: new Set(['onbegin', 'onend', 'onrepeat', 'onload']), animationEvent: new Set(['onbegin', 'onend', 'onrepeat', 'onload']),
@@ -317,7 +311,7 @@ exports.attrsGroups = {
/** /**
* @type {Record<string, Record<string, string>>} * @type {Record<string, Record<string, string>>}
*/ */
exports.attrsGroupsDefaults = { export const attrsGroupsDefaults = {
core: { 'xml:space': 'default' }, core: { 'xml:space': 'default' },
presentation: { presentation: {
clip: 'auto', clip: 'auto',
@@ -391,7 +385,7 @@ exports.attrsGroupsDefaults = {
* }>} * }>}
* @see https://www.w3.org/TR/SVG11/eltindex.html * @see https://www.w3.org/TR/SVG11/eltindex.html
*/ */
exports.elems = { export const elems = {
a: { a: {
attrsGroups: new Set([ attrsGroups: new Set([
'conditionalProcessing', 'conditionalProcessing',
@@ -1971,7 +1965,7 @@ exports.elems = {
}; };
// https://wiki.inkscape.org/wiki/index.php/Inkscape-specific_XML_attributes // https://wiki.inkscape.org/wiki/index.php/Inkscape-specific_XML_attributes
exports.editorNamespaces = new Set([ export const editorNamespaces = new Set([
'http://creativecommons.org/ns#', 'http://creativecommons.org/ns#',
'http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd', 'http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd',
'http://ns.adobe.com/AdobeIllustrator/10.0/', 'http://ns.adobe.com/AdobeIllustrator/10.0/',
@@ -1999,7 +1993,7 @@ exports.editorNamespaces = new Set([
/** /**
* @see https://www.w3.org/TR/SVG11/linking.html#processingIRI * @see https://www.w3.org/TR/SVG11/linking.html#processingIRI
*/ */
exports.referencesProps = new Set([ export const referencesProps = new Set([
'clip-path', 'clip-path',
'color-profile', 'color-profile',
'fill', 'fill',
@@ -2015,7 +2009,7 @@ exports.referencesProps = new Set([
/** /**
* @see https://www.w3.org/TR/SVG11/propidx.html * @see https://www.w3.org/TR/SVG11/propidx.html
*/ */
exports.inheritableAttrs = new Set([ export const inheritableAttrs = new Set([
'clip-rule', 'clip-rule',
'color-interpolation-filters', 'color-interpolation-filters',
'color-interpolation', 'color-interpolation',
@@ -2063,7 +2057,7 @@ exports.inheritableAttrs = new Set([
'writing-mode', 'writing-mode',
]); ]);
exports.presentationNonInheritableGroupAttrs = new Set([ export const presentationNonInheritableGroupAttrs = new Set([
'clip-path', 'clip-path',
'display', 'display',
'filter', 'filter',
@@ -2079,7 +2073,7 @@ exports.presentationNonInheritableGroupAttrs = new Set([
* *
* @type {Record<string, string>} * @type {Record<string, string>}
*/ */
exports.colorsNames = { export const colorsNames = {
aliceblue: '#f0f8ff', aliceblue: '#f0f8ff',
antiquewhite: '#faebd7', antiquewhite: '#faebd7',
aqua: '#0ff', aqua: '#0ff',
@@ -2233,7 +2227,7 @@ exports.colorsNames = {
/** /**
* @type {Record<string, string>} * @type {Record<string, string>}
*/ */
exports.colorsShortNames = { export const colorsShortNames = {
'#f0ffff': 'azure', '#f0ffff': 'azure',
'#f5f5dc': 'beige', '#f5f5dc': 'beige',
'#ffe4c4': 'bisque', '#ffe4c4': 'bisque',
@@ -2271,7 +2265,7 @@ exports.colorsShortNames = {
/** /**
* @see https://www.w3.org/TR/SVG11/single-page.html#types-DataTypeColor * @see https://www.w3.org/TR/SVG11/single-page.html#types-DataTypeColor
*/ */
exports.colorsProps = new Set([ export const colorsProps = new Set([
'color', 'color',
'fill', 'fill',
'flood-color', 'flood-color',
@@ -2281,7 +2275,7 @@ exports.colorsProps = new Set([
]); ]);
/** @see https://developer.mozilla.org/docs/Web/CSS/Pseudo-classes */ /** @see https://developer.mozilla.org/docs/Web/CSS/Pseudo-classes */
exports.pseudoClasses = { export const pseudoClasses = {
displayState: new Set(['fullscreen', 'modal', 'picture-in-picture']), displayState: new Set(['fullscreen', 'modal', 'picture-in-picture']),
input: new Set([ input: new Set([
'autofill', 'autofill',

View File

@@ -1,12 +1,10 @@
'use strict'; import { parsePathData, stringifyPathData } from '../lib/path.js';
/** /**
* @typedef {import('../lib/types').XastElement} XastElement * @typedef {import('../lib/types.js').XastElement} XastElement
* @typedef {import('../lib/types').PathDataItem} PathDataItem * @typedef {import('../lib/types.js').PathDataItem} PathDataItem
*/ */
const { parsePathData, stringifyPathData } = require('../lib/path.js');
/** /**
* @type {[number, number]} * @type {[number, number]}
*/ */
@@ -17,7 +15,7 @@ var prevCtrlPoint;
* *
* @type {(path: XastElement) => PathDataItem[]} * @type {(path: XastElement) => PathDataItem[]}
*/ */
const path2js = (path) => { export const path2js = (path) => {
// @ts-ignore legacy // @ts-ignore legacy
if (path.pathJS) return path.pathJS; if (path.pathJS) return path.pathJS;
/** /**
@@ -36,7 +34,6 @@ const path2js = (path) => {
path.pathJS = pathData; path.pathJS = pathData;
return pathData; return pathData;
}; };
exports.path2js = path2js;
/** /**
* Convert relative Path data to absolute. * Convert relative Path data to absolute.
@@ -181,7 +178,7 @@ const convertRelativeToAbsolute = (data) => {
* *
* @type {(path: XastElement, data: PathDataItem[], params: Js2PathParams) => void} * @type {(path: XastElement, data: PathDataItem[], params: Js2PathParams) => void}
*/ */
exports.js2path = function (path, data, params) { export const js2path = function (path, data, params) {
// @ts-ignore legacy // @ts-ignore legacy
path.pathJS = data; path.pathJS = data;
@@ -226,7 +223,7 @@ function set(dest, source) {
* *
* @type {(path1: PathDataItem[], path2: PathDataItem[]) => boolean} * @type {(path1: PathDataItem[], path2: PathDataItem[]) => boolean}
*/ */
exports.intersects = function (path1, path2) { export const intersects = function (path1, path2) {
// Collect points of every subpath. // Collect points of every subpath.
const points1 = gatherPoints(convertRelativeToAbsolute(path1)); const points1 = gatherPoints(convertRelativeToAbsolute(path1));
const points2 = gatherPoints(convertRelativeToAbsolute(path2)); const points2 = gatherPoints(convertRelativeToAbsolute(path2));

View File

@@ -1,6 +1,4 @@
'use strict'; import { toFixed } from '../lib/svgo/tools.js';
const { toFixed } = require('../lib/svgo/tools');
/** /**
* @typedef {{ name: string, data: number[] }} TransformItem * @typedef {{ name: string, data: number[] }} TransformItem
@@ -38,7 +36,7 @@ const regNumericValues = /[-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?/g;
* @param {string} transformString * @param {string} transformString
* @returns {TransformItem[]} Object representation of transform, or an empty array if it was malformed. * @returns {TransformItem[]} Object representation of transform, or an empty array if it was malformed.
*/ */
exports.transform2js = (transformString) => { export const transform2js = (transformString) => {
/** @type {TransformItem[]} */ /** @type {TransformItem[]} */
const transforms = []; const transforms = [];
/** @type {?TransformItem} */ /** @type {?TransformItem} */
@@ -69,14 +67,13 @@ exports.transform2js = (transformString) => {
? [] ? []
: transforms; : transforms;
}; };
/** /**
* Multiply transforms into one. * Multiply transforms into one.
* *
* @param {TransformItem[]} transforms * @param {TransformItem[]} transforms
* @returns {TransformItem} * @returns {TransformItem}
*/ */
exports.transformsMultiply = (transforms) => { export const transformsMultiply = (transforms) => {
const matrixData = transforms.map((transform) => { const matrixData = transforms.map((transform) => {
if (transform.name === 'matrix') { if (transform.name === 'matrix') {
return transform.data; return transform.data;
@@ -173,7 +170,7 @@ const mth = {
* @returns {TransformItem[]} * @returns {TransformItem[]}
* @see https://frederic-wang.fr/decomposition-of-2d-transform-matrices.html * @see https://frederic-wang.fr/decomposition-of-2d-transform-matrices.html
*/ */
exports.matrixToTransform = (transform, params) => { export const matrixToTransform = (transform, params) => {
const floatPrecision = params.floatPrecision; const floatPrecision = params.floatPrecision;
const data = transform.data; const data = transform.data;
const transforms = []; const transforms = [];
@@ -337,7 +334,7 @@ const transformToMatrix = (transform) => {
* transform: number[] * transform: number[]
* ) => number[]} * ) => number[]}
*/ */
exports.transformArc = (cursor, arc, transform) => { export const transformArc = (cursor, arc, transform) => {
const x = arc[5] - cursor[0]; const x = arc[5] - cursor[0];
const y = arc[6] - cursor[1]; const y = arc[6] - cursor[1];
let a = arc[0]; let a = arc[0];

View File

@@ -1,7 +1,5 @@
'use strict'; export const name = 'addAttributesToSVGElement';
export const description = 'adds attributes to an outer <svg> element';
exports.name = 'addAttributesToSVGElement';
exports.description = 'adds attributes to an outer <svg> element';
var ENOCLS = `Error in plugin "addAttributesToSVGElement": absent parameters. var ENOCLS = `Error in plugin "addAttributesToSVGElement": absent parameters.
It should have a list of "attributes" or one "attribute". It should have a list of "attributes" or one "attribute".
@@ -47,9 +45,9 @@ plugins: [
* *
* @author April Arcus * @author April Arcus
* *
* @type {import('./plugins-types').Plugin<'addAttributesToSVGElement'>} * @type {import('./plugins-types.js').Plugin<'addAttributesToSVGElement'>}
*/ */
exports.fn = (root, params) => { export const fn = (root, params) => {
if (!Array.isArray(params.attributes) && !params.attribute) { if (!Array.isArray(params.attributes) && !params.attribute) {
console.error(ENOCLS); console.error(ENOCLS);
return null; return null;

View File

@@ -1,7 +1,5 @@
'use strict'; export const name = 'addClassesToSVGElement';
export const description = 'adds classnames to an outer <svg> element';
exports.name = 'addClassesToSVGElement';
exports.description = 'adds classnames to an outer <svg> element';
var ENOCLS = `Error in plugin "addClassesToSVGElement": absent parameters. var ENOCLS = `Error in plugin "addClassesToSVGElement": absent parameters.
It should have a list of classes in "classNames" or one "className". It should have a list of classes in "classNames" or one "className".
@@ -49,9 +47,9 @@ plugins: [
* *
* @author April Arcus * @author April Arcus
* *
* @type {import('./plugins-types').Plugin<'addClassesToSVGElement'>} * @type {import('./plugins-types.js').Plugin<'addClassesToSVGElement'>}
*/ */
exports.fn = (root, params) => { export const fn = (root, params) => {
if ( if (
!(Array.isArray(params.classNames) && params.classNames.some(String)) && !(Array.isArray(params.classNames) && params.classNames.some(String)) &&
!params.className !params.className

View File

@@ -1,22 +1,18 @@
'use strict';
/** /**
* @typedef {import('../lib/types').PathDataItem} PathDataItem * @typedef {import('../lib/types.js').PathDataItem} PathDataItem
* @typedef {import('../lib/types').XastElement} XastElement * @typedef {import('../lib/types.js').XastElement} XastElement
*/ */
const { collectStylesheet, computeStyle } = require('../lib/style.js'); import { path2js } from './_path.js';
const { import {
transformsMultiply, transformsMultiply,
transform2js, transform2js,
transformArc, transformArc,
} = require('./_transforms.js'); } from './_transforms.js';
const { path2js } = require('./_path.js'); import { referencesProps, attrsGroupsDefaults } from './_collections.js';
const { import { collectStylesheet, computeStyle } from '../lib/style.js';
removeLeadingZero,
includesUrlReference, import { removeLeadingZero, includesUrlReference } from '../lib/svgo/tools.js';
} = require('../lib/svgo/tools.js');
const { referencesProps, attrsGroupsDefaults } = require('./_collections.js');
/** /**
* @typedef {PathDataItem[]} PathData * @typedef {PathDataItem[]} PathData
@@ -28,12 +24,12 @@ const regNumericValues = /[-+]?(\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?/g;
/** /**
* Apply transformation(s) to the Path data. * Apply transformation(s) to the Path data.
* *
* @type {import('../lib/types').Plugin<{ * @type {import('../lib/types.js').Plugin<{
* transformPrecision: number, * transformPrecision: number,
* applyTransformsStroked: boolean, * applyTransformsStroked: boolean,
* }>} * }>}
*/ */
const applyTransforms = (root, params) => { export const applyTransforms = (root, params) => {
const stylesheet = collectStylesheet(root); const stylesheet = collectStylesheet(root);
return { return {
element: { element: {
@@ -160,7 +156,6 @@ const applyTransforms = (root, params) => {
}, },
}; };
}; };
exports.applyTransforms = applyTransforms;
/** /**
* @type {(matrix: Matrix, x: number, y: number) => [number, number]} * @type {(matrix: Matrix, x: number, y: number) => [number, number]}

View File

@@ -1,7 +1,5 @@
'use strict'; export const name = 'cleanupAttrs';
export const description =
exports.name = 'cleanupAttrs';
exports.description =
'cleanups attributes from newlines, trailing and repeating spaces'; 'cleanups attributes from newlines, trailing and repeating spaces';
const regNewlinesNeedSpace = /(\S)\r?\n(\S)/g; const regNewlinesNeedSpace = /(\S)\r?\n(\S)/g;
@@ -12,10 +10,9 @@ const regSpaces = /\s{2,}/g;
* Cleanup attributes values from newlines, trailing and repeating spaces. * Cleanup attributes values from newlines, trailing and repeating spaces.
* *
* @author Kir Belevich * @author Kir Belevich
* * @type {import('./plugins-types.js').Plugin<'cleanupAttrs'>}
* @type {import('./plugins-types').Plugin<'cleanupAttrs'>}
*/ */
exports.fn = (root, params) => { export const fn = (root, params) => {
const { newlines = true, trim = true, spaces = true } = params; const { newlines = true, trim = true, spaces = true } = params;
return { return {
element: { element: {

View File

@@ -1,10 +1,8 @@
'use strict'; import * as csstree from 'css-tree';
import { visit } from '../lib/xast.js';
const csstree = require('css-tree'); export const name = 'cleanupEnableBackground';
const { visit } = require('../lib/xast.js'); export const description =
exports.name = 'cleanupEnableBackground';
exports.description =
'remove or cleanup enable-background attribute when possible'; 'remove or cleanup enable-background attribute when possible';
const regEnableBackground = const regEnableBackground =
@@ -19,9 +17,9 @@ const regEnableBackground =
* ⬇ * ⬇
* <svg width="100" height="50"> * <svg width="100" height="50">
* @author Kir Belevich * @author Kir Belevich
* @type {import('./plugins-types').Plugin<'cleanupEnableBackground'>} * @type {import('./plugins-types.js').Plugin<'cleanupEnableBackground'>}
*/ */
exports.fn = (root) => { export const fn = (root) => {
let hasFilter = false; let hasFilter = false;
visit(root, { visit(root, {

View File

@@ -1,14 +1,12 @@
'use strict'; import { visitSkip } from '../lib/xast.js';
import { hasScripts, findReferences } from '../lib/svgo/tools.js';
/** /**
* @typedef {import('../lib/types').XastElement} XastElement * @typedef {import('../lib/types.js').XastElement} XastElement
*/ */
const { visitSkip } = require('../lib/xast.js'); export const name = 'cleanupIds';
const { hasScripts, findReferences } = require('../lib/svgo/tools'); export const description = 'removes unused IDs and minifies used';
exports.name = 'cleanupIds';
exports.description = 'removes unused IDs and minifies used';
const generateIdChars = [ const generateIdChars = [
'a', 'a',
@@ -121,9 +119,9 @@ const getIdString = (arr) => {
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'cleanupIds'>} * @type {import('./plugins-types.js').Plugin<'cleanupIds'>}
*/ */
exports.fn = (_root, params) => { export const fn = (_root, params) => {
const { const {
remove = true, remove = true,
minify = true, minify = true,

View File

@@ -1,9 +1,7 @@
'use strict'; import { removeLeadingZero } from '../lib/svgo/tools.js';
const { removeLeadingZero } = require('../lib/svgo/tools.js'); export const name = 'cleanupListOfValues';
export const description = 'rounds list of values to the fixed precision';
exports.name = 'cleanupListOfValues';
exports.description = 'rounds list of values to the fixed precision';
const regNumericValues = const regNumericValues =
/^([-+]?\d*\.?\d+([eE][-+]?\d+)?)(px|pt|pc|mm|cm|m|in|ft|em|ex|%)?$/; /^([-+]?\d*\.?\d+([eE][-+]?\d+)?)(px|pt|pc|mm|cm|m|in|ft|em|ex|%)?$/;
@@ -32,9 +30,9 @@ const absoluteLengths = {
* *
* @author kiyopikko * @author kiyopikko
* *
* @type {import('./plugins-types').Plugin<'cleanupListOfValues'>} * @type {import('./plugins-types.js').Plugin<'cleanupListOfValues'>}
*/ */
exports.fn = (_root, params) => { export const fn = (_root, params) => {
const { const {
floatPrecision = 3, floatPrecision = 3,
leadingZero = true, leadingZero = true,

View File

@@ -1,9 +1,7 @@
'use strict'; import { removeLeadingZero } from '../lib/svgo/tools.js';
const { removeLeadingZero } = require('../lib/svgo/tools'); export const name = 'cleanupNumericValues';
export const description =
exports.name = 'cleanupNumericValues';
exports.description =
'rounds numeric values to the fixed precision, removes default px units'; 'rounds numeric values to the fixed precision, removes default px units';
const regNumericValues = const regNumericValues =
@@ -25,9 +23,9 @@ const absoluteLengths = {
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'cleanupNumericValues'>} * @type {import('./plugins-types.js').Plugin<'cleanupNumericValues'>}
*/ */
exports.fn = (_root, params) => { export const fn = (_root, params) => {
const { const {
floatPrecision = 3, floatPrecision = 3,
leadingZero = true, leadingZero = true,

View File

@@ -1,13 +1,11 @@
'use strict'; import { inheritableAttrs, elemsGroups } from './_collections.js';
/** /**
* @typedef {import('../lib/types').XastNode} XastNode * @typedef {import('../lib/types.js').XastNode} XastNode
*/ */
const { inheritableAttrs, elemsGroups } = require('./_collections.js'); export const name = 'collapseGroups';
export const description = 'collapses useless groups';
exports.name = 'collapseGroups';
exports.description = 'collapses useless groups';
/** /**
* @type {(node: XastNode, name: string) => boolean} * @type {(node: XastNode, name: string) => boolean}
@@ -49,9 +47,9 @@ const hasAnimatedAttr = (node, name) => {
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'collapseGroups'>} * @type {import('./plugins-types.js').Plugin<'collapseGroups'>}
*/ */
exports.fn = () => { export const fn = () => {
return { return {
element: { element: {
exit: (node, parentNode) => { exit: (node, parentNode) => {

View File

@@ -1,9 +1,8 @@
'use strict'; import { colorsNames, colorsProps, colorsShortNames } from './_collections.js';
const collections = require('./_collections.js'); export const name = 'convertColors';
export const description =
exports.name = 'convertColors'; 'converts colors: rgb() to #rrggbb and #rrggbb to #rgb';
exports.description = 'converts colors: rgb() to #rrggbb and #rrggbb to #rgb';
const rNumber = '([+-]?(?:\\d*\\.\\d+|\\d+\\.?)%?)'; const rNumber = '([+-]?(?:\\d*\\.\\d+|\\d+\\.?)%?)';
const rComma = '\\s*,\\s*'; const rComma = '\\s*,\\s*';
@@ -61,9 +60,9 @@ const convertRgbToHex = ([r, g, b]) => {
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'convertColors'>} * @type {import('./plugins-types.js').Plugin<'convertColors'>}
*/ */
exports.fn = (_root, params) => { export const fn = (_root, params) => {
const { const {
currentColor = false, currentColor = false,
names2hex = true, names2hex = true,
@@ -76,7 +75,7 @@ exports.fn = (_root, params) => {
element: { element: {
enter: (node) => { enter: (node) => {
for (const [name, value] of Object.entries(node.attributes)) { for (const [name, value] of Object.entries(node.attributes)) {
if (collections.colorsProps.has(name)) { if (colorsProps.has(name)) {
let val = value; let val = value;
// convert colors to currentColor // convert colors to currentColor
@@ -97,8 +96,8 @@ exports.fn = (_root, params) => {
// convert color name keyword to long hex // convert color name keyword to long hex
if (names2hex) { if (names2hex) {
const colorName = val.toLowerCase(); const colorName = val.toLowerCase();
if (collections.colorsNames[colorName] != null) { if (colorsNames[colorName] != null) {
val = collections.colorsNames[colorName]; val = colorsNames[colorName];
} }
} }
@@ -130,8 +129,8 @@ exports.fn = (_root, params) => {
// convert hex to short name // convert hex to short name
if (shortname) { if (shortname) {
const colorName = val.toLowerCase(); const colorName = val.toLowerCase();
if (collections.colorsShortNames[colorName] != null) { if (colorsShortNames[colorName] != null) {
val = collections.colorsShortNames[colorName]; val = colorsShortNames[colorName];
} }
} }

View File

@@ -1,7 +1,5 @@
'use strict'; export const name = 'convertEllipseToCircle';
export const description = 'converts non-eccentric <ellipse>s to <circle>s';
exports.name = 'convertEllipseToCircle';
exports.description = 'converts non-eccentric <ellipse>s to <circle>s';
/** /**
* Converts non-eccentric <ellipse>s to <circle>s. * Converts non-eccentric <ellipse>s to <circle>s.
@@ -10,9 +8,9 @@ exports.description = 'converts non-eccentric <ellipse>s to <circle>s';
* *
* @author Taylor Hunt * @author Taylor Hunt
* *
* @type {import('./plugins-types').Plugin<'convertEllipseToCircle'>} * @type {import('./plugins-types.js').Plugin<'convertEllipseToCircle'>}
*/ */
exports.fn = () => { export const fn = () => {
return { return {
element: { element: {
enter: (node) => { enter: (node) => {

View File

@@ -1,31 +1,29 @@
'use strict'; import { attrsGroupsDefaults, colorsProps } from './_collections.js';
import {
/**
* @typedef {import('../lib/types').XastElement} XastElement
* @typedef {import('../lib/types').XastParent} XastParent
*/
const { attrsGroupsDefaults, colorsProps } = require('./_collections');
const {
detachNodeFromParent, detachNodeFromParent,
querySelectorAll, querySelectorAll,
querySelector, querySelector,
} = require('../lib/xast'); } from '../lib/xast.js';
const { computeStyle, collectStylesheet } = require('../lib/style'); import { computeStyle, collectStylesheet } from '../lib/style.js';
exports.name = 'convertOneStopGradients'; /**
exports.description = * @typedef {import('../lib/types.js').XastElement} XastElement
* @typedef {import('../lib/types.js').XastParent} XastParent
*/
export const name = 'convertOneStopGradients';
export const description =
'converts one-stop (single color) gradients to a plain color'; 'converts one-stop (single color) gradients to a plain color';
/** /**
* Converts one-stop (single color) gradients to a plain color. * Converts one-stop (single color) gradients to a plain color.
* *
* @author Seth Falco <seth@falco.fun> * @author Seth Falco <seth@falco.fun>
* @type {import('./plugins-types').Plugin<'convertOneStopGradients'>} * @type {import('./plugins-types.js').Plugin<'convertOneStopGradients'>}
* @see https://developer.mozilla.org/docs/Web/SVG/Element/linearGradient * @see https://developer.mozilla.org/docs/Web/SVG/Element/linearGradient
* @see https://developer.mozilla.org/docs/Web/SVG/Element/radialGradient * @see https://developer.mozilla.org/docs/Web/SVG/Element/radialGradient
*/ */
exports.fn = (root) => { export const fn = (root) => {
const stylesheet = collectStylesheet(root); const stylesheet = collectStylesheet(root);
/** /**

View File

@@ -1,18 +1,16 @@
'use strict'; import { path2js, js2path } from './_path.js';
import { pathElems } from './_collections.js';
import { applyTransforms } from './applyTransforms.js';
import { collectStylesheet, computeStyle } from '../lib/style.js';
import { visit } from '../lib/xast.js';
import { cleanupOutData, toFixed } from '../lib/svgo/tools.js';
/** /**
* @typedef {import('../lib//types').PathDataItem} PathDataItem * @typedef {import('../lib/types.js').PathDataItem} PathDataItem
*/ */
const { collectStylesheet, computeStyle } = require('../lib/style.js'); export const name = 'convertPathData';
const { visit } = require('../lib/xast.js'); export const description =
const { pathElems } = require('./_collections.js');
const { path2js, js2path } = require('./_path.js');
const { applyTransforms } = require('./applyTransforms.js');
const { cleanupOutData, toFixed } = require('../lib/svgo/tools');
exports.name = 'convertPathData';
exports.description =
'optimizes path data: writes in shorter form, applies transformations'; 'optimizes path data: writes in shorter form, applies transformations';
/** @type {(data: number[]) => number[]} */ /** @type {(data: number[]) => number[]} */
@@ -75,9 +73,9 @@ let arcTolerance;
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'convertPathData'>} * @type {import('./plugins-types.js').Plugin<'convertPathData'>}
*/ */
exports.fn = (root, params) => { export const fn = (root, params) => {
const { const {
// TODO convert to separate plugin in v3 // TODO convert to separate plugin in v3
applyTransforms: _applyTransforms = true, applyTransforms: _applyTransforms = true,

View File

@@ -1,14 +1,12 @@
'use strict'; import { stringifyPathData } from '../lib/path.js';
import { detachNodeFromParent } from '../lib/xast.js';
/** /**
* @typedef {import('../lib/types').PathDataItem} PathDataItem * @typedef {import('../lib/types.js').PathDataItem} PathDataItem
*/ */
const { stringifyPathData } = require('../lib/path.js'); export const name = 'convertShapeToPath';
const { detachNodeFromParent } = require('../lib/xast.js'); export const description = 'converts basic shapes to more compact path form';
exports.name = 'convertShapeToPath';
exports.description = 'converts basic shapes to more compact path form';
const regNumber = /[-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?/g; const regNumber = /[-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?/g;
@@ -21,9 +19,9 @@ const regNumber = /[-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?/g;
* *
* @author Lev Solntsev * @author Lev Solntsev
* *
* @type {import('./plugins-types').Plugin<'convertShapeToPath'>} * @type {import('./plugins-types.js').Plugin<'convertShapeToPath'>}
*/ */
exports.fn = (root, params) => { export const fn = (root, params) => {
const { convertArcs = false, floatPrecision: precision } = params; const { convertArcs = false, floatPrecision: precision } = params;
return { return {

View File

@@ -1,9 +1,7 @@
'use strict'; import { attrsGroups } from './_collections.js';
const { attrsGroups } = require('./_collections'); export const name = 'convertStyleToAttrs';
export const description = 'converts style to attributes';
exports.name = 'convertStyleToAttrs';
exports.description = 'converts style to attributes';
/** /**
* @type {(...args: string[]) => string} * @type {(...args: string[]) => string}
@@ -65,9 +63,9 @@ const regStripComments = new RegExp(
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'convertStyleToAttrs'>} * @type {import('./plugins-types.js').Plugin<'convertStyleToAttrs'>}
*/ */
exports.fn = (_root, params) => { export const fn = (_root, params) => {
const { keepImportant = false } = params; const { keepImportant = false } = params;
return { return {
element: { element: {

View File

@@ -1,20 +1,19 @@
'use strict'; import { cleanupOutData, toFixed } from '../lib/svgo/tools.js';
import {
/**
* @typedef {import('../lib/types').XastChild} XastChild
* @typedef {import('../lib/types').XastElement} XastElement
* @typedef {import('../lib/types').XastParent} XastParent
*/
const { cleanupOutData, toFixed } = require('../lib/svgo/tools.js');
const {
transform2js, transform2js,
transformsMultiply, transformsMultiply,
matrixToTransform, matrixToTransform,
} = require('./_transforms.js'); } from './_transforms.js';
exports.name = 'convertTransform'; /**
exports.description = 'collapses multiple transformations and optimizes it'; * @typedef {import('../lib/types.js').XastChild} XastChild
* @typedef {import('../lib/types.js').XastElement} XastElement
* @typedef {import('../lib/types.js').XastParent} XastParent
*/
export const name = 'convertTransform';
export const description =
'collapses multiple transformations and optimizes it';
/** /**
* Convert matrices to the short aliases, * Convert matrices to the short aliases,
@@ -26,9 +25,9 @@ exports.description = 'collapses multiple transformations and optimizes it';
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'convertTransform'>} * @type {import('./plugins-types.js').Plugin<'convertTransform'>}
*/ */
exports.fn = (_root, params) => { export const fn = (_root, params) => {
const { const {
convertToShorts = true, convertToShorts = true,
// degPrecision = 3, // transformPrecision (or matrix precision) - 2 by default // degPrecision = 3, // transformPrecision (or matrix precision) - 2 by default

View File

@@ -1,24 +1,20 @@
'use strict'; import * as csstree from 'css-tree';
import { syntax } from 'csso';
/** import { attrsGroups, pseudoClasses } from './_collections.js';
* @typedef {import('../lib/types').XastElement} XastElement import {
* @typedef {import('../lib/types').XastParent} XastParent
*/
const csstree = require('css-tree');
const {
syntax: { specificity },
} = require('csso');
const {
visitSkip, visitSkip,
querySelectorAll, querySelectorAll,
detachNodeFromParent, detachNodeFromParent,
} = require('../lib/xast.js'); } from '../lib/xast.js';
const { compareSpecificity, includesAttrSelector } = require('../lib/style'); import { compareSpecificity, includesAttrSelector } from '../lib/style.js';
const { attrsGroups, pseudoClasses } = require('./_collections');
exports.name = 'inlineStyles'; /**
exports.description = 'inline styles (additional options)'; * @typedef {import('../lib/types.js').XastElement} XastElement
* @typedef {import('../lib/types.js').XastParent} XastParent
*/
export const name = 'inlineStyles';
export const description = 'inline styles (additional options)';
/** /**
* Some pseudo-classes can only be calculated by clients, like :visited, * Some pseudo-classes can only be calculated by clients, like :visited,
@@ -38,10 +34,10 @@ const preservedPseudos = [
/** /**
* Merges styles from style nodes into inline styles. * Merges styles from style nodes into inline styles.
* *
* @type {import('./plugins-types').Plugin<'inlineStyles'>} * @type {import('./plugins-types.js').Plugin<'inlineStyles'>}
* @author strarsis <strarsis@gmail.com> * @author strarsis <strarsis@gmail.com>
*/ */
exports.fn = (root, params) => { export const fn = (root, params) => {
const { const {
onlyMatchedOnce = true, onlyMatchedOnce = true,
removeMatchedSelectors = true, removeMatchedSelectors = true,
@@ -177,8 +173,8 @@ exports.fn = (root, params) => {
const sortedSelectors = selectors const sortedSelectors = selectors
.slice() .slice()
.sort((a, b) => { .sort((a, b) => {
const aSpecificity = specificity(a.item.data); const aSpecificity = syntax.specificity(a.item.data);
const bSpecificity = specificity(b.item.data); const bSpecificity = syntax.specificity(b.item.data);
return compareSpecificity(aSpecificity, bSpecificity); return compareSpecificity(aSpecificity, bSpecificity);
}) })
.reverse(); .reverse();

View File

@@ -1,25 +1,23 @@
'use strict';
/** /**
* @typedef {import("../lib/types").PathDataItem} PathDataItem * @typedef {import("../lib/types.js").PathDataItem} PathDataItem
* @typedef {import('../lib/types').XastChild} XastChild * @typedef {import('../lib/types.js').XastChild} XastChild
* @typedef {import('../lib/types').XastElement} XastElement * @typedef {import('../lib/types.js').XastElement} XastElement
*/ */
const { collectStylesheet, computeStyle } = require('../lib/style.js'); import { collectStylesheet, computeStyle } from '../lib/style.js';
const { path2js, js2path, intersects } = require('./_path.js'); import { path2js, js2path, intersects } from './_path.js';
exports.name = 'mergePaths'; export const name = 'mergePaths';
exports.description = 'merges multiple paths in one if possible'; export const description = 'merges multiple paths in one if possible';
/** /**
* Merge multiple Paths into one. * Merge multiple Paths into one.
* *
* @author Kir Belevich, Lev Solntsev * @author Kir Belevich, Lev Solntsev
* *
* @type {import('./plugins-types').Plugin<'mergePaths'>} * @type {import('./plugins-types.js').Plugin<'mergePaths'>}
*/ */
exports.fn = (root, params) => { export const fn = (root, params) => {
const { const {
force = false, force = false,
floatPrecision, floatPrecision,

View File

@@ -1,23 +1,21 @@
'use strict'; import { visitSkip, detachNodeFromParent } from '../lib/xast.js';
/** /**
* @typedef {import('../lib/types').XastElement} XastElement * @typedef {import('../lib/types.js').XastElement} XastElement
* @typedef {import('../lib/types').XastChild} XastChild * @typedef {import('../lib/types.js').XastChild} XastChild
*/ */
const { visitSkip, detachNodeFromParent } = require('../lib/xast.js'); export const name = 'mergeStyles';
export const description = 'merge multiple style elements into one';
exports.name = 'mergeStyles';
exports.description = 'merge multiple style elements into one';
/** /**
* Merge multiple style elements into one. * Merge multiple style elements into one.
* *
* @author strarsis <strarsis@gmail.com> * @author strarsis <strarsis@gmail.com>
* *
* @type {import('./plugins-types').Plugin<'mergeStyles'>} * @type {import('./plugins-types.js').Plugin<'mergeStyles'>}
*/ */
exports.fn = () => { export const fn = () => {
/** /**
* @type {?XastElement} * @type {?XastElement}
*/ */

View File

@@ -1,24 +1,22 @@
'use strict';
/** /**
* @typedef {import('../lib/types').XastElement} XastElement * @typedef {import('../lib/types.js').XastElement} XastElement
* @typedef {import('../lib/types').XastParent} XastParent * @typedef {import('../lib/types.js').XastParent} XastParent
*/ */
const csso = require('csso'); import * as csso from 'csso';
const { detachNodeFromParent } = require('../lib/xast'); import { detachNodeFromParent } from '../lib/xast.js';
const { hasScripts } = require('../lib/svgo/tools'); import { hasScripts } from '../lib/svgo/tools.js';
exports.name = 'minifyStyles'; export const name = 'minifyStyles';
exports.description = 'minifies styles and removes unused styles'; export const description = 'minifies styles and removes unused styles';
/** /**
* Minifies styles (<style> element + style attribute) using CSSO. * Minifies styles (<style> element + style attribute) using CSSO.
* *
* @author strarsis <strarsis@gmail.com> * @author strarsis <strarsis@gmail.com>
* @type {import('./plugins-types').Plugin<'minifyStyles'>} * @type {import('./plugins-types.js').Plugin<'minifyStyles'>}
*/ */
exports.fn = (_root, { usage, ...params }) => { export const fn = (_root, { usage, ...params }) => {
/** @type {Map<XastElement, XastParent>} */ /** @type {Map<XastElement, XastParent>} */
const styleElements = new Map(); const styleElements = new Map();

View File

@@ -1,10 +1,9 @@
'use strict'; import { visit } from '../lib/xast.js';
import { inheritableAttrs, pathElems } from './_collections.js';
const { visit } = require('../lib/xast.js'); export const name = 'moveElemsAttrsToGroup';
const { inheritableAttrs, pathElems } = require('./_collections.js'); export const description =
'Move common attributes of group children to the group';
exports.name = 'moveElemsAttrsToGroup';
exports.description = 'Move common attributes of group children to the group';
/** /**
* Move common attributes of group children to the group * Move common attributes of group children to the group
@@ -26,9 +25,9 @@ exports.description = 'Move common attributes of group children to the group';
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'moveElemsAttrsToGroup'>} * @type {import('./plugins-types.js').Plugin<'moveElemsAttrsToGroup'>}
*/ */
exports.fn = (root) => { export const fn = (root) => {
// find if any style element is present // find if any style element is present
let deoptimizedWithStyles = false; let deoptimizedWithStyles = false;
visit(root, { visit(root, {

View File

@@ -1,10 +1,9 @@
'use strict'; import { pathElems, referencesProps } from './_collections.js';
import { includesUrlReference } from '../lib/svgo/tools.js';
const { pathElems, referencesProps } = require('./_collections.js'); export const name = 'moveGroupAttrsToElems';
const { includesUrlReference } = require('../lib/svgo/tools.js'); export const description =
'moves some group attributes to the content elements';
exports.name = 'moveGroupAttrsToElems';
exports.description = 'moves some group attributes to the content elements';
const pathElemsWithGroupsAndText = [...pathElems, 'g', 'text']; const pathElemsWithGroupsAndText = [...pathElems, 'g', 'text'];
@@ -24,9 +23,9 @@ const pathElemsWithGroupsAndText = [...pathElems, 'g', 'text'];
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'moveGroupAttrsToElems'>} * @type {import('./plugins-types.js').Plugin<'moveGroupAttrsToElems'>}
*/ */
exports.fn = () => { export const fn = () => {
return { return {
element: { element: {
enter: (node) => { enter: (node) => {

View File

@@ -2,7 +2,7 @@ import type {
Plugin as PluginDef, Plugin as PluginDef,
PluginInfo, PluginInfo,
XastElement, XastElement,
} from '../lib/types'; } from '../lib/types.js';
type DefaultPlugins = { type DefaultPlugins = {
cleanupAttrs: { cleanupAttrs: {

View File

@@ -1,15 +1,13 @@
'use strict'; import * as csstree from 'css-tree';
import { referencesProps } from './_collections.js';
/** /**
* @typedef {import('../lib/types.js').PluginInfo} PluginInfo * @typedef {import('../lib/types.js').PluginInfo} PluginInfo
* @typedef {import('../lib/types').XastElement} XastElement * @typedef {import('../lib/types.js').XastElement} XastElement
*/ */
const csstree = require('css-tree'); export const name = 'prefixIds';
const { referencesProps } = require('./_collections.js'); export const description = 'prefix IDs';
exports.name = 'prefixIds';
exports.description = 'prefix IDs';
/** /**
* extract basename from path * extract basename from path
@@ -118,9 +116,9 @@ const generatePrefix = (body, node, info, prefixGenerator, delim, history) => {
* Prefixes identifiers * Prefixes identifiers
* *
* @author strarsis <strarsis@gmail.com> * @author strarsis <strarsis@gmail.com>
* @type {import('./plugins-types').Plugin<'prefixIds'>} * @type {import('./plugins-types.js').Plugin<'prefixIds'>}
*/ */
exports.fn = (_root, params, info) => { export const fn = (_root, params, info) => {
const { const {
delim = '__', delim = '__',
prefix, prefix,

View File

@@ -1,42 +1,39 @@
'use strict'; import { createPreset } from '../lib/svgo/plugins.js';
import * as removeDoctype from './removeDoctype.js';
const { createPreset } = require('../lib/svgo/plugins.js'); import * as removeXMLProcInst from './removeXMLProcInst.js';
import * as removeComments from './removeComments.js';
const removeDoctype = require('./removeDoctype.js'); import * as removeMetadata from './removeMetadata.js';
const removeXMLProcInst = require('./removeXMLProcInst.js'); import * as removeEditorsNSData from './removeEditorsNSData.js';
const removeComments = require('./removeComments.js'); import * as cleanupAttrs from './cleanupAttrs.js';
const removeMetadata = require('./removeMetadata.js'); import * as mergeStyles from './mergeStyles.js';
const removeEditorsNSData = require('./removeEditorsNSData.js'); import * as inlineStyles from './inlineStyles.js';
const cleanupAttrs = require('./cleanupAttrs.js'); import * as minifyStyles from './minifyStyles.js';
const mergeStyles = require('./mergeStyles.js'); import * as cleanupIds from './cleanupIds.js';
const inlineStyles = require('./inlineStyles.js'); import * as removeUselessDefs from './removeUselessDefs.js';
const minifyStyles = require('./minifyStyles.js'); import * as cleanupNumericValues from './cleanupNumericValues.js';
const cleanupIds = require('./cleanupIds.js'); import * as convertColors from './convertColors.js';
const removeUselessDefs = require('./removeUselessDefs.js'); import * as removeUnknownsAndDefaults from './removeUnknownsAndDefaults.js';
const cleanupNumericValues = require('./cleanupNumericValues.js'); import * as removeNonInheritableGroupAttrs from './removeNonInheritableGroupAttrs.js';
const convertColors = require('./convertColors.js'); import * as removeUselessStrokeAndFill from './removeUselessStrokeAndFill.js';
const removeUnknownsAndDefaults = require('./removeUnknownsAndDefaults.js'); import * as removeViewBox from './removeViewBox.js';
const removeNonInheritableGroupAttrs = require('./removeNonInheritableGroupAttrs.js'); import * as cleanupEnableBackground from './cleanupEnableBackground.js';
const removeUselessStrokeAndFill = require('./removeUselessStrokeAndFill.js'); import * as removeHiddenElems from './removeHiddenElems.js';
const removeViewBox = require('./removeViewBox.js'); import * as removeEmptyText from './removeEmptyText.js';
const cleanupEnableBackground = require('./cleanupEnableBackground.js'); import * as convertShapeToPath from './convertShapeToPath.js';
const removeHiddenElems = require('./removeHiddenElems.js'); import * as convertEllipseToCircle from './convertEllipseToCircle.js';
const removeEmptyText = require('./removeEmptyText.js'); import * as moveElemsAttrsToGroup from './moveElemsAttrsToGroup.js';
const convertShapeToPath = require('./convertShapeToPath.js'); import * as moveGroupAttrsToElems from './moveGroupAttrsToElems.js';
const convertEllipseToCircle = require('./convertEllipseToCircle.js'); import * as collapseGroups from './collapseGroups.js';
const moveElemsAttrsToGroup = require('./moveElemsAttrsToGroup.js'); import * as convertPathData from './convertPathData.js';
const moveGroupAttrsToElems = require('./moveGroupAttrsToElems.js'); import * as convertTransform from './convertTransform.js';
const collapseGroups = require('./collapseGroups.js'); import * as removeEmptyAttrs from './removeEmptyAttrs.js';
const convertPathData = require('./convertPathData.js'); import * as removeEmptyContainers from './removeEmptyContainers.js';
const convertTransform = require('./convertTransform.js'); import * as mergePaths from './mergePaths.js';
const removeEmptyAttrs = require('./removeEmptyAttrs.js'); import * as removeUnusedNS from './removeUnusedNS.js';
const removeEmptyContainers = require('./removeEmptyContainers.js'); import * as sortAttrs from './sortAttrs.js';
const mergePaths = require('./mergePaths.js'); import * as sortDefsChildren from './sortDefsChildren.js';
const removeUnusedNS = require('./removeUnusedNS.js'); import * as removeTitle from './removeTitle.js';
const sortAttrs = require('./sortAttrs.js'); import * as removeDesc from './removeDesc.js';
const sortDefsChildren = require('./sortDefsChildren.js');
const removeTitle = require('./removeTitle.js');
const removeDesc = require('./removeDesc.js');
const presetDefault = createPreset({ const presetDefault = createPreset({
name: 'preset-default', name: 'preset-default',
@@ -79,4 +76,4 @@ const presetDefault = createPreset({
], ],
}); });
module.exports = presetDefault; export default presetDefault;

View File

@@ -1,9 +1,7 @@
'use strict'; import { querySelectorAll } from '../lib/xast.js';
const { querySelectorAll } = require('../lib/xast.js'); export const name = 'removeAttributesBySelector';
export const description =
exports.name = 'removeAttributesBySelector';
exports.description =
'removes attributes of elements that match a css selector'; 'removes attributes of elements that match a css selector';
/** /**
@@ -73,9 +71,9 @@ exports.description =
* *
* @author Bradley Mease * @author Bradley Mease
* *
* @type {import('./plugins-types').Plugin<'removeAttributesBySelector'>} * @type {import('./plugins-types.js').Plugin<'removeAttributesBySelector'>}
*/ */
exports.fn = (root, params) => { export const fn = (root, params) => {
const selectors = Array.isArray(params.selectors) const selectors = Array.isArray(params.selectors)
? params.selectors ? params.selectors
: [params]; : [params];

View File

@@ -1,7 +1,5 @@
'use strict'; export const name = 'removeAttrs';
export const description = 'removes specified attributes';
exports.name = 'removeAttrs';
exports.description = 'removes specified attributes';
const DEFAULT_SEPARATOR = ':'; const DEFAULT_SEPARATOR = ':';
const ENOATTRS = `Warning: The plugin "removeAttrs" requires the "attrs" parameter. const ENOATTRS = `Warning: The plugin "removeAttrs" requires the "attrs" parameter.
@@ -81,9 +79,9 @@ plugins: [
* *
* @author Benny Schudel * @author Benny Schudel
* *
* @type {import('./plugins-types').Plugin<'removeAttrs'>} * @type {import('./plugins-types.js').Plugin<'removeAttrs'>}
*/ */
exports.fn = (root, params) => { export const fn = (root, params) => {
if (typeof params.attrs == 'undefined') { if (typeof params.attrs == 'undefined') {
console.warn(ENOATTRS); console.warn(ENOATTRS);
return null; return null;

View File

@@ -1,9 +1,7 @@
'use strict'; import { detachNodeFromParent } from '../lib/xast.js';
const { detachNodeFromParent } = require('../lib/xast.js'); export const name = 'removeComments';
export const description = 'removes comments';
exports.name = 'removeComments';
exports.description = 'removes comments';
/** /**
* If a comment matches one of the following patterns, it will be * If a comment matches one of the following patterns, it will be
@@ -20,9 +18,9 @@ const DEFAULT_PRESERVE_PATTERNS = [/^!/];
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'removeComments'>} * @type {import('./plugins-types.js').Plugin<'removeComments'>}
*/ */
exports.fn = (_root, params) => { export const fn = (_root, params) => {
const { preservePatterns = DEFAULT_PRESERVE_PATTERNS } = params; const { preservePatterns = DEFAULT_PRESERVE_PATTERNS } = params;
return { return {

View File

@@ -1,9 +1,7 @@
'use strict'; import { detachNodeFromParent } from '../lib/xast.js';
const { detachNodeFromParent } = require('../lib/xast.js'); export const name = 'removeDesc';
export const description = 'removes <desc>';
exports.name = 'removeDesc';
exports.description = 'removes <desc>';
const standardDescs = /^(Created with|Created using)/; const standardDescs = /^(Created with|Created using)/;
@@ -16,9 +14,9 @@ const standardDescs = /^(Created with|Created using)/;
* *
* @author Daniel Wabyick * @author Daniel Wabyick
* *
* @type {import('./plugins-types').Plugin<'removeDesc'>} * @type {import('./plugins-types.js').Plugin<'removeDesc'>}
*/ */
exports.fn = (root, params) => { export const fn = (root, params) => {
const { removeAny = false } = params; const { removeAny = false } = params;
return { return {
element: { element: {

View File

@@ -1,7 +1,5 @@
'use strict'; export const name = 'removeDimensions';
export const description =
exports.name = 'removeDimensions';
exports.description =
'removes width and height in presence of viewBox (opposite to removeViewBox, disable it first)'; 'removes width and height in presence of viewBox (opposite to removeViewBox, disable it first)';
/** /**
@@ -14,9 +12,9 @@ exports.description =
* *
* @author Benny Schudel * @author Benny Schudel
* *
* @type {import('./plugins-types').Plugin<'removeDimensions'>} * @type {import('./plugins-types.js').Plugin<'removeDimensions'>}
*/ */
exports.fn = () => { export const fn = () => {
return { return {
element: { element: {
enter: (node) => { enter: (node) => {

View File

@@ -1,9 +1,7 @@
'use strict'; import { detachNodeFromParent } from '../lib/xast.js';
const { detachNodeFromParent } = require('../lib/xast.js'); export const name = 'removeDoctype';
export const description = 'removes doctype declaration';
exports.name = 'removeDoctype';
exports.description = 'removes doctype declaration';
/** /**
* Remove DOCTYPE declaration. * Remove DOCTYPE declaration.
@@ -27,9 +25,9 @@ exports.description = 'removes doctype declaration';
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'removeDoctype'>} * @type {import('./plugins-types.js').Plugin<'removeDoctype'>}
*/ */
exports.fn = () => { export const fn = () => {
return { return {
doctype: { doctype: {
enter: (node, parentNode) => { enter: (node, parentNode) => {

View File

@@ -1,10 +1,9 @@
'use strict'; import { editorNamespaces } from './_collections.js';
import { detachNodeFromParent } from '../lib/xast.js';
const { detachNodeFromParent } = require('../lib/xast.js'); export const name = 'removeEditorsNSData';
const { editorNamespaces } = require('./_collections.js'); export const description =
'removes editors namespaces, elements and attributes';
exports.name = 'removeEditorsNSData';
exports.description = 'removes editors namespaces, elements and attributes';
/** /**
* Remove editors namespaces, elements and attributes. * Remove editors namespaces, elements and attributes.
@@ -16,9 +15,9 @@ exports.description = 'removes editors namespaces, elements and attributes';
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'removeEditorsNSData'>} * @type {import('./plugins-types.js').Plugin<'removeEditorsNSData'>}
*/ */
exports.fn = (_root, params) => { export const fn = (_root, params) => {
let namespaces = [...editorNamespaces]; let namespaces = [...editorNamespaces];
if (Array.isArray(params.additionalNamespaces)) { if (Array.isArray(params.additionalNamespaces)) {
namespaces = [...editorNamespaces, ...params.additionalNamespaces]; namespaces = [...editorNamespaces, ...params.additionalNamespaces];

View File

@@ -1,9 +1,7 @@
'use strict'; import { detachNodeFromParent } from '../lib/xast.js';
const { detachNodeFromParent } = require('../lib/xast.js'); export const name = 'removeElementsByAttr';
export const description =
exports.name = 'removeElementsByAttr';
exports.description =
'removes arbitrary elements by ID or className (disabled by default)'; 'removes arbitrary elements by ID or className (disabled by default)';
/** /**
@@ -37,9 +35,9 @@ exports.description =
* *
* @author Eli Dupuis (@elidupuis) * @author Eli Dupuis (@elidupuis)
* *
* @type {import('./plugins-types').Plugin<'removeElementsByAttr'>} * @type {import('./plugins-types.js').Plugin<'removeElementsByAttr'>}
*/ */
exports.fn = (root, params) => { export const fn = (root, params) => {
const ids = const ids =
params.id == null ? [] : Array.isArray(params.id) ? params.id : [params.id]; params.id == null ? [] : Array.isArray(params.id) ? params.id : [params.id];
const classes = const classes =

View File

@@ -1,18 +1,16 @@
'use strict'; import { attrsGroups } from './_collections.js';
const { attrsGroups } = require('./_collections.js'); export const name = 'removeEmptyAttrs';
export const description = 'removes empty attributes';
exports.name = 'removeEmptyAttrs';
exports.description = 'removes empty attributes';
/** /**
* Remove attributes with empty values. * Remove attributes with empty values.
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'removeEmptyAttrs'>} * @type {import('./plugins-types.js').Plugin<'removeEmptyAttrs'>}
*/ */
exports.fn = () => { export const fn = () => {
return { return {
element: { element: {
enter: (node) => { enter: (node) => {

View File

@@ -1,10 +1,8 @@
'use strict'; import { elemsGroups } from './_collections.js';
import { detachNodeFromParent } from '../lib/xast.js';
const { detachNodeFromParent } = require('../lib/xast.js'); export const name = 'removeEmptyContainers';
const { elemsGroups } = require('./_collections.js'); export const description = 'removes empty container elements';
exports.name = 'removeEmptyContainers';
exports.description = 'removes empty container elements';
/** /**
* Remove empty containers. * Remove empty containers.
@@ -19,9 +17,9 @@ exports.description = 'removes empty container elements';
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'removeEmptyContainers'>} * @type {import('./plugins-types.js').Plugin<'removeEmptyContainers'>}
*/ */
exports.fn = () => { export const fn = () => {
return { return {
element: { element: {
exit: (node, parentNode) => { exit: (node, parentNode) => {

View File

@@ -1,9 +1,7 @@
'use strict'; import { detachNodeFromParent } from '../lib/xast.js';
const { detachNodeFromParent } = require('../lib/xast.js'); export const name = 'removeEmptyText';
export const description = 'removes empty <text> elements';
exports.name = 'removeEmptyText';
exports.description = 'removes empty <text> elements';
/** /**
* Remove empty Text elements. * Remove empty Text elements.
@@ -22,9 +20,9 @@ exports.description = 'removes empty <text> elements';
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'removeEmptyText'>} * @type {import('./plugins-types.js').Plugin<'removeEmptyText'>}
*/ */
exports.fn = (root, params) => { export const fn = (root, params) => {
const { text = true, tspan = true, tref = true } = params; const { text = true, tspan = true, tref = true } = params;
return { return {
element: { element: {

View File

@@ -1,26 +1,24 @@
'use strict';
/** /**
* @typedef {import('../lib/types').XastChild} XastChild * @typedef {import('../lib/types.js').XastChild} XastChild
* @typedef {import('../lib/types').XastElement} XastElement * @typedef {import('../lib/types.js').XastElement} XastElement
* @typedef {import('../lib/types').XastParent} XastParent * @typedef {import('../lib/types.js').XastParent} XastParent
*/ */
const { elemsGroups } = require('./_collections.js'); import { elemsGroups } from './_collections.js';
const { import {
visit, visit,
visitSkip, visitSkip,
querySelector, querySelector,
detachNodeFromParent, detachNodeFromParent,
} = require('../lib/xast.js'); } from '../lib/xast.js';
const { collectStylesheet, computeStyle } = require('../lib/style.js'); import { collectStylesheet, computeStyle } from '../lib/style.js';
const { parsePathData } = require('../lib/path.js'); import { parsePathData } from '../lib/path.js';
const { hasScripts, findReferences } = require('../lib/svgo/tools.js'); import { hasScripts, findReferences } from '../lib/svgo/tools.js';
const nonRendering = elemsGroups.nonRendering; const nonRendering = elemsGroups.nonRendering;
exports.name = 'removeHiddenElems'; export const name = 'removeHiddenElems';
exports.description = export const description =
'removes hidden elements (zero sized, with absent attributes)'; 'removes hidden elements (zero sized, with absent attributes)';
/** /**
@@ -38,9 +36,9 @@ exports.description =
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'removeHiddenElems'>} * @type {import('./plugins-types.js').Plugin<'removeHiddenElems'>}
*/ */
exports.fn = (root, params) => { export const fn = (root, params) => {
const { const {
isHidden = true, isHidden = true,
displayNone = true, displayNone = true,

View File

@@ -1,9 +1,7 @@
'use strict'; import { detachNodeFromParent } from '../lib/xast.js';
const { detachNodeFromParent } = require('../lib/xast.js'); export const name = 'removeMetadata';
export const description = 'removes <metadata>';
exports.name = 'removeMetadata';
exports.description = 'removes <metadata>';
/** /**
* Remove <metadata>. * Remove <metadata>.
@@ -12,9 +10,9 @@ exports.description = 'removes <metadata>';
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'removeMetadata'>} * @type {import('./plugins-types.js').Plugin<'removeMetadata'>}
*/ */
exports.fn = () => { export const fn = () => {
return { return {
element: { element: {
enter: (node, parentNode) => { enter: (node, parentNode) => {

View File

@@ -1,13 +1,11 @@
'use strict'; import {
const {
inheritableAttrs, inheritableAttrs,
attrsGroups, attrsGroups,
presentationNonInheritableGroupAttrs, presentationNonInheritableGroupAttrs,
} = require('./_collections'); } from './_collections.js';
exports.name = 'removeNonInheritableGroupAttrs'; export const name = 'removeNonInheritableGroupAttrs';
exports.description = export const description =
'removes non-inheritable groups presentational attributes'; 'removes non-inheritable groups presentational attributes';
/** /**
@@ -15,9 +13,9 @@ exports.description =
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'removeNonInheritableGroupAttrs'>} * @type {import('./plugins-types.js').Plugin<'removeNonInheritableGroupAttrs'>}
*/ */
exports.fn = () => { export const fn = () => {
return { return {
element: { element: {
enter: (node) => { enter: (node) => {

View File

@@ -1,15 +1,13 @@
'use strict';
/** /**
* @typedef {import('../lib/types').PathDataItem} PathDataItem * @typedef {import('../lib/types.js').PathDataItem} PathDataItem
*/ */
const { visitSkip, detachNodeFromParent } = require('../lib/xast.js'); import { visitSkip, detachNodeFromParent } from '../lib/xast.js';
const { parsePathData } = require('../lib/path.js'); import { parsePathData } from '../lib/path.js';
const { intersects } = require('./_path.js'); import { intersects } from './_path.js';
exports.name = 'removeOffCanvasPaths'; export const name = 'removeOffCanvasPaths';
exports.description = export const description =
'removes elements that are drawn outside of the viewbox (disabled by default)'; 'removes elements that are drawn outside of the viewbox (disabled by default)';
/** /**
@@ -17,9 +15,9 @@ exports.description =
* *
* @author JoshyPHP * @author JoshyPHP
* *
* @type {import('./plugins-types').Plugin<'removeOffCanvasPaths'>} * @type {import('./plugins-types.js').Plugin<'removeOffCanvasPaths'>}
*/ */
exports.fn = () => { export const fn = () => {
/** /**
* @type {?{ * @type {?{
* top: number, * top: number,

View File

@@ -1,9 +1,7 @@
'use strict'; import { detachNodeFromParent } from '../lib/xast.js';
const { detachNodeFromParent } = require('../lib/xast.js'); export const name = 'removeRasterImages';
export const description = 'removes raster images (disabled by default)';
exports.name = 'removeRasterImages';
exports.description = 'removes raster images (disabled by default)';
/** /**
* Remove raster images references in <image>. * Remove raster images references in <image>.
@@ -12,9 +10,9 @@ exports.description = 'removes raster images (disabled by default)';
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'removeRasterImages'>} * @type {import('./plugins-types.js').Plugin<'removeRasterImages'>}
*/ */
exports.fn = () => { export const fn = () => {
return { return {
element: { element: {
enter: (node, parentNode) => { enter: (node, parentNode) => {

View File

@@ -1,10 +1,8 @@
'use strict'; import { attrsGroups } from './_collections.js';
import { detachNodeFromParent } from '../lib/xast.js';
const { detachNodeFromParent } = require('../lib/xast.js'); export const name = 'removeScriptElement';
const { attrsGroups } = require('./_collections.js'); export const description = 'removes scripts (disabled by default)';
exports.name = 'removeScriptElement';
exports.description = 'removes scripts (disabled by default)';
/** Union of all event attributes. */ /** Union of all event attributes. */
const eventAttrs = [ const eventAttrs = [
@@ -21,9 +19,9 @@ const eventAttrs = [
* https://www.w3.org/TR/SVG11/script.html * https://www.w3.org/TR/SVG11/script.html
* *
* @author Patrick Klingemann * @author Patrick Klingemann
* @type {import('./plugins-types').Plugin<'removeScriptElement'>} * @type {import('./plugins-types.js').Plugin<'removeScriptElement'>}
*/ */
exports.fn = () => { export const fn = () => {
return { return {
element: { element: {
enter: (node, parentNode) => { enter: (node, parentNode) => {

View File

@@ -1,9 +1,7 @@
'use strict'; import { detachNodeFromParent } from '../lib/xast.js';
const { detachNodeFromParent } = require('../lib/xast.js'); export const name = 'removeStyleElement';
export const description = 'removes <style> element (disabled by default)';
exports.name = 'removeStyleElement';
exports.description = 'removes <style> element (disabled by default)';
/** /**
* Remove <style>. * Remove <style>.
@@ -12,9 +10,9 @@ exports.description = 'removes <style> element (disabled by default)';
* *
* @author Betsy Dupuis * @author Betsy Dupuis
* *
* @type {import('./plugins-types').Plugin<'removeStyleElement'>} * @type {import('./plugins-types.js').Plugin<'removeStyleElement'>}
*/ */
exports.fn = () => { export const fn = () => {
return { return {
element: { element: {
enter: (node, parentNode) => { enter: (node, parentNode) => {

View File

@@ -1,9 +1,7 @@
'use strict'; import { detachNodeFromParent } from '../lib/xast.js';
const { detachNodeFromParent } = require('../lib/xast.js'); export const name = 'removeTitle';
export const description = 'removes <title>';
exports.name = 'removeTitle';
exports.description = 'removes <title>';
/** /**
* Remove <title>. * Remove <title>.
@@ -12,9 +10,9 @@ exports.description = 'removes <title>';
* *
* @author Igor Kalashnikov * @author Igor Kalashnikov
* *
* @type {import('./plugins-types').Plugin<'removeTitle'>} * @type {import('./plugins-types.js').Plugin<'removeTitle'>}
*/ */
exports.fn = () => { export const fn = () => {
return { return {
element: { element: {
enter: (node, parentNode) => { enter: (node, parentNode) => {

View File

@@ -1,17 +1,15 @@
'use strict'; import {
const { visitSkip, detachNodeFromParent } = require('../lib/xast.js');
const { collectStylesheet, computeStyle } = require('../lib/style.js');
const {
elems, elems,
attrsGroups, attrsGroups,
elemsGroups, elemsGroups,
attrsGroupsDefaults, attrsGroupsDefaults,
presentationNonInheritableGroupAttrs, presentationNonInheritableGroupAttrs,
} = require('./_collections'); } from './_collections.js';
import { visitSkip, detachNodeFromParent } from '../lib/xast.js';
import { collectStylesheet, computeStyle } from '../lib/style.js';
exports.name = 'removeUnknownsAndDefaults'; export const name = 'removeUnknownsAndDefaults';
exports.description = export const description =
'removes unknown elements content and attributes, removes attrs with default values'; 'removes unknown elements content and attributes, removes attrs with default values';
// resolve all groups references // resolve all groups references
@@ -92,9 +90,9 @@ for (const [name, config] of Object.entries(elems)) {
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'removeUnknownsAndDefaults'>} * @type {import('./plugins-types.js').Plugin<'removeUnknownsAndDefaults'>}
*/ */
exports.fn = (root, params) => { export const fn = (root, params) => {
const { const {
unknownContent = true, unknownContent = true,
unknownAttrs = true, unknownAttrs = true,

View File

@@ -1,7 +1,5 @@
'use strict'; export const name = 'removeUnusedNS';
export const description = 'removes unused namespaces declaration';
exports.name = 'removeUnusedNS';
exports.description = 'removes unused namespaces declaration';
/** /**
* Remove unused namespaces declaration from svg element * Remove unused namespaces declaration from svg element
@@ -9,9 +7,9 @@ exports.description = 'removes unused namespaces declaration';
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'removeUnusedNS'>} * @type {import('./plugins-types.js').Plugin<'removeUnusedNS'>}
*/ */
exports.fn = () => { export const fn = () => {
/** /**
* @type {Set<string>} * @type {Set<string>}
*/ */

View File

@@ -1,23 +1,21 @@
'use strict'; import { detachNodeFromParent } from '../lib/xast.js';
import { elemsGroups } from './_collections.js';
/** /**
* @typedef {import('../lib/types').XastElement} XastElement * @typedef {import('../lib/types.js').XastElement} XastElement
*/ */
const { detachNodeFromParent } = require('../lib/xast.js'); export const name = 'removeUselessDefs';
const { elemsGroups } = require('./_collections.js'); export const description = 'removes elements in <defs> without id';
exports.name = 'removeUselessDefs';
exports.description = 'removes elements in <defs> without id';
/** /**
* Removes content of defs and properties that aren't rendered directly without ids. * Removes content of defs and properties that aren't rendered directly without ids.
* *
* @author Lev Solntsev * @author Lev Solntsev
* *
* @type {import('./plugins-types').Plugin<'removeUselessDefs'>} * @type {import('./plugins-types.js').Plugin<'removeUselessDefs'>}
*/ */
exports.fn = () => { export const fn = () => {
return { return {
element: { element: {
enter: (node, parentNode) => { enter: (node, parentNode) => {

View File

@@ -1,21 +1,19 @@
'use strict'; import { visit, visitSkip, detachNodeFromParent } from '../lib/xast.js';
import { collectStylesheet, computeStyle } from '../lib/style.js';
import { hasScripts } from '../lib/svgo/tools.js';
import { elemsGroups } from './_collections.js';
const { visit, visitSkip, detachNodeFromParent } = require('../lib/xast.js'); export const name = 'removeUselessStrokeAndFill';
const { collectStylesheet, computeStyle } = require('../lib/style.js'); export const description = 'removes useless stroke and fill attributes';
const { hasScripts } = require('../lib/svgo/tools.js');
const { elemsGroups } = require('./_collections.js');
exports.name = 'removeUselessStrokeAndFill';
exports.description = 'removes useless stroke and fill attributes';
/** /**
* Remove useless stroke and fill attrs. * Remove useless stroke and fill attrs.
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'removeUselessStrokeAndFill'>} * @type {import('./plugins-types.js').Plugin<'removeUselessStrokeAndFill'>}
*/ */
exports.fn = (root, params) => { export const fn = (root, params) => {
const { const {
stroke: removeStroke = true, stroke: removeStroke = true,
fill: removeFill = true, fill: removeFill = true,

View File

@@ -1,7 +1,5 @@
'use strict'; export const name = 'removeViewBox';
export const description = 'removes viewBox attribute when possible';
exports.name = 'removeViewBox';
exports.description = 'removes viewBox attribute when possible';
const viewBoxElems = new Set(['pattern', 'svg', 'symbol']); const viewBoxElems = new Set(['pattern', 'svg', 'symbol']);
@@ -17,9 +15,9 @@ const viewBoxElems = new Set(['pattern', 'svg', 'symbol']);
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'removeViewBox'>} * @type {import('./plugins-types.js').Plugin<'removeViewBox'>}
*/ */
exports.fn = () => { export const fn = () => {
return { return {
element: { element: {
enter: (node, parentNode) => { enter: (node, parentNode) => {

View File

@@ -1,7 +1,5 @@
'use strict'; export const name = 'removeXMLNS';
export const description =
exports.name = 'removeXMLNS';
exports.description =
'removes xmlns attribute (for inline svg, disabled by default)'; 'removes xmlns attribute (for inline svg, disabled by default)';
/** /**
@@ -14,9 +12,9 @@ exports.description =
* *
* @author Ricardo Tomasi * @author Ricardo Tomasi
* *
* @type {import('./plugins-types').Plugin<'removeXMLNS'>} * @type {import('./plugins-types.js').Plugin<'removeXMLNS'>}
*/ */
exports.fn = () => { export const fn = () => {
return { return {
element: { element: {
enter: (node) => { enter: (node) => {

View File

@@ -1,9 +1,7 @@
'use strict'; import { detachNodeFromParent } from '../lib/xast.js';
const { detachNodeFromParent } = require('../lib/xast.js'); export const name = 'removeXMLProcInst';
export const description = 'removes XML processing instructions';
exports.name = 'removeXMLProcInst';
exports.description = 'removes XML processing instructions';
/** /**
* Remove XML Processing Instruction. * Remove XML Processing Instruction.
@@ -13,9 +11,9 @@ exports.description = 'removes XML processing instructions';
* *
* @author Kir Belevich * @author Kir Belevich
* *
* @type {import('./plugins-types').Plugin<'removeXMLProcInst'>} * @type {import('./plugins-types.js').Plugin<'removeXMLProcInst'>}
*/ */
exports.fn = () => { export const fn = () => {
return { return {
instruction: { instruction: {
enter: (node, parentNode) => { enter: (node, parentNode) => {

View File

@@ -1,13 +1,11 @@
'use strict'; import { elems } from './_collections.js';
const { elems } = require('./_collections');
/** /**
* @typedef {import('../lib/types').XastElement} XastElement * @typedef {import('../lib/types.js').XastElement} XastElement
*/ */
exports.name = 'removeXlink'; export const name = 'removeXlink';
exports.description = export const description =
'remove xlink namespace and replaces attributes with the SVG 2 equivalent where applicable'; 'remove xlink namespace and replaces attributes with the SVG 2 equivalent where applicable';
/** URI indicating the Xlink namespace. */ /** URI indicating the Xlink namespace. */
@@ -58,10 +56,10 @@ const findPrefixedAttrs = (node, prefixes, attr) => {
* *
* The XLink namespace is deprecated in SVG 2. * The XLink namespace is deprecated in SVG 2.
* *
* @type {import('./plugins-types').Plugin<'removeXlink'>} * @type {import('./plugins-types.js').Plugin<'removeXlink'>}
* @see https://developer.mozilla.org/docs/Web/SVG/Attribute/xlink:href * @see https://developer.mozilla.org/docs/Web/SVG/Attribute/xlink:href
*/ */
exports.fn = (_, params) => { export const fn = (_, params) => {
const { includeLegacy } = params; const { includeLegacy } = params;
/** /**

View File

@@ -1,16 +1,14 @@
'use strict'; import { collectStylesheet } from '../lib/style.js';
import { detachNodeFromParent, querySelectorAll } from '../lib/xast.js';
const { collectStylesheet } = require('../lib/style');
const { detachNodeFromParent, querySelectorAll } = require('../lib/xast');
/** /**
* @typedef {import('../lib/types').XastElement} XastElement * @typedef {import('../lib/types.js').XastElement} XastElement
* @typedef {import('../lib/types').XastParent} XastParent * @typedef {import('../lib/types.js').XastParent} XastParent
* @typedef {import('../lib/types').XastNode} XastNode * @typedef {import('../lib/types.js').XastNode} XastNode
*/ */
exports.name = 'reusePaths'; export const name = 'reusePaths';
exports.description = export const description =
'Finds <path> elements with the same d, fill, and ' + 'Finds <path> elements with the same d, fill, and ' +
'stroke, and converts them to <use> elements ' + 'stroke, and converts them to <use> elements ' +
'referencing a single <path> def.'; 'referencing a single <path> def.';
@@ -21,9 +19,9 @@ exports.description =
* *
* @author Jacob Howcroft * @author Jacob Howcroft
* *
* @type {import('./plugins-types').Plugin<'reusePaths'>} * @type {import('./plugins-types.js').Plugin<'reusePaths'>}
*/ */
exports.fn = (root) => { export const fn = (root) => {
const stylesheet = collectStylesheet(root); const stylesheet = collectStylesheet(root);
/** /**

View File

@@ -1,16 +1,14 @@
'use strict'; export const name = 'sortAttrs';
export const description = 'Sort element attributes for better compression';
exports.name = 'sortAttrs';
exports.description = 'Sort element attributes for better compression';
/** /**
* Sort element attributes for better compression * Sort element attributes for better compression
* *
* @author Nikolay Frantsev * @author Nikolay Frantsev
* *
* @type {import('./plugins-types').Plugin<'sortAttrs'>} * @type {import('./plugins-types.js').Plugin<'sortAttrs'>}
*/ */
exports.fn = (_root, params) => { export const fn = (_root, params) => {
const { const {
order = [ order = [
'id', 'id',

View File

@@ -1,7 +1,5 @@
'use strict'; export const name = 'sortDefsChildren';
export const description = 'Sorts children of <defs> to improve compression';
exports.name = 'sortDefsChildren';
exports.description = 'Sorts children of <defs> to improve compression';
/** /**
* Sorts children of defs in order to improve compression. * Sorts children of defs in order to improve compression.
@@ -9,9 +7,9 @@ exports.description = 'Sorts children of <defs> to improve compression';
* *
* @author David Leston * @author David Leston
* *
* @type {import('./plugins-types').Plugin<'sortDefsChildren'>} * @type {import('./plugins-types.js').Plugin<'sortDefsChildren'>}
*/ */
exports.fn = () => { export const fn = () => {
return { return {
element: { element: {
enter: (node) => { enter: (node) => {

View File

@@ -1,25 +1,44 @@
import path from 'path';
import { fileURLToPath } from 'url';
import * as fs from 'node:fs';
import { nodeResolve } from '@rollup/plugin-node-resolve'; import { nodeResolve } from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs'; import commonjs from '@rollup/plugin-commonjs';
import { terser } from 'rollup-plugin-terser'; import terser from '@rollup/plugin-terser';
export default { const __dirname = path.dirname(fileURLToPath(import.meta.url));
input: './lib/svgo.js', const pkgPath = path.join(__dirname, './package.json');
output: { const PKG = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
file: './dist/svgo.browser.js',
format: 'esm', export default [
{
input: './lib/svgo.js',
output: {
file: './dist/svgo-node.cjs',
format: 'cjs',
},
external: Object.keys(PKG.dependencies),
onwarn(warning) {
throw Error(warning.toString());
},
plugins: [terser()],
}, },
onwarn(warning) { {
throw Error(warning.toString()); input: './lib/svgo.js',
output: {
file: './dist/svgo.browser.js',
format: 'esm',
},
onwarn(warning) {
throw Error(warning.toString());
},
plugins: [
nodeResolve({ browser: true, preferBuiltins: false }),
commonjs(),
terser({
compress: false,
mangle: false,
format: { comments: false },
}),
],
}, },
plugins: [ ];
nodeResolve({ browser: true, preferBuiltins: false }),
commonjs(),
// Whitespaces and comments removal makes the browser bundle lighter
// while retaining the ability to debug errors
terser({
compress: false,
mangle: false,
format: { comments: false },
}),
],
};

View File

@@ -1,7 +1,7 @@
const assert = require('assert'); import assert from 'assert';
const fs = require('node:fs/promises'); import fs from 'node:fs/promises';
const http = require('http'); import http from 'http';
const { chromium } = require('playwright'); import { chromium } from 'playwright';
const fixture = `<svg xmlns="http://www.w3.org/2000/svg"> const fixture = `<svg xmlns="http://www.w3.org/2000/svg">
<g attr1="val1"> <g attr1="val1">

View File

@@ -1,12 +1,13 @@
'use strict';
/** /**
* @typedef {import('child_process').ChildProcessWithoutNullStreams} ChildProcessWithoutNullStreams * @typedef {import('child_process').ChildProcessWithoutNullStreams} ChildProcessWithoutNullStreams
*/ */
const fs = require('fs'); import fs from 'fs';
const path = require('path'); import path from 'path';
const { spawn } = require('child_process'); import { spawn } from 'child_process';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
/** /**
* @type {(proc: ChildProcessWithoutNullStreams) => Promise<string>} * @type {(proc: ChildProcessWithoutNullStreams) => Promise<string>}

View File

@@ -1,10 +1,11 @@
'use strict'; import fs from 'fs';
import path from 'path';
import del from 'del';
import { Command } from 'commander';
import { fileURLToPath } from 'url';
import svgo, { checkIsDir } from '../../lib/svgo/coa.js';
const fs = require('fs'); const __dirname = path.dirname(fileURLToPath(import.meta.url));
const path = require('path');
const del = require('del');
const { Command } = require('commander');
const svgo = require('../../lib/svgo/coa.js');
const svgFolderPath = path.resolve(__dirname, 'testSvg'); const svgFolderPath = path.resolve(__dirname, 'testSvg');
const svgFolderPathRecursively = path.resolve(__dirname, 'testSvgRecursively'); const svgFolderPathRecursively = path.resolve(__dirname, 'testSvgRecursively');
@@ -15,8 +16,6 @@ const svgFiles = [
const tempFolder = 'temp'; const tempFolder = 'temp';
const noop = () => {}; const noop = () => {};
const { checkIsDir } = svgo;
function runProgram(args) { function runProgram(args) {
const program = new Command(); const program = new Command();
svgo(program); svgo(program);

View File

@@ -1 +1 @@
module.exports = []; export default [];

View File

@@ -1 +1 @@
module.exports = null; export default null;

View File

@@ -1 +1,2 @@
module.exports = { plugins }; // eslint-disable-line no-undef /* eslint-disable no-undef */
export default { plugins };

View File

@@ -1 +1 @@
module.exports = ''; export default '';

View File

@@ -1,2 +1,2 @@
require('unknown-module'); import 'unknown-module';
module.exports = {}; export default {};

View File

@@ -1 +1 @@
module.exports = { plugins: [] }; export default { plugins: [] };

View File

@@ -1 +1 @@
module.exports = { plugins: [] }; export default { plugins: [] };

View File

@@ -1,11 +1,12 @@
'use strict'; import FS from 'fs';
import PATH from 'path';
import { EOL } from 'os';
import { fileURLToPath } from 'url';
import { optimize } from '../../lib/svgo.js';
const FS = require('fs');
const PATH = require('path');
const EOL = require('os').EOL;
const regEOL = new RegExp(EOL, 'g'); const regEOL = new RegExp(EOL, 'g');
const regFilename = /^(.*)\.(\d+)\.svg$/; const regFilename = /^(.*)\.(\d+)\.svg$/;
const { optimize } = require('../../lib/svgo.js'); const __dirname = PATH.dirname(fileURLToPath(import.meta.url));
describe('plugins tests', function () { describe('plugins tests', function () {
FS.readdirSync(__dirname).forEach(function (file) { FS.readdirSync(__dirname).forEach(function (file) {
@@ -41,7 +42,6 @@ describe('plugins tests', function () {
js2svg: { pretty: true }, js2svg: { pretty: true },
}); });
lastResultData = result.data; lastResultData = result.data;
expect(result.error).not.toStrictEqual(expect.anything());
//FIXME: results.data has a '\n' at the end while it should not //FIXME: results.data has a '\n' at the end while it should not
expect(normalize(result.data)).toStrictEqual(should); expect(normalize(result.data)).toStrictEqual(should);
} }

View File

@@ -1,6 +1,4 @@
'use strict'; import { matrixToTransform } from '../../plugins/_transforms.js';
const { matrixToTransform } = require('../../plugins/_transforms');
/** /**
* @typedef {import('../../plugins/_transforms').TransformParams} TransformParams * @typedef {import('../../plugins/_transforms').TransformParams} TransformParams

View File

@@ -1,6 +1,4 @@
'use strict'; import { optimize } from '../../lib/svgo.js';
const { optimize } = require('../../lib/svgo.js');
test('should extract prefix from path basename', () => { test('should extract prefix from path basename', () => {
const svg = `<svg id="my-id"></svg>`; const svg = `<svg id="my-id"></svg>`;

View File

@@ -1,12 +1,13 @@
'use strict'; import fs from 'fs';
import path from 'path';
import stream from 'stream';
import util from 'util';
import zlib from 'zlib';
import fetch from 'node-fetch';
import tarStream from 'tar-stream';
import { fileURLToPath } from 'url';
const fs = require('fs'); const __dirname = path.dirname(fileURLToPath(import.meta.url));
const path = require('path');
const stream = require('stream');
const util = require('util');
const zlib = require('zlib');
const { default: fetch } = require('node-fetch');
const tarStream = require('tar-stream');
const pipeline = util.promisify(stream.pipeline); const pipeline = util.promisify(stream.pipeline);

View File

@@ -1,18 +1,19 @@
'use strict';
/** /**
* @typedef {import('playwright').Page} Page * @typedef {import('playwright').Page} Page
* @typedef {import('playwright').PageScreenshotOptions} PageScreenshotOptions * @typedef {import('playwright').PageScreenshotOptions} PageScreenshotOptions
*/ */
const fs = require('node:fs/promises'); import fs from 'node:fs/promises';
const http = require('http'); import http from 'http';
const os = require('os'); import os from 'os';
const path = require('path'); import path from 'path';
const pixelmatch = require('pixelmatch'); import pixelmatch from 'pixelmatch';
const { chromium } = require('playwright'); import { chromium } from 'playwright';
const { PNG } = require('pngjs'); import { PNG } from 'pngjs';
const { optimize } = require('../lib/svgo.js'); import { fileURLToPath } from 'url';
import { optimize } from '../lib/svgo.js';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const width = 960; const width = 960;
const height = 720; const height = 720;

View File

@@ -1,8 +1,9 @@
'use strict'; import FS from 'fs';
import PATH from 'path';
import { fileURLToPath } from 'url';
import { parseSvg } from '../../lib/parser.js';
const FS = require('fs'); const __dirname = PATH.dirname(fileURLToPath(import.meta.url));
const PATH = require('path');
const { parseSvg } = require('../../lib/parser.js');
describe('svg2js', function () { describe('svg2js', function () {
describe('working svg', function () { describe('working svg', function () {

33
test/svgo.cjs Normal file
View File

@@ -0,0 +1,33 @@
const { optimize } = require('../dist/svgo-node.cjs');
const assert = require('assert');
const fixture = `<svg xmlns="http://www.w3.org/2000/svg">
<g attr1="val1">
<g attr2="val2">
<path attr2="val3" d="..."/>
</g>
<path d="..."/>
</g>
</svg>`;
const expected = `<svg xmlns="http://www.w3.org/2000/svg">
<g attr1="val1">
<g attr2="val2">
<path attr2="val3" d="..."/>
</g>
<path d="..."/>
</g>
</svg>
`;
const runTest = () => {
const result = optimize(fixture, {
plugins: [],
js2svg: { pretty: true, indent: 2 },
});
const actual = result.data;
assert.equal(actual, expected);
};
runTest();

Some files were not shown because too many files have changed in this diff Show More