Reputation: 9858
When I include a non-breaking space (character encoded as \u00A0
) in an SVG text
element, it works fine on a HTML page, but the resulting SVG contains an
character and is therefore not valid as an SVG file. For example, if I save the SVG to a file (using a function like this) and open that file in Chrome, it reports an error "Entity 'nbsp' not defined" and does not display the text.
const NS = { SVG: "http://www.w3.org/2000/svg" };
const svg = document.createElementNS(NS.SVG, 'svg');
const text = document.createElementNS(NS.SVG, "text");
text.setAttribute("y", 20);
const s = "Non-breaking> <space"; // the space here is a non-breaking one
text.appendChild(document.createTextNode(s));
svg.appendChild(text);
document.body.appendChild(svg);
console.log(svg.outerHTML);
I can easily replace the problematic character with s.replace("\u00A0", " ")
. But is there a more general way of sanitizing text going into an SVG to ensure it is valid and replacing the non-valid characters?
Upvotes: 0
Views: 620
Reputation: 10221
Since svg recognizes only 5 html entities: &
, "
, '
, <
, and >
, we can filter out the rest:
const NS = { SVG: "http://www.w3.org/2000/svg" };
const svg = document.createElementNS(NS.SVG, 'svg');
const text = document.createElementNS(NS.SVG, "text");
text.setAttribute("y", 20);
const s = "Non-breaking> <space & other\r\u0009characters"; // the space here is a non-breaking one
text.appendChild(document.createTextNode(s));
svg.appendChild(text);
document.body.appendChild(svg);
console.log(svg.outerHTML);
saveSvg(svg, "test")
function saveSvg(svgEl, name) {
svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
const dummy = document.createElement("div");
/* find all html entities and replace them with real value */
var svgData = svgEl.outerHTML.replace(/(&(?!(amp|gt|lt|quot|apos))[^;]+;)/g, a =>
{
dummy.innerHTML = a;
return dummy.textContent;
});
var preface = '<?xml version="1.0" standalone="no"?>\r\n';
var svgBlob = new Blob([preface, svgData], {type:"image/svg+xml;charset=utf-8"});
var svgUrl = URL.createObjectURL(svgBlob);
var downloadLink = document.createElement("a");
downloadLink.href = svgUrl;
downloadLink.download = name;
downloadLink.textContent = "download";
document.body.appendChild(downloadLink);
downloadLink.click();
// document.body.removeChild(downloadLink);
}
Upvotes: 2