-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enabling both cleanupIDs
and prefixIds
does not work as expected
#1406
Comments
My misunderstanding of needing unique IDJust curious but aren't you able to produce a unique ID, class or depending on context a selector that relies on more than just the svg element for querying (eg Last I knew, relying on IDs was generally frowned upon vs classes, be that for styling or targeting an element with JS. In some cases where users ask for this, I imagine you would still have the scenario of using the same SVG graphic multiple times but also wanting to isolate them for using JS or CSS to produce variations or different behaviour logic. I'm curious how that's resolved other than giving the
eg instead of If you're going to use a selector to modify the SVG via JS or styles via CSS, might as well use a better selector. I get that's not always an option though if you're distributing a large library of SVG files for third-parties and you want to minimize the upfront effort for those users. EDIT: Technically this works on SVGO v1, just not with your example which has a bug. Static plugin processing order was added in v2.1 and appears to have accidentally mixed the order up (v2.0 also changed plugin order earlier but I'm not sure if was an issue back then too): Lines 5 to 18 in 3d79f57
More info (original message while looking into the issue)Earlier NotesWhile I was able to reproduce this, it turned out to be with SVGO v1.x via SVGR. I identified the bug which was specific to The I'm not sure why the current processing order is like that. I noticed that with the mentioned v1.x bug fix that only made it to v2 did work as you'd expect with
-- Workarounds for the time beingWorkaroundsNote that you can specify a prefix in Lines 12 to 19 in 3d79f57
How useful that is to you depends on how you want to run SVGO, if using something like webpack you can pass the filename context in to adjust the config param for each asset processed. It only accepts a string, not a function like Alternatively in the meantime you should be able to do two passes using slightly different config each: Sidenote - Optimizing prefix sizeSidenote - Optimizing prefix sizeIn looking into this, I'm now better aware of the need for the unique ID regarding internal usage with defs. I had two instances of this MDN gradient example and noticed changing ones gradient colours affected the other when they're both used as separate inline SVG elements in an HTML document. When you're only interested in avoiding internal conflicts like that, rather than targeting those IDs via selectors for adjustments at runtime, you could potentially have shorter prefixes via a hash on the filename instead,
// DJB2a (XOR variant) is a simple hashing function, reduces input to 32-bits
// Same hashing algorithm as used by `styled-components`.
const SEED = 5381
function djb2a(str) {
let hash = SEED
for (let i = 0; i < str.length; i++) {
hash = (hash * 33) ^ str.charCodeAt(i)
}
// Cast to 32-bit uint
return hash >>> 0
}
// Converts string input to a 32-bit base36 string (0-9, a-z)
// '_' prefix to prevent invalid first chars for CSS class names
const getShortKey = (node, extra) => `_` + djb2a(extra.path).toString(36)
module.exports = {
datauri: 'unenc',
js2svg: {
indent: 2,
pretty: true,
},
plugins: [{
name: 'prefixIds',
params: {
prefix: getShortKey
}
}]
} Would be more optimal as a suffix (you'd still want a delimiter between the minified class/id though). Using it as a generator function for EDIT: DJB is pretty bad if it processes short string inputs, I found a very large amount of collisions for a charset of
That said it seems to fair well on larger string inputs or pure numbers. By contrast another well known simple hashing algorithm (not the fastest or best distribution either) is FNV1a-32, which is a 32-bit hash(there are variants for larger sizes) and it did not have any collisions at all with that same test input. const fnvOffset = 2166136261
function fnv1a32(str) {
let h = fnvOffset
for (let i = 0; i < str.length; i++) {
h ^= str.charCodeAt(i)
// JS number type is inaccurate at calculating 'h *= fnvPrime',
// Uses bit-shifts to accurately multiply the prime: '16777619'
h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24)
}
// Cast to 32-bit uint
return h >>> 0
} |
Should be fixed in https://github.com/svg/svgo/releases/tag/v2.6.0 |
Describe the bug
When attempting to optimize with both
cleanupIDs
andprefixIds
plugins enabled, I expect the IDs to be minified AND prefixed with the SVG filename. However, it instead only prefixes the IDs with the filename ifcleanupIDs.minify
is disabled.There are valid reasons why minifying the ID and then prefixing it with the filename are necessary, mainly when inlining multiple SVGs on the same page. Without unique prefixes, duplicate IDs will conflict with one another.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
Expected SVG should be as follows
Desktop (please complete the following information):
The text was updated successfully, but these errors were encountered: