mgieseki / dvisvgm

A fast DVI, EPS, and PDF to SVG converter
https://dvisvgm.de
GNU General Public License v3.0
305 stars 33 forks source link

element id overlap #269

Open c-ding-math opened 4 months ago

c-ding-math commented 4 months ago

Consider the following two svg:

<svg>
    <defs>
        <g id="myCircle">
            <circle cx="50" cy="50" r="50"/>
        </g>
    </defs>
    <use xlink:href="#myCircle" x="200" y="200" style="fill:blue;"/>
</svg>

<svg>
    <defs>
        <g id="myCircle">
            <circle cx="25" cy="25" r="25"/>
        </g>
    </defs>
    <use xlink:href="#myCircle" x="200" y="200" style="fill:blue;"/>
</svg>

If we put them in one document, the second svg won't display correctly, because there are two g elements with the same id. Could you consider adding an option that allow people to add a prefix to the id attribute in a svg?

mgieseki commented 4 months ago

There's already a similar feature request (#234). It's on my list but not of very high priority because you can post-process the SVG files and replace the IDs with your own ones or just prefix them, e.g. with a short Python script or sed. A proper implementation in dvisvgm is not that easy and requires quite a few changes. So, I'm afraid, this won't be implemented in the next few releases.

jvsteiner commented 3 months ago

Understood, and will look for some alternate options, but just for the record, and to make sure I am following this issue, I will mention that I also have this issue.

jvsteiner commented 3 months ago

in case anyone is using typescript for this kind of thing, here is a function I have found to work:

addRandomPrefixToIds(svgStr: string) {
    function generateRandomPrefix() {
        let letters = "abcdefghijklmnopqrstuvwxyz";
        letters += letters.toUpperCase();
        let prefix = "";
        for (let i = 0; i < 4; i++) {
            prefix += letters[Math.floor(Math.random() * letters.length)];
        }
        return prefix;
    }

    // Generate a random 4-letter prefix
    const randomPrefix = generateRandomPrefix();

    // Replace the id substrings
    let updatedSvgStr = svgStr
        .toString()
        .replace(/xlink:href='#g/g, `xlink:href='#g${randomPrefix}`);

    updatedSvgStr = updatedSvgStr
        .toString()
        .replace(/<path id='g/g, `<path id='g${randomPrefix}`);

    return updatedSvgStr;
}