diff --git a/lib/stringifier.js b/lib/stringifier.js index 712d62fbc..e50e723c5 100644 --- a/lib/stringifier.js +++ b/lib/stringifier.js @@ -33,9 +33,7 @@ const encodeEntity = (char) => { return entities[char]; }; -/** - * @type {Options} - */ +/** @type {Options} */ const defaults = { doctypeStart: '', @@ -58,16 +56,14 @@ const defaults = { indent: 4, regEntities: /[&'"<>]/g, regValEntities: /[&"<>]/g, - encodeEntity: encodeEntity, + encodeEntity, pretty: false, useShortTags: true, eol: 'lf', finalNewline: false, }; -/** - * @type {Record} - */ +/** @type {Record} */ const entities = { '&': '&', "'": ''', @@ -113,7 +109,7 @@ const stringifySvg = (data, userOptions = {}) => { config.textEnd += eol; } let svg = stringifyNode(data, config, state); - if (config.finalNewline && svg.length > 0 && svg[svg.length - 1] !== '\n') { + if (config.finalNewline && svg.length > 0 && !svg.endsWith('\n')) { svg += eol; } return svg; diff --git a/lib/svgo/tools.js b/lib/svgo/tools.js index 355c4b39e..22133d25d 100644 --- a/lib/svgo/tools.js +++ b/lib/svgo/tools.js @@ -176,3 +176,18 @@ 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 + * return true: + * + * * `url(#gradient001)` + * * `url('#gradient001')` + * + * @param {string} body + * @returns {boolean} If the given string includes a URL reference. + */ +const includesUrlReference = (body) => { + return /\burl\((["'])?#(.+?)\1\)/g.test(body); +}; +exports.includesUrlReference = includesUrlReference; diff --git a/plugins/applyTransforms.js b/plugins/applyTransforms.js index bf60ac89f..49388ba8e 100644 --- a/plugins/applyTransforms.js +++ b/plugins/applyTransforms.js @@ -12,7 +12,10 @@ const { transformArc, } = require('./_transforms.js'); const { path2js } = require('./_path.js'); -const { removeLeadingZero } = require('../lib/svgo/tools.js'); +const { + removeLeadingZero, + includesUrlReference, +} = require('../lib/svgo/tools.js'); const { referencesProps, attrsGroupsDefaults } = require('./_collections.js'); /** @@ -35,9 +38,6 @@ const applyTransforms = (root, params) => { return { element: { enter: (node) => { - const computedStyle = computeStyle(stylesheet, node); - - // used only for paths for now if (node.attributes.d == null) { return; } @@ -48,7 +48,7 @@ const applyTransforms = (root, params) => { } // if there are no 'stroke' attr and references to other objects such as - // gradiends or clip-path which are also subjects to transform. + // gradients or clip-path which are also subjects to transform. if ( node.attributes.transform == null || node.attributes.transform === '' || @@ -57,32 +57,41 @@ const applyTransforms = (root, params) => { node.attributes.style != null || Object.entries(node.attributes).some( ([name, value]) => - referencesProps.includes(name) && value.includes('url(') + referencesProps.includes(name) && includesUrlReference(value) ) ) { return; } + const computedStyle = computeStyle(stylesheet, node); + const transformStyle = computedStyle.transform; + + // Transform overridden in