svg/svgo

Multiple plugins make unsafe transformations in the presence of a style element.

johnkenny54 opened this issue · 0 comments

To Reproduce

Optimize the following using default SVGO settings:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -10 120 120">
    <style>
        g {transform:rotate(-15deg)}
        g + g {translate:30px 30px;opacity:.5}
        g rect {fill:red} path[d*="L"] {fill:green;opacity:.2}
        ellipse {fill:orange;opacity:.4}
        g + g rect {fill:blue}
        rect + rect {fill:yellow;transform:translate(10px,20px)}
    </style>
    <g>
        <rect x="10" y="20" width="30" height="40"/>
        <rect x="10" y="20" width="30" height="40"/>
        <g>
            <rect x="10" y="20" width="30" height="40"/>
        </g>
        <ellipse cx="10" cy="20" rx="10" ry="20" />
        <path d="M10 50h30v40H10 L10 50"/>
    </g>
    <g>
        <rect x="10" y="20" width="30" height="40"/>
        <rect x="10" y="20" width="30" height="40"/>
        <g>
            <rect x="10" y="20" width="30" height="40"/>
        </g>
        <ellipse cx="10" cy="20" rx="10" ry="20" />
        <path d="M10 50h30v40H10 L10 50"/>
    </g>
</svg>

Expected behavior

The input and output files look identical in a browser. In fact, the "optimized" SVG is:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -10 120 120">
    <style>
        g{transform:rotate(-15deg)}g rect{fill:red}path[d*=L]{fill:green;opacity:.2}ellipse{fill:orange;opacity:.4}g+g rect{fill:#00f}rect+rect{fill:#ff0;transform:translate(10px,20px)}
    </style>
    <path d="M10 20h30v40H10z"/>
    <path d="M10 20h30v40H10z"/>
    <path d="M10 20h30v40H10z"/>
    <ellipse cx="10" cy="20" rx="10" ry="20"/>
    <path d="M10 50h30v40H10z"/>
    <g style="translate:30px 30px;opacity:.5">
        <path d="M10 20h30v40H10z"/>
        <path d="M10 20h30v40H10z"/>
        <path d="M10 20h30v40H10z"/>
        <ellipse cx="10" cy="20" rx="10" ry="20"/>
        <path d="M10 50h30v40H10z"/>
    </g>
</svg>

This displays very differently from the original.

Additional context
In this case, the problem is with the collapseGroups, convertShapeToPath, and convertPathData plugins. Similar problems are likely present in any plugin that tries to change the SVG in the presence of style elements, particular those with complicated selectors.

SVGO 3.2