"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Parser = void 0; const index_js_1 = require("../tokenizer/index.js"); const open_element_stack_js_1 = require("./open-element-stack.js"); const formatting_element_list_js_1 = require("./formatting-element-list.js"); const default_js_1 = require("../tree-adapters/default.js"); const doctype = require("../common/doctype.js"); const foreignContent = require("../common/foreign-content.js"); const error_codes_js_1 = require("../common/error-codes.js"); const unicode = require("../common/unicode.js"); const html_js_1 = require("../common/html.js"); const token_js_1 = require("../common/token.js"); //Misc constants const HIDDEN_INPUT_TYPE = 'hidden'; //Adoption agency loops iteration count const AA_OUTER_LOOP_ITER = 8; const AA_INNER_LOOP_ITER = 3; //Insertion modes var InsertionMode; (function (InsertionMode) { InsertionMode[InsertionMode["INITIAL"] = 0] = "INITIAL"; InsertionMode[InsertionMode["BEFORE_HTML"] = 1] = "BEFORE_HTML"; InsertionMode[InsertionMode["BEFORE_HEAD"] = 2] = "BEFORE_HEAD"; InsertionMode[InsertionMode["IN_HEAD"] = 3] = "IN_HEAD"; InsertionMode[InsertionMode["IN_HEAD_NO_SCRIPT"] = 4] = "IN_HEAD_NO_SCRIPT"; InsertionMode[InsertionMode["AFTER_HEAD"] = 5] = "AFTER_HEAD"; InsertionMode[InsertionMode["IN_BODY"] = 6] = "IN_BODY"; InsertionMode[InsertionMode["TEXT"] = 7] = "TEXT"; InsertionMode[InsertionMode["IN_TABLE"] = 8] = "IN_TABLE"; InsertionMode[InsertionMode["IN_TABLE_TEXT"] = 9] = "IN_TABLE_TEXT"; InsertionMode[InsertionMode["IN_CAPTION"] = 10] = "IN_CAPTION"; InsertionMode[InsertionMode["IN_COLUMN_GROUP"] = 11] = "IN_COLUMN_GROUP"; InsertionMode[InsertionMode["IN_TABLE_BODY"] = 12] = "IN_TABLE_BODY"; InsertionMode[InsertionMode["IN_ROW"] = 13] = "IN_ROW"; InsertionMode[InsertionMode["IN_CELL"] = 14] = "IN_CELL"; InsertionMode[InsertionMode["IN_SELECT"] = 15] = "IN_SELECT"; InsertionMode[InsertionMode["IN_SELECT_IN_TABLE"] = 16] = "IN_SELECT_IN_TABLE"; InsertionMode[InsertionMode["IN_TEMPLATE"] = 17] = "IN_TEMPLATE"; InsertionMode[InsertionMode["AFTER_BODY"] = 18] = "AFTER_BODY"; InsertionMode[InsertionMode["IN_FRAMESET"] = 19] = "IN_FRAMESET"; InsertionMode[InsertionMode["AFTER_FRAMESET"] = 20] = "AFTER_FRAMESET"; InsertionMode[InsertionMode["AFTER_AFTER_BODY"] = 21] = "AFTER_AFTER_BODY"; InsertionMode[InsertionMode["AFTER_AFTER_FRAMESET"] = 22] = "AFTER_AFTER_FRAMESET"; })(InsertionMode || (InsertionMode = {})); const BASE_LOC = { startLine: -1, startCol: -1, startOffset: -1, endLine: -1, endCol: -1, endOffset: -1, }; const TABLE_STRUCTURE_TAGS = new Set([html_js_1.TAG_ID.TABLE, html_js_1.TAG_ID.TBODY, html_js_1.TAG_ID.TFOOT, html_js_1.TAG_ID.THEAD, html_js_1.TAG_ID.TR]); const defaultParserOptions = { scriptingEnabled: true, sourceCodeLocationInfo: false, treeAdapter: default_js_1.defaultTreeAdapter, onParseError: null, }; //Parser class Parser { constructor(options, document, fragmentContext = null, scriptHandler = null) { this.fragmentContext = fragmentContext; this.scriptHandler = scriptHandler; this.currentToken = null; this.stopped = false; this.insertionMode = InsertionMode.INITIAL; this.originalInsertionMode = InsertionMode.INITIAL; this.headElement = null; this.formElement = null; /** Indicates that the current node is not an element in the HTML namespace */ this.currentNotInHTML = false; /** * The template insertion mode stack is maintained from the left. * Ie. the topmost element will always have index 0. */ this.tmplInsertionModeStack = []; this.pendingCharacterTokens = []; this.hasNonWhitespacePendingCharacterToken = false; this.framesetOk = true; this.skipNextNewLine = false; this.fosterParentingEnabled = false; this.options = Object.assign(Object.assign({}, defaultParserOptions), options); this.treeAdapter = this.options.treeAdapter; this.onParseError = this.options.onParseError; // Always enable location info if we report parse errors. if (this.onParseError) { this.options.sourceCodeLocationInfo = true; } this.document = document !== null && document !== void 0 ? document : this.treeAdapter.createDocument(); this.tokenizer = new index_js_1.Tokenizer(this.options, this); this.activeFormattingElements = new formatting_element_list_js_1.FormattingElementList(this.treeAdapter); this.fragmentContextID = fragmentContext ? (0, html_js_1.getTagID)(this.treeAdapter.getTagName(fragmentContext)) : html_js_1.TAG_ID.UNKNOWN; this._setContextModes(fragmentContext !== null && fragmentContext !== void 0 ? fragmentContext : this.document, this.fragmentContextID); this.openElements = new open_element_stack_js_1.OpenElementStack(this.document, this.treeAdapter, this); } // API static parse(html, options) { const parser = new this(options); parser.tokenizer.write(html, true); return parser.document; } static getFragmentParser(fragmentContext, options) { const opts = Object.assign(Object.assign({}, defaultParserOptions), options); //NOTE: use a