Parsing declarative shadow DOM
parseFromString
does not play nicely with declarative shadow DOM. Let’s say you fetch a HTML document, grab some of its contents and inject it into the current page:
<div id="container"></div>
<script>
const container = document.getElementById('container');
fetch('stuff.html')
.then(response => response.text())
.then((html) => {
const parser = new DOMParser();
const fetcheddoc = parser.parseFromString(html, "text/html");
const main = fetcheddoc.getElementsByTagName('main')[0];
container.appendChild(main);
})
</script>
If the fetched HTML contains a <template>
element with a shadowrootmode
attribute, it will remain just a <template>
, rather than becoming shadow DOM.
parseHTMLUnsafe
is a new alternative to parseFromString
that will correctly instantiate shadow DOM from a template element.
const container = document.getElementById('container');
fetch('stuff.html')
.then(response => response.text())
.then((html) => {
const fetcheddoc = Document.parseHTMLUnsafe(html);
const main = fetcheddoc.getElementsByTagName('main')[0];
container.appendChild(main);
})
parseHTMLUnsafe
has been supported since Chrome and Edge 124, Safari 17.4 and Firefox 123.
If you are not using shadow DOM in your project, its still one less line of code. The HTML spec states:
“The design of
DOMParser
, as a class that needs to be constructed and then have itsparseFromString
method called, is an unfortunate historical artifact. If we were designing this functionality today it would be a standalone function. For parsing HTML, the modern alternative isDocument.parseHTMLUnsafe()
.”
The naming might put you off, but parseHTMLUnsafe
is no more “unsafe” than .parseFromString
. In the HTML specification, both methods display the same warning note:
“This method performs no sanitization to remove potentially-dangerous elements and attributes like script or event handler content attributes.”
Shadow DOM is the main reason this new function exists, but it can be adopted as a general replacement for .parseFromString
.