From f07e9de0892b1294cf2eceeb4818247382619bf3 Mon Sep 17 00:00:00 2001 From: Seth Falco Date: Mon, 25 Sep 2023 19:04:06 +0100 Subject: [PATCH] fix: resolve regression test for removeHiddenElems (#1793) --- plugins/removeHiddenElems.js | 45 ++++++++++++++++++++++++++++++++++-- test/regression.js | 2 -- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/plugins/removeHiddenElems.js b/plugins/removeHiddenElems.js index 5c1a01355..1e6c8a1eb 100644 --- a/plugins/removeHiddenElems.js +++ b/plugins/removeHiddenElems.js @@ -1,5 +1,11 @@ 'use strict'; +/** + * @typedef {import('../lib/types').XastElement} XastElement + * @typedef {import('../lib/types').XastParent} XastParent + */ + +const { elemsGroups, referencesProps } = require('./_collections.js'); const { visit, visitSkip, @@ -9,6 +15,8 @@ const { const { collectStylesheet, computeStyle } = require('../lib/style.js'); const { parsePathData } = require('../lib/path.js'); +const nonRendering = elemsGroups.nonRendering; + exports.name = 'removeHiddenElems'; exports.description = 'removes hidden elements (zero sized, with absent attributes)'; @@ -50,11 +58,20 @@ exports.fn = (root, params) => { } = params; const stylesheet = collectStylesheet(root); + /** + * Skip non-rendered nodes initially, and only detach if they have no ID, or + * their ID is not referenced by another node. + * + * @type {Map} + */ + const nonRenderedNodes = new Map(); + visit(root, { element: { enter: (node, parentNode) => { - // transparent element inside clipPath still affect clipped elements - if (node.name === 'clipPath') { + // transparent non-rendering elements still apply where referenced + if (nonRendering.includes(node.name)) { + nonRenderedNodes.set(node, parentNode); return visitSkip; } const computedStyle = computeStyle(stylesheet, node); @@ -305,6 +322,30 @@ exports.fn = (root, params) => { return; } }, + + exit: (node, parentNode) => { + if (node.name !== 'svg' || parentNode.type !== 'root') { + return; + } + for (const [ + nonRenderedNode, + nonRenderedParent, + ] of nonRenderedNodes.entries()) { + if (nonRenderedNode.attributes.id == null) { + detachNodeFromParent(node, nonRenderedParent); + continue; + } + + const selector = referencesProps + .map((attr) => `[${attr}="url(#${nonRenderedNode.attributes.id})"]`) + .join(','); + + const element = querySelector(root, selector); + if (element == null) { + detachNodeFromParent(node, nonRenderedParent); + } + } + }, }, }; }; diff --git a/test/regression.js b/test/regression.js index 65fc3ba4e..e41c05ecb 100644 --- a/test/regression.js +++ b/test/regression.js @@ -28,8 +28,6 @@ const runTests = async ({ list }) => { if ( // hard to detect the end of animation name.startsWith('w3c-svg-11-test-suite/svg/animate-') || - // breaks because of optimisation despite of script - name === 'w3c-svg-11-test-suite/svg/interact-pointer-04-f.svg' || // messed gradients name === 'w3c-svg-11-test-suite/svg/pservers-grad-18-b.svg' || // animated filter