Closed donomron closed 6 years ago
I have the same situation with my svg sprite
I am also having this same issue.
I have the same problem.
Plus, different SVG files might actually already have ids with the same name.
Is there a way to generate a file hash based on the original file name or something to be prefixed to each linearGradient id?
For instance, the final SVG would have a bike symbol with something like bike-a
, bike-b
, etc as linearGradients ids. Or just a-a
, a-b
, and then b-a
, b-b
for the next symbol, and so on
I've made some code that fix this problem
...
.pipe(svgSprite({
mode: "symbols",
preview: {
symbols: './preview/symbols.html'
},
selector: "%f",
svg: {
symbols: 'symbols.svg'
},
transformData: function (data, config) {
data.svg.map(function(item) {
//change id attribute
item.data=item.data.replace(/id=\"([^\"]+)\"/gm, 'id="'+item.name+'-$1"');
//change id in fill attribute
item.data=item.data.replace(/fill=\"url\(\#([^\"]+)\)\"/gm, 'fill="url(#'+item.name+'-$1)"');
//change id in mask attribute
item.data=item.data.replace(/mask=\"url\(\#([^\"]+)\)\"/gm, 'mask="url(#'+item.name+'-$1)"');
//replace double id for the symbol tag
item.data=item.data.replace('id="'+item.name+'-'+item.name+'"', 'id="'+item.name+'"');
return item;
});
return data; // modify the data and return it
}
}))
...
I should have looked here first 🤦♂️ I just coded the same regexes as Krill in one of my projects because of gradients. But I've also changed the symbols.svg template to have it extract all the "defs" into a single one outside of symbols because of that issue in Firefox https://stackoverflow.com/questions/12867704/svg-linear-gradient-does-not-work-in-firefox. Came to leave it here in case someone needs it :
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="0" height="0" style="position:absolute">
<defs>
<% _.forEach(svg, function(svgItem, index) { %>
<% var defs = svgItem.data.match(/<defs.*?\/defs>/gi) || [] %>
<%= defs.join('').replace('<defs>', '').replace('</defs>', '') %>
<% }); %>
</defs>
<% _.forEach(svg, function(svgItem) { %>
<symbol id="<%= svgItem.name %>" viewBox="<%= svgItem.viewBox %>">
<%= svgItem.data.replace(/<svg.*?>(.*?)<\/svg>/, "$1") %>
</symbol>
<% }); %>
</svg>
Btw, this seems to be a svgo problem coming from the options passed here in svg-sprite-data : https://github.com/shakyShane/svg-sprite-data/blob/master/lib/svg-sprite.js (cleanupIDs). The problem would be easily fixable if svgo was run after the combining strings / files since it already smartly manages duplicate and url referencing ids. I think changing the order of the waterfall here would do it : https://github.com/shakyShane/svg-sprite-data/blob/b73293731d3aa8866dcc50081def6629b9c741be/lib/svg-sprite.js#L378
@kirill-talk 's answer is what worked best for us too. However, it was lacking one more replace for us, for "filter" which also got a url(#a). I'm attaching the entire transformData @kirill-talk posted, modified w/ two more lines for clarity sake.
transformData: function (data) {
data.svg.map(function(item) {
//change id attribute
item.data=item.data.replace(/id=\"([^\"]+)\"/gm, 'id="'+item.name+'-$1"');
//change id in fill attribute
item.data=item.data.replace(/fill=\"url\(\#([^\"]+)\)\"/gm, 'fill="url(#'+item.name+'-$1)"');
//change id in filter attribute
item.data=item.data.replace(/filter=\"url\(\#([^\"]+)\)\"/gm, 'filter="url(#'+item.name+')"');
//change id in mask attribute
item.data=item.data.replace(/mask=\"url\(\#([^\"]+)\)\"/gm, 'mask="url(#'+item.name+'-$1)"');
//replace double id for the symbol tag
item.data=item.data.replace('id="'+item.name+'-'+item.name+'"', 'id="'+item.name+'"');
return item;
});
return data;
}
@kirill-talk sorry for my late response. this solves the problem
I'm closing this issue as @kirill-talk and @idmistir solutions worked for me.
Consider two icons with linear gradient and each gradient having its own unique id. for example:
and second icon:
When sprite.svg is generated using
symbol
mode, these unique ids are replaced witha
,b
,c
, .... and since this auto generating id names is reset in each file, we might face a sprite.svg file with more than one id name corresponding to a gradient. Is there any way to stop generating these ids automatically and use the ones which are in original svg files?