"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const VoidElements_1 = __importDefault(require("../config/VoidElements"));
const UnnestableElements_1 = __importDefault(require("../config/UnnestableElements"));
const ChildLessElements_1 = __importDefault(require("../config/ChildLessElements"));
const he_1 = require("he");
const NamespaceURI_1 = __importDefault(require("../config/NamespaceURI"));
const PlainTextElements_1 = __importDefault(require("../config/PlainTextElements"));
const CONDITION_COMMENT_REGEXP = //gi;
const CONDITION_COMMENT_END_REGEXP = //gi;
const MARKUP_REGEXP = /<(\/?)([a-z][-.0-9_a-z]*)\s*([^<>]*?)(\/?)>/gi;
const COMMENT_REGEXP = /|<([!?])([^>]*)>/gi;
const DOCUMENT_TYPE_ATTRIBUTE_REGEXP = /"([^"]+)"/gm;
const ATTRIBUTE_REGEXP = /([^\s=]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|(\S+)))/gms;
/**
* XML parser.
*/
class XMLParser {
/**
* Parses XML/HTML and returns a root element.
*
* @param document Document.
* @param data HTML data.
* @param [evaluateScripts = false] Set to "true" to enable script execution.
* @returns Root element.
*/
static parse(document, data, evaluateScripts = false) {
const root = document.createDocumentFragment();
const stack = [root];
const markupRegexp = new RegExp(MARKUP_REGEXP, 'gi');
let parent = root;
let parentTagName = null;
let parentUnnestableTagName = null;
let lastTextIndex = 0;
let match;
if (data !== null && data !== undefined) {
data = String(data);
while ((match = markupRegexp.exec(data))) {
const tagName = match[2].toLowerCase();
const isStartTag = !match[1];
if (parent && match.index !== lastTextIndex) {
const text = data.substring(lastTextIndex, match.index);
if (parentTagName && PlainTextElements_1.default.includes(parentTagName)) {
parent.appendChild(document.createTextNode(text));
}
else {
let condCommMatch;
let condCommEndMatch;
const condCommRegexp = new RegExp(CONDITION_COMMENT_REGEXP, 'gi');
const condCommEndRegexp = new RegExp(CONDITION_COMMENT_END_REGEXP, 'gi');
// @Refer: https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/?redirectedfrom=MSDN
if (isStartTag &&
(condCommMatch = condCommRegexp.exec(text)) &&
condCommMatch[0] &&
(condCommEndMatch = condCommEndRegexp.exec(data.substring(markupRegexp.lastIndex))) &&
condCommEndMatch[0]) {
markupRegexp.lastIndex += condCommEndRegexp.lastIndex;
continue;
}
else {
this.appendTextAndCommentNodes(document, parent, text);
}
}
}
if (isStartTag) {
const namespaceURI = tagName === 'svg'
? NamespaceURI_1.default.svg
: parent.namespaceURI || NamespaceURI_1.default.html;
const newElement = document.createElementNS(namespaceURI, tagName);
// Scripts are not allowed to be executed when they are parsed using innerHTML, outerHTML, replaceWith() etc.
// However, they are allowed to be executed when document.write() is used.
// See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLScriptElement
if (tagName === 'script') {
newElement._evaluateScript = evaluateScripts;
}
// An assumption that the same rule should be applied for the HTMLLinkElement is made here.
if (tagName === 'link') {
newElement._evaluateCSS = evaluateScripts;
}
this.setAttributes(newElement, match[3]);
if (!match[4] && !VoidElements_1.default.includes(tagName)) {
// Some elements are not allowed to be nested (e.g. "" is not allowed.).
// Therefore we will auto-close the tag.
if (parentUnnestableTagName === tagName) {
stack.pop();
parent = parent.parentNode || root;
}
parent = parent.appendChild(newElement);
parentTagName = tagName;
parentUnnestableTagName = this.getUnnestableTagName(parent);
stack.push(parent);
}
else {
parent.appendChild(newElement);
}
lastTextIndex = markupRegexp.lastIndex;
// Tags which contain non-parsed content
// For example: