svg / svgo

⚙️ Node.js tool for optimizing SVG files
https://svgo.dev/
MIT License
20.92k stars 1.38k forks source link

Option to generate unique IDs? #674

Closed pluma closed 7 years ago

pluma commented 7 years ago

This is a feature request.

There's a plugin for minifying IDs but this is basically useless when inlining SVGs in HTML because it is guaranteed to cause problems (i.e. when inlining at least two SVGs that contain IDs you're guaranteed to have a conflict on ID "a").

It would be very useful if SVGO allowed prefixing IDs with a configurable key. This would allow tooling like react-svg-loader to generate a unique prefix and pass it to SVGO to guarantee the IDs don't break when the SVGs are inlined.

A problem is that the IDs can be referenced with xlink:href attributes and url() values but this is already addressed by the cleanupIDs plugin.

ricardo-fnd commented 1 year ago

@maxarias-io did you managed to do it in the new svgo.config format? Wonder why this issue is closed, if this problem stills persist.

maxarias-io commented 1 year ago

@maxarias-io did you managed to do it in the new svgo.config format? Wonder why this issue is closed, if this problem stills persist.

I didn't. As a stop-gap I'm using https://github.com/shubhamjain/svg-loader

ricardo-fnd commented 1 year ago

Ok. thanks for your anwser. My solution was just change the svgs files names... The IDs are generated with the name of the file, so if you have unique file names, they dont conflit! 👍

lcallanan-instabase commented 1 year ago

In order to be deterministic without requiring an explicit config or relying on the file name, would it make any sense to: generate w/ default ids -> get file content hash -> use file hash as prefix & update id names in final output?

loick commented 1 year ago

Hi there, the last answers didn't work for me. However the svgo API is pretty flexible so it's easy to custom it on demand.

Example here: I wanted to add an id on my svg, to be able to use it when imported, so I did as follow (⚠️ maybe there is an easier way and official way, but couldn't find it):

/**
 * @type {import("svgo").Config}
 */
module.exports = {
  multipass: false,
  js2svg: {
    indent: 2,
    pretty: true,
  },
  plugins: [
    'preset-default',
    {
      name: 'createId',
      fn: ({ children }, _, info) => {
        const childAttributes = children[0].attributes
        const [fileName] = info.path.split('/').reverse()[0].split('.')

        childAttributes.id = fileName
      },
    },
  ],
}

If it can help.. :)

karlhorky commented 11 months ago

Since @SethFalco fixed some problems with prefixIds in svgo@3.0.3, there is now a simpler way of making sure that IDs are unique:

A simpler alternative which does not rely on any imports is a simple counter, can also confirm this works in our project:

let svgoPrefixIdsCount = 0;

/** @type {import('svgo').Config} */
const svgoConfig = {
  plugins: [
    'preset-default',

    // Avoid collisions with ids in other SVGs,
    // which was causing incorrect gradient directions
    // https://github.com/svg/svgo/issues/1746#issuecomment-1803600573
    //
    // Previously, this was a problem where unique ids
    // could not be generated since svgo@3
    // https://github.com/svg/svgo/issues/674
    // https://github.com/svg/svgo/issues/1746
    {
      name: 'prefixIds',
      params: {
        delim: '',
        prefix: () => svgoPrefixIdsCount++,
      },
    },
  ],
};

export default svgoConfig;

More discussion in https://github.com/svg/svgo/issues/1746