I'm building a library, that interacts with template tags, and watches for new ones that might be added to the page using a MutationObserver.
<script>
const upgradeNewNodes = (mutationRecords) => {
mutationRecords.forEach((mutationRecord) => {
mutationRecord.addedNodes.forEach((newNode) => {
if (newNode.matches?.('template')) {
console.log([...newNode.content.childNodes].map(child => child.nodeName))
}
});
});
};
const observer = new MutationObserver(upgradeNewNodes);
observer.observe(document, { subtree: true, childList: true });
</script>
<template>
<span>Beginning</span>
<script>
console.log('foo')
</script>
<span>Ending</span>
</template>
However, when my mutation observer picks up this template tag, it only sees up to the script tag.
// [object NodeList] (4)
[#text,<span/>,#text,<script/>]
Codepen Link: https://codepen.io/JRJurman/pen/WNLEaqp?editors=1001
My current hypothesis is that the HTML parser is stopped when it hits the script tag.
In my actual library, I can only process the contents once, so adding another MutationObserver for the content in the template isn't really an option.
Is there a way to know when the template has completely loaded? Are there other ways that I can progressively catch template tags being added to the page (other than MutationObserver)?
One potential option here appears to be watching for nodes right after a template tag - these are almost always guaranteed to exist, because there are always TEXT nodes before, between, and after elements.
<script>
const upgradeNewNodes = (mutationRecords) => {
mutationRecords.forEach((mutationRecord) => {
mutationRecord.addedNodes.forEach((newNode) => {
// check if this node is after a template (if it is, process that template)
// this is almost always guaranteed to exist, and be a TEXT node
if (newNode.previousSibling?.matches?.('template')) {
console.log([...newNode.previousSibling.content.childNodes].map(child => child.nodeName))
}
});
});
};
const observer = new MutationObserver(upgradeNewNodes);
observer.observe(document, { subtree: true, childList: true });
</script>
<template>
<span>Beginning</span>
<script>
console.log('foo')
</script>
<span>Ending</span>
</template>
Results in:
// [object NodeList] (7)
[#text,<span/>,#text,<script/>,#text,<span/>,#text]
Codepen Link: https://codepen.io/JRJurman/pen/jOXLQmY?editors=1001