Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Randomize SVG def element id's</title>
<style>
.container {
display:grid;
width:100%;
grid-template-columns: 50% 50%;
height:100vh;
}
textarea {
height:100%;
}
</style>
</head>
<body>
<div class="container">
<textarea placeholder="Paste the SVG code here. <def> element id attributes will be randomized" name="svgin" id="svgin" cols="30" rows="10"></textarea>
<textarea name="svgout" id="svgout" cols="30" rows="10"></textarea>
</div>
<script type="text/javascript">
window.document.addEventListener('DOMContentLoaded', ()=>{
console.log('ready')
var txtin = document.querySelector('#svgin');
var txtout = document.querySelector('#svgout');
txtin.addEventListener('change', (ev)=>{
const val = ev.target.value;
txtout.value = fix(val);
})
})
/**
Change def element ids to something unique to avoid
conflicts as multiple svgs can wrongly use the same def
elements
**/
function fix(svg) {
var parser = new DOMParser();
let strout = '';
var xmlDoc = parser.parseFromString(
svg,
"text/xml"
);
console.log(xmlDoc)
var iriElementsAndProperties = {
clipPath: ["clip-path"],
"color-profile": ["color-profile"],
cursor: ["cursor"],
filter: ["filter"],
linearGradient: ["fill", "stroke"],
marker: ["marker", "marker-start", "marker-mid", "marker-end"],
mask: ["mask"],
pattern: ["fill", "stroke"],
radialGradient: ["fill", "stroke"]
};
//Change definition ids and their usages
const elementDefs = xmlDoc.querySelectorAll("defs " + "[id]");
for (let i = 0; i < elementDefs.length; i++) {
let def = elementDefs[i];
let oldId = def.id
let newId = guid()
def.id = newId
//Update xlink:href="#text-3"
//This fiddle was useful: http://fiddle.jshell.net/eg43L/3/
const uses = xmlDoc.querySelectorAll(`[*|href="#${oldId}"]`)
Array.from(uses).forEach((use)=>{
console.log('use found')
//use.setAttribute("http://www.w3.org/1999/xlink", 'href', '#'+newId)
//use.setAttributeNS('xlink', 'href', '#'+newId)
use.setAttribute('xlink:href','#'+newId)
})
//Update attributes like: filter="url(#filter-4)"
Object.keys(iriElementsAndProperties).forEach((elem)=>{
let properties = iriElementsAndProperties[elem]
properties.forEach((prop)=>{
let referencingElements = xmlDoc.querySelectorAll(
"[" + prop + '*="' + oldId + '"]'
);
Array.from(referencingElements).forEach((refelem)=>{
refelem.setAttribute(prop, `url(#${newId})`)
})
})
})
}
return xmlDoc.documentElement.outerHTML;
}
function guid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.