mirror of
https://github.com/svg/svgo.git
synced 2025-04-19 10:22:15 +03:00
Fixes a bug where we were too eager to remove empty containers. We already had logic to skip removing empty containers if it had the filter attribute, which is needed to apply a filter to the whole area. However, the filter can also be defined through CSS. We did not properly handle this case, and treated the node as if it had no filter at all. This computes the styles and checks the stylesheet as well. (We also move the logic down to avoid computing the styles eagerly.)
68 lines
1.7 KiB
JavaScript
68 lines
1.7 KiB
JavaScript
import { elemsGroups } from './_collections.js';
|
|
import { detachNodeFromParent } from '../lib/xast.js';
|
|
import { collectStylesheet, computeStyle } from '../lib/style.js';
|
|
|
|
export const name = 'removeEmptyContainers';
|
|
export const description = 'removes empty container elements';
|
|
|
|
/**
|
|
* Remove empty containers.
|
|
*
|
|
* @see https://www.w3.org/TR/SVG11/intro.html#TermContainerElement
|
|
*
|
|
* @example
|
|
* <defs/>
|
|
*
|
|
* @example
|
|
* <g><marker><a/></marker></g>
|
|
*
|
|
* @author Kir Belevich
|
|
*
|
|
* @type {import('./plugins-types.js').Plugin<'removeEmptyContainers'>}
|
|
*/
|
|
export const fn = (root) => {
|
|
const stylesheet = collectStylesheet(root);
|
|
|
|
return {
|
|
element: {
|
|
exit: (node, parentNode) => {
|
|
// remove only empty non-svg containers
|
|
if (
|
|
node.name === 'svg' ||
|
|
!elemsGroups.container.has(node.name) ||
|
|
node.children.length !== 0
|
|
) {
|
|
return;
|
|
}
|
|
// empty patterns may contain reusable configuration
|
|
if (
|
|
node.name === 'pattern' &&
|
|
Object.keys(node.attributes).length !== 0
|
|
) {
|
|
return;
|
|
}
|
|
|
|
// empty <mask> hides masked element
|
|
if (node.name === 'mask' && node.attributes.id != null) {
|
|
return;
|
|
}
|
|
if (parentNode.type === 'element' && parentNode.name === 'switch') {
|
|
return;
|
|
}
|
|
|
|
// The <g> may not have content, but the filter may cause a rectangle
|
|
// to be created and filled with pattern.
|
|
if (
|
|
node.name === 'g' &&
|
|
(node.attributes.filter != null ||
|
|
computeStyle(stylesheet, node).filter)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
detachNodeFromParent(node, parentNode);
|
|
},
|
|
},
|
|
};
|
|
};
|