diff options
Diffstat (limited to 'includes/external/school/node_modules/parse5/lib/parser/index.js')
-rw-r--r-- | includes/external/school/node_modules/parse5/lib/parser/index.js | 2956 |
1 files changed, 0 insertions, 2956 deletions
diff --git a/includes/external/school/node_modules/parse5/lib/parser/index.js b/includes/external/school/node_modules/parse5/lib/parser/index.js deleted file mode 100644 index 45d3e83..0000000 --- a/includes/external/school/node_modules/parse5/lib/parser/index.js +++ /dev/null @@ -1,2956 +0,0 @@ -'use strict'; - -const Tokenizer = require('../tokenizer'); -const OpenElementStack = require('./open-element-stack'); -const FormattingElementList = require('./formatting-element-list'); -const LocationInfoParserMixin = require('../extensions/location-info/parser-mixin'); -const ErrorReportingParserMixin = require('../extensions/error-reporting/parser-mixin'); -const Mixin = require('../utils/mixin'); -const defaultTreeAdapter = require('../tree-adapters/default'); -const mergeOptions = require('../utils/merge-options'); -const doctype = require('../common/doctype'); -const foreignContent = require('../common/foreign-content'); -const ERR = require('../common/error-codes'); -const unicode = require('../common/unicode'); -const HTML = require('../common/html'); - -//Aliases -const $ = HTML.TAG_NAMES; -const NS = HTML.NAMESPACES; -const ATTRS = HTML.ATTRS; - -const DEFAULT_OPTIONS = { - scriptingEnabled: true, - sourceCodeLocationInfo: false, - onParseError: null, - treeAdapter: defaultTreeAdapter -}; - -//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 -const INITIAL_MODE = 'INITIAL_MODE'; -const BEFORE_HTML_MODE = 'BEFORE_HTML_MODE'; -const BEFORE_HEAD_MODE = 'BEFORE_HEAD_MODE'; -const IN_HEAD_MODE = 'IN_HEAD_MODE'; -const IN_HEAD_NO_SCRIPT_MODE = 'IN_HEAD_NO_SCRIPT_MODE'; -const AFTER_HEAD_MODE = 'AFTER_HEAD_MODE'; -const IN_BODY_MODE = 'IN_BODY_MODE'; -const TEXT_MODE = 'TEXT_MODE'; -const IN_TABLE_MODE = 'IN_TABLE_MODE'; -const IN_TABLE_TEXT_MODE = 'IN_TABLE_TEXT_MODE'; -const IN_CAPTION_MODE = 'IN_CAPTION_MODE'; -const IN_COLUMN_GROUP_MODE = 'IN_COLUMN_GROUP_MODE'; -const IN_TABLE_BODY_MODE = 'IN_TABLE_BODY_MODE'; -const IN_ROW_MODE = 'IN_ROW_MODE'; -const IN_CELL_MODE = 'IN_CELL_MODE'; -const IN_SELECT_MODE = 'IN_SELECT_MODE'; -const IN_SELECT_IN_TABLE_MODE = 'IN_SELECT_IN_TABLE_MODE'; -const IN_TEMPLATE_MODE = 'IN_TEMPLATE_MODE'; -const AFTER_BODY_MODE = 'AFTER_BODY_MODE'; -const IN_FRAMESET_MODE = 'IN_FRAMESET_MODE'; -const AFTER_FRAMESET_MODE = 'AFTER_FRAMESET_MODE'; -const AFTER_AFTER_BODY_MODE = 'AFTER_AFTER_BODY_MODE'; -const AFTER_AFTER_FRAMESET_MODE = 'AFTER_AFTER_FRAMESET_MODE'; - -//Insertion mode reset map -const INSERTION_MODE_RESET_MAP = { - [$.TR]: IN_ROW_MODE, - [$.TBODY]: IN_TABLE_BODY_MODE, - [$.THEAD]: IN_TABLE_BODY_MODE, - [$.TFOOT]: IN_TABLE_BODY_MODE, - [$.CAPTION]: IN_CAPTION_MODE, - [$.COLGROUP]: IN_COLUMN_GROUP_MODE, - [$.TABLE]: IN_TABLE_MODE, - [$.BODY]: IN_BODY_MODE, - [$.FRAMESET]: IN_FRAMESET_MODE -}; - -//Template insertion mode switch map -const TEMPLATE_INSERTION_MODE_SWITCH_MAP = { - [$.CAPTION]: IN_TABLE_MODE, - [$.COLGROUP]: IN_TABLE_MODE, - [$.TBODY]: IN_TABLE_MODE, - [$.TFOOT]: IN_TABLE_MODE, - [$.THEAD]: IN_TABLE_MODE, - [$.COL]: IN_COLUMN_GROUP_MODE, - [$.TR]: IN_TABLE_BODY_MODE, - [$.TD]: IN_ROW_MODE, - [$.TH]: IN_ROW_MODE -}; - -//Token handlers map for insertion modes -const TOKEN_HANDLERS = { - [INITIAL_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: tokenInInitialMode, - [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInInitialMode, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: doctypeInInitialMode, - [Tokenizer.START_TAG_TOKEN]: tokenInInitialMode, - [Tokenizer.END_TAG_TOKEN]: tokenInInitialMode, - [Tokenizer.EOF_TOKEN]: tokenInInitialMode - }, - [BEFORE_HTML_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: tokenBeforeHtml, - [Tokenizer.NULL_CHARACTER_TOKEN]: tokenBeforeHtml, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagBeforeHtml, - [Tokenizer.END_TAG_TOKEN]: endTagBeforeHtml, - [Tokenizer.EOF_TOKEN]: tokenBeforeHtml - }, - [BEFORE_HEAD_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: tokenBeforeHead, - [Tokenizer.NULL_CHARACTER_TOKEN]: tokenBeforeHead, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype, - [Tokenizer.START_TAG_TOKEN]: startTagBeforeHead, - [Tokenizer.END_TAG_TOKEN]: endTagBeforeHead, - [Tokenizer.EOF_TOKEN]: tokenBeforeHead - }, - [IN_HEAD_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: tokenInHead, - [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInHead, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype, - [Tokenizer.START_TAG_TOKEN]: startTagInHead, - [Tokenizer.END_TAG_TOKEN]: endTagInHead, - [Tokenizer.EOF_TOKEN]: tokenInHead - }, - [IN_HEAD_NO_SCRIPT_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: tokenInHeadNoScript, - [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInHeadNoScript, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype, - [Tokenizer.START_TAG_TOKEN]: startTagInHeadNoScript, - [Tokenizer.END_TAG_TOKEN]: endTagInHeadNoScript, - [Tokenizer.EOF_TOKEN]: tokenInHeadNoScript - }, - [AFTER_HEAD_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: tokenAfterHead, - [Tokenizer.NULL_CHARACTER_TOKEN]: tokenAfterHead, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype, - [Tokenizer.START_TAG_TOKEN]: startTagAfterHead, - [Tokenizer.END_TAG_TOKEN]: endTagAfterHead, - [Tokenizer.EOF_TOKEN]: tokenAfterHead - }, - [IN_BODY_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: characterInBody, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInBody, - [Tokenizer.END_TAG_TOKEN]: endTagInBody, - [Tokenizer.EOF_TOKEN]: eofInBody - }, - [TEXT_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.NULL_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.COMMENT_TOKEN]: ignoreToken, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: ignoreToken, - [Tokenizer.END_TAG_TOKEN]: endTagInText, - [Tokenizer.EOF_TOKEN]: eofInText - }, - [IN_TABLE_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: characterInTable, - [Tokenizer.NULL_CHARACTER_TOKEN]: characterInTable, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: characterInTable, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInTable, - [Tokenizer.END_TAG_TOKEN]: endTagInTable, - [Tokenizer.EOF_TOKEN]: eofInBody - }, - [IN_TABLE_TEXT_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: characterInTableText, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInTableText, - [Tokenizer.COMMENT_TOKEN]: tokenInTableText, - [Tokenizer.DOCTYPE_TOKEN]: tokenInTableText, - [Tokenizer.START_TAG_TOKEN]: tokenInTableText, - [Tokenizer.END_TAG_TOKEN]: tokenInTableText, - [Tokenizer.EOF_TOKEN]: tokenInTableText - }, - [IN_CAPTION_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: characterInBody, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInCaption, - [Tokenizer.END_TAG_TOKEN]: endTagInCaption, - [Tokenizer.EOF_TOKEN]: eofInBody - }, - [IN_COLUMN_GROUP_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: tokenInColumnGroup, - [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInColumnGroup, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInColumnGroup, - [Tokenizer.END_TAG_TOKEN]: endTagInColumnGroup, - [Tokenizer.EOF_TOKEN]: eofInBody - }, - [IN_TABLE_BODY_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: characterInTable, - [Tokenizer.NULL_CHARACTER_TOKEN]: characterInTable, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: characterInTable, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInTableBody, - [Tokenizer.END_TAG_TOKEN]: endTagInTableBody, - [Tokenizer.EOF_TOKEN]: eofInBody - }, - [IN_ROW_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: characterInTable, - [Tokenizer.NULL_CHARACTER_TOKEN]: characterInTable, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: characterInTable, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInRow, - [Tokenizer.END_TAG_TOKEN]: endTagInRow, - [Tokenizer.EOF_TOKEN]: eofInBody - }, - [IN_CELL_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: characterInBody, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInCell, - [Tokenizer.END_TAG_TOKEN]: endTagInCell, - [Tokenizer.EOF_TOKEN]: eofInBody - }, - [IN_SELECT_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInSelect, - [Tokenizer.END_TAG_TOKEN]: endTagInSelect, - [Tokenizer.EOF_TOKEN]: eofInBody - }, - [IN_SELECT_IN_TABLE_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInSelectInTable, - [Tokenizer.END_TAG_TOKEN]: endTagInSelectInTable, - [Tokenizer.EOF_TOKEN]: eofInBody - }, - [IN_TEMPLATE_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: characterInBody, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInTemplate, - [Tokenizer.END_TAG_TOKEN]: endTagInTemplate, - [Tokenizer.EOF_TOKEN]: eofInTemplate - }, - [AFTER_BODY_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: tokenAfterBody, - [Tokenizer.NULL_CHARACTER_TOKEN]: tokenAfterBody, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, - [Tokenizer.COMMENT_TOKEN]: appendCommentToRootHtmlElement, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagAfterBody, - [Tokenizer.END_TAG_TOKEN]: endTagAfterBody, - [Tokenizer.EOF_TOKEN]: stopParsing - }, - [IN_FRAMESET_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagInFrameset, - [Tokenizer.END_TAG_TOKEN]: endTagInFrameset, - [Tokenizer.EOF_TOKEN]: stopParsing - }, - [AFTER_FRAMESET_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters, - [Tokenizer.COMMENT_TOKEN]: appendComment, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagAfterFrameset, - [Tokenizer.END_TAG_TOKEN]: endTagAfterFrameset, - [Tokenizer.EOF_TOKEN]: stopParsing - }, - [AFTER_AFTER_BODY_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: tokenAfterAfterBody, - [Tokenizer.NULL_CHARACTER_TOKEN]: tokenAfterAfterBody, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, - [Tokenizer.COMMENT_TOKEN]: appendCommentToDocument, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagAfterAfterBody, - [Tokenizer.END_TAG_TOKEN]: tokenAfterAfterBody, - [Tokenizer.EOF_TOKEN]: stopParsing - }, - [AFTER_AFTER_FRAMESET_MODE]: { - [Tokenizer.CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken, - [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody, - [Tokenizer.COMMENT_TOKEN]: appendCommentToDocument, - [Tokenizer.DOCTYPE_TOKEN]: ignoreToken, - [Tokenizer.START_TAG_TOKEN]: startTagAfterAfterFrameset, - [Tokenizer.END_TAG_TOKEN]: ignoreToken, - [Tokenizer.EOF_TOKEN]: stopParsing - } -}; - -//Parser -class Parser { - constructor(options) { - this.options = mergeOptions(DEFAULT_OPTIONS, options); - - this.treeAdapter = this.options.treeAdapter; - this.pendingScript = null; - - if (this.options.sourceCodeLocationInfo) { - Mixin.install(this, LocationInfoParserMixin); - } - - if (this.options.onParseError) { - Mixin.install(this, ErrorReportingParserMixin, { onParseError: this.options.onParseError }); - } - } - - // API - parse(html) { - const document = this.treeAdapter.createDocument(); - - this._bootstrap(document, null); - this.tokenizer.write(html, true); - this._runParsingLoop(null); - - return document; - } - - parseFragment(html, fragmentContext) { - //NOTE: use <template> element as a fragment context if context element was not provided, - //so we will parse in "forgiving" manner - if (!fragmentContext) { - fragmentContext = this.treeAdapter.createElement($.TEMPLATE, NS.HTML, []); - } - - //NOTE: create fake element which will be used as 'document' for fragment parsing. - //This is important for jsdom there 'document' can't be recreated, therefore - //fragment parsing causes messing of the main `document`. - const documentMock = this.treeAdapter.createElement('documentmock', NS.HTML, []); - - this._bootstrap(documentMock, fragmentContext); - - if (this.treeAdapter.getTagName(fragmentContext) === $.TEMPLATE) { - this._pushTmplInsertionMode(IN_TEMPLATE_MODE); - } - - this._initTokenizerForFragmentParsing(); - this._insertFakeRootElement(); - this._resetInsertionMode(); - this._findFormInFragmentContext(); - this.tokenizer.write(html, true); - this._runParsingLoop(null); - - const rootElement = this.treeAdapter.getFirstChild(documentMock); - const fragment = this.treeAdapter.createDocumentFragment(); - - this._adoptNodes(rootElement, fragment); - - return fragment; - } - - //Bootstrap parser - _bootstrap(document, fragmentContext) { - this.tokenizer = new Tokenizer(this.options); - - this.stopped = false; - - this.insertionMode = INITIAL_MODE; - this.originalInsertionMode = ''; - - this.document = document; - this.fragmentContext = fragmentContext; - - this.headElement = null; - this.formElement = null; - - this.openElements = new OpenElementStack(this.document, this.treeAdapter); - this.activeFormattingElements = new FormattingElementList(this.treeAdapter); - - this.tmplInsertionModeStack = []; - this.tmplInsertionModeStackTop = -1; - this.currentTmplInsertionMode = null; - - this.pendingCharacterTokens = []; - this.hasNonWhitespacePendingCharacterToken = false; - - this.framesetOk = true; - this.skipNextNewLine = false; - this.fosterParentingEnabled = false; - } - - //Errors - _err() { - // NOTE: err reporting is noop by default. Enabled by mixin. - } - - //Parsing loop - _runParsingLoop(scriptHandler) { - while (!this.stopped) { - this._setupTokenizerCDATAMode(); - - const token = this.tokenizer.getNextToken(); - - if (token.type === Tokenizer.HIBERNATION_TOKEN) { - break; - } - - if (this.skipNextNewLine) { - this.skipNextNewLine = false; - - if (token.type === Tokenizer.WHITESPACE_CHARACTER_TOKEN && token.chars[0] === '\n') { - if (token.chars.length === 1) { - continue; - } - - token.chars = token.chars.substr(1); - } - } - - this._processInputToken(token); - - if (scriptHandler && this.pendingScript) { - break; - } - } - } - - runParsingLoopForCurrentChunk(writeCallback, scriptHandler) { - this._runParsingLoop(scriptHandler); - - if (scriptHandler && this.pendingScript) { - const script = this.pendingScript; - - this.pendingScript = null; - - scriptHandler(script); - - return; - } - - if (writeCallback) { - writeCallback(); - } - } - - //Text parsing - _setupTokenizerCDATAMode() { - const current = this._getAdjustedCurrentElement(); - - this.tokenizer.allowCDATA = - current && - current !== this.document && - this.treeAdapter.getNamespaceURI(current) !== NS.HTML && - !this._isIntegrationPoint(current); - } - - _switchToTextParsing(currentToken, nextTokenizerState) { - this._insertElement(currentToken, NS.HTML); - this.tokenizer.state = nextTokenizerState; - this.originalInsertionMode = this.insertionMode; - this.insertionMode = TEXT_MODE; - } - - switchToPlaintextParsing() { - this.insertionMode = TEXT_MODE; - this.originalInsertionMode = IN_BODY_MODE; - this.tokenizer.state = Tokenizer.MODE.PLAINTEXT; - } - - //Fragment parsing - _getAdjustedCurrentElement() { - return this.openElements.stackTop === 0 && this.fragmentContext - ? this.fragmentContext - : this.openElements.current; - } - - _findFormInFragmentContext() { - let node = this.fragmentContext; - - do { - if (this.treeAdapter.getTagName(node) === $.FORM) { - this.formElement = node; - break; - } - - node = this.treeAdapter.getParentNode(node); - } while (node); - } - - _initTokenizerForFragmentParsing() { - if (this.treeAdapter.getNamespaceURI(this.fragmentContext) === NS.HTML) { - const tn = this.treeAdapter.getTagName(this.fragmentContext); - - if (tn === $.TITLE || tn === $.TEXTAREA) { - this.tokenizer.state = Tokenizer.MODE.RCDATA; - } else if ( - tn === $.STYLE || - tn === $.XMP || - tn === $.IFRAME || - tn === $.NOEMBED || - tn === $.NOFRAMES || - tn === $.NOSCRIPT - ) { - this.tokenizer.state = Tokenizer.MODE.RAWTEXT; - } else if (tn === $.SCRIPT) { - this.tokenizer.state = Tokenizer.MODE.SCRIPT_DATA; - } else if (tn === $.PLAINTEXT) { - this.tokenizer.state = Tokenizer.MODE.PLAINTEXT; - } - } - } - - //Tree mutation - _setDocumentType(token) { - const name = token.name || ''; - const publicId = token.publicId || ''; - const systemId = token.systemId || ''; - - this.treeAdapter.setDocumentType(this.document, name, publicId, systemId); - } - - _attachElementToTree(element) { - if (this._shouldFosterParentOnInsertion()) { - this._fosterParentElement(element); - } else { - const parent = this.openElements.currentTmplContent || this.openElements.current; - - this.treeAdapter.appendChild(parent, element); - } - } - - _appendElement(token, namespaceURI) { - const element = this.treeAdapter.createElement(token.tagName, namespaceURI, token.attrs); - - this._attachElementToTree(element); - } - - _insertElement(token, namespaceURI) { - const element = this.treeAdapter.createElement(token.tagName, namespaceURI, token.attrs); - - this._attachElementToTree(element); - this.openElements.push(element); - } - - _insertFakeElement(tagName) { - const element = this.treeAdapter.createElement(tagName, NS.HTML, []); - - this._attachElementToTree(element); - this.openElements.push(element); - } - - _insertTemplate(token) { - const tmpl = this.treeAdapter.createElement(token.tagName, NS.HTML, token.attrs); - const content = this.treeAdapter.createDocumentFragment(); - - this.treeAdapter.setTemplateContent(tmpl, content); - this._attachElementToTree(tmpl); - this.openElements.push(tmpl); - } - - _insertFakeRootElement() { - const element = this.treeAdapter.createElement($.HTML, NS.HTML, []); - - this.treeAdapter.appendChild(this.openElements.current, element); - this.openElements.push(element); - } - - _appendCommentNode(token, parent) { - const commentNode = this.treeAdapter.createCommentNode(token.data); - - this.treeAdapter.appendChild(parent, commentNode); - } - - _insertCharacters(token) { - if (this._shouldFosterParentOnInsertion()) { - this._fosterParentText(token.chars); - } else { - const parent = this.openElements.currentTmplContent || this.openElements.current; - - this.treeAdapter.insertText(parent, token.chars); - } - } - - _adoptNodes(donor, recipient) { - for (let child = this.treeAdapter.getFirstChild(donor); child; child = this.treeAdapter.getFirstChild(donor)) { - this.treeAdapter.detachNode(child); - this.treeAdapter.appendChild(recipient, child); - } - } - - //Token processing - _shouldProcessTokenInForeignContent(token) { - const current = this._getAdjustedCurrentElement(); - - if (!current || current === this.document) { - return false; - } - - const ns = this.treeAdapter.getNamespaceURI(current); - - if (ns === NS.HTML) { - return false; - } - - if ( - this.treeAdapter.getTagName(current) === $.ANNOTATION_XML && - ns === NS.MATHML && - token.type === Tokenizer.START_TAG_TOKEN && - token.tagName === $.SVG - ) { - return false; - } - - const isCharacterToken = - token.type === Tokenizer.CHARACTER_TOKEN || - token.type === Tokenizer.NULL_CHARACTER_TOKEN || - token.type === Tokenizer.WHITESPACE_CHARACTER_TOKEN; - - const isMathMLTextStartTag = - token.type === Tokenizer.START_TAG_TOKEN && token.tagName !== $.MGLYPH && token.tagName !== $.MALIGNMARK; - - if ((isMathMLTextStartTag || isCharacterToken) && this._isIntegrationPoint(current, NS.MATHML)) { - return false; - } - - if ( - (token.type === Tokenizer.START_TAG_TOKEN || isCharacterToken) && - this._isIntegrationPoint(current, NS.HTML) - ) { - return false; - } - - return token.type !== Tokenizer.EOF_TOKEN; - } - - _processToken(token) { - TOKEN_HANDLERS[this.insertionMode][token.type](this, token); - } - - _processTokenInBodyMode(token) { - TOKEN_HANDLERS[IN_BODY_MODE][token.type](this, token); - } - - _processTokenInForeignContent(token) { - if (token.type === Tokenizer.CHARACTER_TOKEN) { - characterInForeignContent(this, token); - } else if (token.type === Tokenizer.NULL_CHARACTER_TOKEN) { - nullCharacterInForeignContent(this, token); - } else if (token.type === Tokenizer.WHITESPACE_CHARACTER_TOKEN) { - insertCharacters(this, token); - } else if (token.type === Tokenizer.COMMENT_TOKEN) { - appendComment(this, token); - } else if (token.type === Tokenizer.START_TAG_TOKEN) { - startTagInForeignContent(this, token); - } else if (token.type === Tokenizer.END_TAG_TOKEN) { - endTagInForeignContent(this, token); - } - } - - _processInputToken(token) { - if (this._shouldProcessTokenInForeignContent(token)) { - this._processTokenInForeignContent(token); - } else { - this._processToken(token); - } - - if (token.type === Tokenizer.START_TAG_TOKEN && token.selfClosing && !token.ackSelfClosing) { - this._err(ERR.nonVoidHtmlElementStartTagWithTrailingSolidus); - } - } - - //Integration points - _isIntegrationPoint(element, foreignNS) { - const tn = this.treeAdapter.getTagName(element); - const ns = this.treeAdapter.getNamespaceURI(element); - const attrs = this.treeAdapter.getAttrList(element); - - return foreignContent.isIntegrationPoint(tn, ns, attrs, foreignNS); - } - - //Active formatting elements reconstruction - _reconstructActiveFormattingElements() { - const listLength = this.activeFormattingElements.length; - - if (listLength) { - let unopenIdx = listLength; - let entry = null; - - do { - unopenIdx--; - entry = this.activeFormattingElements.entries[unopenIdx]; - - if (entry.type === FormattingElementList.MARKER_ENTRY || this.openElements.contains(entry.element)) { - unopenIdx++; - break; - } - } while (unopenIdx > 0); - - for (let i = unopenIdx; i < listLength; i++) { - entry = this.activeFormattingElements.entries[i]; - this._insertElement(entry.token, this.treeAdapter.getNamespaceURI(entry.element)); - entry.element = this.openElements.current; - } - } - } - - //Close elements - _closeTableCell() { - this.openElements.generateImpliedEndTags(); - this.openElements.popUntilTableCellPopped(); - this.activeFormattingElements.clearToLastMarker(); - this.insertionMode = IN_ROW_MODE; - } - - _closePElement() { - this.openElements.generateImpliedEndTagsWithExclusion($.P); - this.openElements.popUntilTagNamePopped($.P); - } - - //Insertion modes - _resetInsertionMode() { - for (let i = this.openElements.stackTop, last = false; i >= 0; i--) { - let element = this.openElements.items[i]; - - if (i === 0) { - last = true; - - if (this.fragmentContext) { - element = this.fragmentContext; - } - } - - const tn = this.treeAdapter.getTagName(element); - const newInsertionMode = INSERTION_MODE_RESET_MAP[tn]; - - if (newInsertionMode) { - this.insertionMode = newInsertionMode; - break; - } else if (!last && (tn === $.TD || tn === $.TH)) { - this.insertionMode = IN_CELL_MODE; - break; - } else if (!last && tn === $.HEAD) { - this.insertionMode = IN_HEAD_MODE; - break; - } else if (tn === $.SELECT) { - this._resetInsertionModeForSelect(i); - break; - } else if (tn === $.TEMPLATE) { - this.insertionMode = this.currentTmplInsertionMode; - break; - } else if (tn === $.HTML) { - this.insertionMode = this.headElement ? AFTER_HEAD_MODE : BEFORE_HEAD_MODE; - break; - } else if (last) { - this.insertionMode = IN_BODY_MODE; - break; - } - } - } - - _resetInsertionModeForSelect(selectIdx) { - if (selectIdx > 0) { - for (let i = selectIdx - 1; i > 0; i--) { - const ancestor = this.openElements.items[i]; - const tn = this.treeAdapter.getTagName(ancestor); - - if (tn === $.TEMPLATE) { - break; - } else if (tn === $.TABLE) { - this.insertionMode = IN_SELECT_IN_TABLE_MODE; - return; - } - } - } - - this.insertionMode = IN_SELECT_MODE; - } - - _pushTmplInsertionMode(mode) { - this.tmplInsertionModeStack.push(mode); - this.tmplInsertionModeStackTop++; - this.currentTmplInsertionMode = mode; - } - - _popTmplInsertionMode() { - this.tmplInsertionModeStack.pop(); - this.tmplInsertionModeStackTop--; - this.currentTmplInsertionMode = this.tmplInsertionModeStack[this.tmplInsertionModeStackTop]; - } - - //Foster parenting - _isElementCausesFosterParenting(element) { - const tn = this.treeAdapter.getTagName(element); - - return tn === $.TABLE || tn === $.TBODY || tn === $.TFOOT || tn === $.THEAD || tn === $.TR; - } - - _shouldFosterParentOnInsertion() { - return this.fosterParentingEnabled && this._isElementCausesFosterParenting(this.openElements.current); - } - - _findFosterParentingLocation() { - const location = { - parent: null, - beforeElement: null - }; - - for (let i = this.openElements.stackTop; i >= 0; i--) { - const openElement = this.openElements.items[i]; - const tn = this.treeAdapter.getTagName(openElement); - const ns = this.treeAdapter.getNamespaceURI(openElement); - - if (tn === $.TEMPLATE && ns === NS.HTML) { - location.parent = this.treeAdapter.getTemplateContent(openElement); - break; - } else if (tn === $.TABLE) { - location.parent = this.treeAdapter.getParentNode(openElement); - - if (location.parent) { - location.beforeElement = openElement; - } else { - location.parent = this.openElements.items[i - 1]; - } - - break; - } - } - - if (!location.parent) { - location.parent = this.openElements.items[0]; - } - - return location; - } - - _fosterParentElement(element) { - const location = this._findFosterParentingLocation(); - - if (location.beforeElement) { - this.treeAdapter.insertBefore(location.parent, element, location.beforeElement); - } else { - this.treeAdapter.appendChild(location.parent, element); - } - } - - _fosterParentText(chars) { - const location = this._findFosterParentingLocation(); - - if (location.beforeElement) { - this.treeAdapter.insertTextBefore(location.parent, chars, location.beforeElement); - } else { - this.treeAdapter.insertText(location.parent, chars); - } - } - - //Special elements - _isSpecialElement(element) { - const tn = this.treeAdapter.getTagName(element); - const ns = this.treeAdapter.getNamespaceURI(element); - - return HTML.SPECIAL_ELEMENTS[ns][tn]; - } -} - -module.exports = Parser; - -//Adoption agency algorithm -//(see: http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#adoptionAgency) -//------------------------------------------------------------------ - -//Steps 5-8 of the algorithm -function aaObtainFormattingElementEntry(p, token) { - let formattingElementEntry = p.activeFormattingElements.getElementEntryInScopeWithTagName(token.tagName); - - if (formattingElementEntry) { - if (!p.openElements.contains(formattingElementEntry.element)) { - p.activeFormattingElements.removeEntry(formattingElementEntry); - formattingElementEntry = null; - } else if (!p.openElements.hasInScope(token.tagName)) { - formattingElementEntry = null; - } - } else { - genericEndTagInBody(p, token); - } - - return formattingElementEntry; -} - -//Steps 9 and 10 of the algorithm -function aaObtainFurthestBlock(p, formattingElementEntry) { - let furthestBlock = null; - - for (let i = p.openElements.stackTop; i >= 0; i--) { - const element = p.openElements.items[i]; - - if (element === formattingElementEntry.element) { - break; - } - - if (p._isSpecialElement(element)) { - furthestBlock = element; - } - } - - if (!furthestBlock) { - p.openElements.popUntilElementPopped(formattingElementEntry.element); - p.activeFormattingElements.removeEntry(formattingElementEntry); - } - - return furthestBlock; -} - -//Step 13 of the algorithm -function aaInnerLoop(p, furthestBlock, formattingElement) { - let lastElement = furthestBlock; - let nextElement = p.openElements.getCommonAncestor(furthestBlock); - - for (let i = 0, element = nextElement; element !== formattingElement; i++, element = nextElement) { - //NOTE: store next element for the next loop iteration (it may be deleted from the stack by step 9.5) - nextElement = p.openElements.getCommonAncestor(element); - - const elementEntry = p.activeFormattingElements.getElementEntry(element); - const counterOverflow = elementEntry && i >= AA_INNER_LOOP_ITER; - const shouldRemoveFromOpenElements = !elementEntry || counterOverflow; - - if (shouldRemoveFromOpenElements) { - if (counterOverflow) { - p.activeFormattingElements.removeEntry(elementEntry); - } - - p.openElements.remove(element); - } else { - element = aaRecreateElementFromEntry(p, elementEntry); - - if (lastElement === furthestBlock) { - p.activeFormattingElements.bookmark = elementEntry; - } - - p.treeAdapter.detachNode(lastElement); - p.treeAdapter.appendChild(element, lastElement); - lastElement = element; - } - } - - return lastElement; -} - -//Step 13.7 of the algorithm -function aaRecreateElementFromEntry(p, elementEntry) { - const ns = p.treeAdapter.getNamespaceURI(elementEntry.element); - const newElement = p.treeAdapter.createElement(elementEntry.token.tagName, ns, elementEntry.token.attrs); - - p.openElements.replace(elementEntry.element, newElement); - elementEntry.element = newElement; - - return newElement; -} - -//Step 14 of the algorithm -function aaInsertLastNodeInCommonAncestor(p, commonAncestor, lastElement) { - if (p._isElementCausesFosterParenting(commonAncestor)) { - p._fosterParentElement(lastElement); - } else { - const tn = p.treeAdapter.getTagName(commonAncestor); - const ns = p.treeAdapter.getNamespaceURI(commonAncestor); - - if (tn === $.TEMPLATE && ns === NS.HTML) { - commonAncestor = p.treeAdapter.getTemplateContent(commonAncestor); - } - - p.treeAdapter.appendChild(commonAncestor, lastElement); - } -} - -//Steps 15-19 of the algorithm -function aaReplaceFormattingElement(p, furthestBlock, formattingElementEntry) { - const ns = p.treeAdapter.getNamespaceURI(formattingElementEntry.element); - const token = formattingElementEntry.token; - const newElement = p.treeAdapter.createElement(token.tagName, ns, token.attrs); - - p._adoptNodes(furthestBlock, newElement); - p.treeAdapter.appendChild(furthestBlock, newElement); - - p.activeFormattingElements.insertElementAfterBookmark(newElement, formattingElementEntry.token); - p.activeFormattingElements.removeEntry(formattingElementEntry); - - p.openElements.remove(formattingElementEntry.element); - p.openElements.insertAfter(furthestBlock, newElement); -} - -//Algorithm entry point -function callAdoptionAgency(p, token) { - let formattingElementEntry; - - for (let i = 0; i < AA_OUTER_LOOP_ITER; i++) { - formattingElementEntry = aaObtainFormattingElementEntry(p, token, formattingElementEntry); - - if (!formattingElementEntry) { - break; - } - - const furthestBlock = aaObtainFurthestBlock(p, formattingElementEntry); - - if (!furthestBlock) { - break; - } - - p.activeFormattingElements.bookmark = formattingElementEntry; - - const lastElement = aaInnerLoop(p, furthestBlock, formattingElementEntry.element); - const commonAncestor = p.openElements.getCommonAncestor(formattingElementEntry.element); - - p.treeAdapter.detachNode(lastElement); - aaInsertLastNodeInCommonAncestor(p, commonAncestor, lastElement); - aaReplaceFormattingElement(p, furthestBlock, formattingElementEntry); - } -} - -//Generic token handlers -//------------------------------------------------------------------ -function ignoreToken() { - //NOTE: do nothing =) -} - -function misplacedDoctype(p) { - p._err(ERR.misplacedDoctype); -} - -function appendComment(p, token) { - p._appendCommentNode(token, p.openElements.currentTmplContent || p.openElements.current); -} - -function appendCommentToRootHtmlElement(p, token) { - p._appendCommentNode(token, p.openElements.items[0]); -} - -function appendCommentToDocument(p, token) { - p._appendCommentNode(token, p.document); -} - -function insertCharacters(p, token) { - p._insertCharacters(token); -} - -function stopParsing(p) { - p.stopped = true; -} - -// The "initial" insertion mode -//------------------------------------------------------------------ -function doctypeInInitialMode(p, token) { - p._setDocumentType(token); - - const mode = token.forceQuirks ? HTML.DOCUMENT_MODE.QUIRKS : doctype.getDocumentMode(token); - - if (!doctype.isConforming(token)) { - p._err(ERR.nonConformingDoctype); - } - - p.treeAdapter.setDocumentMode(p.document, mode); - - p.insertionMode = BEFORE_HTML_MODE; -} - -function tokenInInitialMode(p, token) { - p._err(ERR.missingDoctype, { beforeToken: true }); - p.treeAdapter.setDocumentMode(p.document, HTML.DOCUMENT_MODE.QUIRKS); - p.insertionMode = BEFORE_HTML_MODE; - p._processToken(token); -} - -// The "before html" insertion mode -//------------------------------------------------------------------ -function startTagBeforeHtml(p, token) { - if (token.tagName === $.HTML) { - p._insertElement(token, NS.HTML); - p.insertionMode = BEFORE_HEAD_MODE; - } else { - tokenBeforeHtml(p, token); - } -} - -function endTagBeforeHtml(p, token) { - const tn = token.tagName; - - if (tn === $.HTML || tn === $.HEAD || tn === $.BODY || tn === $.BR) { - tokenBeforeHtml(p, token); - } -} - -function tokenBeforeHtml(p, token) { - p._insertFakeRootElement(); - p.insertionMode = BEFORE_HEAD_MODE; - p._processToken(token); -} - -// The "before head" insertion mode -//------------------------------------------------------------------ -function startTagBeforeHead(p, token) { - const tn = token.tagName; - - if (tn === $.HTML) { - startTagInBody(p, token); - } else if (tn === $.HEAD) { - p._insertElement(token, NS.HTML); - p.headElement = p.openElements.current; - p.insertionMode = IN_HEAD_MODE; - } else { - tokenBeforeHead(p, token); - } -} - -function endTagBeforeHead(p, token) { - const tn = token.tagName; - - if (tn === $.HEAD || tn === $.BODY || tn === $.HTML || tn === $.BR) { - tokenBeforeHead(p, token); - } else { - p._err(ERR.endTagWithoutMatchingOpenElement); - } -} - -function tokenBeforeHead(p, token) { - p._insertFakeElement($.HEAD); - p.headElement = p.openElements.current; - p.insertionMode = IN_HEAD_MODE; - p._processToken(token); -} - -// The "in head" insertion mode -//------------------------------------------------------------------ -function startTagInHead(p, token) { - const tn = token.tagName; - - if (tn === $.HTML) { - startTagInBody(p, token); - } else if (tn === $.BASE || tn === $.BASEFONT || tn === $.BGSOUND || tn === $.LINK || tn === $.META) { - p._appendElement(token, NS.HTML); - token.ackSelfClosing = true; - } else if (tn === $.TITLE) { - p._switchToTextParsing(token, Tokenizer.MODE.RCDATA); - } else if (tn === $.NOSCRIPT) { - if (p.options.scriptingEnabled) { - p._switchToTextParsing(token, Tokenizer.MODE.RAWTEXT); - } else { - p._insertElement(token, NS.HTML); - p.insertionMode = IN_HEAD_NO_SCRIPT_MODE; - } - } else if (tn === $.NOFRAMES || tn === $.STYLE) { - p._switchToTextParsing(token, Tokenizer.MODE.RAWTEXT); - } else if (tn === $.SCRIPT) { - p._switchToTextParsing(token, Tokenizer.MODE.SCRIPT_DATA); - } else if (tn === $.TEMPLATE) { - p._insertTemplate(token, NS.HTML); - p.activeFormattingElements.insertMarker(); - p.framesetOk = false; - p.insertionMode = IN_TEMPLATE_MODE; - p._pushTmplInsertionMode(IN_TEMPLATE_MODE); - } else if (tn === $.HEAD) { - p._err(ERR.misplacedStartTagForHeadElement); - } else { - tokenInHead(p, token); - } -} - -function endTagInHead(p, token) { - const tn = token.tagName; - - if (tn === $.HEAD) { - p.openElements.pop(); - p.insertionMode = AFTER_HEAD_MODE; - } else if (tn === $.BODY || tn === $.BR || tn === $.HTML) { - tokenInHead(p, token); - } else if (tn === $.TEMPLATE) { - if (p.openElements.tmplCount > 0) { - p.openElements.generateImpliedEndTagsThoroughly(); - - if (p.openElements.currentTagName !== $.TEMPLATE) { - p._err(ERR.closingOfElementWithOpenChildElements); - } - - p.openElements.popUntilTagNamePopped($.TEMPLATE); - p.activeFormattingElements.clearToLastMarker(); - p._popTmplInsertionMode(); - p._resetInsertionMode(); - } else { - p._err(ERR.endTagWithoutMatchingOpenElement); - } - } else { - p._err(ERR.endTagWithoutMatchingOpenElement); - } -} - -function tokenInHead(p, token) { - p.openElements.pop(); - p.insertionMode = AFTER_HEAD_MODE; - p._processToken(token); -} - -// The "in head no script" insertion mode -//------------------------------------------------------------------ -function startTagInHeadNoScript(p, token) { - const tn = token.tagName; - - if (tn === $.HTML) { - startTagInBody(p, token); - } else if ( - tn === $.BASEFONT || - tn === $.BGSOUND || - tn === $.HEAD || - tn === $.LINK || - tn === $.META || - tn === $.NOFRAMES || - tn === $.STYLE - ) { - startTagInHead(p, token); - } else if (tn === $.NOSCRIPT) { - p._err(ERR.nestedNoscriptInHead); - } else { - tokenInHeadNoScript(p, token); - } -} - -function endTagInHeadNoScript(p, token) { - const tn = token.tagName; - - if (tn === $.NOSCRIPT) { - p.openElements.pop(); - p.insertionMode = IN_HEAD_MODE; - } else if (tn === $.BR) { - tokenInHeadNoScript(p, token); - } else { - p._err(ERR.endTagWithoutMatchingOpenElement); - } -} - -function tokenInHeadNoScript(p, token) { - const errCode = - token.type === Tokenizer.EOF_TOKEN ? ERR.openElementsLeftAfterEof : ERR.disallowedContentInNoscriptInHead; - - p._err(errCode); - p.openElements.pop(); - p.insertionMode = IN_HEAD_MODE; - p._processToken(token); -} - -// The "after head" insertion mode -//------------------------------------------------------------------ -function startTagAfterHead(p, token) { - const tn = token.tagName; - - if (tn === $.HTML) { - startTagInBody(p, token); - } else if (tn === $.BODY) { - p._insertElement(token, NS.HTML); - p.framesetOk = false; - p.insertionMode = IN_BODY_MODE; - } else if (tn === $.FRAMESET) { - p._insertElement(token, NS.HTML); - p.insertionMode = IN_FRAMESET_MODE; - } else if ( - tn === $.BASE || - tn === $.BASEFONT || - tn === $.BGSOUND || - tn === $.LINK || - tn === $.META || - tn === $.NOFRAMES || - tn === $.SCRIPT || - tn === $.STYLE || - tn === $.TEMPLATE || - tn === $.TITLE - ) { - p._err(ERR.abandonedHeadElementChild); - p.openElements.push(p.headElement); - startTagInHead(p, token); - p.openElements.remove(p.headElement); - } else if (tn === $.HEAD) { - p._err(ERR.misplacedStartTagForHeadElement); - } else { - tokenAfterHead(p, token); - } -} - -function endTagAfterHead(p, token) { - const tn = token.tagName; - - if (tn === $.BODY || tn === $.HTML || tn === $.BR) { - tokenAfterHead(p, token); - } else if (tn === $.TEMPLATE) { - endTagInHead(p, token); - } else { - p._err(ERR.endTagWithoutMatchingOpenElement); - } -} - -function tokenAfterHead(p, token) { - p._insertFakeElement($.BODY); - p.insertionMode = IN_BODY_MODE; - p._processToken(token); -} - -// The "in body" insertion mode -//------------------------------------------------------------------ -function whitespaceCharacterInBody(p, token) { - p._reconstructActiveFormattingElements(); - p._insertCharacters(token); -} - -function characterInBody(p, token) { - p._reconstructActiveFormattingElements(); - p._insertCharacters(token); - p.framesetOk = false; -} - -function htmlStartTagInBody(p, token) { - if (p.openElements.tmplCount === 0) { - p.treeAdapter.adoptAttributes(p.openElements.items[0], token.attrs); - } -} - -function bodyStartTagInBody(p, token) { - const bodyElement = p.openElements.tryPeekProperlyNestedBodyElement(); - - if (bodyElement && p.openElements.tmplCount === 0) { - p.framesetOk = false; - p.treeAdapter.adoptAttributes(bodyElement, token.attrs); - } -} - -function framesetStartTagInBody(p, token) { - const bodyElement = p.openElements.tryPeekProperlyNestedBodyElement(); - - if (p.framesetOk && bodyElement) { - p.treeAdapter.detachNode(bodyElement); - p.openElements.popAllUpToHtmlElement(); - p._insertElement(token, NS.HTML); - p.insertionMode = IN_FRAMESET_MODE; - } -} - -function addressStartTagInBody(p, token) { - if (p.openElements.hasInButtonScope($.P)) { - p._closePElement(); - } - - p._insertElement(token, NS.HTML); -} - -function numberedHeaderStartTagInBody(p, token) { - if (p.openElements.hasInButtonScope($.P)) { - p._closePElement(); - } - - const tn = p.openElements.currentTagName; - - if (tn === $.H1 || tn === $.H2 || tn === $.H3 || tn === $.H4 || tn === $.H5 || tn === $.H6) { - p.openElements.pop(); - } - - p._insertElement(token, NS.HTML); -} - -function preStartTagInBody(p, token) { - if (p.openElements.hasInButtonScope($.P)) { - p._closePElement(); - } - - p._insertElement(token, NS.HTML); - //NOTE: If the next token is a U+000A LINE FEED (LF) character token, then ignore that token and move - //on to the next one. (Newlines at the start of pre blocks are ignored as an authoring convenience.) - p.skipNextNewLine = true; - p.framesetOk = false; -} - -function formStartTagInBody(p, token) { - const inTemplate = p.openElements.tmplCount > 0; - - if (!p.formElement || inTemplate) { - if (p.openElements.hasInButtonScope($.P)) { - p._closePElement(); - } - - p._insertElement(token, NS.HTML); - - if (!inTemplate) { - p.formElement = p.openElements.current; - } - } -} - -function listItemStartTagInBody(p, token) { - p.framesetOk = false; - - const tn = token.tagName; - - for (let i = p.openElements.stackTop; i >= 0; i--) { - const element = p.openElements.items[i]; - const elementTn = p.treeAdapter.getTagName(element); - let closeTn = null; - - if (tn === $.LI && elementTn === $.LI) { - closeTn = $.LI; - } else if ((tn === $.DD || tn === $.DT) && (elementTn === $.DD || elementTn === $.DT)) { - closeTn = elementTn; - } - - if (closeTn) { - p.openElements.generateImpliedEndTagsWithExclusion(closeTn); - p.openElements.popUntilTagNamePopped(closeTn); - break; - } - - if (elementTn !== $.ADDRESS && elementTn !== $.DIV && elementTn !== $.P && p._isSpecialElement(element)) { - break; - } - } - - if (p.openElements.hasInButtonScope($.P)) { - p._closePElement(); - } - - p._insertElement(token, NS.HTML); -} - -function plaintextStartTagInBody(p, token) { - if (p.openElements.hasInButtonScope($.P)) { - p._closePElement(); - } - - p._insertElement(token, NS.HTML); - p.tokenizer.state = Tokenizer.MODE.PLAINTEXT; -} - -function buttonStartTagInBody(p, token) { - if (p.openElements.hasInScope($.BUTTON)) { - p.openElements.generateImpliedEndTags(); - p.openElements.popUntilTagNamePopped($.BUTTON); - } - - p._reconstructActiveFormattingElements(); - p._insertElement(token, NS.HTML); - p.framesetOk = false; -} - -function aStartTagInBody(p, token) { - const activeElementEntry = p.activeFormattingElements.getElementEntryInScopeWithTagName($.A); - - if (activeElementEntry) { - callAdoptionAgency(p, token); - p.openElements.remove(activeElementEntry.element); - p.activeFormattingElements.removeEntry(activeElementEntry); - } - - p._reconstructActiveFormattingElements(); - p._insertElement(token, NS.HTML); - p.activeFormattingElements.pushElement(p.openElements.current, token); -} - -function bStartTagInBody(p, token) { - p._reconstructActiveFormattingElements(); - p._insertElement(token, NS.HTML); - p.activeFormattingElements.pushElement(p.openElements.current, token); -} - -function nobrStartTagInBody(p, token) { - p._reconstructActiveFormattingElements(); - - if (p.openElements.hasInScope($.NOBR)) { - callAdoptionAgency(p, token); - p._reconstructActiveFormattingElements(); - } - - p._insertElement(token, NS.HTML); - p.activeFormattingElements.pushElement(p.openElements.current, token); -} - -function appletStartTagInBody(p, token) { - p._reconstructActiveFormattingElements(); - p._insertElement(token, NS.HTML); - p.activeFormattingElements.insertMarker(); - p.framesetOk = false; -} - -function tableStartTagInBody(p, token) { - if ( - p.treeAdapter.getDocumentMode(p.document) !== HTML.DOCUMENT_MODE.QUIRKS && - p.openElements.hasInButtonScope($.P) - ) { - p._closePElement(); - } - - p._insertElement(token, NS.HTML); - p.framesetOk = false; - p.insertionMode = IN_TABLE_MODE; -} - -function areaStartTagInBody(p, token) { - p._reconstructActiveFormattingElements(); - p._appendElement(token, NS.HTML); - p.framesetOk = false; - token.ackSelfClosing = true; -} - -function inputStartTagInBody(p, token) { - p._reconstructActiveFormattingElements(); - p._appendElement(token, NS.HTML); - - const inputType = Tokenizer.getTokenAttr(token, ATTRS.TYPE); - - if (!inputType || inputType.toLowerCase() !== HIDDEN_INPUT_TYPE) { - p.framesetOk = false; - } - - token.ackSelfClosing = true; -} - -function paramStartTagInBody(p, token) { - p._appendElement(token, NS.HTML); - token.ackSelfClosing = true; -} - -function hrStartTagInBody(p, token) { - if (p.openElements.hasInButtonScope($.P)) { - p._closePElement(); - } - - p._appendElement(token, NS.HTML); - p.framesetOk = false; - token.ackSelfClosing = true; -} - -function imageStartTagInBody(p, token) { - token.tagName = $.IMG; - areaStartTagInBody(p, token); -} - -function textareaStartTagInBody(p, token) { - p._insertElement(token, NS.HTML); - //NOTE: If the next token is a U+000A LINE FEED (LF) character token, then ignore that token and move - //on to the next one. (Newlines at the start of textarea elements are ignored as an authoring convenience.) - p.skipNextNewLine = true; - p.tokenizer.state = Tokenizer.MODE.RCDATA; - p.originalInsertionMode = p.insertionMode; - p.framesetOk = false; - p.insertionMode = TEXT_MODE; -} - -function xmpStartTagInBody(p, token) { - if (p.openElements.hasInButtonScope($.P)) { - p._closePElement(); - } - - p._reconstructActiveFormattingElements(); - p.framesetOk = false; - p._switchToTextParsing(token, Tokenizer.MODE.RAWTEXT); -} - -function iframeStartTagInBody(p, token) { - p.framesetOk = false; - p._switchToTextParsing(token, Tokenizer.MODE.RAWTEXT); -} - -//NOTE: here we assume that we always act as an user agent with enabled plugins, so we parse -//<noembed> as a rawtext. -function noembedStartTagInBody(p, token) { - p._switchToTextParsing(token, Tokenizer.MODE.RAWTEXT); -} - -function selectStartTagInBody(p, token) { - p._reconstructActiveFormattingElements(); - p._insertElement(token, NS.HTML); - p.framesetOk = false; - - if ( - p.insertionMode === IN_TABLE_MODE || - p.insertionMode === IN_CAPTION_MODE || - p.insertionMode === IN_TABLE_BODY_MODE || - p.insertionMode === IN_ROW_MODE || - p.insertionMode === IN_CELL_MODE - ) { - p.insertionMode = IN_SELECT_IN_TABLE_MODE; - } else { - p.insertionMode = IN_SELECT_MODE; - } -} - -function optgroupStartTagInBody(p, token) { - if (p.openElements.currentTagName === $.OPTION) { - p.openElements.pop(); - } - - p._reconstructActiveFormattingElements(); - p._insertElement(token, NS.HTML); -} - -function rbStartTagInBody(p, token) { - if (p.openElements.hasInScope($.RUBY)) { - p.openElements.generateImpliedEndTags(); - } - - p._insertElement(token, NS.HTML); -} - -function rtStartTagInBody(p, token) { - if (p.openElements.hasInScope($.RUBY)) { - p.openElements.generateImpliedEndTagsWithExclusion($.RTC); - } - - p._insertElement(token, NS.HTML); -} - -function menuStartTagInBody(p, token) { - if (p.openElements.hasInButtonScope($.P)) { - p._closePElement(); - } - - p._insertElement(token, NS.HTML); -} - -function mathStartTagInBody(p, token) { - p._reconstructActiveFormattingElements(); - - foreignContent.adjustTokenMathMLAttrs(token); - foreignContent.adjustTokenXMLAttrs(token); - - if (token.selfClosing) { - p._appendElement(token, NS.MATHML); - } else { - p._insertElement(token, NS.MATHML); - } - - token.ackSelfClosing = true; -} - -function svgStartTagInBody(p, token) { - p._reconstructActiveFormattingElements(); - - foreignContent.adjustTokenSVGAttrs(token); - foreignContent.adjustTokenXMLAttrs(token); - - if (token.selfClosing) { - p._appendElement(token, NS.SVG); - } else { - p._insertElement(token, NS.SVG); - } - - token.ackSelfClosing = true; -} - -function genericStartTagInBody(p, token) { - p._reconstructActiveFormattingElements(); - p._insertElement(token, NS.HTML); -} - -//OPTIMIZATION: Integer comparisons are low-cost, so we can use very fast tag name length filters here. -//It's faster than using dictionary. -function startTagInBody(p, token) { - const tn = token.tagName; - - switch (tn.length) { - case 1: - if (tn === $.I || tn === $.S || tn === $.B || tn === $.U) { - bStartTagInBody(p, token); - } else if (tn === $.P) { - addressStartTagInBody(p, token); - } else if (tn === $.A) { - aStartTagInBody(p, token); - } else { - genericStartTagInBody(p, token); - } - - break; - - case 2: - if (tn === $.DL || tn === $.OL || tn === $.UL) { - addressStartTagInBody(p, token); - } else if (tn === $.H1 || tn === $.H2 || tn === $.H3 || tn === $.H4 || tn === $.H5 || tn === $.H6) { - numberedHeaderStartTagInBody(p, token); - } else if (tn === $.LI || tn === $.DD || tn === $.DT) { - listItemStartTagInBody(p, token); - } else if (tn === $.EM || tn === $.TT) { - bStartTagInBody(p, token); - } else if (tn === $.BR) { - areaStartTagInBody(p, token); - } else if (tn === $.HR) { - hrStartTagInBody(p, token); - } else if (tn === $.RB) { - rbStartTagInBody(p, token); - } else if (tn === $.RT || tn === $.RP) { - rtStartTagInBody(p, token); - } else if (tn !== $.TH && tn !== $.TD && tn !== $.TR) { - genericStartTagInBody(p, token); - } - - break; - - case 3: - if (tn === $.DIV || tn === $.DIR || tn === $.NAV) { - addressStartTagInBody(p, token); - } else if (tn === $.PRE) { - preStartTagInBody(p, token); - } else if (tn === $.BIG) { - bStartTagInBody(p, token); - } else if (tn === $.IMG || tn === $.WBR) { - areaStartTagInBody(p, token); - } else if (tn === $.XMP) { - xmpStartTagInBody(p, token); - } else if (tn === $.SVG) { - svgStartTagInBody(p, token); - } else if (tn === $.RTC) { - rbStartTagInBody(p, token); - } else if (tn !== $.COL) { - genericStartTagInBody(p, token); - } - - break; - - case 4: - if (tn === $.HTML) { - htmlStartTagInBody(p, token); - } else if (tn === $.BASE || tn === $.LINK || tn === $.META) { - startTagInHead(p, token); - } else if (tn === $.BODY) { - bodyStartTagInBody(p, token); - } else if (tn === $.MAIN || tn === $.MENU) { - addressStartTagInBody(p, token); - } else if (tn === $.FORM) { - formStartTagInBody(p, token); - } else if (tn === $.CODE || tn === $.FONT) { - bStartTagInBody(p, token); - } else if (tn === $.NOBR) { - nobrStartTagInBody(p, token); - } else if (tn === $.AREA) { - areaStartTagInBody(p, token); - } else if (tn === $.MATH) { - mathStartTagInBody(p, token); - } else if (tn === $.MENU) { - menuStartTagInBody(p, token); - } else if (tn !== $.HEAD) { - genericStartTagInBody(p, token); - } - - break; - - case 5: - if (tn === $.STYLE || tn === $.TITLE) { - startTagInHead(p, token); - } else if (tn === $.ASIDE) { - addressStartTagInBody(p, token); - } else if (tn === $.SMALL) { - bStartTagInBody(p, token); - } else if (tn === $.TABLE) { - tableStartTagInBody(p, token); - } else if (tn === $.EMBED) { - areaStartTagInBody(p, token); - } else if (tn === $.INPUT) { - inputStartTagInBody(p, token); - } else if (tn === $.PARAM || tn === $.TRACK) { - paramStartTagInBody(p, token); - } else if (tn === $.IMAGE) { - imageStartTagInBody(p, token); - } else if (tn !== $.FRAME && tn !== $.TBODY && tn !== $.TFOOT && tn !== $.THEAD) { - genericStartTagInBody(p, token); - } - - break; - - case 6: - if (tn === $.SCRIPT) { - startTagInHead(p, token); - } else if ( - tn === $.CENTER || - tn === $.FIGURE || - tn === $.FOOTER || - tn === $.HEADER || - tn === $.HGROUP || - tn === $.DIALOG - ) { - addressStartTagInBody(p, token); - } else if (tn === $.BUTTON) { - buttonStartTagInBody(p, token); - } else if (tn === $.STRIKE || tn === $.STRONG) { - bStartTagInBody(p, token); - } else if (tn === $.APPLET || tn === $.OBJECT) { - appletStartTagInBody(p, token); - } else if (tn === $.KEYGEN) { - areaStartTagInBody(p, token); - } else if (tn === $.SOURCE) { - paramStartTagInBody(p, token); - } else if (tn === $.IFRAME) { - iframeStartTagInBody(p, token); - } else if (tn === $.SELECT) { - selectStartTagInBody(p, token); - } else if (tn === $.OPTION) { - optgroupStartTagInBody(p, token); - } else { - genericStartTagInBody(p, token); - } - - break; - - case 7: - if (tn === $.BGSOUND) { - startTagInHead(p, token); - } else if ( - tn === $.DETAILS || - tn === $.ADDRESS || - tn === $.ARTICLE || - tn === $.SECTION || - tn === $.SUMMARY - ) { - addressStartTagInBody(p, token); - } else if (tn === $.LISTING) { - preStartTagInBody(p, token); - } else if (tn === $.MARQUEE) { - appletStartTagInBody(p, token); - } else if (tn === $.NOEMBED) { - noembedStartTagInBody(p, token); - } else if (tn !== $.CAPTION) { - genericStartTagInBody(p, token); - } - - break; - - case 8: - if (tn === $.BASEFONT) { - startTagInHead(p, token); - } else if (tn === $.FRAMESET) { - framesetStartTagInBody(p, token); - } else if (tn === $.FIELDSET) { - addressStartTagInBody(p, token); - } else if (tn === $.TEXTAREA) { - textareaStartTagInBody(p, token); - } else if (tn === $.TEMPLATE) { - startTagInHead(p, token); - } else if (tn === $.NOSCRIPT) { - if (p.options.scriptingEnabled) { - noembedStartTagInBody(p, token); - } else { - genericStartTagInBody(p, token); - } - } else if (tn === $.OPTGROUP) { - optgroupStartTagInBody(p, token); - } else if (tn !== $.COLGROUP) { - genericStartTagInBody(p, token); - } - - break; - - case 9: - if (tn === $.PLAINTEXT) { - plaintextStartTagInBody(p, token); - } else { - genericStartTagInBody(p, token); - } - - break; - - case 10: - if (tn === $.BLOCKQUOTE || tn === $.FIGCAPTION) { - addressStartTagInBody(p, token); - } else { - genericStartTagInBody(p, token); - } - - break; - - default: - genericStartTagInBody(p, token); - } -} - -function bodyEndTagInBody(p) { - if (p.openElements.hasInScope($.BODY)) { - p.insertionMode = AFTER_BODY_MODE; - } -} - -function htmlEndTagInBody(p, token) { - if (p.openElements.hasInScope($.BODY)) { - p.insertionMode = AFTER_BODY_MODE; - p._processToken(token); - } -} - -function addressEndTagInBody(p, token) { - const tn = token.tagName; - - if (p.openElements.hasInScope(tn)) { - p.openElements.generateImpliedEndTags(); - p.openElements.popUntilTagNamePopped(tn); - } -} - -function formEndTagInBody(p) { - const inTemplate = p.openElements.tmplCount > 0; - const formElement = p.formElement; - - if (!inTemplate) { - p.formElement = null; - } - - if ((formElement || inTemplate) && p.openElements.hasInScope($.FORM)) { - p.openElements.generateImpliedEndTags(); - - if (inTemplate) { - p.openElements.popUntilTagNamePopped($.FORM); - } else { - p.openElements.remove(formElement); - } - } -} - -function pEndTagInBody(p) { - if (!p.openElements.hasInButtonScope($.P)) { - p._insertFakeElement($.P); - } - - p._closePElement(); -} - -function liEndTagInBody(p) { - if (p.openElements.hasInListItemScope($.LI)) { - p.openElements.generateImpliedEndTagsWithExclusion($.LI); - p.openElements.popUntilTagNamePopped($.LI); - } -} - -function ddEndTagInBody(p, token) { - const tn = token.tagName; - - if (p.openElements.hasInScope(tn)) { - p.openElements.generateImpliedEndTagsWithExclusion(tn); - p.openElements.popUntilTagNamePopped(tn); - } -} - -function numberedHeaderEndTagInBody(p) { - if (p.openElements.hasNumberedHeaderInScope()) { - p.openElements.generateImpliedEndTags(); - p.openElements.popUntilNumberedHeaderPopped(); - } -} - -function appletEndTagInBody(p, token) { - const tn = token.tagName; - - if (p.openElements.hasInScope(tn)) { - p.openElements.generateImpliedEndTags(); - p.openElements.popUntilTagNamePopped(tn); - p.activeFormattingElements.clearToLastMarker(); - } -} - -function brEndTagInBody(p) { - p._reconstructActiveFormattingElements(); - p._insertFakeElement($.BR); - p.openElements.pop(); - p.framesetOk = false; -} - -function genericEndTagInBody(p, token) { - const tn = token.tagName; - - for (let i = p.openElements.stackTop; i > 0; i--) { - const element = p.openElements.items[i]; - - if (p.treeAdapter.getTagName(element) === tn) { - p.openElements.generateImpliedEndTagsWithExclusion(tn); - p.openElements.popUntilElementPopped(element); - break; - } - - if (p._isSpecialElement(element)) { - break; - } - } -} - -//OPTIMIZATION: Integer comparisons are low-cost, so we can use very fast tag name length filters here. -//It's faster than using dictionary. -function endTagInBody(p, token) { - const tn = token.tagName; - - switch (tn.length) { - case 1: - if (tn === $.A || tn === $.B || tn === $.I || tn === $.S || tn === $.U) { - callAdoptionAgency(p, token); - } else if (tn === $.P) { - pEndTagInBody(p, token); - } else { - genericEndTagInBody(p, token); - } - - break; - - case 2: - if (tn === $.DL || tn === $.UL || tn === $.OL) { - addressEndTagInBody(p, token); - } else if (tn === $.LI) { - liEndTagInBody(p, token); - } else if (tn === $.DD || tn === $.DT) { - ddEndTagInBody(p, token); - } else if (tn === $.H1 || tn === $.H2 || tn === $.H3 || tn === $.H4 || tn === $.H5 || tn === $.H6) { - numberedHeaderEndTagInBody(p, token); - } else if (tn === $.BR) { - brEndTagInBody(p, token); - } else if (tn === $.EM || tn === $.TT) { - callAdoptionAgency(p, token); - } else { - genericEndTagInBody(p, token); - } - - break; - - case 3: - if (tn === $.BIG) { - callAdoptionAgency(p, token); - } else if (tn === $.DIR || tn === $.DIV || tn === $.NAV || tn === $.PRE) { - addressEndTagInBody(p, token); - } else { - genericEndTagInBody(p, token); - } - - break; - - case 4: - if (tn === $.BODY) { - bodyEndTagInBody(p, token); - } else if (tn === $.HTML) { - htmlEndTagInBody(p, token); - } else if (tn === $.FORM) { - formEndTagInBody(p, token); - } else if (tn === $.CODE || tn === $.FONT || tn === $.NOBR) { - callAdoptionAgency(p, token); - } else if (tn === $.MAIN || tn === $.MENU) { - addressEndTagInBody(p, token); - } else { - genericEndTagInBody(p, token); - } - - break; - - case 5: - if (tn === $.ASIDE) { - addressEndTagInBody(p, token); - } else if (tn === $.SMALL) { - callAdoptionAgency(p, token); - } else { - genericEndTagInBody(p, token); - } - - break; - - case 6: - if ( - tn === $.CENTER || - tn === $.FIGURE || - tn === $.FOOTER || - tn === $.HEADER || - tn === $.HGROUP || - tn === $.DIALOG - ) { - addressEndTagInBody(p, token); - } else if (tn === $.APPLET || tn === $.OBJECT) { - appletEndTagInBody(p, token); - } else if (tn === $.STRIKE || tn === $.STRONG) { - callAdoptionAgency(p, token); - } else { - genericEndTagInBody(p, token); - } - - break; - - case 7: - if ( - tn === $.ADDRESS || - tn === $.ARTICLE || - tn === $.DETAILS || - tn === $.SECTION || - tn === $.SUMMARY || - tn === $.LISTING - ) { - addressEndTagInBody(p, token); - } else if (tn === $.MARQUEE) { - appletEndTagInBody(p, token); - } else { - genericEndTagInBody(p, token); - } - - break; - - case 8: - if (tn === $.FIELDSET) { - addressEndTagInBody(p, token); - } else if (tn === $.TEMPLATE) { - endTagInHead(p, token); - } else { - genericEndTagInBody(p, token); - } - - break; - - case 10: - if (tn === $.BLOCKQUOTE || tn === $.FIGCAPTION) { - addressEndTagInBody(p, token); - } else { - genericEndTagInBody(p, token); - } - - break; - - default: - genericEndTagInBody(p, token); - } -} - -function eofInBody(p, token) { - if (p.tmplInsertionModeStackTop > -1) { - eofInTemplate(p, token); - } else { - p.stopped = true; - } -} - -// The "text" insertion mode -//------------------------------------------------------------------ -function endTagInText(p, token) { - if (token.tagName === $.SCRIPT) { - p.pendingScript = p.openElements.current; - } - - p.openElements.pop(); - p.insertionMode = p.originalInsertionMode; -} - -function eofInText(p, token) { - p._err(ERR.eofInElementThatCanContainOnlyText); - p.openElements.pop(); - p.insertionMode = p.originalInsertionMode; - p._processToken(token); -} - -// The "in table" insertion mode -//------------------------------------------------------------------ -function characterInTable(p, token) { - const curTn = p.openElements.currentTagName; - - if (curTn === $.TABLE || curTn === $.TBODY || curTn === $.TFOOT || curTn === $.THEAD || curTn === $.TR) { - p.pendingCharacterTokens = []; - p.hasNonWhitespacePendingCharacterToken = false; - p.originalInsertionMode = p.insertionMode; - p.insertionMode = IN_TABLE_TEXT_MODE; - p._processToken(token); - } else { - tokenInTable(p, token); - } -} - -function captionStartTagInTable(p, token) { - p.openElements.clearBackToTableContext(); - p.activeFormattingElements.insertMarker(); - p._insertElement(token, NS.HTML); - p.insertionMode = IN_CAPTION_MODE; -} - -function colgroupStartTagInTable(p, token) { - p.openElements.clearBackToTableContext(); - p._insertElement(token, NS.HTML); - p.insertionMode = IN_COLUMN_GROUP_MODE; -} - -function colStartTagInTable(p, token) { - p.openElements.clearBackToTableContext(); - p._insertFakeElement($.COLGROUP); - p.insertionMode = IN_COLUMN_GROUP_MODE; - p._processToken(token); -} - -function tbodyStartTagInTable(p, token) { - p.openElements.clearBackToTableContext(); - p._insertElement(token, NS.HTML); - p.insertionMode = IN_TABLE_BODY_MODE; -} - -function tdStartTagInTable(p, token) { - p.openElements.clearBackToTableContext(); - p._insertFakeElement($.TBODY); - p.insertionMode = IN_TABLE_BODY_MODE; - p._processToken(token); -} - -function tableStartTagInTable(p, token) { - if (p.openElements.hasInTableScope($.TABLE)) { - p.openElements.popUntilTagNamePopped($.TABLE); - p._resetInsertionMode(); - p._processToken(token); - } -} - -function inputStartTagInTable(p, token) { - const inputType = Tokenizer.getTokenAttr(token, ATTRS.TYPE); - - if (inputType && inputType.toLowerCase() === HIDDEN_INPUT_TYPE) { - p._appendElement(token, NS.HTML); - } else { - tokenInTable(p, token); - } - - token.ackSelfClosing = true; -} - -function formStartTagInTable(p, token) { - if (!p.formElement && p.openElements.tmplCount === 0) { - p._insertElement(token, NS.HTML); - p.formElement = p.openElements.current; - p.openElements.pop(); - } -} - -function startTagInTable(p, token) { - const tn = token.tagName; - - switch (tn.length) { - case 2: - if (tn === $.TD || tn === $.TH || tn === $.TR) { - tdStartTagInTable(p, token); - } else { - tokenInTable(p, token); - } - - break; - - case 3: - if (tn === $.COL) { - colStartTagInTable(p, token); - } else { - tokenInTable(p, token); - } - - break; - - case 4: - if (tn === $.FORM) { - formStartTagInTable(p, token); - } else { - tokenInTable(p, token); - } - - break; - - case 5: - if (tn === $.TABLE) { - tableStartTagInTable(p, token); - } else if (tn === $.STYLE) { - startTagInHead(p, token); - } else if (tn === $.TBODY || tn === $.TFOOT || tn === $.THEAD) { - tbodyStartTagInTable(p, token); - } else if (tn === $.INPUT) { - inputStartTagInTable(p, token); - } else { - tokenInTable(p, token); - } - - break; - - case 6: - if (tn === $.SCRIPT) { - startTagInHead(p, token); - } else { - tokenInTable(p, token); - } - - break; - - case 7: - if (tn === $.CAPTION) { - captionStartTagInTable(p, token); - } else { - tokenInTable(p, token); - } - - break; - - case 8: - if (tn === $.COLGROUP) { - colgroupStartTagInTable(p, token); - } else if (tn === $.TEMPLATE) { - startTagInHead(p, token); - } else { - tokenInTable(p, token); - } - - break; - - default: - tokenInTable(p, token); - } -} - -function endTagInTable(p, token) { - const tn = token.tagName; - - if (tn === $.TABLE) { - if (p.openElements.hasInTableScope($.TABLE)) { - p.openElements.popUntilTagNamePopped($.TABLE); - p._resetInsertionMode(); - } - } else if (tn === $.TEMPLATE) { - endTagInHead(p, token); - } else if ( - tn !== $.BODY && - tn !== $.CAPTION && - tn !== $.COL && - tn !== $.COLGROUP && - tn !== $.HTML && - tn !== $.TBODY && - tn !== $.TD && - tn !== $.TFOOT && - tn !== $.TH && - tn !== $.THEAD && - tn !== $.TR - ) { - tokenInTable(p, token); - } -} - -function tokenInTable(p, token) { - const savedFosterParentingState = p.fosterParentingEnabled; - - p.fosterParentingEnabled = true; - p._processTokenInBodyMode(token); - p.fosterParentingEnabled = savedFosterParentingState; -} - -// The "in table text" insertion mode -//------------------------------------------------------------------ -function whitespaceCharacterInTableText(p, token) { - p.pendingCharacterTokens.push(token); -} - -function characterInTableText(p, token) { - p.pendingCharacterTokens.push(token); - p.hasNonWhitespacePendingCharacterToken = true; -} - -function tokenInTableText(p, token) { - let i = 0; - - if (p.hasNonWhitespacePendingCharacterToken) { - for (; i < p.pendingCharacterTokens.length; i++) { - tokenInTable(p, p.pendingCharacterTokens[i]); - } - } else { - for (; i < p.pendingCharacterTokens.length; i++) { - p._insertCharacters(p.pendingCharacterTokens[i]); - } - } - - p.insertionMode = p.originalInsertionMode; - p._processToken(token); -} - -// The "in caption" insertion mode -//------------------------------------------------------------------ -function startTagInCaption(p, token) { - const tn = token.tagName; - - if ( - tn === $.CAPTION || - tn === $.COL || - tn === $.COLGROUP || - tn === $.TBODY || - tn === $.TD || - tn === $.TFOOT || - tn === $.TH || - tn === $.THEAD || - tn === $.TR - ) { - if (p.openElements.hasInTableScope($.CAPTION)) { - p.openElements.generateImpliedEndTags(); - p.openElements.popUntilTagNamePopped($.CAPTION); - p.activeFormattingElements.clearToLastMarker(); - p.insertionMode = IN_TABLE_MODE; - p._processToken(token); - } - } else { - startTagInBody(p, token); - } -} - -function endTagInCaption(p, token) { - const tn = token.tagName; - - if (tn === $.CAPTION || tn === $.TABLE) { - if (p.openElements.hasInTableScope($.CAPTION)) { - p.openElements.generateImpliedEndTags(); - p.openElements.popUntilTagNamePopped($.CAPTION); - p.activeFormattingElements.clearToLastMarker(); - p.insertionMode = IN_TABLE_MODE; - - if (tn === $.TABLE) { - p._processToken(token); - } - } - } else if ( - tn !== $.BODY && - tn !== $.COL && - tn !== $.COLGROUP && - tn !== $.HTML && - tn !== $.TBODY && - tn !== $.TD && - tn !== $.TFOOT && - tn !== $.TH && - tn !== $.THEAD && - tn !== $.TR - ) { - endTagInBody(p, token); - } -} - -// The "in column group" insertion mode -//------------------------------------------------------------------ -function startTagInColumnGroup(p, token) { - const tn = token.tagName; - - if (tn === $.HTML) { - startTagInBody(p, token); - } else if (tn === $.COL) { - p._appendElement(token, NS.HTML); - token.ackSelfClosing = true; - } else if (tn === $.TEMPLATE) { - startTagInHead(p, token); - } else { - tokenInColumnGroup(p, token); - } -} - -function endTagInColumnGroup(p, token) { - const tn = token.tagName; - - if (tn === $.COLGROUP) { - if (p.openElements.currentTagName === $.COLGROUP) { - p.openElements.pop(); - p.insertionMode = IN_TABLE_MODE; - } - } else if (tn === $.TEMPLATE) { - endTagInHead(p, token); - } else if (tn !== $.COL) { - tokenInColumnGroup(p, token); - } -} - -function tokenInColumnGroup(p, token) { - if (p.openElements.currentTagName === $.COLGROUP) { - p.openElements.pop(); - p.insertionMode = IN_TABLE_MODE; - p._processToken(token); - } -} - -// The "in table body" insertion mode -//------------------------------------------------------------------ -function startTagInTableBody(p, token) { - const tn = token.tagName; - - if (tn === $.TR) { - p.openElements.clearBackToTableBodyContext(); - p._insertElement(token, NS.HTML); - p.insertionMode = IN_ROW_MODE; - } else if (tn === $.TH || tn === $.TD) { - p.openElements.clearBackToTableBodyContext(); - p._insertFakeElement($.TR); - p.insertionMode = IN_ROW_MODE; - p._processToken(token); - } else if ( - tn === $.CAPTION || - tn === $.COL || - tn === $.COLGROUP || - tn === $.TBODY || - tn === $.TFOOT || - tn === $.THEAD - ) { - if (p.openElements.hasTableBodyContextInTableScope()) { - p.openElements.clearBackToTableBodyContext(); - p.openElements.pop(); - p.insertionMode = IN_TABLE_MODE; - p._processToken(token); - } - } else { - startTagInTable(p, token); - } -} - -function endTagInTableBody(p, token) { - const tn = token.tagName; - - if (tn === $.TBODY || tn === $.TFOOT || tn === $.THEAD) { - if (p.openElements.hasInTableScope(tn)) { - p.openElements.clearBackToTableBodyContext(); - p.openElements.pop(); - p.insertionMode = IN_TABLE_MODE; - } - } else if (tn === $.TABLE) { - if (p.openElements.hasTableBodyContextInTableScope()) { - p.openElements.clearBackToTableBodyContext(); - p.openElements.pop(); - p.insertionMode = IN_TABLE_MODE; - p._processToken(token); - } - } else if ( - (tn !== $.BODY && tn !== $.CAPTION && tn !== $.COL && tn !== $.COLGROUP) || - (tn !== $.HTML && tn !== $.TD && tn !== $.TH && tn !== $.TR) - ) { - endTagInTable(p, token); - } -} - -// The "in row" insertion mode -//------------------------------------------------------------------ -function startTagInRow(p, token) { - const tn = token.tagName; - - if (tn === $.TH || tn === $.TD) { - p.openElements.clearBackToTableRowContext(); - p._insertElement(token, NS.HTML); - p.insertionMode = IN_CELL_MODE; - p.activeFormattingElements.insertMarker(); - } else if ( - tn === $.CAPTION || - tn === $.COL || - tn === $.COLGROUP || - tn === $.TBODY || - tn === $.TFOOT || - tn === $.THEAD || - tn === $.TR - ) { - if (p.openElements.hasInTableScope($.TR)) { - p.openElements.clearBackToTableRowContext(); - p.openElements.pop(); - p.insertionMode = IN_TABLE_BODY_MODE; - p._processToken(token); - } - } else { - startTagInTable(p, token); - } -} - -function endTagInRow(p, token) { - const tn = token.tagName; - - if (tn === $.TR) { - if (p.openElements.hasInTableScope($.TR)) { - p.openElements.clearBackToTableRowContext(); - p.openElements.pop(); - p.insertionMode = IN_TABLE_BODY_MODE; - } - } else if (tn === $.TABLE) { - if (p.openElements.hasInTableScope($.TR)) { - p.openElements.clearBackToTableRowContext(); - p.openElements.pop(); - p.insertionMode = IN_TABLE_BODY_MODE; - p._processToken(token); - } - } else if (tn === $.TBODY || tn === $.TFOOT || tn === $.THEAD) { - if (p.openElements.hasInTableScope(tn) || p.openElements.hasInTableScope($.TR)) { - p.openElements.clearBackToTableRowContext(); - p.openElements.pop(); - p.insertionMode = IN_TABLE_BODY_MODE; - p._processToken(token); - } - } else if ( - (tn !== $.BODY && tn !== $.CAPTION && tn !== $.COL && tn !== $.COLGROUP) || - (tn !== $.HTML && tn !== $.TD && tn !== $.TH) - ) { - endTagInTable(p, token); - } -} - -// The "in cell" insertion mode -//------------------------------------------------------------------ -function startTagInCell(p, token) { - const tn = token.tagName; - - if ( - tn === $.CAPTION || - tn === $.COL || - tn === $.COLGROUP || - tn === $.TBODY || - tn === $.TD || - tn === $.TFOOT || - tn === $.TH || - tn === $.THEAD || - tn === $.TR - ) { - if (p.openElements.hasInTableScope($.TD) || p.openElements.hasInTableScope($.TH)) { - p._closeTableCell(); - p._processToken(token); - } - } else { - startTagInBody(p, token); - } -} - -function endTagInCell(p, token) { - const tn = token.tagName; - - if (tn === $.TD || tn === $.TH) { - if (p.openElements.hasInTableScope(tn)) { - p.openElements.generateImpliedEndTags(); - p.openElements.popUntilTagNamePopped(tn); - p.activeFormattingElements.clearToLastMarker(); - p.insertionMode = IN_ROW_MODE; - } - } else if (tn === $.TABLE || tn === $.TBODY || tn === $.TFOOT || tn === $.THEAD || tn === $.TR) { - if (p.openElements.hasInTableScope(tn)) { - p._closeTableCell(); - p._processToken(token); - } - } else if (tn !== $.BODY && tn !== $.CAPTION && tn !== $.COL && tn !== $.COLGROUP && tn !== $.HTML) { - endTagInBody(p, token); - } -} - -// The "in select" insertion mode -//------------------------------------------------------------------ -function startTagInSelect(p, token) { - const tn = token.tagName; - - if (tn === $.HTML) { - startTagInBody(p, token); - } else if (tn === $.OPTION) { - if (p.openElements.currentTagName === $.OPTION) { - p.openElements.pop(); - } - - p._insertElement(token, NS.HTML); - } else if (tn === $.OPTGROUP) { - if (p.openElements.currentTagName === $.OPTION) { - p.openElements.pop(); - } - - if (p.openElements.currentTagName === $.OPTGROUP) { - p.openElements.pop(); - } - - p._insertElement(token, NS.HTML); - } else if (tn === $.INPUT || tn === $.KEYGEN || tn === $.TEXTAREA || tn === $.SELECT) { - if (p.openElements.hasInSelectScope($.SELECT)) { - p.openElements.popUntilTagNamePopped($.SELECT); - p._resetInsertionMode(); - - if (tn !== $.SELECT) { - p._processToken(token); - } - } - } else if (tn === $.SCRIPT || tn === $.TEMPLATE) { - startTagInHead(p, token); - } -} - -function endTagInSelect(p, token) { - const tn = token.tagName; - - if (tn === $.OPTGROUP) { - const prevOpenElement = p.openElements.items[p.openElements.stackTop - 1]; - const prevOpenElementTn = prevOpenElement && p.treeAdapter.getTagName(prevOpenElement); - - if (p.openElements.currentTagName === $.OPTION && prevOpenElementTn === $.OPTGROUP) { - p.openElements.pop(); - } - - if (p.openElements.currentTagName === $.OPTGROUP) { - p.openElements.pop(); - } - } else if (tn === $.OPTION) { - if (p.openElements.currentTagName === $.OPTION) { - p.openElements.pop(); - } - } else if (tn === $.SELECT && p.openElements.hasInSelectScope($.SELECT)) { - p.openElements.popUntilTagNamePopped($.SELECT); - p._resetInsertionMode(); - } else if (tn === $.TEMPLATE) { - endTagInHead(p, token); - } -} - -//12.2.5.4.17 The "in select in table" insertion mode -//------------------------------------------------------------------ -function startTagInSelectInTable(p, token) { - const tn = token.tagName; - - if ( - tn === $.CAPTION || - tn === $.TABLE || - tn === $.TBODY || - tn === $.TFOOT || - tn === $.THEAD || - tn === $.TR || - tn === $.TD || - tn === $.TH - ) { - p.openElements.popUntilTagNamePopped($.SELECT); - p._resetInsertionMode(); - p._processToken(token); - } else { - startTagInSelect(p, token); - } -} - -function endTagInSelectInTable(p, token) { - const tn = token.tagName; - - if ( - tn === $.CAPTION || - tn === $.TABLE || - tn === $.TBODY || - tn === $.TFOOT || - tn === $.THEAD || - tn === $.TR || - tn === $.TD || - tn === $.TH - ) { - if (p.openElements.hasInTableScope(tn)) { - p.openElements.popUntilTagNamePopped($.SELECT); - p._resetInsertionMode(); - p._processToken(token); - } - } else { - endTagInSelect(p, token); - } -} - -// The "in template" insertion mode -//------------------------------------------------------------------ -function startTagInTemplate(p, token) { - const tn = token.tagName; - - if ( - tn === $.BASE || - tn === $.BASEFONT || - tn === $.BGSOUND || - tn === $.LINK || - tn === $.META || - tn === $.NOFRAMES || - tn === $.SCRIPT || - tn === $.STYLE || - tn === $.TEMPLATE || - tn === $.TITLE - ) { - startTagInHead(p, token); - } else { - const newInsertionMode = TEMPLATE_INSERTION_MODE_SWITCH_MAP[tn] || IN_BODY_MODE; - - p._popTmplInsertionMode(); - p._pushTmplInsertionMode(newInsertionMode); - p.insertionMode = newInsertionMode; - p._processToken(token); - } -} - -function endTagInTemplate(p, token) { - if (token.tagName === $.TEMPLATE) { - endTagInHead(p, token); - } -} - -function eofInTemplate(p, token) { - if (p.openElements.tmplCount > 0) { - p.openElements.popUntilTagNamePopped($.TEMPLATE); - p.activeFormattingElements.clearToLastMarker(); - p._popTmplInsertionMode(); - p._resetInsertionMode(); - p._processToken(token); - } else { - p.stopped = true; - } -} - -// The "after body" insertion mode -//------------------------------------------------------------------ -function startTagAfterBody(p, token) { - if (token.tagName === $.HTML) { - startTagInBody(p, token); - } else { - tokenAfterBody(p, token); - } -} - -function endTagAfterBody(p, token) { - if (token.tagName === $.HTML) { - if (!p.fragmentContext) { - p.insertionMode = AFTER_AFTER_BODY_MODE; - } - } else { - tokenAfterBody(p, token); - } -} - -function tokenAfterBody(p, token) { - p.insertionMode = IN_BODY_MODE; - p._processToken(token); -} - -// The "in frameset" insertion mode -//------------------------------------------------------------------ -function startTagInFrameset(p, token) { - const tn = token.tagName; - - if (tn === $.HTML) { - startTagInBody(p, token); - } else if (tn === $.FRAMESET) { - p._insertElement(token, NS.HTML); - } else if (tn === $.FRAME) { - p._appendElement(token, NS.HTML); - token.ackSelfClosing = true; - } else if (tn === $.NOFRAMES) { - startTagInHead(p, token); - } -} - -function endTagInFrameset(p, token) { - if (token.tagName === $.FRAMESET && !p.openElements.isRootHtmlElementCurrent()) { - p.openElements.pop(); - - if (!p.fragmentContext && p.openElements.currentTagName !== $.FRAMESET) { - p.insertionMode = AFTER_FRAMESET_MODE; - } - } -} - -// The "after frameset" insertion mode -//------------------------------------------------------------------ -function startTagAfterFrameset(p, token) { - const tn = token.tagName; - - if (tn === $.HTML) { - startTagInBody(p, token); - } else if (tn === $.NOFRAMES) { - startTagInHead(p, token); - } -} - -function endTagAfterFrameset(p, token) { - if (token.tagName === $.HTML) { - p.insertionMode = AFTER_AFTER_FRAMESET_MODE; - } -} - -// The "after after body" insertion mode -//------------------------------------------------------------------ -function startTagAfterAfterBody(p, token) { - if (token.tagName === $.HTML) { - startTagInBody(p, token); - } else { - tokenAfterAfterBody(p, token); - } -} - -function tokenAfterAfterBody(p, token) { - p.insertionMode = IN_BODY_MODE; - p._processToken(token); -} - -// The "after after frameset" insertion mode -//------------------------------------------------------------------ -function startTagAfterAfterFrameset(p, token) { - const tn = token.tagName; - - if (tn === $.HTML) { - startTagInBody(p, token); - } else if (tn === $.NOFRAMES) { - startTagInHead(p, token); - } -} - -// The rules for parsing tokens in foreign content -//------------------------------------------------------------------ -function nullCharacterInForeignContent(p, token) { - token.chars = unicode.REPLACEMENT_CHARACTER; - p._insertCharacters(token); -} - -function characterInForeignContent(p, token) { - p._insertCharacters(token); - p.framesetOk = false; -} - -function startTagInForeignContent(p, token) { - if (foreignContent.causesExit(token) && !p.fragmentContext) { - while ( - p.treeAdapter.getNamespaceURI(p.openElements.current) !== NS.HTML && - !p._isIntegrationPoint(p.openElements.current) - ) { - p.openElements.pop(); - } - - p._processToken(token); - } else { - const current = p._getAdjustedCurrentElement(); - const currentNs = p.treeAdapter.getNamespaceURI(current); - - if (currentNs === NS.MATHML) { - foreignContent.adjustTokenMathMLAttrs(token); - } else if (currentNs === NS.SVG) { - foreignContent.adjustTokenSVGTagName(token); - foreignContent.adjustTokenSVGAttrs(token); - } - - foreignContent.adjustTokenXMLAttrs(token); - - if (token.selfClosing) { - p._appendElement(token, currentNs); - } else { - p._insertElement(token, currentNs); - } - - token.ackSelfClosing = true; - } -} - -function endTagInForeignContent(p, token) { - for (let i = p.openElements.stackTop; i > 0; i--) { - const element = p.openElements.items[i]; - - if (p.treeAdapter.getNamespaceURI(element) === NS.HTML) { - p._processToken(token); - break; - } - - if (p.treeAdapter.getTagName(element).toLowerCase() === token.tagName) { - p.openElements.popUntilElementPopped(element); - break; - } - } -} |