Skip to content

Instantly share code, notes, and snippets.

Last active March 8, 2022 05:27
Show Gist options
  • Save dgp1130/1283773eb5890fb3cf59005892231211 to your computer and use it in GitHub Desktop.
Save dgp1130/1283773eb5890fb3cf59005892231211 to your computer and use it in GitHub Desktop.
HTML Fragments
* Parse a network response as an HTML document fragment, then returns each
* top-level element.
export async function parseDomFragment(res) {
// Parse a fully rendered document fragment from the network response.
const html = await res.text();
const contentType = res.headers.get('Content-Type');
if (!contentType)
throw new Error('Response has no Content-Type.');
const simpleContentType = contentType.indexOf(';') === -1
? contentType
: contentType.slice(0, contentType.indexOf(';'));
// Parse the HTML, extract the top-level nodes, adopt them into the current
// document, and fix the `<script />` tags.
const parse = DOMParser.prototype.parseFromString;
const fragment = parse.apply(new DOMParser(), [
{ includeShadowRoots: true },
const adoptedNodes = Array.from(fragment.body.children).map((fragEl) => {
const el = document.adoptNode(fragEl);
return el;
// Wrap everything in a template so it can be cloned as necessary.
const template = document.createElement('template');
return template;
* Replace each `<script />` in the given element with a copy.
* `DOMParser.parseFromString()` disables `<script />` tags. Cloning and
* replacing each `<script />` tag means it will be loaded when attached to the
* active document.
* Also note that `<script />` tags should include `type="module"`, or else
* multiple DOM fragments with the same `<script src="..."></script>` will fetch
* and execute the resource multiple times on the same page. Module scripts have
* a cache so multiple tags of the same resource won't duplicate execution.
* @link
* @link
* @link
function replaceScripts(el) {
for (const oldScript of Array.from(el.querySelectorAll('script'))) {
const newScript = document.createElement('script');
for (const name of oldScript.getAttributeNames()) {
newScript.setAttribute(name, oldScript.getAttribute(name));
newScript.textContent = oldScript.textContent;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment