html-dom-parser
Version:
HTML to DOM parser.
122 lines (121 loc) • 4.28 kB
JavaScript
const require_utilities = require("./utilities.js");
//#region src/client/domparser.ts
const HTML = "html";
const HEAD = "head";
const BODY = "body";
const FIRST_TAG_REGEX = /<([a-zA-Z]+[0-9]?)/;
function getHTMLForInnerHTML(html, trustedTypePolicy) {
return trustedTypePolicy ? trustedTypePolicy.createHTML(html) : html;
}
/* v8 ignore start */
let parseFromDocument = (html, tagName, trustedTypePolicy) => {
throw new Error("This browser does not support `document.implementation.createHTMLDocument`");
};
let parseFromString = (html, tagName, trustedTypePolicy) => {
throw new Error("This browser does not support `DOMParser.prototype.parseFromString`");
};
const DOMParser = typeof window === "object" && window.DOMParser;
/**
* DOMParser (performance: slow).
*
* @see https://developer.mozilla.org/docs/Web/API/DOMParser#Parsing_an_SVG_or_HTML_document
*/
if (typeof DOMParser === "function") {
const domParser = new DOMParser();
const mimeType = "text/html";
/**
* Creates an HTML document using `DOMParser.parseFromString`.
*
* @param html - The HTML string.
* @param tagName - The element to render the HTML (with 'body' as fallback).
* @returns - Document.
*/
parseFromString = (html, tagName, trustedTypePolicy) => {
if (tagName) html = `<${tagName}>${html}</${tagName}>`;
return domParser.parseFromString(html, mimeType);
};
parseFromDocument = parseFromString;
}
/**
* DOMImplementation (performance: fair).
*
* @see https://developer.mozilla.org/docs/Web/API/DOMImplementation/createHTMLDocument
*/
if (typeof document === "object" && document.implementation) {
const htmlDocument = document.implementation.createHTMLDocument();
/**
* Use HTML document created by `document.implementation.createHTMLDocument`.
*
* @param html - The HTML string.
* @param tagName - The element to render the HTML (with 'body' as fallback).
* @returns - Document
*/
parseFromDocument = function(html, tagName, trustedTypePolicy) {
if (tagName) {
const element = htmlDocument.documentElement.querySelector(tagName);
if (element) element.innerHTML = getHTMLForInnerHTML(html, trustedTypePolicy);
return htmlDocument;
}
htmlDocument.documentElement.innerHTML = getHTMLForInnerHTML(html, trustedTypePolicy);
return htmlDocument;
};
}
/**
* Template (performance: fast).
*
* @see https://developer.mozilla.org/docs/Web/HTML/Element/template
*/
const template = typeof document === "object" && document.createElement("template");
let parseFromTemplate;
if (template && template.content)
/**
* Uses a template element (content fragment) to parse HTML.
*
* @param html - HTML string.
* @returns - Nodes.
*/
parseFromTemplate = (html, trustedTypePolicy) => {
template.innerHTML = getHTMLForInnerHTML(html, trustedTypePolicy);
return template.content.childNodes;
};
const createNodeList = () => document.createDocumentFragment().childNodes;
/* v8 ignore stop */
/**
* Parses HTML string to DOM nodes.
*
* @param html - HTML markup.
* @param trustedTypePolicy - Trusted Types policy.
* @returns - DOM nodes.
*/
function domparser(html, trustedTypePolicy) {
html = require_utilities.escapeSpecialCharacters(html);
const firstTagName = FIRST_TAG_REGEX.exec(html)?.[1]?.toLowerCase();
switch (firstTagName) {
case HTML: {
const doc = parseFromString(html);
if (!require_utilities.hasOpenTag(html, HEAD)) {
const element = doc.querySelector(HEAD);
element?.parentNode?.removeChild(element);
}
if (!require_utilities.hasOpenTag(html, BODY)) {
const element = doc.querySelector(BODY);
element?.parentNode?.removeChild(element);
}
return doc.querySelectorAll(HTML);
}
case HEAD:
case BODY: {
const elements = parseFromDocument(html, void 0, trustedTypePolicy).querySelectorAll(firstTagName);
/* v8 ignore next */
if (require_utilities.hasOpenTag(html, BODY) && require_utilities.hasOpenTag(html, HEAD)) return elements[0].parentNode?.childNodes ?? createNodeList();
return elements;
}
/* v8 ignore start */
default:
if (parseFromTemplate) return parseFromTemplate(html, trustedTypePolicy);
return parseFromDocument(html, BODY, trustedTypePolicy).querySelector(BODY)?.childNodes ?? createNodeList();
}
}
//#endregion
exports.default = domparser;
//# sourceMappingURL=domparser.js.map