summaryrefslogtreecommitdiff
path: root/node_modules/svgo/plugins/cleanupEnableBackground.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/svgo/plugins/cleanupEnableBackground.js')
-rw-r--r--node_modules/svgo/plugins/cleanupEnableBackground.js148
1 files changed, 120 insertions, 28 deletions
diff --git a/node_modules/svgo/plugins/cleanupEnableBackground.js b/node_modules/svgo/plugins/cleanupEnableBackground.js
index 80be32be..1d2690d8 100644
--- a/node_modules/svgo/plugins/cleanupEnableBackground.js
+++ b/node_modules/svgo/plugins/cleanupEnableBackground.js
@@ -1,30 +1,29 @@
'use strict';
+const csstree = require('css-tree');
const { visit } = require('../lib/xast.js');
exports.name = 'cleanupEnableBackground';
exports.description =
'remove or cleanup enable-background attribute when possible';
+const regEnableBackground =
+ /^new\s0\s0\s([-+]?\d*\.?\d+([eE][-+]?\d+)?)\s([-+]?\d*\.?\d+([eE][-+]?\d+)?)$/;
+
/**
* Remove or cleanup enable-background attr which coincides with a width/height box.
*
* @see https://www.w3.org/TR/SVG11/filters.html#EnableBackgroundProperty
- *
* @example
* <svg width="100" height="50" enable-background="new 0 0 100 50">
* ⬇
* <svg width="100" height="50">
- *
* @author Kir Belevich
- *
* @type {import('./plugins-types').Plugin<'cleanupEnableBackground'>}
*/
exports.fn = (root) => {
- const regEnableBackground =
- /^new\s0\s0\s([-+]?\d*\.?\d+([eE][-+]?\d+)?)\s([-+]?\d*\.?\d+([eE][-+]?\d+)?)$/;
-
let hasFilter = false;
+
visit(root, {
element: {
enter: (node) => {
@@ -38,36 +37,129 @@ exports.fn = (root) => {
return {
element: {
enter: (node) => {
- if (node.attributes['enable-background'] == null) {
+ /** @type {?csstree.CssNode} */
+ let newStyle = null;
+ /** @type {?csstree.ListItem<csstree.CssNode>} */
+ let enableBackgroundDeclaration = null;
+
+ if (node.attributes.style != null) {
+ newStyle = csstree.parse(node.attributes.style, {
+ context: 'declarationList',
+ });
+
+ if (newStyle.type === 'DeclarationList') {
+ /** @type {csstree.ListItem<csstree.CssNode>[]} */
+ const enableBackgroundDeclarations = [];
+
+ csstree.walk(newStyle, (node, nodeItem) => {
+ if (
+ node.type === 'Declaration' &&
+ node.property === 'enable-background'
+ ) {
+ enableBackgroundDeclarations.push(nodeItem);
+ enableBackgroundDeclaration = nodeItem;
+ }
+ });
+
+ for (let i = 0; i < enableBackgroundDeclarations.length - 1; i++) {
+ newStyle.children.remove(enableBackgroundDeclarations[i]);
+ }
+ }
+ }
+
+ if (!hasFilter) {
+ delete node.attributes['enable-background'];
+
+ if (newStyle?.type === 'DeclarationList') {
+ if (enableBackgroundDeclaration) {
+ newStyle.children.remove(enableBackgroundDeclaration);
+ }
+
+ if (newStyle.children.isEmpty) {
+ delete node.attributes.style;
+ } else {
+ node.attributes.style = csstree.generate(newStyle);
+ }
+ }
+
return;
}
- if (hasFilter) {
+
+ const hasDimensions =
+ node.attributes.width != null && node.attributes.height != null;
+
+ if (
+ (node.name === 'svg' ||
+ node.name === 'mask' ||
+ node.name === 'pattern') &&
+ hasDimensions
+ ) {
+ const attrValue = node.attributes['enable-background'];
+ const attrCleaned = cleanupValue(
+ attrValue,
+ node.name,
+ node.attributes.width,
+ node.attributes.height
+ );
+
+ if (attrCleaned) {
+ node.attributes['enable-background'] = attrCleaned;
+ } else {
+ delete node.attributes['enable-background'];
+ }
+
if (
- (node.name === 'svg' ||
- node.name === 'mask' ||
- node.name === 'pattern') &&
- node.attributes.width != null &&
- node.attributes.height != null
+ newStyle?.type === 'DeclarationList' &&
+ enableBackgroundDeclaration
) {
- const match =
- node.attributes['enable-background'].match(regEnableBackground);
- if (
- match != null &&
- node.attributes.width === match[1] &&
- node.attributes.height === match[3]
- ) {
- if (node.name === 'svg') {
- delete node.attributes['enable-background'];
- } else {
- node.attributes['enable-background'] = 'new';
- }
+ const styleValue = csstree.generate(
+ // @ts-ignore
+ enableBackgroundDeclaration.data.value
+ );
+ const styleCleaned = cleanupValue(
+ styleValue,
+ node.name,
+ node.attributes.width,
+ node.attributes.height
+ );
+
+ if (styleCleaned) {
+ // @ts-ignore
+ enableBackgroundDeclaration.data.value = {
+ type: 'Raw',
+ value: styleCleaned,
+ };
+ } else {
+ newStyle.children.remove(enableBackgroundDeclaration);
}
}
- } else {
- //we don't need 'enable-background' if we have no filters
- delete node.attributes['enable-background'];
+ }
+
+ if (newStyle?.type === 'DeclarationList') {
+ if (newStyle.children.isEmpty) {
+ delete node.attributes.style;
+ } else {
+ node.attributes.style = csstree.generate(newStyle);
+ }
}
},
},
};
};
+
+/**
+ * @param {string} value Value of a enable-background attribute or style declaration.
+ * @param {string} nodeName Name of the node the value was assigned to.
+ * @param {string} width Width of the node the value was assigned to.
+ * @param {string} height Height of the node the value was assigned to.
+ * @returns {string | undefined} Cleaned up value, or undefined if it's redundant.
+ */
+const cleanupValue = (value, nodeName, width, height) => {
+ const match = regEnableBackground.exec(value);
+
+ if (match != null && width === match[1] && height === match[3]) {
+ return nodeName === 'svg' ? undefined : 'new';
+ }
+
+ return value;
+};