1
0
mirror of https://github.com/svg/svgo.git synced 2025-07-31 07:44:22 +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": {
"ecmaVersion": 2021
"ecmaVersion": 2021,
"sourceType": "module"
},
"env": {
"node": true,
@ -8,12 +9,6 @@
},
"extends": ["eslint:recommended"],
"overrides": [
{
"files": ["rollup.config.js", "**/*.mjs"],
"parserOptions": {
"sourceType": "module"
}
},
{
"files": ["**/*.cjs"],
"parserOptions": {

View File

@ -47,7 +47,6 @@ jobs:
- 20
- 18
- 16
- 14
os:
- ubuntu-latest
- windows-latest
@ -61,4 +60,4 @@ jobs:
- run: yarn install
- run: yarn playwright install --with-deps chromium
- 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`**
```js
module.exports = {
export default {
multipass: false, // boolean
datauri: 'base64', // 'base64'|'enc'|'unenc'
js2svg: {
@ -83,7 +83,7 @@ Instead of configuring SVGO from scratch, you can tweak the default preset to su
**`svgo.config.js`**
```js
module.exports = {
export default {
plugins: [
{
name: 'preset-default',
@ -112,9 +112,9 @@ You can also specify custom plugins:
**`svgo.config.js`**
```js
const importedPlugin = require('./imported-plugin');
import importedPlugin from './imported-plugin';
module.exports = {
export default {
plugins: [
// plugin imported from another JavaScript file
importedPlugin,
@ -140,7 +140,7 @@ SVGO provides a few low level utilities.
The core of SVGO is `optimize` function.
```js
const { optimize } = require('svgo');
import { optimize } from 'svgo';
const result = optimize(svgString, {
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.
```js
const { loadConfig } = require('svgo');
import { loadConfig } from 'svgo';
const config = await loadConfig();
```

View File

@ -1,8 +1,8 @@
#!/usr/bin/env node
const colors = require('picocolors');
const { program } = require('commander');
const makeProgram = require('../lib/svgo/coa');
import colors from 'picocolors';
import { program } from 'commander';
import makeProgram from '../lib/svgo/coa.js';
makeProgram(program);
program.parseAsync(process.argv).catch((error) => {
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 = [
require('../plugins/preset-default.js'),
require('../plugins/addAttributesToSVGElement.js'),
require('../plugins/addClassesToSVGElement.js'),
require('../plugins/cleanupAttrs.js'),
require('../plugins/cleanupEnableBackground.js'),
require('../plugins/cleanupIds.js'),
require('../plugins/cleanupListOfValues.js'),
require('../plugins/cleanupNumericValues.js'),
require('../plugins/collapseGroups.js'),
require('../plugins/convertColors.js'),
require('../plugins/convertEllipseToCircle.js'),
require('../plugins/convertOneStopGradients.js'),
require('../plugins/convertPathData.js'),
require('../plugins/convertShapeToPath.js'),
require('../plugins/convertStyleToAttrs.js'),
require('../plugins/convertTransform.js'),
require('../plugins/mergeStyles.js'),
require('../plugins/inlineStyles.js'),
require('../plugins/mergePaths.js'),
require('../plugins/minifyStyles.js'),
require('../plugins/moveElemsAttrsToGroup.js'),
require('../plugins/moveGroupAttrsToElems.js'),
require('../plugins/prefixIds.js'),
require('../plugins/removeAttributesBySelector.js'),
require('../plugins/removeAttrs.js'),
require('../plugins/removeComments.js'),
require('../plugins/removeDesc.js'),
require('../plugins/removeDimensions.js'),
require('../plugins/removeDoctype.js'),
require('../plugins/removeEditorsNSData.js'),
require('../plugins/removeElementsByAttr.js'),
require('../plugins/removeEmptyAttrs.js'),
require('../plugins/removeEmptyContainers.js'),
require('../plugins/removeEmptyText.js'),
require('../plugins/removeHiddenElems.js'),
require('../plugins/removeMetadata.js'),
require('../plugins/removeNonInheritableGroupAttrs.js'),
require('../plugins/removeOffCanvasPaths.js'),
require('../plugins/removeRasterImages.js'),
require('../plugins/removeScriptElement.js'),
require('../plugins/removeStyleElement.js'),
require('../plugins/removeTitle.js'),
require('../plugins/removeUnknownsAndDefaults.js'),
require('../plugins/removeUnusedNS.js'),
require('../plugins/removeUselessDefs.js'),
require('../plugins/removeUselessStrokeAndFill.js'),
require('../plugins/removeViewBox.js'),
require('../plugins/removeXlink.js'),
require('../plugins/removeXMLNS.js'),
require('../plugins/removeXMLProcInst.js'),
require('../plugins/reusePaths.js'),
require('../plugins/sortAttrs.js'),
require('../plugins/sortDefsChildren.js'),
export const builtin = [
presetDefault,
addAttributesToSVGElement,
addClassesToSVGElement,
cleanupAttrs,
cleanupEnableBackground,
cleanupIds,
cleanupListOfValues,
cleanupNumericValues,
collapseGroups,
convertColors,
convertEllipseToCircle,
convertOneStopGradients,
convertPathData,
convertShapeToPath,
convertStyleToAttrs,
convertTransform,
mergeStyles,
inlineStyles,
mergePaths,
minifyStyles,
moveElemsAttrsToGroup,
moveGroupAttrsToElems,
prefixIds,
removeAttributesBySelector,
removeAttrs,
removeComments,
removeDesc,
removeDimensions,
removeDoctype,
removeEditorsNSData,
removeElementsByAttr,
removeEmptyAttrs,
removeEmptyContainers,
removeEmptyText,
removeHiddenElems,
removeMetadata,
removeNonInheritableGroupAttrs,
removeOffCanvasPaths,
removeRasterImages,
removeScriptElement,
removeStyleElement,
removeTitle,
removeUnknownsAndDefaults,
removeUnusedNS,
removeUselessDefs,
removeUselessStrokeAndFill,
removeViewBox,
removeXlink,
removeXMLNS,
removeXMLProcInst,
reusePaths,
sortAttrs,
sortDefsChildren,
];

View File

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

View File

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

View File

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

View File

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

View File

@ -1,24 +1,15 @@
'use strict';
const os = require('os');
const fs = require('fs');
const { pathToFileURL } = require('url');
const path = require('path');
const { optimize: optimizeAgnostic } = require('./svgo.js');
import os from 'os';
import fs from 'fs';
import { pathToFileURL } from 'url';
import path from 'path';
import { optimize as optimizeAgnostic } from './svgo.js';
const importConfig = async (configFile) => {
let config;
// at the moment dynamic import may randomly fail with segfault
// to workaround this for some users .cjs extension is loaded
// exclusively with require
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;
}
// dynamic import expects file url instead of path and may fail
// when windows path is provided
const imported = await import(pathToFileURL(configFile));
const config = imported.default;
if (config == null || typeof config !== 'object' || Array.isArray(config)) {
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 (path.isAbsolute(configFile)) {
return await importConfig(configFile);
@ -64,9 +55,8 @@ const loadConfig = async (configFile, cwd = process.cwd()) => {
dir = parent;
}
};
exports.loadConfig = loadConfig;
const optimize = (input, config) => {
export const optimize = (input, config) => {
if (config == null) {
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 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 {
BuiltinsWithOptionalParams,
BuiltinsWithRequiredParams,
} from '../plugins/plugins-types';
} from '../plugins/plugins-types.js';
type CustomPlugin = {
name: string;
fn: PluginFn<void>;
fn: Plugin<void>;
};
type PluginConfig =

View File

@ -1,10 +1,8 @@
'use strict';
const { parseSvg } = require('./parser.js');
const { stringifySvg } = require('./stringifier.js');
const { builtin } = require('./builtin.js');
const { invokePlugins } = require('./svgo/plugins.js');
const { encodeSVGDatauri } = require('./svgo/tools.js');
import { parseSvg } from './parser.js';
import { stringifySvg } from './stringifier.js';
import { builtin } from './builtin.js';
import { invokePlugins } from './svgo/plugins.js';
import { encodeSVGDatauri } from './svgo/tools.js';
const pluginsMap = {};
for (const plugin of builtin) {
@ -47,7 +45,7 @@ const resolvePluginConfig = (plugin) => {
return null;
};
const optimize = (input, config) => {
export const optimize = (input, config) => {
if (config == null) {
config = {};
}
@ -99,4 +97,3 @@ const optimize = (input, config) => {
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', () => {
const svg = `
<?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 path = require('path');
const colors = require('picocolors');
const { loadConfig, optimize } = require('../svgo-node.js');
const { builtin } = require('../builtin.js');
const PKG = require('../../package.json');
const { encodeSVGDatauri, decodeSVGDatauri } = require('./tools.js');
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const pkgPath = path.join(__dirname, '../../package.json');
const PKG = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
const regSVGFile = /\.svg$/i;
@ -15,7 +17,7 @@ const regSVGFile = /\.svg$/i;
*
* @param {string} path
*/
function checkIsDir(path) {
export function checkIsDir(path) {
try {
return fs.lstatSync(path).isDirectory();
} catch (e) {
@ -23,7 +25,7 @@ function checkIsDir(path) {
}
}
module.exports = function makeProgram(program) {
export default function makeProgram(program) {
program
.name(PKG.name)
.description(PKG.description, {
@ -77,7 +79,7 @@ module.exports = function makeProgram(program) {
// used by picocolors internally
.option('--no-color', 'Output plain text without color')
.action(action);
};
}
async function action(args, opts, command) {
var input = opts.input || args;
@ -524,5 +526,3 @@ function showAvailablePlugins() {
.join('\n');
console.log('Currently available plugins:\n' + list);
}
module.exports.checkIsDir = checkIsDir;

View File

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

View File

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

View File

@ -1,6 +1,4 @@
'use strict';
const { visit } = require('../xast.js');
import { visit } from '../xast.js';
/**
* Plugins engine.
@ -12,7 +10,13 @@ const { visit } = require('../xast.js');
* @param {Array} plugins plugins object from config
* @return {Object} output ast
*/
const invokePlugins = (ast, info, plugins, overrides, globalOverrides) => {
export const invokePlugins = (
ast,
info,
plugins,
overrides,
globalOverrides,
) => {
for (const plugin of plugins) {
const override = overrides?.[plugin.name];
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 {
name,
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').PathDataCommand} PathDataCommand
* @typedef {import('../types').DataUri} DataUri
* @typedef {import('../types.js').DataUri} DataUri
* @typedef {import('../types.js').PathDataCommand} PathDataCommand
* @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 regReferencesHref = /^#(.+?)$/;
@ -17,7 +15,7 @@ const regReferencesBegin = /(\w+)\.[a-zA-Z]/;
*
* @type {(str: string, type?: DataUri) => string}
*/
exports.encodeSVGDatauri = (str, type) => {
export const encodeSVGDatauri = (str, type) => {
var prefix = 'data:image/svg+xml';
if (!type || type === 'base64') {
// base64
@ -38,7 +36,7 @@ exports.encodeSVGDatauri = (str, type) => {
*
* @type {(str: string) => string}
*/
exports.decodeSVGDatauri = (str) => {
export const decodeSVGDatauri = (str) => {
var regexp = /data:image\/svg\+xml(;charset=[^;,]*)?(;base64)?,(.*)/;
var match = regexp.exec(str);
@ -76,7 +74,7 @@ exports.decodeSVGDatauri = (str) => {
*
* @type {(data: number[], params: CleanupOutDataParams, command?: PathDataCommand) => string}
*/
exports.cleanupOutData = (data, params, command) => {
export const cleanupOutData = (data, params, command) => {
let str = '';
let delimiter;
/**
@ -130,7 +128,7 @@ exports.cleanupOutData = (data, params, command) => {
* 0.5 → .5
* -0.5 → -.5
*/
const removeLeadingZero = (value) => {
export const removeLeadingZero = (value) => {
const strValue = value.toString();
if (0 < value && value < 1 && strValue.startsWith('0')) {
@ -143,7 +141,6 @@ const removeLeadingZero = (value) => {
return strValue;
};
exports.removeLeadingZero = removeLeadingZero;
/**
* 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.
* @returns {boolean} If the current node contains scripts.
*/
const hasScripts = (node) => {
export const hasScripts = (node) => {
if (node.name === 'script' && node.children.length !== 0) {
return true;
}
@ -180,7 +177,6 @@ const hasScripts = (node) => {
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
@ -192,17 +188,16 @@ exports.hasScripts = hasScripts;
* @param {string} body
* @returns {boolean} If the given string includes a URL reference.
*/
const includesUrlReference = (body) => {
export const includesUrlReference = (body) => {
return new RegExp(regReferencesUrl).test(body);
};
exports.includesUrlReference = includesUrlReference;
/**
* @param {string} attribute
* @param {string} value
* @returns {string[]}
*/
const findReferences = (attribute, value) => {
export const findReferences = (attribute, value) => {
const results = [];
if (referencesProps.has(attribute)) {
@ -228,7 +223,6 @@ const findReferences = (attribute, value) => {
return results.map((body) => decodeURI(body));
};
exports.findReferences = findReferences;
/**
* Does the same as {@link Number.toFixed} but without casting
@ -238,8 +232,7 @@ exports.findReferences = findReferences;
* @param {number} precision
* @returns {number}
*/
const toFixed = (num, precision) => {
export const toFixed = (num, precision) => {
const pow = 10 ** precision;
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').XastChild} XastChild
* @typedef {import('./types').XastParent} XastParent
* @typedef {import('./types').Visitor} Visitor
* @typedef {import('./types.js').XastNode} XastNode
* @typedef {import('./types.js').XastChild} XastChild
* @typedef {import('./types.js').XastParent} XastParent
* @typedef {import('./types.js').Visitor} Visitor
*/
const { selectAll, selectOne, is } = require('css-select');
const xastAdaptor = require('./svgo/css-select-adapter.js');
const cssSelectOptions = {
xmlMode: true,
adapter: xastAdaptor,
@ -18,34 +16,30 @@ const cssSelectOptions = {
/**
* @type {(node: XastNode, selector: string) => XastChild[]}
*/
const querySelectorAll = (node, selector) => {
export const querySelectorAll = (node, selector) => {
return selectAll(selector, node, cssSelectOptions);
};
exports.querySelectorAll = querySelectorAll;
/**
* @type {(node: XastNode, selector: string) => ?XastChild}
*/
const querySelector = (node, selector) => {
export const querySelector = (node, selector) => {
return selectOne(selector, node, cssSelectOptions);
};
exports.querySelector = querySelector;
/**
* @type {(node: XastChild, selector: string) => boolean}
*/
const matches = (node, selector) => {
export const matches = (node, selector) => {
return is(node, selector, cssSelectOptions);
};
exports.matches = matches;
const visitSkip = Symbol();
exports.visitSkip = visitSkip;
export const visitSkip = Symbol();
/**
* @type {(node: XastNode, visitor: Visitor, parentNode?: any) => void}
*/
const visit = (node, visitor, parentNode) => {
export const visit = (node, visitor, parentNode) => {
const callbacks = visitor[node.type];
if (callbacks && callbacks.enter) {
// @ts-ignore hard to infer
@ -74,14 +68,12 @@ const visit = (node, visitor, parentNode) => {
callbacks.exit(node, parentNode);
}
};
exports.visit = visit;
/**
* @param {XastChild} node
* @param {XastParent} parentNode
*/
const detachNodeFromParent = (node, parentNode) => {
export const detachNodeFromParent = (node, parentNode) => {
// avoid splice to not break for loops
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').XastElement} XastElement
* @typedef {import('./types.js').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}

View File

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

View File

@ -1,11 +1,9 @@
'use strict';
// https://www.w3.org/TR/SVG11/intro.html#Definitions
/**
* @type {Record<string, Set<string>>}
*/
exports.elemsGroups = {
export const elemsGroups = {
animation: new Set([
'animate',
'animateColor',
@ -107,19 +105,15 @@ exports.elemsGroups = {
*
* @see https://developer.mozilla.org/docs/Web/HTML/Element/pre
*/
exports.textElems = new Set([
...exports.elemsGroups.textContent,
'pre',
'title',
]);
export const textElems = new Set([...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>>}
* @see https://www.w3.org/TR/SVG11/intro.html#Definitions
*/
exports.attrsGroups = {
export const attrsGroups = {
animationAddition: new Set(['additive', 'accumulate']),
animationAttributeTarget: new Set(['attributeType', 'attributeName']),
animationEvent: new Set(['onbegin', 'onend', 'onrepeat', 'onload']),
@ -317,7 +311,7 @@ exports.attrsGroups = {
/**
* @type {Record<string, Record<string, string>>}
*/
exports.attrsGroupsDefaults = {
export const attrsGroupsDefaults = {
core: { 'xml:space': 'default' },
presentation: {
clip: 'auto',
@ -391,7 +385,7 @@ exports.attrsGroupsDefaults = {
* }>}
* @see https://www.w3.org/TR/SVG11/eltindex.html
*/
exports.elems = {
export const elems = {
a: {
attrsGroups: new Set([
'conditionalProcessing',
@ -1971,7 +1965,7 @@ exports.elems = {
};
// 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://inkscape.sourceforge.net/DTD/sodipodi-0.dtd',
'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
*/
exports.referencesProps = new Set([
export const referencesProps = new Set([
'clip-path',
'color-profile',
'fill',
@ -2015,7 +2009,7 @@ exports.referencesProps = new Set([
/**
* @see https://www.w3.org/TR/SVG11/propidx.html
*/
exports.inheritableAttrs = new Set([
export const inheritableAttrs = new Set([
'clip-rule',
'color-interpolation-filters',
'color-interpolation',
@ -2063,7 +2057,7 @@ exports.inheritableAttrs = new Set([
'writing-mode',
]);
exports.presentationNonInheritableGroupAttrs = new Set([
export const presentationNonInheritableGroupAttrs = new Set([
'clip-path',
'display',
'filter',
@ -2079,7 +2073,7 @@ exports.presentationNonInheritableGroupAttrs = new Set([
*
* @type {Record<string, string>}
*/
exports.colorsNames = {
export const colorsNames = {
aliceblue: '#f0f8ff',
antiquewhite: '#faebd7',
aqua: '#0ff',
@ -2233,7 +2227,7 @@ exports.colorsNames = {
/**
* @type {Record<string, string>}
*/
exports.colorsShortNames = {
export const colorsShortNames = {
'#f0ffff': 'azure',
'#f5f5dc': 'beige',
'#ffe4c4': 'bisque',
@ -2271,7 +2265,7 @@ exports.colorsShortNames = {
/**
* @see https://www.w3.org/TR/SVG11/single-page.html#types-DataTypeColor
*/
exports.colorsProps = new Set([
export const colorsProps = new Set([
'color',
'fill',
'flood-color',
@ -2281,7 +2275,7 @@ exports.colorsProps = new Set([
]);
/** @see https://developer.mozilla.org/docs/Web/CSS/Pseudo-classes */
exports.pseudoClasses = {
export const pseudoClasses = {
displayState: new Set(['fullscreen', 'modal', 'picture-in-picture']),
input: new Set([
'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').PathDataItem} PathDataItem
* @typedef {import('../lib/types.js').XastElement} XastElement
* @typedef {import('../lib/types.js').PathDataItem} PathDataItem
*/
const { parsePathData, stringifyPathData } = require('../lib/path.js');
/**
* @type {[number, number]}
*/
@ -17,7 +15,7 @@ var prevCtrlPoint;
*
* @type {(path: XastElement) => PathDataItem[]}
*/
const path2js = (path) => {
export const path2js = (path) => {
// @ts-ignore legacy
if (path.pathJS) return path.pathJS;
/**
@ -36,7 +34,6 @@ const path2js = (path) => {
path.pathJS = pathData;
return pathData;
};
exports.path2js = path2js;
/**
* Convert relative Path data to absolute.
@ -181,7 +178,7 @@ const convertRelativeToAbsolute = (data) => {
*
* @type {(path: XastElement, data: PathDataItem[], params: Js2PathParams) => void}
*/
exports.js2path = function (path, data, params) {
export const js2path = function (path, data, params) {
// @ts-ignore legacy
path.pathJS = data;
@ -226,7 +223,7 @@ function set(dest, source) {
*
* @type {(path1: PathDataItem[], path2: PathDataItem[]) => boolean}
*/
exports.intersects = function (path1, path2) {
export const intersects = function (path1, path2) {
// Collect points of every subpath.
const points1 = gatherPoints(convertRelativeToAbsolute(path1));
const points2 = gatherPoints(convertRelativeToAbsolute(path2));

View File

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

View File

@ -1,7 +1,5 @@
'use strict';
exports.name = 'addAttributesToSVGElement';
exports.description = 'adds attributes to an outer <svg> element';
export const name = 'addAttributesToSVGElement';
export const description = 'adds attributes to an outer <svg> element';
var ENOCLS = `Error in plugin "addAttributesToSVGElement": absent parameters.
It should have a list of "attributes" or one "attribute".
@ -47,9 +45,9 @@ plugins: [
*
* @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) {
console.error(ENOCLS);
return null;

View File

@ -1,7 +1,5 @@
'use strict';
exports.name = 'addClassesToSVGElement';
exports.description = 'adds classnames to an outer <svg> element';
export const name = 'addClassesToSVGElement';
export const description = 'adds classnames to an outer <svg> element';
var ENOCLS = `Error in plugin "addClassesToSVGElement": absent parameters.
It should have a list of classes in "classNames" or one "className".
@ -49,9 +47,9 @@ plugins: [
*
* @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 (
!(Array.isArray(params.classNames) && params.classNames.some(String)) &&
!params.className

View File

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

View File

@ -1,7 +1,5 @@
'use strict';
exports.name = 'cleanupAttrs';
exports.description =
export const name = 'cleanupAttrs';
export const description =
'cleanups attributes from newlines, trailing and repeating spaces';
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.
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'cleanupAttrs'>}
* @type {import('./plugins-types.js').Plugin<'cleanupAttrs'>}
*/
exports.fn = (root, params) => {
export const fn = (root, params) => {
const { newlines = true, trim = true, spaces = true } = params;
return {
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');
const { visit } = require('../lib/xast.js');
exports.name = 'cleanupEnableBackground';
exports.description =
export const name = 'cleanupEnableBackground';
export const description =
'remove or cleanup enable-background attribute when possible';
const regEnableBackground =
@ -19,9 +17,9 @@ const regEnableBackground =
* ⬇
* <svg width="100" height="50">
* @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;
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');
const { hasScripts, findReferences } = require('../lib/svgo/tools');
exports.name = 'cleanupIds';
exports.description = 'removes unused IDs and minifies used';
export const name = 'cleanupIds';
export const description = 'removes unused IDs and minifies used';
const generateIdChars = [
'a',
@ -121,9 +119,9 @@ const getIdString = (arr) => {
*
* @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 {
remove = 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');
exports.name = 'cleanupListOfValues';
exports.description = 'rounds list of values to the fixed precision';
export const name = 'cleanupListOfValues';
export const description = 'rounds list of values to the fixed precision';
const regNumericValues =
/^([-+]?\d*\.?\d+([eE][-+]?\d+)?)(px|pt|pc|mm|cm|m|in|ft|em|ex|%)?$/;
@ -32,9 +30,9 @@ const absoluteLengths = {
*
* @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 {
floatPrecision = 3,
leadingZero = true,

View File

@ -1,9 +1,7 @@
'use strict';
import { removeLeadingZero } from '../lib/svgo/tools.js';
const { removeLeadingZero } = require('../lib/svgo/tools');
exports.name = 'cleanupNumericValues';
exports.description =
export const name = 'cleanupNumericValues';
export const description =
'rounds numeric values to the fixed precision, removes default px units';
const regNumericValues =
@ -25,9 +23,9 @@ const absoluteLengths = {
*
* @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 {
floatPrecision = 3,
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');
exports.name = 'collapseGroups';
exports.description = 'collapses useless groups';
export const name = 'collapseGroups';
export const description = 'collapses useless groups';
/**
* @type {(node: XastNode, name: string) => boolean}
@ -49,9 +47,9 @@ const hasAnimatedAttr = (node, name) => {
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'collapseGroups'>}
* @type {import('./plugins-types.js').Plugin<'collapseGroups'>}
*/
exports.fn = () => {
export const fn = () => {
return {
element: {
exit: (node, parentNode) => {

View File

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

View File

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

View File

@ -1,31 +1,29 @@
'use strict';
/**
* @typedef {import('../lib/types').XastElement} XastElement
* @typedef {import('../lib/types').XastParent} XastParent
*/
const { attrsGroupsDefaults, colorsProps } = require('./_collections');
const {
import { attrsGroupsDefaults, colorsProps } from './_collections.js';
import {
detachNodeFromParent,
querySelectorAll,
querySelector,
} = require('../lib/xast');
const { computeStyle, collectStylesheet } = require('../lib/style');
} from '../lib/xast.js';
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.
*
* @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/radialGradient
*/
exports.fn = (root) => {
export const fn = (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');
const { visit } = require('../lib/xast.js');
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 =
export const name = 'convertPathData';
export const description =
'optimizes path data: writes in shorter form, applies transformations';
/** @type {(data: number[]) => number[]} */
@ -75,9 +73,9 @@ let arcTolerance;
*
* @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 {
// TODO convert to separate plugin in v3
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');
const { detachNodeFromParent } = require('../lib/xast.js');
exports.name = 'convertShapeToPath';
exports.description = 'converts basic shapes to more compact path form';
export const name = 'convertShapeToPath';
export const description = 'converts basic shapes to more compact path form';
const regNumber = /[-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?/g;
@ -21,9 +19,9 @@ const regNumber = /[-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?/g;
*
* @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;
return {

View File

@ -1,9 +1,7 @@
'use strict';
import { attrsGroups } from './_collections.js';
const { attrsGroups } = require('./_collections');
exports.name = 'convertStyleToAttrs';
exports.description = 'converts style to attributes';
export const name = 'convertStyleToAttrs';
export const description = 'converts style to attributes';
/**
* @type {(...args: string[]) => string}
@ -65,9 +63,9 @@ const regStripComments = new RegExp(
*
* @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;
return {
element: {

View File

@ -1,20 +1,19 @@
'use strict';
/**
* @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 {
import { cleanupOutData, toFixed } from '../lib/svgo/tools.js';
import {
transform2js,
transformsMultiply,
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,
@ -26,9 +25,9 @@ exports.description = 'collapses multiple transformations and optimizes it';
*
* @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 {
convertToShorts = true,
// degPrecision = 3, // transformPrecision (or matrix precision) - 2 by default

View File

@ -1,24 +1,20 @@
'use strict';
/**
* @typedef {import('../lib/types').XastElement} XastElement
* @typedef {import('../lib/types').XastParent} XastParent
*/
const csstree = require('css-tree');
const {
syntax: { specificity },
} = require('csso');
const {
import * as csstree from 'css-tree';
import { syntax } from 'csso';
import { attrsGroups, pseudoClasses } from './_collections.js';
import {
visitSkip,
querySelectorAll,
detachNodeFromParent,
} = require('../lib/xast.js');
const { compareSpecificity, includesAttrSelector } = require('../lib/style');
const { attrsGroups, pseudoClasses } = require('./_collections');
} from '../lib/xast.js';
import { compareSpecificity, includesAttrSelector } from '../lib/style.js';
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,
@ -38,10 +34,10 @@ const preservedPseudos = [
/**
* 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>
*/
exports.fn = (root, params) => {
export const fn = (root, params) => {
const {
onlyMatchedOnce = true,
removeMatchedSelectors = true,
@ -177,8 +173,8 @@ exports.fn = (root, params) => {
const sortedSelectors = selectors
.slice()
.sort((a, b) => {
const aSpecificity = specificity(a.item.data);
const bSpecificity = specificity(b.item.data);
const aSpecificity = syntax.specificity(a.item.data);
const bSpecificity = syntax.specificity(b.item.data);
return compareSpecificity(aSpecificity, bSpecificity);
})
.reverse();

View File

@ -1,25 +1,23 @@
'use strict';
/**
* @typedef {import("../lib/types").PathDataItem} PathDataItem
* @typedef {import('../lib/types').XastChild} XastChild
* @typedef {import('../lib/types').XastElement} XastElement
* @typedef {import("../lib/types.js").PathDataItem} PathDataItem
* @typedef {import('../lib/types.js').XastChild} XastChild
* @typedef {import('../lib/types.js').XastElement} XastElement
*/
const { collectStylesheet, computeStyle } = require('../lib/style.js');
const { path2js, js2path, intersects } = require('./_path.js');
import { collectStylesheet, computeStyle } from '../lib/style.js';
import { path2js, js2path, intersects } from './_path.js';
exports.name = 'mergePaths';
exports.description = 'merges multiple paths in one if possible';
export const name = 'mergePaths';
export const description = 'merges multiple paths in one if possible';
/**
* Merge multiple Paths into one.
*
* @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 {
force = false,
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').XastChild} XastChild
* @typedef {import('../lib/types.js').XastElement} XastElement
* @typedef {import('../lib/types.js').XastChild} XastChild
*/
const { visitSkip, detachNodeFromParent } = require('../lib/xast.js');
exports.name = 'mergeStyles';
exports.description = 'merge multiple style elements into one';
export const name = 'mergeStyles';
export const description = 'merge multiple style elements into one';
/**
* Merge multiple style elements into one.
*
* @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}
*/

View File

@ -1,24 +1,22 @@
'use strict';
/**
* @typedef {import('../lib/types').XastElement} XastElement
* @typedef {import('../lib/types').XastParent} XastParent
* @typedef {import('../lib/types.js').XastElement} XastElement
* @typedef {import('../lib/types.js').XastParent} XastParent
*/
const csso = require('csso');
const { detachNodeFromParent } = require('../lib/xast');
const { hasScripts } = require('../lib/svgo/tools');
import * as csso from 'csso';
import { detachNodeFromParent } from '../lib/xast.js';
import { hasScripts } from '../lib/svgo/tools.js';
exports.name = 'minifyStyles';
exports.description = 'minifies styles and removes unused styles';
export const name = 'minifyStyles';
export const description = 'minifies styles and removes unused styles';
/**
* Minifies styles (<style> element + style attribute) using CSSO.
*
* @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>} */
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');
const { inheritableAttrs, pathElems } = require('./_collections.js');
exports.name = 'moveElemsAttrsToGroup';
exports.description = 'Move common attributes of group children to the group';
export const name = 'moveElemsAttrsToGroup';
export const description =
'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
*
* @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
let deoptimizedWithStyles = false;
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');
const { includesUrlReference } = require('../lib/svgo/tools.js');
exports.name = 'moveGroupAttrsToElems';
exports.description = 'moves some group attributes to the content elements';
export const name = 'moveGroupAttrsToElems';
export const description =
'moves some group attributes to the content elements';
const pathElemsWithGroupsAndText = [...pathElems, 'g', 'text'];
@ -24,9 +23,9 @@ const pathElemsWithGroupsAndText = [...pathElems, 'g', 'text'];
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'moveGroupAttrsToElems'>}
* @type {import('./plugins-types.js').Plugin<'moveGroupAttrsToElems'>}
*/
exports.fn = () => {
export const fn = () => {
return {
element: {
enter: (node) => {

View File

@ -2,7 +2,7 @@ import type {
Plugin as PluginDef,
PluginInfo,
XastElement,
} from '../lib/types';
} from '../lib/types.js';
type DefaultPlugins = {
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').XastElement} XastElement
* @typedef {import('../lib/types.js').XastElement} XastElement
*/
const csstree = require('css-tree');
const { referencesProps } = require('./_collections.js');
exports.name = 'prefixIds';
exports.description = 'prefix IDs';
export const name = 'prefixIds';
export const description = 'prefix IDs';
/**
* extract basename from path
@ -118,9 +116,9 @@ const generatePrefix = (body, node, info, prefixGenerator, delim, history) => {
* Prefixes identifiers
*
* @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 {
delim = '__',
prefix,

View File

@ -1,42 +1,39 @@
'use strict';
const { createPreset } = require('../lib/svgo/plugins.js');
const removeDoctype = require('./removeDoctype.js');
const removeXMLProcInst = require('./removeXMLProcInst.js');
const removeComments = require('./removeComments.js');
const removeMetadata = require('./removeMetadata.js');
const removeEditorsNSData = require('./removeEditorsNSData.js');
const cleanupAttrs = require('./cleanupAttrs.js');
const mergeStyles = require('./mergeStyles.js');
const inlineStyles = require('./inlineStyles.js');
const minifyStyles = require('./minifyStyles.js');
const cleanupIds = require('./cleanupIds.js');
const removeUselessDefs = require('./removeUselessDefs.js');
const cleanupNumericValues = require('./cleanupNumericValues.js');
const convertColors = require('./convertColors.js');
const removeUnknownsAndDefaults = require('./removeUnknownsAndDefaults.js');
const removeNonInheritableGroupAttrs = require('./removeNonInheritableGroupAttrs.js');
const removeUselessStrokeAndFill = require('./removeUselessStrokeAndFill.js');
const removeViewBox = require('./removeViewBox.js');
const cleanupEnableBackground = require('./cleanupEnableBackground.js');
const removeHiddenElems = require('./removeHiddenElems.js');
const removeEmptyText = require('./removeEmptyText.js');
const convertShapeToPath = require('./convertShapeToPath.js');
const convertEllipseToCircle = require('./convertEllipseToCircle.js');
const moveElemsAttrsToGroup = require('./moveElemsAttrsToGroup.js');
const moveGroupAttrsToElems = require('./moveGroupAttrsToElems.js');
const collapseGroups = require('./collapseGroups.js');
const convertPathData = require('./convertPathData.js');
const convertTransform = require('./convertTransform.js');
const removeEmptyAttrs = require('./removeEmptyAttrs.js');
const removeEmptyContainers = require('./removeEmptyContainers.js');
const mergePaths = require('./mergePaths.js');
const removeUnusedNS = require('./removeUnusedNS.js');
const sortAttrs = require('./sortAttrs.js');
const sortDefsChildren = require('./sortDefsChildren.js');
const removeTitle = require('./removeTitle.js');
const removeDesc = require('./removeDesc.js');
import { createPreset } from '../lib/svgo/plugins.js';
import * as removeDoctype from './removeDoctype.js';
import * as removeXMLProcInst from './removeXMLProcInst.js';
import * as removeComments from './removeComments.js';
import * as removeMetadata from './removeMetadata.js';
import * as removeEditorsNSData from './removeEditorsNSData.js';
import * as cleanupAttrs from './cleanupAttrs.js';
import * as mergeStyles from './mergeStyles.js';
import * as inlineStyles from './inlineStyles.js';
import * as minifyStyles from './minifyStyles.js';
import * as cleanupIds from './cleanupIds.js';
import * as removeUselessDefs from './removeUselessDefs.js';
import * as cleanupNumericValues from './cleanupNumericValues.js';
import * as convertColors from './convertColors.js';
import * as removeUnknownsAndDefaults from './removeUnknownsAndDefaults.js';
import * as removeNonInheritableGroupAttrs from './removeNonInheritableGroupAttrs.js';
import * as removeUselessStrokeAndFill from './removeUselessStrokeAndFill.js';
import * as removeViewBox from './removeViewBox.js';
import * as cleanupEnableBackground from './cleanupEnableBackground.js';
import * as removeHiddenElems from './removeHiddenElems.js';
import * as removeEmptyText from './removeEmptyText.js';
import * as convertShapeToPath from './convertShapeToPath.js';
import * as convertEllipseToCircle from './convertEllipseToCircle.js';
import * as moveElemsAttrsToGroup from './moveElemsAttrsToGroup.js';
import * as moveGroupAttrsToElems from './moveGroupAttrsToElems.js';
import * as collapseGroups from './collapseGroups.js';
import * as convertPathData from './convertPathData.js';
import * as convertTransform from './convertTransform.js';
import * as removeEmptyAttrs from './removeEmptyAttrs.js';
import * as removeEmptyContainers from './removeEmptyContainers.js';
import * as mergePaths from './mergePaths.js';
import * as removeUnusedNS from './removeUnusedNS.js';
import * as sortAttrs from './sortAttrs.js';
import * as sortDefsChildren from './sortDefsChildren.js';
import * as removeTitle from './removeTitle.js';
import * as removeDesc from './removeDesc.js';
const presetDefault = createPreset({
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');
exports.name = 'removeAttributesBySelector';
exports.description =
export const name = 'removeAttributesBySelector';
export const description =
'removes attributes of elements that match a css selector';
/**
@ -73,9 +71,9 @@ exports.description =
*
* @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)
? params.selectors
: [params];

View File

@ -1,7 +1,5 @@
'use strict';
exports.name = 'removeAttrs';
exports.description = 'removes specified attributes';
export const name = 'removeAttrs';
export const description = 'removes specified attributes';
const DEFAULT_SEPARATOR = ':';
const ENOATTRS = `Warning: The plugin "removeAttrs" requires the "attrs" parameter.
@ -81,9 +79,9 @@ plugins: [
*
* @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') {
console.warn(ENOATTRS);
return null;

View File

@ -1,9 +1,7 @@
'use strict';
import { detachNodeFromParent } from '../lib/xast.js';
const { detachNodeFromParent } = require('../lib/xast.js');
exports.name = 'removeComments';
exports.description = 'removes comments';
export const name = 'removeComments';
export const description = 'removes comments';
/**
* If a comment matches one of the following patterns, it will be
@ -20,9 +18,9 @@ const DEFAULT_PRESERVE_PATTERNS = [/^!/];
*
* @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;
return {

View File

@ -1,9 +1,7 @@
'use strict';
import { detachNodeFromParent } from '../lib/xast.js';
const { detachNodeFromParent } = require('../lib/xast.js');
exports.name = 'removeDesc';
exports.description = 'removes <desc>';
export const name = 'removeDesc';
export const description = 'removes <desc>';
const standardDescs = /^(Created with|Created using)/;
@ -16,9 +14,9 @@ const standardDescs = /^(Created with|Created using)/;
*
* @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;
return {
element: {

View File

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

View File

@ -1,9 +1,7 @@
'use strict';
import { detachNodeFromParent } from '../lib/xast.js';
const { detachNodeFromParent } = require('../lib/xast.js');
exports.name = 'removeDoctype';
exports.description = 'removes doctype declaration';
export const name = 'removeDoctype';
export const description = 'removes doctype declaration';
/**
* Remove DOCTYPE declaration.
@ -27,9 +25,9 @@ exports.description = 'removes doctype declaration';
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeDoctype'>}
* @type {import('./plugins-types.js').Plugin<'removeDoctype'>}
*/
exports.fn = () => {
export const fn = () => {
return {
doctype: {
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');
const { editorNamespaces } = require('./_collections.js');
exports.name = 'removeEditorsNSData';
exports.description = 'removes editors namespaces, elements and attributes';
export const name = 'removeEditorsNSData';
export const description =
'removes 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
*
* @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];
if (Array.isArray(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');
exports.name = 'removeElementsByAttr';
exports.description =
export const name = 'removeElementsByAttr';
export const description =
'removes arbitrary elements by ID or className (disabled by default)';
/**
@ -37,9 +35,9 @@ exports.description =
*
* @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 =
params.id == null ? [] : Array.isArray(params.id) ? params.id : [params.id];
const classes =

View File

@ -1,18 +1,16 @@
'use strict';
import { attrsGroups } from './_collections.js';
const { attrsGroups } = require('./_collections.js');
exports.name = 'removeEmptyAttrs';
exports.description = 'removes empty attributes';
export const name = 'removeEmptyAttrs';
export const description = 'removes empty attributes';
/**
* Remove attributes with empty values.
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeEmptyAttrs'>}
* @type {import('./plugins-types.js').Plugin<'removeEmptyAttrs'>}
*/
exports.fn = () => {
export const fn = () => {
return {
element: {
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');
const { elemsGroups } = require('./_collections.js');
exports.name = 'removeEmptyContainers';
exports.description = 'removes empty container elements';
export const name = 'removeEmptyContainers';
export const description = 'removes empty container elements';
/**
* Remove empty containers.
@ -19,9 +17,9 @@ exports.description = 'removes empty container elements';
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeEmptyContainers'>}
* @type {import('./plugins-types.js').Plugin<'removeEmptyContainers'>}
*/
exports.fn = () => {
export const fn = () => {
return {
element: {
exit: (node, parentNode) => {

View File

@ -1,9 +1,7 @@
'use strict';
import { detachNodeFromParent } from '../lib/xast.js';
const { detachNodeFromParent } = require('../lib/xast.js');
exports.name = 'removeEmptyText';
exports.description = 'removes empty <text> elements';
export const name = 'removeEmptyText';
export const description = 'removes empty <text> elements';
/**
* Remove empty Text elements.
@ -22,9 +20,9 @@ exports.description = 'removes empty <text> elements';
*
* @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;
return {
element: {

View File

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

View File

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

View File

@ -1,13 +1,11 @@
'use strict';
const {
import {
inheritableAttrs,
attrsGroups,
presentationNonInheritableGroupAttrs,
} = require('./_collections');
} from './_collections.js';
exports.name = 'removeNonInheritableGroupAttrs';
exports.description =
export const name = 'removeNonInheritableGroupAttrs';
export const description =
'removes non-inheritable groups presentational attributes';
/**
@ -15,9 +13,9 @@ exports.description =
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeNonInheritableGroupAttrs'>}
* @type {import('./plugins-types.js').Plugin<'removeNonInheritableGroupAttrs'>}
*/
exports.fn = () => {
export const fn = () => {
return {
element: {
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');
const { parsePathData } = require('../lib/path.js');
const { intersects } = require('./_path.js');
import { visitSkip, detachNodeFromParent } from '../lib/xast.js';
import { parsePathData } from '../lib/path.js';
import { intersects } from './_path.js';
exports.name = 'removeOffCanvasPaths';
exports.description =
export const name = 'removeOffCanvasPaths';
export const description =
'removes elements that are drawn outside of the viewbox (disabled by default)';
/**
@ -17,9 +15,9 @@ exports.description =
*
* @author JoshyPHP
*
* @type {import('./plugins-types').Plugin<'removeOffCanvasPaths'>}
* @type {import('./plugins-types.js').Plugin<'removeOffCanvasPaths'>}
*/
exports.fn = () => {
export const fn = () => {
/**
* @type {?{
* top: number,

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,5 @@
'use strict';
exports.name = 'removeUnusedNS';
exports.description = 'removes unused namespaces declaration';
export const name = 'removeUnusedNS';
export const description = 'removes unused namespaces declaration';
/**
* Remove unused namespaces declaration from svg element
@ -9,9 +7,9 @@ exports.description = 'removes unused namespaces declaration';
*
* @author Kir Belevich
*
* @type {import('./plugins-types').Plugin<'removeUnusedNS'>}
* @type {import('./plugins-types.js').Plugin<'removeUnusedNS'>}
*/
exports.fn = () => {
export const fn = () => {
/**
* @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');
const { elemsGroups } = require('./_collections.js');
exports.name = 'removeUselessDefs';
exports.description = 'removes elements in <defs> without id';
export const name = 'removeUselessDefs';
export const description = 'removes elements in <defs> without id';
/**
* Removes content of defs and properties that aren't rendered directly without ids.
*
* @author Lev Solntsev
*
* @type {import('./plugins-types').Plugin<'removeUselessDefs'>}
* @type {import('./plugins-types.js').Plugin<'removeUselessDefs'>}
*/
exports.fn = () => {
export const fn = () => {
return {
element: {
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');
const { collectStylesheet, computeStyle } = require('../lib/style.js');
const { hasScripts } = require('../lib/svgo/tools.js');
const { elemsGroups } = require('./_collections.js');
exports.name = 'removeUselessStrokeAndFill';
exports.description = 'removes useless stroke and fill attributes';
export const name = 'removeUselessStrokeAndFill';
export const description = 'removes useless stroke and fill attributes';
/**
* Remove useless stroke and fill attrs.
*
* @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 {
stroke: removeStroke = true,
fill: removeFill = true,

View File

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

View File

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

View File

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

View File

@ -1,13 +1,11 @@
'use strict';
const { elems } = require('./_collections');
import { elems } from './_collections.js';
/**
* @typedef {import('../lib/types').XastElement} XastElement
* @typedef {import('../lib/types.js').XastElement} XastElement
*/
exports.name = 'removeXlink';
exports.description =
export const name = 'removeXlink';
export const description =
'remove xlink namespace and replaces attributes with the SVG 2 equivalent where applicable';
/** URI indicating the Xlink namespace. */
@ -58,10 +56,10 @@ const findPrefixedAttrs = (node, prefixes, attr) => {
*
* 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
*/
exports.fn = (_, params) => {
export const fn = (_, params) => {
const { includeLegacy } = params;
/**

View File

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

View File

@ -1,16 +1,14 @@
'use strict';
exports.name = 'sortAttrs';
exports.description = 'Sort element attributes for better compression';
export const name = 'sortAttrs';
export const description = 'Sort element attributes for better compression';
/**
* Sort element attributes for better compression
*
* @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 {
order = [
'id',

View File

@ -1,7 +1,5 @@
'use strict';
exports.name = 'sortDefsChildren';
exports.description = 'Sorts children of <defs> to improve compression';
export const name = 'sortDefsChildren';
export const description = 'Sorts children of <defs> 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
*
* @type {import('./plugins-types').Plugin<'sortDefsChildren'>}
* @type {import('./plugins-types.js').Plugin<'sortDefsChildren'>}
*/
exports.fn = () => {
export const fn = () => {
return {
element: {
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 commonjs from '@rollup/plugin-commonjs';
import { terser } from 'rollup-plugin-terser';
import terser from '@rollup/plugin-terser';
export default {
input: './lib/svgo.js',
output: {
file: './dist/svgo.browser.js',
format: 'esm',
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const pkgPath = path.join(__dirname, './package.json');
const PKG = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
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');
const fs = require('node:fs/promises');
const http = require('http');
const { chromium } = require('playwright');
import assert from 'assert';
import fs from 'node:fs/promises';
import http from 'http';
import { chromium } from 'playwright';
const fixture = `<svg xmlns="http://www.w3.org/2000/svg">
<g attr1="val1">

View File

@ -1,12 +1,13 @@
'use strict';
/**
* @typedef {import('child_process').ChildProcessWithoutNullStreams} ChildProcessWithoutNullStreams
*/
const fs = require('fs');
const path = require('path');
const { spawn } = require('child_process');
import fs from 'fs';
import path from 'path';
import { spawn } from 'child_process';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
/**
* @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 path = require('path');
const del = require('del');
const { Command } = require('commander');
const svgo = require('../../lib/svgo/coa.js');
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const svgFolderPath = path.resolve(__dirname, 'testSvg');
const svgFolderPathRecursively = path.resolve(__dirname, 'testSvgRecursively');
@ -15,8 +16,6 @@ const svgFiles = [
const tempFolder = 'temp';
const noop = () => {};
const { checkIsDir } = svgo;
function runProgram(args) {
const program = new Command();
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');
module.exports = {};
import 'unknown-module';
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 regFilename = /^(.*)\.(\d+)\.svg$/;
const { optimize } = require('../../lib/svgo.js');
const __dirname = PATH.dirname(fileURLToPath(import.meta.url));
describe('plugins tests', function () {
FS.readdirSync(__dirname).forEach(function (file) {
@ -41,7 +42,6 @@ describe('plugins tests', function () {
js2svg: { pretty: true },
});
lastResultData = result.data;
expect(result.error).not.toStrictEqual(expect.anything());
//FIXME: results.data has a '\n' at the end while it should not
expect(normalize(result.data)).toStrictEqual(should);
}

View File

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

View File

@ -1,6 +1,4 @@
'use strict';
const { optimize } = require('../../lib/svgo.js');
import { optimize } from '../../lib/svgo.js';
test('should extract prefix from path basename', () => {
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 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 __dirname = path.dirname(fileURLToPath(import.meta.url));
const pipeline = util.promisify(stream.pipeline);

View File

@ -1,18 +1,19 @@
'use strict';
/**
* @typedef {import('playwright').Page} Page
* @typedef {import('playwright').PageScreenshotOptions} PageScreenshotOptions
*/
const fs = require('node:fs/promises');
const http = require('http');
const os = require('os');
const path = require('path');
const pixelmatch = require('pixelmatch');
const { chromium } = require('playwright');
const { PNG } = require('pngjs');
const { optimize } = require('../lib/svgo.js');
import fs from 'node:fs/promises';
import http from 'http';
import os from 'os';
import path from 'path';
import pixelmatch from 'pixelmatch';
import { chromium } from 'playwright';
import { PNG } from 'pngjs';
import { fileURLToPath } from 'url';
import { optimize } from '../lib/svgo.js';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const width = 960;
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 PATH = require('path');
const { parseSvg } = require('../../lib/parser.js');
const __dirname = PATH.dirname(fileURLToPath(import.meta.url));
describe('svg2js', 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