HTML entities like and & are tolerated in SVG when embedded directly in an HTML page. The same entities fail to render under the more strict constraints of a data URL. We demonstrate the problem and a workaround using a carefully constructed DOCTYPE declaration.
In the frame below we can view the results. The first example is the SVG embedded in HTML. Second example shows a broken image with the same SVG in a data URL. Third example shows a working image using our SVG, prefixed with the doctype and base64 encoded.
//wiki.dbbs.co/assets/pages/js-snippet-template/importjs.html HEIGHT 500
.
We begin with a simple SVG document with a <text> element containing HTML entities.
let svg = `<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 100"> <text x="0" y="75" transform="rotate(-20)">This & That</text> <circle fill="lightblue" cx="150" cy="50" r="30" /> </svg>` let result = document.createElement("div") result.innerHTML = svg
The and & expressions work fine when the SVG document is embedded within an HTML document. But they break when we try to create a Data URL.
let broken = document.createElement("img") broken.setAttribute("width", "100%") broken.setAttribute("height", "70px") broken.setAttribute("src",`data:image/svg+xml,${svg}`) result.appendChild(broken)
Declaring the entities in a DOCTYPE and encoding with base64 does what we want.
let entities = `<!ENTITY amp "&"> <!ENTITY nbsp " ">` let doctype = `<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [${entities}]>` let fixed = document.createElement("img") fixed.setAttribute("width", "100%") fixed.setAttribute( "src", `data:image/svg+xml;base64,${btoa(doctype+svg)}`) result.appendChild(fixed)
We export the markup for the interpreter in the frame.
export default result.innerHTML