summaryrefslogtreecommitdiff
path: root/node_modules/svgo/plugins/removeUselessStrokeAndFill.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/svgo/plugins/removeUselessStrokeAndFill.js')
-rw-r--r--node_modules/svgo/plugins/removeUselessStrokeAndFill.js138
1 files changed, 138 insertions, 0 deletions
diff --git a/node_modules/svgo/plugins/removeUselessStrokeAndFill.js b/node_modules/svgo/plugins/removeUselessStrokeAndFill.js
new file mode 100644
index 00000000..1dff61cc
--- /dev/null
+++ b/node_modules/svgo/plugins/removeUselessStrokeAndFill.js
@@ -0,0 +1,138 @@
+'use strict';
+
+const { visit, visitSkip, detachNodeFromParent } = require('../lib/xast.js');
+const { collectStylesheet, computeStyle } = require('../lib/style.js');
+const { elemsGroups } = require('./_collections.js');
+
+exports.name = 'removeUselessStrokeAndFill';
+exports.description = 'removes useless stroke and fill attributes';
+
+/**
+ * Remove useless stroke and fill attrs.
+ *
+ * @author Kir Belevich
+ *
+ * @type {import('./plugins-types').Plugin<'removeUselessStrokeAndFill'>}
+ */
+exports.fn = (root, params) => {
+ const {
+ stroke: removeStroke = true,
+ fill: removeFill = true,
+ removeNone = false,
+ } = params;
+
+ // style and script elements deoptimise this plugin
+ let hasStyleOrScript = false;
+ visit(root, {
+ element: {
+ enter: (node) => {
+ if (node.name === 'style' || node.name === 'script') {
+ hasStyleOrScript = true;
+ }
+ },
+ },
+ });
+ if (hasStyleOrScript) {
+ return null;
+ }
+
+ const stylesheet = collectStylesheet(root);
+
+ return {
+ element: {
+ enter: (node, parentNode) => {
+ // id attribute deoptimise the whole subtree
+ if (node.attributes.id != null) {
+ return visitSkip;
+ }
+ if (elemsGroups.shape.includes(node.name) == false) {
+ return;
+ }
+ const computedStyle = computeStyle(stylesheet, node);
+ const stroke = computedStyle.stroke;
+ const strokeOpacity = computedStyle['stroke-opacity'];
+ const strokeWidth = computedStyle['stroke-width'];
+ const markerEnd = computedStyle['marker-end'];
+ const fill = computedStyle.fill;
+ const fillOpacity = computedStyle['fill-opacity'];
+ const computedParentStyle =
+ parentNode.type === 'element'
+ ? computeStyle(stylesheet, parentNode)
+ : null;
+ const parentStroke =
+ computedParentStyle == null ? null : computedParentStyle.stroke;
+
+ // remove stroke*
+ if (removeStroke) {
+ if (
+ stroke == null ||
+ (stroke.type === 'static' && stroke.value == 'none') ||
+ (strokeOpacity != null &&
+ strokeOpacity.type === 'static' &&
+ strokeOpacity.value === '0') ||
+ (strokeWidth != null &&
+ strokeWidth.type === 'static' &&
+ strokeWidth.value === '0')
+ ) {
+ // stroke-width may affect the size of marker-end
+ // marker is not visible when stroke-width is 0
+ if (
+ (strokeWidth != null &&
+ strokeWidth.type === 'static' &&
+ strokeWidth.value === '0') ||
+ markerEnd == null
+ ) {
+ for (const name of Object.keys(node.attributes)) {
+ if (name.startsWith('stroke')) {
+ delete node.attributes[name];
+ }
+ }
+ // set explicit none to not inherit from parent
+ if (
+ parentStroke != null &&
+ parentStroke.type === 'static' &&
+ parentStroke.value !== 'none'
+ ) {
+ node.attributes.stroke = 'none';
+ }
+ }
+ }
+ }
+
+ // remove fill*
+ if (removeFill) {
+ if (
+ (fill != null && fill.type === 'static' && fill.value === 'none') ||
+ (fillOpacity != null &&
+ fillOpacity.type === 'static' &&
+ fillOpacity.value === '0')
+ ) {
+ for (const name of Object.keys(node.attributes)) {
+ if (name.startsWith('fill-')) {
+ delete node.attributes[name];
+ }
+ }
+ if (
+ fill == null ||
+ (fill.type === 'static' && fill.value !== 'none')
+ ) {
+ node.attributes.fill = 'none';
+ }
+ }
+ }
+
+ if (removeNone) {
+ if (
+ (stroke == null || node.attributes.stroke === 'none') &&
+ ((fill != null &&
+ fill.type === 'static' &&
+ fill.value === 'none') ||
+ node.attributes.fill === 'none')
+ ) {
+ detachNodeFromParent(node, parentNode);
+ }
+ }
+ },
+ },
+ };
+};