imagemin / imagemin-svgo

SVGO plugin for imagemin
MIT License
125 stars 28 forks source link

Incorrect SVGO prefix with prefixIds #41

Open johnkhughes opened 4 years ago

johnkhughes commented 4 years ago

I originally opened this issue on gulp-imagemin but was advised it should be opened here instead.

SVGO lets you set a prefix for id attributes with the prefixIds option. If this is option is set, the default prefix should be the SVG file name. However, when the option is set in gulp-imagemin, the prefix output in the SVG files is prefix. Here is the relevant part of the script I am using:

return gulp.src('./src/*.svg')
    .pipe(imagemin([
        imagemin.svgo({
            plugins: [
                {
                    prefixIds: {
                        prefix: true
                    }
                }
            ]
        })
    ]))
    .pipe(gulp.dest('./dist'));

My aim was to have the id attributes in each file have a unique prefix to avoid naming collisions when they are embedded in an HTML file. Is there any way to get the default, documented behaviour of SVGO to work here?

karthikbalajikb commented 3 years ago

@johnkhughes How did you overcome this ? Is it fixed ? Facing same issue

johnkhughes commented 3 years ago

The short answer is that I didn't overcome it and it isn't fixed. Right now, I am optimizing my images separately, outside of my gulp tasks. Sorry I can't be much more help.

karthikbalajikb commented 3 years ago

cool @johnkhughes . Actually I need id in my symbol tag while creating svg sprite so have used svgstore -o ${outputFileName} ${inputFilePath} -p ${SVG_ICON_PREFIX} --inline to overcome it . -p adds the prefix to the id generated by svgo

SethFalco commented 9 months ago

The issue is that the prefixIds can only use the filename as documented if a path was passed to SVGO through the options.

So to resolve this, either:

From what I can see from the documentation, these might not be viable, though.

If you're alright with not using the filename as the prefix, an alternative solution is to use the prefix parameter of Prefix IDs and pass a function.

A config like one of these should work for you, feel free to make the prefix longer to reduce risk of collisions:

const crypto = require('crypto');

const options = {
  plugins: [
    {
      name: "prefixIds",
      params: {
        delim: "",
        prefix: () => crypto.randomBytes(20).toString('hex').slice(0, 2)
      }
    }
  ]
};
const options = {
  plugins: [
    {
      name: "prefixIds",
      params: {
        delim: "",
        prefix: () => Math.floor(Math.random() * 99).toString()
      }
    }
  ]
};

More info: https://svgo.dev/docs/plugins/prefix-ids/#parameters