diff --git a/plugins/removeEmptyContainers.js b/plugins/removeEmptyContainers.js index cb4ce0c0f..907cb524a 100644 --- a/plugins/removeEmptyContainers.js +++ b/plugins/removeEmptyContainers.js @@ -1,5 +1,11 @@ import { elemsGroups } from './_collections.js'; import { detachNodeFromParent } from '../lib/xast.js'; +import { findReferences } from '../lib/svgo/tools.js'; + +/** + * @typedef {import('../lib/types.js').XastElement} XastElement + * @typedef {import('../lib/types.js').XastParent} XastParent + */ export const name = 'removeEmptyContainers'; export const description = 'removes empty container elements'; @@ -20,8 +26,30 @@ export const description = 'removes empty container elements'; * @type {import('./plugins-types.js').Plugin<'removeEmptyContainers'>} */ export const fn = () => { + const removedIds = new Set(); + /** + * @type {Map} + */ + const usesById = new Map(); + return { element: { + enter: (node, parentNode) => { + if (node.name === 'use') { + // Record uses so those referencing empty containers can be removed. + for (const [name, value] of Object.entries(node.attributes)) { + const ids = findReferences(name, value); + for (const id of ids) { + let references = usesById.get(id); + if (references === undefined) { + references = []; + usesById.set(id, references); + } + references.push({ node: node, parent: parentNode }); + } + } + } + }, exit: (node, parentNode) => { // remove only empty non-svg containers if ( @@ -50,7 +78,24 @@ export const fn = () => { if (parentNode.type === 'element' && parentNode.name === 'switch') { return; } + detachNodeFromParent(node, parentNode); + if (node.attributes.id) { + removedIds.add(node.attributes.id); + } + }, + }, + root: { + exit: () => { + // Remove any elements that referenced an empty container. + for (const id of removedIds) { + const uses = usesById.get(id); + if (uses) { + for (const use of uses) { + detachNodeFromParent(use.node, use.parent); + } + } + } }, }, }; diff --git a/test/plugins/removeEmptyContainers.07.svg.txt b/test/plugins/removeEmptyContainers.07.svg.txt new file mode 100644 index 000000000..9c1dc9adb --- /dev/null +++ b/test/plugins/removeEmptyContainers.07.svg.txt @@ -0,0 +1,31 @@ +If a container with an id attribute is removed, remove any s associated with the id. + +=== + + + + + + + + + + + + + + + + +@@@ + + + + + + + + + + +