| Index: node_modules/vulcanize/node_modules/whacko/node_modules/parse5/lib/tree_construction/parser.js
|
| diff --git a/node_modules/vulcanize/node_modules/whacko/node_modules/parse5/lib/tree_construction/parser.js b/node_modules/vulcanize/node_modules/whacko/node_modules/parse5/lib/tree_construction/parser.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..42cf8e15084735d689ea8e63c0c726280f5119d9
|
| --- /dev/null
|
| +++ b/node_modules/vulcanize/node_modules/whacko/node_modules/parse5/lib/tree_construction/parser.js
|
| @@ -0,0 +1,2810 @@
|
| +'use strict';
|
| +
|
| +var Tokenizer = require('../tokenization/tokenizer'),
|
| + OpenElementStack = require('./open_element_stack'),
|
| + FormattingElementList = require('./formatting_element_list'),
|
| + Doctype = require('./doctype'),
|
| + DefaultTreeAdapter = require('../tree_adapters/default'),
|
| + ForeignContent = require('../common/foreign_content'),
|
| + UNICODE = require('../common/unicode'),
|
| + HTML = require('../common/html');
|
| +
|
| +//Aliases
|
| +var $ = HTML.TAG_NAMES,
|
| + NS = HTML.NAMESPACES,
|
| + ATTRS = HTML.ATTRS;
|
| +
|
| +//Misc constants
|
| +var SEARCHABLE_INDEX_DEFAULT_PROMPT = 'This is a searchable index. Enter search keywords: ',
|
| + SEARCHABLE_INDEX_INPUT_NAME = 'isindex',
|
| + HIDDEN_INPUT_TYPE = 'hidden';
|
| +
|
| +//Adoption agency loops iteration count
|
| +var AA_OUTER_LOOP_ITER = 8,
|
| + AA_INNER_LOOP_ITER = 3;
|
| +
|
| +//Insertion modes
|
| +var INITIAL_MODE = 'INITIAL_MODE',
|
| + BEFORE_HTML_MODE = 'BEFORE_HTML_MODE',
|
| + BEFORE_HEAD_MODE = 'BEFORE_HEAD_MODE',
|
| + IN_HEAD_MODE = 'IN_HEAD_MODE',
|
| + AFTER_HEAD_MODE = 'AFTER_HEAD_MODE',
|
| + IN_BODY_MODE = 'IN_BODY_MODE',
|
| + TEXT_MODE = 'TEXT_MODE',
|
| + IN_TABLE_MODE = 'IN_TABLE_MODE',
|
| + IN_TABLE_TEXT_MODE = 'IN_TABLE_TEXT_MODE',
|
| + IN_CAPTION_MODE = 'IN_CAPTION_MODE',
|
| + IN_COLUMN_GROUP_MODE = 'IN_COLUMN_GROUP_MODE',
|
| + IN_TABLE_BODY_MODE = 'IN_TABLE_BODY_MODE',
|
| + IN_ROW_MODE = 'IN_ROW_MODE',
|
| + IN_CELL_MODE = 'IN_CELL_MODE',
|
| + IN_SELECT_MODE = 'IN_SELECT_MODE',
|
| + IN_SELECT_IN_TABLE_MODE = 'IN_SELECT_IN_TABLE_MODE',
|
| + IN_TEMPLATE_MODE = 'IN_TEMPLATE_MODE',
|
| + AFTER_BODY_MODE = 'AFTER_BODY_MODE',
|
| + IN_FRAMESET_MODE = 'IN_FRAMESET_MODE',
|
| + AFTER_FRAMESET_MODE = 'AFTER_FRAMESET_MODE',
|
| + AFTER_AFTER_BODY_MODE = 'AFTER_AFTER_BODY_MODE',
|
| + AFTER_AFTER_FRAMESET_MODE = 'AFTER_AFTER_FRAMESET_MODE';
|
| +
|
| +//Insertion mode reset map
|
| +var INSERTION_MODE_RESET_MAP = {};
|
| +
|
| +INSERTION_MODE_RESET_MAP[$.TR] = IN_ROW_MODE;
|
| +INSERTION_MODE_RESET_MAP[$.TBODY] =
|
| +INSERTION_MODE_RESET_MAP[$.THEAD] =
|
| +INSERTION_MODE_RESET_MAP[$.TFOOT] = IN_TABLE_BODY_MODE;
|
| +INSERTION_MODE_RESET_MAP[$.CAPTION] = IN_CAPTION_MODE;
|
| +INSERTION_MODE_RESET_MAP[$.COLGROUP] = IN_COLUMN_GROUP_MODE;
|
| +INSERTION_MODE_RESET_MAP[$.TABLE] = IN_TABLE_MODE;
|
| +INSERTION_MODE_RESET_MAP[$.BODY] = IN_BODY_MODE;
|
| +INSERTION_MODE_RESET_MAP[$.FRAMESET] = IN_FRAMESET_MODE;
|
| +
|
| +//Template insertion mode switch map
|
| +var TEMPLATE_INSERTION_MODE_SWITCH_MAP = {};
|
| +
|
| +TEMPLATE_INSERTION_MODE_SWITCH_MAP[$.CAPTION] =
|
| +TEMPLATE_INSERTION_MODE_SWITCH_MAP[$.COLGROUP] =
|
| +TEMPLATE_INSERTION_MODE_SWITCH_MAP[$.TBODY] =
|
| +TEMPLATE_INSERTION_MODE_SWITCH_MAP[$.TFOOT] =
|
| +TEMPLATE_INSERTION_MODE_SWITCH_MAP[$.THEAD] = IN_TABLE_MODE;
|
| +TEMPLATE_INSERTION_MODE_SWITCH_MAP[$.COL] = IN_COLUMN_GROUP_MODE;
|
| +TEMPLATE_INSERTION_MODE_SWITCH_MAP[$.TR] = IN_TABLE_BODY_MODE;
|
| +TEMPLATE_INSERTION_MODE_SWITCH_MAP[$.TD] =
|
| +TEMPLATE_INSERTION_MODE_SWITCH_MAP[$.TH] = IN_ROW_MODE;
|
| +
|
| +//Token handlers map for insertion modes
|
| +var _ = {};
|
| +
|
| +_[INITIAL_MODE] = {};
|
| +_[INITIAL_MODE][Tokenizer.CHARACTER_TOKEN] =
|
| +_[INITIAL_MODE][Tokenizer.NULL_CHARACTER_TOKEN] = tokenInInitialMode;
|
| +_[INITIAL_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = ignoreToken;
|
| +_[INITIAL_MODE][Tokenizer.COMMENT_TOKEN] = appendComment;
|
| +_[INITIAL_MODE][Tokenizer.DOCTYPE_TOKEN] = doctypeInInitialMode;
|
| +_[INITIAL_MODE][Tokenizer.START_TAG_TOKEN] =
|
| +_[INITIAL_MODE][Tokenizer.END_TAG_TOKEN] =
|
| +_[INITIAL_MODE][Tokenizer.EOF_TOKEN] = tokenInInitialMode;
|
| +
|
| +_[BEFORE_HTML_MODE] = {};
|
| +_[BEFORE_HTML_MODE][Tokenizer.CHARACTER_TOKEN] =
|
| +_[BEFORE_HTML_MODE][Tokenizer.NULL_CHARACTER_TOKEN] = tokenBeforeHtml;
|
| +_[BEFORE_HTML_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = ignoreToken;
|
| +_[BEFORE_HTML_MODE][Tokenizer.COMMENT_TOKEN] = appendComment;
|
| +_[BEFORE_HTML_MODE][Tokenizer.DOCTYPE_TOKEN] = ignoreToken;
|
| +_[BEFORE_HTML_MODE][Tokenizer.START_TAG_TOKEN] = startTagBeforeHtml;
|
| +_[BEFORE_HTML_MODE][Tokenizer.END_TAG_TOKEN] = endTagBeforeHtml;
|
| +_[BEFORE_HTML_MODE][Tokenizer.EOF_TOKEN] = tokenBeforeHtml;
|
| +
|
| +_[BEFORE_HEAD_MODE] = {};
|
| +_[BEFORE_HEAD_MODE][Tokenizer.CHARACTER_TOKEN] =
|
| +_[BEFORE_HEAD_MODE][Tokenizer.NULL_CHARACTER_TOKEN] = tokenBeforeHead;
|
| +_[BEFORE_HEAD_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = ignoreToken;
|
| +_[BEFORE_HEAD_MODE][Tokenizer.COMMENT_TOKEN] = appendComment;
|
| +_[BEFORE_HEAD_MODE][Tokenizer.DOCTYPE_TOKEN] = ignoreToken;
|
| +_[BEFORE_HEAD_MODE][Tokenizer.START_TAG_TOKEN] = startTagBeforeHead;
|
| +_[BEFORE_HEAD_MODE][Tokenizer.END_TAG_TOKEN] = endTagBeforeHead;
|
| +_[BEFORE_HEAD_MODE][Tokenizer.EOF_TOKEN] = tokenBeforeHead;
|
| +
|
| +_[IN_HEAD_MODE] = {};
|
| +_[IN_HEAD_MODE][Tokenizer.CHARACTER_TOKEN] =
|
| +_[IN_HEAD_MODE][Tokenizer.NULL_CHARACTER_TOKEN] = tokenInHead;
|
| +_[IN_HEAD_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = insertCharacters;
|
| +_[IN_HEAD_MODE][Tokenizer.COMMENT_TOKEN] = appendComment;
|
| +_[IN_HEAD_MODE][Tokenizer.DOCTYPE_TOKEN] = ignoreToken;
|
| +_[IN_HEAD_MODE][Tokenizer.START_TAG_TOKEN] = startTagInHead;
|
| +_[IN_HEAD_MODE][Tokenizer.END_TAG_TOKEN] = endTagInHead;
|
| +_[IN_HEAD_MODE][Tokenizer.EOF_TOKEN] = tokenInHead;
|
| +
|
| +_[AFTER_HEAD_MODE] = {};
|
| +_[AFTER_HEAD_MODE][Tokenizer.CHARACTER_TOKEN] =
|
| +_[AFTER_HEAD_MODE][Tokenizer.NULL_CHARACTER_TOKEN] = tokenAfterHead;
|
| +_[AFTER_HEAD_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = insertCharacters;
|
| +_[AFTER_HEAD_MODE][Tokenizer.COMMENT_TOKEN] = appendComment;
|
| +_[AFTER_HEAD_MODE][Tokenizer.DOCTYPE_TOKEN] = ignoreToken;
|
| +_[AFTER_HEAD_MODE][Tokenizer.START_TAG_TOKEN] = startTagAfterHead;
|
| +_[AFTER_HEAD_MODE][Tokenizer.END_TAG_TOKEN] = endTagAfterHead;
|
| +_[AFTER_HEAD_MODE][Tokenizer.EOF_TOKEN] = tokenAfterHead;
|
| +
|
| +_[IN_BODY_MODE] = {};
|
| +_[IN_BODY_MODE][Tokenizer.CHARACTER_TOKEN] = characterInBody;
|
| +_[IN_BODY_MODE][Tokenizer.NULL_CHARACTER_TOKEN] = ignoreToken;
|
| +_[IN_BODY_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = whitespaceCharacterInBody;
|
| +_[IN_BODY_MODE][Tokenizer.COMMENT_TOKEN] = appendComment;
|
| +_[IN_BODY_MODE][Tokenizer.DOCTYPE_TOKEN] = ignoreToken;
|
| +_[IN_BODY_MODE][Tokenizer.START_TAG_TOKEN] = startTagInBody;
|
| +_[IN_BODY_MODE][Tokenizer.END_TAG_TOKEN] = endTagInBody;
|
| +_[IN_BODY_MODE][Tokenizer.EOF_TOKEN] = eofInBody;
|
| +
|
| +_[TEXT_MODE] = {};
|
| +_[TEXT_MODE][Tokenizer.CHARACTER_TOKEN] =
|
| +_[TEXT_MODE][Tokenizer.NULL_CHARACTER_TOKEN] =
|
| +_[TEXT_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = insertCharacters;
|
| +_[TEXT_MODE][Tokenizer.COMMENT_TOKEN] =
|
| +_[TEXT_MODE][Tokenizer.DOCTYPE_TOKEN] =
|
| +_[TEXT_MODE][Tokenizer.START_TAG_TOKEN] = ignoreToken;
|
| +_[TEXT_MODE][Tokenizer.END_TAG_TOKEN] = endTagInText;
|
| +_[TEXT_MODE][Tokenizer.EOF_TOKEN] = eofInText;
|
| +
|
| +_[IN_TABLE_MODE] = {};
|
| +_[IN_TABLE_MODE][Tokenizer.CHARACTER_TOKEN] =
|
| +_[IN_TABLE_MODE][Tokenizer.NULL_CHARACTER_TOKEN] =
|
| +_[IN_TABLE_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = characterInTable;
|
| +_[IN_TABLE_MODE][Tokenizer.COMMENT_TOKEN] = appendComment;
|
| +_[IN_TABLE_MODE][Tokenizer.DOCTYPE_TOKEN] = ignoreToken;
|
| +_[IN_TABLE_MODE][Tokenizer.START_TAG_TOKEN] = startTagInTable;
|
| +_[IN_TABLE_MODE][Tokenizer.END_TAG_TOKEN] = endTagInTable;
|
| +_[IN_TABLE_MODE][Tokenizer.EOF_TOKEN] = eofInBody;
|
| +
|
| +_[IN_TABLE_TEXT_MODE] = {};
|
| +_[IN_TABLE_TEXT_MODE][Tokenizer.CHARACTER_TOKEN] = characterInTableText;
|
| +_[IN_TABLE_TEXT_MODE][Tokenizer.NULL_CHARACTER_TOKEN] = ignoreToken;
|
| +_[IN_TABLE_TEXT_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = whitespaceCharacterInTableText;
|
| +_[IN_TABLE_TEXT_MODE][Tokenizer.COMMENT_TOKEN] =
|
| +_[IN_TABLE_TEXT_MODE][Tokenizer.DOCTYPE_TOKEN] =
|
| +_[IN_TABLE_TEXT_MODE][Tokenizer.START_TAG_TOKEN] =
|
| +_[IN_TABLE_TEXT_MODE][Tokenizer.END_TAG_TOKEN] =
|
| +_[IN_TABLE_TEXT_MODE][Tokenizer.EOF_TOKEN] = tokenInTableText;
|
| +
|
| +_[IN_CAPTION_MODE] = {};
|
| +_[IN_CAPTION_MODE][Tokenizer.CHARACTER_TOKEN] = characterInBody;
|
| +_[IN_CAPTION_MODE][Tokenizer.NULL_CHARACTER_TOKEN] = ignoreToken;
|
| +_[IN_CAPTION_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = whitespaceCharacterInBody;
|
| +_[IN_CAPTION_MODE][Tokenizer.COMMENT_TOKEN] = appendComment;
|
| +_[IN_CAPTION_MODE][Tokenizer.DOCTYPE_TOKEN] = ignoreToken;
|
| +_[IN_CAPTION_MODE][Tokenizer.START_TAG_TOKEN] = startTagInCaption;
|
| +_[IN_CAPTION_MODE][Tokenizer.END_TAG_TOKEN] = endTagInCaption;
|
| +_[IN_CAPTION_MODE][Tokenizer.EOF_TOKEN] = eofInBody;
|
| +
|
| +_[IN_COLUMN_GROUP_MODE] = {};
|
| +_[IN_COLUMN_GROUP_MODE][Tokenizer.CHARACTER_TOKEN] =
|
| +_[IN_COLUMN_GROUP_MODE][Tokenizer.NULL_CHARACTER_TOKEN] = tokenInColumnGroup;
|
| +_[IN_COLUMN_GROUP_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = insertCharacters;
|
| +_[IN_COLUMN_GROUP_MODE][Tokenizer.COMMENT_TOKEN] = appendComment;
|
| +_[IN_COLUMN_GROUP_MODE][Tokenizer.DOCTYPE_TOKEN] = ignoreToken;
|
| +_[IN_COLUMN_GROUP_MODE][Tokenizer.START_TAG_TOKEN] = startTagInColumnGroup;
|
| +_[IN_COLUMN_GROUP_MODE][Tokenizer.END_TAG_TOKEN] = endTagInColumnGroup;
|
| +_[IN_COLUMN_GROUP_MODE][Tokenizer.EOF_TOKEN] = eofInBody;
|
| +
|
| +_[IN_TABLE_BODY_MODE] = {};
|
| +_[IN_TABLE_BODY_MODE][Tokenizer.CHARACTER_TOKEN] =
|
| +_[IN_TABLE_BODY_MODE][Tokenizer.NULL_CHARACTER_TOKEN] =
|
| +_[IN_TABLE_BODY_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = characterInTable;
|
| +_[IN_TABLE_BODY_MODE][Tokenizer.COMMENT_TOKEN] = appendComment;
|
| +_[IN_TABLE_BODY_MODE][Tokenizer.DOCTYPE_TOKEN] = ignoreToken;
|
| +_[IN_TABLE_BODY_MODE][Tokenizer.START_TAG_TOKEN] = startTagInTableBody;
|
| +_[IN_TABLE_BODY_MODE][Tokenizer.END_TAG_TOKEN] = endTagInTableBody;
|
| +_[IN_TABLE_BODY_MODE][Tokenizer.EOF_TOKEN] = eofInBody;
|
| +
|
| +_[IN_ROW_MODE] = {};
|
| +_[IN_ROW_MODE][Tokenizer.CHARACTER_TOKEN] =
|
| +_[IN_ROW_MODE][Tokenizer.NULL_CHARACTER_TOKEN] =
|
| +_[IN_ROW_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = characterInTable;
|
| +_[IN_ROW_MODE][Tokenizer.COMMENT_TOKEN] = appendComment;
|
| +_[IN_ROW_MODE][Tokenizer.DOCTYPE_TOKEN] = ignoreToken;
|
| +_[IN_ROW_MODE][Tokenizer.START_TAG_TOKEN] = startTagInRow;
|
| +_[IN_ROW_MODE][Tokenizer.END_TAG_TOKEN] = endTagInRow;
|
| +_[IN_ROW_MODE][Tokenizer.EOF_TOKEN] = eofInBody;
|
| +
|
| +_[IN_CELL_MODE] = {};
|
| +_[IN_CELL_MODE][Tokenizer.CHARACTER_TOKEN] = characterInBody;
|
| +_[IN_CELL_MODE][Tokenizer.NULL_CHARACTER_TOKEN] = ignoreToken;
|
| +_[IN_CELL_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = whitespaceCharacterInBody;
|
| +_[IN_CELL_MODE][Tokenizer.COMMENT_TOKEN] = appendComment;
|
| +_[IN_CELL_MODE][Tokenizer.DOCTYPE_TOKEN] = ignoreToken;
|
| +_[IN_CELL_MODE][Tokenizer.START_TAG_TOKEN] = startTagInCell;
|
| +_[IN_CELL_MODE][Tokenizer.END_TAG_TOKEN] = endTagInCell;
|
| +_[IN_CELL_MODE][Tokenizer.EOF_TOKEN] = eofInBody;
|
| +
|
| +_[IN_SELECT_MODE] = {};
|
| +_[IN_SELECT_MODE][Tokenizer.CHARACTER_TOKEN] = insertCharacters;
|
| +_[IN_SELECT_MODE][Tokenizer.NULL_CHARACTER_TOKEN] = ignoreToken;
|
| +_[IN_SELECT_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = insertCharacters;
|
| +_[IN_SELECT_MODE][Tokenizer.COMMENT_TOKEN] = appendComment;
|
| +_[IN_SELECT_MODE][Tokenizer.DOCTYPE_TOKEN] = ignoreToken;
|
| +_[IN_SELECT_MODE][Tokenizer.START_TAG_TOKEN] = startTagInSelect;
|
| +_[IN_SELECT_MODE][Tokenizer.END_TAG_TOKEN] = endTagInSelect;
|
| +_[IN_SELECT_MODE][Tokenizer.EOF_TOKEN] = eofInBody;
|
| +
|
| +_[IN_SELECT_IN_TABLE_MODE] = {};
|
| +_[IN_SELECT_IN_TABLE_MODE][Tokenizer.CHARACTER_TOKEN] = insertCharacters;
|
| +_[IN_SELECT_IN_TABLE_MODE][Tokenizer.NULL_CHARACTER_TOKEN] = ignoreToken;
|
| +_[IN_SELECT_IN_TABLE_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = insertCharacters;
|
| +_[IN_SELECT_IN_TABLE_MODE][Tokenizer.COMMENT_TOKEN] = appendComment;
|
| +_[IN_SELECT_IN_TABLE_MODE][Tokenizer.DOCTYPE_TOKEN] = ignoreToken;
|
| +_[IN_SELECT_IN_TABLE_MODE][Tokenizer.START_TAG_TOKEN] = startTagInSelectInTable;
|
| +_[IN_SELECT_IN_TABLE_MODE][Tokenizer.END_TAG_TOKEN] = endTagInSelectInTable;
|
| +_[IN_SELECT_IN_TABLE_MODE][Tokenizer.EOF_TOKEN] = eofInBody;
|
| +
|
| +_[IN_TEMPLATE_MODE] = {};
|
| +_[IN_TEMPLATE_MODE][Tokenizer.CHARACTER_TOKEN] = characterInBody;
|
| +_[IN_TEMPLATE_MODE][Tokenizer.NULL_CHARACTER_TOKEN] = ignoreToken;
|
| +_[IN_TEMPLATE_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = whitespaceCharacterInBody;
|
| +_[IN_TEMPLATE_MODE][Tokenizer.COMMENT_TOKEN] = appendComment;
|
| +_[IN_TEMPLATE_MODE][Tokenizer.DOCTYPE_TOKEN] = ignoreToken;
|
| +_[IN_TEMPLATE_MODE][Tokenizer.START_TAG_TOKEN] = startTagInTemplate;
|
| +_[IN_TEMPLATE_MODE][Tokenizer.END_TAG_TOKEN] = endTagInTemplate;
|
| +_[IN_TEMPLATE_MODE][Tokenizer.EOF_TOKEN] = eofInTemplate;
|
| +
|
| +_[AFTER_BODY_MODE] = {};
|
| +_[AFTER_BODY_MODE][Tokenizer.CHARACTER_TOKEN] =
|
| +_[AFTER_BODY_MODE][Tokenizer.NULL_CHARACTER_TOKEN] = tokenAfterBody;
|
| +_[AFTER_BODY_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = whitespaceCharacterInBody;
|
| +_[AFTER_BODY_MODE][Tokenizer.COMMENT_TOKEN] = appendCommentToRootHtmlElement;
|
| +_[AFTER_BODY_MODE][Tokenizer.DOCTYPE_TOKEN] = ignoreToken;
|
| +_[AFTER_BODY_MODE][Tokenizer.START_TAG_TOKEN] = startTagAfterBody;
|
| +_[AFTER_BODY_MODE][Tokenizer.END_TAG_TOKEN] = endTagAfterBody;
|
| +_[AFTER_BODY_MODE][Tokenizer.EOF_TOKEN] = stopParsing;
|
| +
|
| +_[IN_FRAMESET_MODE] = {};
|
| +_[IN_FRAMESET_MODE][Tokenizer.CHARACTER_TOKEN] =
|
| +_[IN_FRAMESET_MODE][Tokenizer.NULL_CHARACTER_TOKEN] = ignoreToken;
|
| +_[IN_FRAMESET_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = insertCharacters;
|
| +_[IN_FRAMESET_MODE][Tokenizer.COMMENT_TOKEN] = appendComment;
|
| +_[IN_FRAMESET_MODE][Tokenizer.DOCTYPE_TOKEN] = ignoreToken;
|
| +_[IN_FRAMESET_MODE][Tokenizer.START_TAG_TOKEN] = startTagInFrameset;
|
| +_[IN_FRAMESET_MODE][Tokenizer.END_TAG_TOKEN] = endTagInFrameset;
|
| +_[IN_FRAMESET_MODE][Tokenizer.EOF_TOKEN] = stopParsing;
|
| +
|
| +_[AFTER_FRAMESET_MODE] = {};
|
| +_[AFTER_FRAMESET_MODE][Tokenizer.CHARACTER_TOKEN] =
|
| +_[AFTER_FRAMESET_MODE][Tokenizer.NULL_CHARACTER_TOKEN] = ignoreToken;
|
| +_[AFTER_FRAMESET_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = insertCharacters;
|
| +_[AFTER_FRAMESET_MODE][Tokenizer.COMMENT_TOKEN] = appendComment;
|
| +_[AFTER_FRAMESET_MODE][Tokenizer.DOCTYPE_TOKEN] = ignoreToken;
|
| +_[AFTER_FRAMESET_MODE][Tokenizer.START_TAG_TOKEN] = startTagAfterFrameset;
|
| +_[AFTER_FRAMESET_MODE][Tokenizer.END_TAG_TOKEN] = endTagAfterFrameset;
|
| +_[AFTER_FRAMESET_MODE][Tokenizer.EOF_TOKEN] = stopParsing;
|
| +
|
| +_[AFTER_AFTER_BODY_MODE] = {};
|
| +_[AFTER_AFTER_BODY_MODE][Tokenizer.CHARACTER_TOKEN] = tokenAfterAfterBody;
|
| +_[AFTER_AFTER_BODY_MODE][Tokenizer.NULL_CHARACTER_TOKEN] = tokenAfterAfterBody;
|
| +_[AFTER_AFTER_BODY_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = whitespaceCharacterInBody;
|
| +_[AFTER_AFTER_BODY_MODE][Tokenizer.COMMENT_TOKEN] = appendCommentToDocument;
|
| +_[AFTER_AFTER_BODY_MODE][Tokenizer.DOCTYPE_TOKEN] = ignoreToken;
|
| +_[AFTER_AFTER_BODY_MODE][Tokenizer.START_TAG_TOKEN] = startTagAfterAfterBody;
|
| +_[AFTER_AFTER_BODY_MODE][Tokenizer.END_TAG_TOKEN] = tokenAfterAfterBody;
|
| +_[AFTER_AFTER_BODY_MODE][Tokenizer.EOF_TOKEN] = stopParsing;
|
| +
|
| +_[AFTER_AFTER_FRAMESET_MODE] = {};
|
| +_[AFTER_AFTER_FRAMESET_MODE][Tokenizer.CHARACTER_TOKEN] =
|
| +_[AFTER_AFTER_FRAMESET_MODE][Tokenizer.NULL_CHARACTER_TOKEN] = ignoreToken;
|
| +_[AFTER_AFTER_FRAMESET_MODE][Tokenizer.WHITESPACE_CHARACTER_TOKEN] = whitespaceCharacterInBody;
|
| +_[AFTER_AFTER_FRAMESET_MODE][Tokenizer.COMMENT_TOKEN] = appendCommentToDocument;
|
| +_[AFTER_AFTER_FRAMESET_MODE][Tokenizer.DOCTYPE_TOKEN] = ignoreToken;
|
| +_[AFTER_AFTER_FRAMESET_MODE][Tokenizer.START_TAG_TOKEN] = startTagAfterAfterFrameset;
|
| +_[AFTER_AFTER_FRAMESET_MODE][Tokenizer.END_TAG_TOKEN] = ignoreToken;
|
| +_[AFTER_AFTER_FRAMESET_MODE][Tokenizer.EOF_TOKEN] = stopParsing;
|
| +
|
| +//Searchable index building utils (<isindex> tag)
|
| +function getSearchableIndexFormAttrs(isindexStartTagToken) {
|
| + var indexAction = Tokenizer.getTokenAttr(isindexStartTagToken, ATTRS.ACTION),
|
| + attrs = [];
|
| +
|
| + if (indexAction !== null) {
|
| + attrs.push({
|
| + name: ATTRS.ACTION,
|
| + value: indexAction
|
| + });
|
| + }
|
| +
|
| + return attrs;
|
| +}
|
| +
|
| +function getSearchableIndexLabelText(isindexStartTagToken) {
|
| + var indexPrompt = Tokenizer.getTokenAttr(isindexStartTagToken, ATTRS.PROMPT);
|
| +
|
| + return indexPrompt === null ? SEARCHABLE_INDEX_DEFAULT_PROMPT : indexPrompt;
|
| +}
|
| +
|
| +function getSearchableIndexInputAttrs(isindexStartTagToken) {
|
| + var isindexAttrs = isindexStartTagToken.attrs,
|
| + inputAttrs = [];
|
| +
|
| + for (var i = 0; i < isindexAttrs.length; i++) {
|
| + var name = isindexAttrs[i].name;
|
| +
|
| + if (name !== ATTRS.NAME && name !== ATTRS.ACTION && name !== ATTRS.PROMPT)
|
| + inputAttrs.push(isindexAttrs[i]);
|
| + }
|
| +
|
| + inputAttrs.push({
|
| + name: ATTRS.NAME,
|
| + value: SEARCHABLE_INDEX_INPUT_NAME
|
| + });
|
| +
|
| + return inputAttrs;
|
| +}
|
| +
|
| +//Parser
|
| +var Parser = module.exports = function (treeAdapter) {
|
| + this.treeAdapter = treeAdapter || DefaultTreeAdapter;
|
| + this.scriptHandler = null;
|
| +};
|
| +
|
| +//API
|
| +Parser.prototype.parse = function (html) {
|
| + var document = this.treeAdapter.createDocument();
|
| +
|
| + this._reset(html, document, null);
|
| + this._runParsingLoop();
|
| +
|
| + return document;
|
| +};
|
| +
|
| +Parser.prototype.parseFragment = function (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`.
|
| + var documentMock = this.treeAdapter.createElement('documentmock', NS.HTML, []);
|
| +
|
| + this._reset(html, documentMock, fragmentContext);
|
| +
|
| + if (this.treeAdapter.getTagName(fragmentContext) === $.TEMPLATE)
|
| + this._pushTmplInsertionMode(IN_TEMPLATE_MODE);
|
| +
|
| + this._initTokenizerForFragmentParsing();
|
| + this._insertFakeRootElement();
|
| + this._resetInsertionMode();
|
| + this._findFormInFragmentContext();
|
| + this._runParsingLoop();
|
| +
|
| + var rootElement = this.treeAdapter.getFirstChild(documentMock),
|
| + fragment = this.treeAdapter.createDocumentFragment();
|
| +
|
| + this._adoptNodes(rootElement, fragment);
|
| +
|
| + return fragment;
|
| +};
|
| +
|
| +//Reset state
|
| +Parser.prototype._reset = function (html, document, fragmentContext) {
|
| + this.tokenizer = new Tokenizer(html);
|
| +
|
| + 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;
|
| +};
|
| +
|
| +//Parsing loop
|
| +Parser.prototype._iterateParsingLoop = function () {
|
| + this._setupTokenizerCDATAMode();
|
| +
|
| + var token = this.tokenizer.getNextToken();
|
| +
|
| + if (this.skipNextNewLine) {
|
| + this.skipNextNewLine = false;
|
| +
|
| + if (token.type === Tokenizer.WHITESPACE_CHARACTER_TOKEN && token.chars[0] === '\n') {
|
| + if (token.chars.length === 1)
|
| + return;
|
| +
|
| + token.chars = token.chars.substr(1);
|
| + }
|
| + }
|
| +
|
| + if (this._shouldProcessTokenInForeignContent(token))
|
| + this._processTokenInForeignContent(token);
|
| +
|
| + else
|
| + this._processToken(token);
|
| +};
|
| +
|
| +Parser.prototype._runParsingLoop = function () {
|
| + while (!this.stopped)
|
| + this._iterateParsingLoop();
|
| +};
|
| +
|
| +//Text parsing
|
| +Parser.prototype._setupTokenizerCDATAMode = function () {
|
| + var current = this._getAdjustedCurrentElement();
|
| +
|
| + this.tokenizer.allowCDATA = current && current !== this.document &&
|
| + this.treeAdapter.getNamespaceURI(current) !== NS.HTML &&
|
| + (!this._isHtmlIntegrationPoint(current)) &&
|
| + (!this._isMathMLTextIntegrationPoint(current));
|
| +};
|
| +
|
| +Parser.prototype._switchToTextParsing = function (currentToken, nextTokenizerState) {
|
| + this._insertElement(currentToken, NS.HTML);
|
| + this.tokenizer.state = nextTokenizerState;
|
| + this.originalInsertionMode = this.insertionMode;
|
| + this.insertionMode = TEXT_MODE;
|
| +};
|
| +
|
| +//Fragment parsing
|
| +Parser.prototype._getAdjustedCurrentElement = function () {
|
| + return this.openElements.stackTop === 0 && this.fragmentContext ?
|
| + this.fragmentContext :
|
| + this.openElements.current;
|
| +};
|
| +
|
| +Parser.prototype._findFormInFragmentContext = function () {
|
| + var node = this.fragmentContext;
|
| +
|
| + do {
|
| + if (this.treeAdapter.getTagName(node) === $.FORM) {
|
| + this.formElement = node;
|
| + break;
|
| + }
|
| +
|
| + node = this.treeAdapter.getParentNode(node);
|
| + } while (node);
|
| +};
|
| +
|
| +Parser.prototype._initTokenizerForFragmentParsing = function () {
|
| + var tn = this.treeAdapter.getTagName(this.fragmentContext);
|
| +
|
| + if (tn === $.TITLE || tn === $.TEXTAREA)
|
| + this.tokenizer.state = Tokenizer.RCDATA_STATE;
|
| +
|
| + else if (tn === $.STYLE || tn === $.XMP || tn === $.IFRAME ||
|
| + tn === $.NOEMBED || tn === $.NOFRAMES || tn === $.NOSCRIPT) {
|
| + this.tokenizer.state = Tokenizer.RAWTEXT_STATE;
|
| + }
|
| +
|
| + else if (tn === $.SCRIPT)
|
| + this.tokenizer.state = Tokenizer.SCRIPT_DATA_STATE;
|
| +
|
| + else if (tn === $.PLAINTEXT)
|
| + this.tokenizer.state = Tokenizer.PLAINTEXT_STATE;
|
| +};
|
| +
|
| +//Tree mutation
|
| +Parser.prototype._setDocumentType = function (token) {
|
| + this.treeAdapter.setDocumentType(this.document, token.name, token.publicId, token.systemId);
|
| +};
|
| +
|
| +Parser.prototype._attachElementToTree = function (element) {
|
| + if (this.fosterParentingEnabled && this._isElementCausesFosterParenting(this.openElements.current))
|
| + this._fosterParentElement(element);
|
| +
|
| + else {
|
| + var parent = this.openElements.currentTmplContent || this.openElements.current;
|
| +
|
| + this.treeAdapter.appendChild(parent, element);
|
| + }
|
| +};
|
| +
|
| +Parser.prototype._appendElement = function (token, namespaceURI) {
|
| + var element = this.treeAdapter.createElement(token.tagName, namespaceURI, token.attrs);
|
| +
|
| + this._attachElementToTree(element);
|
| +};
|
| +
|
| +Parser.prototype._insertElement = function (token, namespaceURI) {
|
| + var element = this.treeAdapter.createElement(token.tagName, namespaceURI, token.attrs);
|
| +
|
| + this._attachElementToTree(element);
|
| + this.openElements.push(element);
|
| +};
|
| +
|
| +Parser.prototype._insertTemplate = function (token) {
|
| + var tmpl = this.treeAdapter.createElement(token.tagName, NS.HTML, token.attrs),
|
| + content = this.treeAdapter.createDocumentFragment();
|
| +
|
| + this.treeAdapter.appendChild(tmpl, content);
|
| + this._attachElementToTree(tmpl);
|
| + this.openElements.push(tmpl);
|
| +};
|
| +
|
| +Parser.prototype._insertFakeRootElement = function () {
|
| + var element = this.treeAdapter.createElement($.HTML, NS.HTML, []);
|
| +
|
| + this.treeAdapter.appendChild(this.openElements.current, element);
|
| + this.openElements.push(element);
|
| +};
|
| +
|
| +Parser.prototype._appendCommentNode = function (token, parent) {
|
| + var commentNode = this.treeAdapter.createCommentNode(token.data);
|
| +
|
| + this.treeAdapter.appendChild(parent, commentNode);
|
| +};
|
| +
|
| +Parser.prototype._insertCharacters = function (token) {
|
| + if (this.fosterParentingEnabled && this._isElementCausesFosterParenting(this.openElements.current))
|
| + this._fosterParentText(token.chars);
|
| +
|
| + else {
|
| + var parent = this.openElements.currentTmplContent || this.openElements.current;
|
| +
|
| + this.treeAdapter.insertText(parent, token.chars);
|
| + }
|
| +};
|
| +
|
| +Parser.prototype._adoptNodes = function (donor, recipient) {
|
| + while (true) {
|
| + var child = this.treeAdapter.getFirstChild(donor);
|
| +
|
| + if (!child)
|
| + break;
|
| +
|
| + this.treeAdapter.detachNode(child);
|
| + this.treeAdapter.appendChild(recipient, child);
|
| + }
|
| +};
|
| +
|
| +//Token processing
|
| +Parser.prototype._shouldProcessTokenInForeignContent = function (token) {
|
| + var current = this._getAdjustedCurrentElement();
|
| +
|
| + if (!current || current === this.document)
|
| + return false;
|
| +
|
| + var 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;
|
| + }
|
| +
|
| + var isCharacterToken = token.type === Tokenizer.CHARACTER_TOKEN ||
|
| + token.type === Tokenizer.NULL_CHARACTER_TOKEN ||
|
| + token.type === Tokenizer.WHITESPACE_CHARACTER_TOKEN,
|
| + isMathMLTextStartTag = token.type === Tokenizer.START_TAG_TOKEN &&
|
| + token.tagName !== $.MGLYPH &&
|
| + token.tagName !== $.MALIGNMARK;
|
| +
|
| + if ((isMathMLTextStartTag || isCharacterToken) && this._isMathMLTextIntegrationPoint(current))
|
| + return false;
|
| +
|
| + if ((token.type === Tokenizer.START_TAG_TOKEN || isCharacterToken) && this._isHtmlIntegrationPoint(current))
|
| + return false;
|
| +
|
| + return token.type !== Tokenizer.EOF_TOKEN;
|
| +};
|
| +
|
| +Parser.prototype._processToken = function (token) {
|
| + _[this.insertionMode][token.type](this, token);
|
| +};
|
| +
|
| +Parser.prototype._processTokenInBodyMode = function (token) {
|
| + _[IN_BODY_MODE][token.type](this, token);
|
| +};
|
| +
|
| +Parser.prototype._processTokenInForeignContent = function (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);
|
| +};
|
| +
|
| +Parser.prototype._processFakeStartTagWithAttrs = function (tagName, attrs) {
|
| + var fakeToken = this.tokenizer.buildStartTagToken(tagName);
|
| +
|
| + fakeToken.attrs = attrs;
|
| + this._processToken(fakeToken);
|
| +};
|
| +
|
| +Parser.prototype._processFakeStartTag = function (tagName) {
|
| + var fakeToken = this.tokenizer.buildStartTagToken(tagName);
|
| +
|
| + this._processToken(fakeToken);
|
| + return fakeToken;
|
| +};
|
| +
|
| +Parser.prototype._processFakeEndTag = function (tagName) {
|
| + var fakeToken = this.tokenizer.buildEndTagToken(tagName);
|
| +
|
| + this._processToken(fakeToken);
|
| + return fakeToken;
|
| +};
|
| +
|
| +//Integration points
|
| +Parser.prototype._isMathMLTextIntegrationPoint = function (element) {
|
| + var tn = this.treeAdapter.getTagName(element),
|
| + ns = this.treeAdapter.getNamespaceURI(element);
|
| +
|
| + return ForeignContent.isMathMLTextIntegrationPoint(tn, ns);
|
| +};
|
| +
|
| +Parser.prototype._isHtmlIntegrationPoint = function (element) {
|
| + var tn = this.treeAdapter.getTagName(element),
|
| + ns = this.treeAdapter.getNamespaceURI(element),
|
| + attrs = this.treeAdapter.getAttrList(element);
|
| +
|
| + return ForeignContent.isHtmlIntegrationPoint(tn, ns, attrs);
|
| +};
|
| +
|
| +//Active formatting elements reconstruction
|
| +Parser.prototype._reconstructActiveFormattingElements = function () {
|
| + var listLength = this.activeFormattingElements.length;
|
| +
|
| + if (listLength) {
|
| + var unopenIdx = listLength,
|
| + 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 (var 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
|
| +Parser.prototype._closeTableCell = function () {
|
| + if (this.openElements.hasInTableScope($.TD))
|
| + this._processFakeEndTag($.TD);
|
| +
|
| + else
|
| + this._processFakeEndTag($.TH);
|
| +};
|
| +
|
| +Parser.prototype._closePElement = function () {
|
| + this.openElements.generateImpliedEndTagsWithExclusion($.P);
|
| + this.openElements.popUntilTagNamePopped($.P);
|
| +};
|
| +
|
| +//Insertion modes
|
| +Parser.prototype._resetInsertionMode = function () {
|
| + for (var i = this.openElements.stackTop, last = false; i >= 0; i--) {
|
| + var element = this.openElements.items[i];
|
| +
|
| + if (i === 0) {
|
| + last = true;
|
| +
|
| + if (this.fragmentContext)
|
| + element = this.fragmentContext;
|
| + }
|
| +
|
| + var tn = this.treeAdapter.getTagName(element),
|
| + 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;
|
| + }
|
| + }
|
| +};
|
| +
|
| +Parser.prototype._resetInsertionModeForSelect = function (selectIdx) {
|
| + if (selectIdx > 0) {
|
| + for (var i = selectIdx - 1; i > 0; i--) {
|
| + var ancestor = this.openElements.items[i],
|
| + 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;
|
| +};
|
| +
|
| +Parser.prototype._pushTmplInsertionMode = function (mode) {
|
| + this.tmplInsertionModeStack.push(mode);
|
| + this.tmplInsertionModeStackTop++;
|
| + this.currentTmplInsertionMode = mode;
|
| +};
|
| +
|
| +Parser.prototype._popTmplInsertionMode = function () {
|
| + this.tmplInsertionModeStack.pop();
|
| + this.tmplInsertionModeStackTop--;
|
| + this.currentTmplInsertionMode = this.tmplInsertionModeStack[this.tmplInsertionModeStackTop];
|
| +};
|
| +
|
| +//Foster parenting
|
| +Parser.prototype._isElementCausesFosterParenting = function (element) {
|
| + var tn = this.treeAdapter.getTagName(element);
|
| +
|
| + return tn === $.TABLE || tn === $.TBODY || tn === $.TFOOT || tn == $.THEAD || tn === $.TR;
|
| +};
|
| +
|
| +Parser.prototype._findFosterParentingLocation = function () {
|
| + var location = {
|
| + parent: null,
|
| + beforeElement: null
|
| + };
|
| +
|
| + for (var i = this.openElements.stackTop; i >= 0; i--) {
|
| + var openElement = this.openElements.items[i],
|
| + tn = this.treeAdapter.getTagName(openElement),
|
| + ns = this.treeAdapter.getNamespaceURI(openElement);
|
| +
|
| + if (tn === $.TEMPLATE && ns === NS.HTML) {
|
| + location.parent = this.treeAdapter.getChildNodes(openElement)[0];
|
| + 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;
|
| +};
|
| +
|
| +Parser.prototype._fosterParentElement = function (element) {
|
| + var location = this._findFosterParentingLocation();
|
| +
|
| + if (location.beforeElement)
|
| + this.treeAdapter.insertBefore(location.parent, element, location.beforeElement);
|
| + else
|
| + this.treeAdapter.appendChild(location.parent, element);
|
| +};
|
| +
|
| +Parser.prototype._fosterParentText = function (chars) {
|
| + var location = this._findFosterParentingLocation();
|
| +
|
| + if (location.beforeElement)
|
| + this.treeAdapter.insertTextBefore(location.parent, chars, location.beforeElement);
|
| + else
|
| + this.treeAdapter.insertText(location.parent, chars);
|
| +};
|
| +
|
| +//Special elements
|
| +Parser.prototype._isSpecialElement = function (element) {
|
| + var tn = this.treeAdapter.getTagName(element),
|
| + ns = this.treeAdapter.getNamespaceURI(element);
|
| +
|
| + return HTML.SPECIAL_ELEMENTS[ns][tn];
|
| +};
|
| +
|
| +//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) {
|
| + var 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) {
|
| + var furthestBlock = null;
|
| +
|
| + for (var i = p.openElements.stackTop; i >= 0; i--) {
|
| + var 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) {
|
| + var element = null,
|
| + lastElement = furthestBlock,
|
| + nextElement = p.openElements.getCommonAncestor(furthestBlock);
|
| +
|
| + for (var i = 0; i < AA_INNER_LOOP_ITER; 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);
|
| +
|
| + var elementEntry = p.activeFormattingElements.getElementEntry(element);
|
| +
|
| + if (!elementEntry) {
|
| + p.openElements.remove(element);
|
| + continue;
|
| + }
|
| +
|
| + if (element === formattingElement)
|
| + break;
|
| +
|
| + 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) {
|
| + var ns = p.treeAdapter.getNamespaceURI(elementEntry.element),
|
| + 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 {
|
| + var tn = p.treeAdapter.getTagName(commonAncestor),
|
| + ns = p.treeAdapter.getNamespaceURI(commonAncestor);
|
| +
|
| + if (tn === $.TEMPLATE && ns === NS.HTML)
|
| + commonAncestor = p.treeAdapter.getChildNodes(commonAncestor)[0];
|
| +
|
| + p.treeAdapter.appendChild(commonAncestor, lastElement);
|
| + }
|
| +}
|
| +
|
| +//Steps 15-19 of the algorithm
|
| +function aaReplaceFormattingElement(p, furthestBlock, formattingElementEntry) {
|
| + var ns = p.treeAdapter.getNamespaceURI(formattingElementEntry.element),
|
| + token = formattingElementEntry.token,
|
| + 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) {
|
| + for (var i = 0; i < AA_OUTER_LOOP_ITER; i++) {
|
| + var formattingElementEntry = aaObtainFormattingElementEntry(p, token, formattingElementEntry);
|
| +
|
| + if (!formattingElementEntry)
|
| + break;
|
| +
|
| + var furthestBlock = aaObtainFurthestBlock(p, formattingElementEntry);
|
| +
|
| + if (!furthestBlock)
|
| + break;
|
| +
|
| + p.activeFormattingElements.bookmark = formattingElementEntry;
|
| +
|
| + var lastElement = aaInnerLoop(p, furthestBlock, formattingElementEntry.element),
|
| + commonAncestor = p.openElements.getCommonAncestor(formattingElementEntry.element);
|
| +
|
| + p.treeAdapter.detachNode(lastElement);
|
| + aaInsertLastNodeInCommonAncestor(p, commonAncestor, lastElement);
|
| + aaReplaceFormattingElement(p, furthestBlock, formattingElementEntry);
|
| + }
|
| +}
|
| +
|
| +
|
| +//Generic token handlers
|
| +//------------------------------------------------------------------
|
| +function ignoreToken(p, token) {
|
| + //NOTE: do nothing =)
|
| +}
|
| +
|
| +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, token) {
|
| + p.stopped = true;
|
| +}
|
| +
|
| +//12.2.5.4.1 The "initial" insertion mode
|
| +//------------------------------------------------------------------
|
| +function doctypeInInitialMode(p, token) {
|
| + p._setDocumentType(token);
|
| +
|
| + if (token.forceQuirks || Doctype.isQuirks(token.name, token.publicId, token.systemId))
|
| + p.treeAdapter.setQuirksMode(p.document);
|
| +
|
| + p.insertionMode = BEFORE_HTML_MODE;
|
| +}
|
| +
|
| +function tokenInInitialMode(p, token) {
|
| + p.treeAdapter.setQuirksMode(p.document);
|
| + p.insertionMode = BEFORE_HTML_MODE;
|
| + p._processToken(token);
|
| +}
|
| +
|
| +
|
| +//12.2.5.4.2 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) {
|
| + var 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);
|
| +}
|
| +
|
| +
|
| +//12.2.5.4.3 The "before head" insertion mode
|
| +//------------------------------------------------------------------
|
| +function startTagBeforeHead(p, token) {
|
| + var 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) {
|
| + var tn = token.tagName;
|
| +
|
| + if (tn === $.HEAD || tn === $.BODY || tn === $.HTML || tn === $.BR)
|
| + tokenBeforeHead(p, token);
|
| +}
|
| +
|
| +function tokenBeforeHead(p, token) {
|
| + p._processFakeStartTag($.HEAD);
|
| + p._processToken(token);
|
| +}
|
| +
|
| +
|
| +//12.2.5.4.4 The "in head" insertion mode
|
| +//------------------------------------------------------------------
|
| +function startTagInHead(p, token) {
|
| + var tn = token.tagName;
|
| +
|
| + if (tn === $.HTML)
|
| + startTagInBody(p, token);
|
| +
|
| + else if (tn === $.BASE || tn === $.BASEFONT || tn === $.BGSOUND ||
|
| + tn === $.COMMAND || tn === $.LINK || tn === $.META) {
|
| + p._appendElement(token, NS.HTML);
|
| + }
|
| +
|
| + else if (tn === $.TITLE)
|
| + p._switchToTextParsing(token, Tokenizer.RCDATA_STATE);
|
| +
|
| + //NOTE: here we assume that we always act as an interactive user agent with enabled scripting, so we parse
|
| + //<noscript> as a rawtext.
|
| + else if (tn === $.NOSCRIPT || tn === $.NOFRAMES || tn === $.STYLE)
|
| + p._switchToTextParsing(token, Tokenizer.RAWTEXT_STATE);
|
| +
|
| + else if (tn === $.SCRIPT) {
|
| + p._insertElement(token, NS.HTML);
|
| + p.tokenizer.state = Tokenizer.SCRIPT_DATA_STATE;
|
| + p.originalInsertionMode = p.insertionMode;
|
| + p.insertionMode = TEXT_MODE;
|
| + }
|
| +
|
| + 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)
|
| + tokenInHead(p, token);
|
| +}
|
| +
|
| +function endTagInHead(p, token) {
|
| + var 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 && p.openElements.tmplCount > 0) {
|
| + p.openElements.generateImpliedEndTags();
|
| + p.openElements.popUntilTemplatePopped();
|
| + p.activeFormattingElements.clearToLastMarker();
|
| + p._popTmplInsertionMode();
|
| + p._resetInsertionMode();
|
| + }
|
| +}
|
| +
|
| +function tokenInHead(p, token) {
|
| + p._processFakeEndTag($.HEAD);
|
| + p._processToken(token);
|
| +}
|
| +
|
| +
|
| +//12.2.5.4.6 The "after head" insertion mode
|
| +//------------------------------------------------------------------
|
| +function startTagAfterHead(p, token) {
|
| + var 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.openElements.push(p.headElement);
|
| + startTagInHead(p, token);
|
| + p.openElements.remove(p.headElement);
|
| + }
|
| +
|
| + else if (tn !== $.HEAD)
|
| + tokenAfterHead(p, token);
|
| +}
|
| +
|
| +function endTagAfterHead(p, token) {
|
| + var tn = token.tagName;
|
| +
|
| + if (tn === $.BODY || tn === $.HTML || tn === $.BR)
|
| + tokenAfterHead(p, token);
|
| +
|
| + else if (tn === $.TEMPLATE)
|
| + endTagInHead(p, token);
|
| +}
|
| +
|
| +function tokenAfterHead(p, token) {
|
| + p._processFakeStartTag($.BODY);
|
| + p.framesetOk = true;
|
| + p._processToken(token);
|
| +}
|
| +
|
| +
|
| +//12.2.5.4.7 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) {
|
| + var bodyElement = p.openElements.tryPeekProperlyNestedBodyElement();
|
| +
|
| + if (bodyElement && p.openElements.tmplCount === 0) {
|
| + p.framesetOk = false;
|
| + p.treeAdapter.adoptAttributes(bodyElement, token.attrs);
|
| + }
|
| +}
|
| +
|
| +function framesetStartTagInBody(p, token) {
|
| + var 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();
|
| +
|
| + var 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) {
|
| + var 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;
|
| +
|
| + for (var i = p.openElements.stackTop; i >= 0; i--) {
|
| + var element = p.openElements.items[i],
|
| + tn = p.treeAdapter.getTagName(element);
|
| +
|
| + if ((token.tagName === $.LI && tn === $.LI) ||
|
| + ((token.tagName === $.DD || token.tagName === $.DT) && (tn === $.DD || tn == $.DT))) {
|
| + p._processFakeEndTag(tn);
|
| + break;
|
| + }
|
| +
|
| + if (tn !== $.ADDRESS && tn !== $.DIV && tn !== $.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.PLAINTEXT_STATE;
|
| +}
|
| +
|
| +function buttonStartTagInBody(p, token) {
|
| + if (p.openElements.hasInScope($.BUTTON)) {
|
| + p._processFakeEndTag($.BUTTON);
|
| + buttonStartTagInBody(p, token);
|
| + }
|
| +
|
| + else {
|
| + p._reconstructActiveFormattingElements();
|
| + p._insertElement(token, NS.HTML);
|
| + p.framesetOk = false;
|
| + }
|
| +}
|
| +
|
| +function aStartTagInBody(p, token) {
|
| + var activeElementEntry = p.activeFormattingElements.getElementEntryInScopeWithTagName($.A);
|
| +
|
| + if (activeElementEntry) {
|
| + p._processFakeEndTag($.A);
|
| + 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)) {
|
| + p._processFakeEndTag($.NOBR);
|
| + 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.isQuirksMode(p.document) && 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;
|
| +}
|
| +
|
| +function inputStartTagInBody(p, token) {
|
| + p._reconstructActiveFormattingElements();
|
| + p._appendElement(token, NS.HTML);
|
| +
|
| + var inputType = Tokenizer.getTokenAttr(token, ATTRS.TYPE);
|
| +
|
| + if (!inputType || inputType.toLowerCase() !== HIDDEN_INPUT_TYPE)
|
| + p.framesetOk = false;
|
| +
|
| +}
|
| +
|
| +function paramStartTagInBody(p, token) {
|
| + p._appendElement(token, NS.HTML);
|
| +}
|
| +
|
| +function hrStartTagInBody(p, token) {
|
| + if (p.openElements.hasInButtonScope($.P))
|
| + p._closePElement();
|
| +
|
| + p._appendElement(token, NS.HTML);
|
| + p.framesetOk = false;
|
| +}
|
| +
|
| +function imageStartTagInBody(p, token) {
|
| + token.tagName = $.IMG;
|
| + areaStartTagInBody(p, token);
|
| +}
|
| +
|
| +function isindexStartTagInBody(p, token) {
|
| + if (!p.formElement || p.openElements.tmplCount > 0) {
|
| + p._processFakeStartTagWithAttrs($.FORM, getSearchableIndexFormAttrs(token));
|
| + p._processFakeStartTag($.HR);
|
| + p._processFakeStartTag($.LABEL);
|
| + p.treeAdapter.insertText(p.openElements.current, getSearchableIndexLabelText(token));
|
| + p._processFakeStartTagWithAttrs($.INPUT, getSearchableIndexInputAttrs(token));
|
| + p._processFakeEndTag($.LABEL);
|
| + p._processFakeStartTag($.HR);
|
| + p._processFakeEndTag($.FORM);
|
| + }
|
| +}
|
| +
|
| +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.RCDATA_STATE;
|
| + 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.RAWTEXT_STATE);
|
| +}
|
| +
|
| +function iframeStartTagInBody(p, token) {
|
| + p.framesetOk = false;
|
| + p._switchToTextParsing(token, Tokenizer.RAWTEXT_STATE);
|
| +}
|
| +
|
| +//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.RAWTEXT_STATE);
|
| +}
|
| +
|
| +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._processFakeEndTag($.OPTION);
|
| +
|
| + p._reconstructActiveFormattingElements();
|
| + p._insertElement(token, NS.HTML);
|
| +}
|
| +
|
| +function rpStartTagInBody(p, token) {
|
| + if (p.openElements.hasInScope($.RUBY))
|
| + p.openElements.generateImpliedEndTags();
|
| +
|
| + p._insertElement(token, NS.HTML);
|
| +}
|
| +
|
| +function menuitemStartTagInBody(p, token) {
|
| + p._appendElement(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);
|
| +}
|
| +
|
| +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);
|
| +}
|
| +
|
| +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) {
|
| + var 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 === $.RP || tn === $.RT)
|
| + rpStartTagInBody(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 !== $.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 !== $.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)
|
| + 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 || tn === $.COMMAND)
|
| + 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 === $.ISINDEX)
|
| + isindexStartTagInBody(p, token);
|
| +
|
| + else if (tn === $.NOEMBED)
|
| + noembedStartTagInBody(p, token);
|
| +
|
| + else if (tn !== $.CAPTION)
|
| + genericStartTagInBody(p, token);
|
| +
|
| + break;
|
| +
|
| + case 8:
|
| + if (tn === $.BASEFONT || tn === $.MENUITEM)
|
| + menuitemStartTagInBody(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)
|
| + noembedStartTagInBody(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, token) {
|
| + if (p.openElements.hasInScope($.BODY))
|
| + p.insertionMode = AFTER_BODY_MODE;
|
| +
|
| + else
|
| + token.ignored = true;
|
| +}
|
| +
|
| +function htmlEndTagInBody(p, token) {
|
| + var fakeToken = p._processFakeEndTag($.BODY);
|
| +
|
| + if (!fakeToken.ignored)
|
| + p._processToken(token);
|
| +}
|
| +
|
| +function addressEndTagInBody(p, token) {
|
| + var tn = token.tagName;
|
| +
|
| + if (p.openElements.hasInScope(tn)) {
|
| + p.openElements.generateImpliedEndTags();
|
| + p.openElements.popUntilTagNamePopped(tn);
|
| + }
|
| +}
|
| +
|
| +function formEndTagInBody(p, token) {
|
| + var inTemplate = p.openElements.tmplCount > 0,
|
| + formElement = p.formElement;
|
| +
|
| + if (!inTemplate)
|
| + p.formElement = null;
|
| +
|
| + if ((formElement || inTemplate) && p.openElements.hasInScope($.FORM)) {
|
| + p.openElements.generateImpliedEndTags();
|
| + p.openElements.remove(formElement);
|
| + }
|
| +}
|
| +
|
| +function pEndTagInBody(p, token) {
|
| + if (p.openElements.hasInButtonScope($.P)) {
|
| + p.openElements.generateImpliedEndTagsWithExclusion($.P);
|
| + p.openElements.popUntilTagNamePopped($.P);
|
| + }
|
| +
|
| + else {
|
| + p._processFakeStartTag($.P);
|
| + p._processToken(token);
|
| + }
|
| +}
|
| +
|
| +function liEndTagInBody(p, token) {
|
| + if (p.openElements.hasInListItemScope($.LI)) {
|
| + p.openElements.generateImpliedEndTagsWithExclusion($.LI);
|
| + p.openElements.popUntilTagNamePopped($.LI);
|
| + }
|
| +}
|
| +
|
| +function ddEndTagInBody(p, token) {
|
| + var tn = token.tagName;
|
| +
|
| + if (p.openElements.hasInScope(tn)) {
|
| + p.openElements.generateImpliedEndTagsWithExclusion(tn);
|
| + p.openElements.popUntilTagNamePopped(tn);
|
| + }
|
| +}
|
| +
|
| +function numberedHeaderEndTagInBody(p, token) {
|
| + if (p.openElements.hasNumberedHeaderInScope()) {
|
| + p.openElements.generateImpliedEndTags();
|
| + p.openElements.popUntilNumberedHeaderPopped();
|
| + }
|
| +}
|
| +
|
| +function appletEndTagInBody(p, token) {
|
| + var tn = token.tagName;
|
| +
|
| + if (p.openElements.hasInScope(tn)) {
|
| + p.openElements.generateImpliedEndTags();
|
| + p.openElements.popUntilTagNamePopped(tn);
|
| + p.activeFormattingElements.clearToLastMarker();
|
| + }
|
| +}
|
| +
|
| +function brEndTagInBody(p, token) {
|
| + p._processFakeStartTag($.BR);
|
| +}
|
| +
|
| +function genericEndTagInBody(p, token) {
|
| + var tn = token.tagName;
|
| +
|
| + for (var i = p.openElements.stackTop; i > 0; i--) {
|
| + var 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) {
|
| + var 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)
|
| + 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)
|
| + 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)
|
| + 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;
|
| +}
|
| +
|
| +//12.2.5.4.8 The "text" insertion mode
|
| +//------------------------------------------------------------------
|
| +function endTagInText(p, token) {
|
| + if (!p.fragmentContext && p.scriptHandler && token.tagName === $.SCRIPT)
|
| + p.scriptHandler(p.document, p.openElements.current);
|
| +
|
| + p.openElements.pop();
|
| + p.insertionMode = p.originalInsertionMode;
|
| +}
|
| +
|
| +
|
| +function eofInText(p, token) {
|
| + p.openElements.pop();
|
| + p.insertionMode = p.originalInsertionMode;
|
| + p._processToken(token);
|
| +}
|
| +
|
| +
|
| +//12.2.5.4.9 The "in table" insertion mode
|
| +//------------------------------------------------------------------
|
| +function characterInTable(p, token) {
|
| + var 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._processFakeStartTag($.COLGROUP);
|
| + 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._processFakeStartTag($.TBODY);
|
| + p._processToken(token);
|
| +}
|
| +
|
| +function tableStartTagInTable(p, token) {
|
| + var fakeToken = p._processFakeEndTag($.TABLE);
|
| +
|
| + //NOTE: The fake end tag token here can only be ignored in the fragment case.
|
| + if (!fakeToken.ignored)
|
| + p._processToken(token);
|
| +}
|
| +
|
| +function inputStartTagInTable(p, token) {
|
| + var inputType = Tokenizer.getTokenAttr(token, ATTRS.TYPE);
|
| +
|
| + if (inputType && inputType.toLowerCase() === HIDDEN_INPUT_TYPE)
|
| + p._appendElement(token, NS.HTML);
|
| +
|
| + else
|
| + tokenInTable(p, token);
|
| +}
|
| +
|
| +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) {
|
| + var 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) {
|
| + var tn = token.tagName;
|
| +
|
| + if (tn === $.TABLE) {
|
| + if (p.openElements.hasInTableScope($.TABLE)) {
|
| + p.openElements.popUntilTagNamePopped($.TABLE);
|
| + p._resetInsertionMode();
|
| + }
|
| +
|
| + else
|
| + token.ignored = true;
|
| + }
|
| +
|
| + 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) {
|
| + var savedFosterParentingState = p.fosterParentingEnabled;
|
| +
|
| + p.fosterParentingEnabled = true;
|
| + p._processTokenInBodyMode(token);
|
| + p.fosterParentingEnabled = savedFosterParentingState;
|
| +}
|
| +
|
| +
|
| +//12.2.5.4.10 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) {
|
| + if (p.hasNonWhitespacePendingCharacterToken) {
|
| + for (var i = 0; i < p.pendingCharacterTokens.length; i++)
|
| + tokenInTable(p, p.pendingCharacterTokens[i]);
|
| + }
|
| +
|
| + else {
|
| + for (var i = 0; i < p.pendingCharacterTokens.length; i++)
|
| + p._insertCharacters(p.pendingCharacterTokens[i]);
|
| + }
|
| +
|
| + p.insertionMode = p.originalInsertionMode;
|
| + p._processToken(token);
|
| +}
|
| +
|
| +
|
| +//12.2.5.4.11 The "in caption" insertion mode
|
| +//------------------------------------------------------------------
|
| +function startTagInCaption(p, token) {
|
| + var tn = token.tagName;
|
| +
|
| + if (tn === $.CAPTION || tn === $.COL || tn === $.COLGROUP || tn === $.TBODY ||
|
| + tn === $.TD || tn === $.TFOOT || tn === $.TH || tn === $.THEAD || tn === $.TR) {
|
| + var fakeToken = p._processFakeEndTag($.CAPTION);
|
| +
|
| + //NOTE: The fake end tag token here can only be ignored in the fragment case.
|
| + if (!fakeToken.ignored)
|
| + p._processToken(token);
|
| + }
|
| +
|
| + else
|
| + startTagInBody(p, token);
|
| +}
|
| +
|
| +function endTagInCaption(p, token) {
|
| + var tn = token.tagName;
|
| +
|
| + if (tn === $.CAPTION) {
|
| + if (p.openElements.hasInTableScope($.CAPTION)) {
|
| + p.openElements.generateImpliedEndTags();
|
| + p.openElements.popUntilTagNamePopped($.CAPTION);
|
| + p.activeFormattingElements.clearToLastMarker();
|
| + p.insertionMode = IN_TABLE_MODE;
|
| + }
|
| +
|
| + else
|
| + token.ignored = true;
|
| + }
|
| +
|
| + else if (tn === $.TABLE) {
|
| + var fakeToken = p._processFakeEndTag($.CAPTION);
|
| +
|
| + //NOTE: The fake end tag token here can only be ignored in the fragment case.
|
| + if (!fakeToken.ignored)
|
| + 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);
|
| + }
|
| +}
|
| +
|
| +
|
| +//12.2.5.4.12 The "in column group" insertion mode
|
| +//------------------------------------------------------------------
|
| +function startTagInColumnGroup(p, token) {
|
| + var tn = token.tagName;
|
| +
|
| + if (tn === $.HTML)
|
| + startTagInBody(p, token);
|
| +
|
| + else if (tn === $.COL)
|
| + p._appendElement(token, NS.HTML);
|
| +
|
| + else if (tn === $.TEMPLATE)
|
| + startTagInHead(p, token);
|
| +
|
| + else
|
| + tokenInColumnGroup(p, token);
|
| +}
|
| +
|
| +function endTagInColumnGroup(p, token) {
|
| + var tn = token.tagName;
|
| +
|
| + if (tn === $.COLGROUP) {
|
| + if (p.openElements.currentTagName !== $.COLGROUP)
|
| + token.ignored = true;
|
| +
|
| + else {
|
| + 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) {
|
| + var fakeToken = p._processFakeEndTag($.COLGROUP);
|
| +
|
| + //NOTE: The fake end tag token here can only be ignored in the fragment case.
|
| + if (!fakeToken.ignored)
|
| + p._processToken(token);
|
| +}
|
| +
|
| +//12.2.5.4.13 The "in table body" insertion mode
|
| +//------------------------------------------------------------------
|
| +function startTagInTableBody(p, token) {
|
| + var 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._processFakeStartTag($.TR);
|
| + 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._processFakeEndTag(p.openElements.currentTagName);
|
| + p._processToken(token);
|
| + }
|
| + }
|
| +
|
| + else
|
| + startTagInTable(p, token);
|
| +}
|
| +
|
| +function endTagInTableBody(p, token) {
|
| + var 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._processFakeEndTag(p.openElements.currentTagName);
|
| + p._processToken(token);
|
| + }
|
| + }
|
| +
|
| + else if (tn !== $.BODY && tn !== $.CAPTION && tn !== $.COL && tn !== $.COLGROUP ||
|
| + tn !== $.HTML && tn !== $.TD && tn !== $.TH && tn !== $.TR) {
|
| + endTagInTable(p, token);
|
| + }
|
| +}
|
| +
|
| +//12.2.5.4.14 The "in row" insertion mode
|
| +//------------------------------------------------------------------
|
| +function startTagInRow(p, token) {
|
| + var 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) {
|
| + var fakeToken = p._processFakeEndTag($.TR);
|
| +
|
| + //NOTE: The fake end tag token here can only be ignored in the fragment case.
|
| + if (!fakeToken.ignored)
|
| + p._processToken(token);
|
| + }
|
| +
|
| + else
|
| + startTagInTable(p, token);
|
| +}
|
| +
|
| +function endTagInRow(p, token) {
|
| + var tn = token.tagName;
|
| +
|
| + if (tn === $.TR) {
|
| + if (p.openElements.hasInTableScope($.TR)) {
|
| + p.openElements.clearBackToTableRowContext();
|
| + p.openElements.pop();
|
| + p.insertionMode = IN_TABLE_BODY_MODE;
|
| + }
|
| +
|
| + else
|
| + token.ignored = true;
|
| + }
|
| +
|
| + else if (tn === $.TABLE) {
|
| + var fakeToken = p._processFakeEndTag($.TR);
|
| +
|
| + //NOTE: The fake end tag token here can only be ignored in the fragment case.
|
| + if (!fakeToken.ignored)
|
| + p._processToken(token);
|
| + }
|
| +
|
| + else if (tn === $.TBODY || tn === $.TFOOT || tn === $.THEAD) {
|
| + if (p.openElements.hasInTableScope(tn)) {
|
| + p._processFakeEndTag($.TR);
|
| + p._processToken(token);
|
| + }
|
| + }
|
| +
|
| + else if (tn !== $.BODY && tn !== $.CAPTION && tn !== $.COL && tn !== $.COLGROUP ||
|
| + tn !== $.HTML && tn !== $.TD && tn !== $.TH) {
|
| + endTagInTable(p, token);
|
| + }
|
| +}
|
| +
|
| +
|
| +//12.2.5.4.15 The "in cell" insertion mode
|
| +//------------------------------------------------------------------
|
| +function startTagInCell(p, token) {
|
| + var 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) {
|
| + var 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);
|
| +}
|
| +
|
| +//12.2.5.4.16 The "in select" insertion mode
|
| +//------------------------------------------------------------------
|
| +function startTagInSelect(p, token) {
|
| + var tn = token.tagName;
|
| +
|
| + if (tn === $.HTML)
|
| + startTagInBody(p, token);
|
| +
|
| + else if (tn === $.OPTION) {
|
| + if (p.openElements.currentTagName === $.OPTION)
|
| + p._processFakeEndTag($.OPTION);
|
| +
|
| + p._insertElement(token, NS.HTML);
|
| + }
|
| +
|
| + else if (tn === $.OPTGROUP) {
|
| + if (p.openElements.currentTagName === $.OPTION)
|
| + p._processFakeEndTag($.OPTION);
|
| +
|
| + if (p.openElements.currentTagName === $.OPTGROUP)
|
| + p._processFakeEndTag($.OPTGROUP);
|
| +
|
| + p._insertElement(token, NS.HTML);
|
| + }
|
| +
|
| + else if (tn === $.SELECT)
|
| + p._processFakeEndTag($.SELECT);
|
| +
|
| + else if (tn === $.INPUT || tn === $.KEYGEN || tn === $.TEXTAREA) {
|
| + if (p.openElements.hasInSelectScope($.SELECT)) {
|
| + p._processFakeEndTag($.SELECT);
|
| + p._processToken(token);
|
| + }
|
| + }
|
| +
|
| + else if (tn === $.SCRIPT || tn === $.TEMPLATE)
|
| + startTagInHead(p, token);
|
| +}
|
| +
|
| +function endTagInSelect(p, token) {
|
| + var tn = token.tagName;
|
| +
|
| + if (tn === $.OPTGROUP) {
|
| + var prevOpenElement = p.openElements.items[p.openElements.stackTop - 1],
|
| + prevOpenElementTn = prevOpenElement && p.treeAdapter.getTagName(prevOpenElement);
|
| +
|
| + if (p.openElements.currentTagName === $.OPTION && prevOpenElementTn === $.OPTGROUP)
|
| + p._processFakeEndTag($.OPTION);
|
| +
|
| + 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) {
|
| + var tn = token.tagName;
|
| +
|
| + if (tn === $.CAPTION || tn === $.TABLE || tn === $.TBODY || tn === $.TFOOT ||
|
| + tn === $.THEAD || tn === $.TR || tn === $.TD || tn === $.TH) {
|
| + p._processFakeEndTag($.SELECT);
|
| + p._processToken(token);
|
| + }
|
| +
|
| + else
|
| + startTagInSelect(p, token);
|
| +}
|
| +
|
| +function endTagInSelectInTable(p, token) {
|
| + var 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._processFakeEndTag($.SELECT);
|
| + p._processToken(token);
|
| + }
|
| + }
|
| +
|
| + else
|
| + endTagInSelect(p, token);
|
| +}
|
| +
|
| +//12.2.5.4.18 The "in template" insertion mode
|
| +//------------------------------------------------------------------
|
| +function startTagInTemplate(p, token) {
|
| + var 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 {
|
| + var 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.popUntilTemplatePopped();
|
| + p.activeFormattingElements.clearToLastMarker();
|
| + p._popTmplInsertionMode();
|
| + p._resetInsertionMode();
|
| + p._processToken(token);
|
| + }
|
| +
|
| + else
|
| + p.stopped = true;
|
| +}
|
| +
|
| +
|
| +//12.2.5.4.19 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);
|
| +}
|
| +
|
| +//12.2.5.4.20 The "in frameset" insertion mode
|
| +//------------------------------------------------------------------
|
| +function startTagInFrameset(p, token) {
|
| + var 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);
|
| +
|
| + 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;
|
| + }
|
| +}
|
| +
|
| +//12.2.5.4.21 The "after frameset" insertion mode
|
| +//------------------------------------------------------------------
|
| +function startTagAfterFrameset(p, token) {
|
| + var 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;
|
| +}
|
| +
|
| +//12.2.5.4.22 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);
|
| +}
|
| +
|
| +//12.2.5.4.23 The "after after frameset" insertion mode
|
| +//------------------------------------------------------------------
|
| +function startTagAfterAfterFrameset(p, token) {
|
| + var tn = token.tagName;
|
| +
|
| + if (tn === $.HTML)
|
| + startTagInBody(p, token);
|
| +
|
| + else if (tn === $.NOFRAMES)
|
| + startTagInHead(p, token);
|
| +}
|
| +
|
| +
|
| +//12.2.5.5 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._isMathMLTextIntegrationPoint(p.openElements.current)) &&
|
| + (!p._isHtmlIntegrationPoint(p.openElements.current))) {
|
| + p.openElements.pop();
|
| + }
|
| +
|
| + p._processToken(token);
|
| + }
|
| +
|
| + else {
|
| + var current = p._getAdjustedCurrentElement(),
|
| + 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);
|
| + }
|
| +}
|
| +
|
| +function endTagInForeignContent(p, token) {
|
| + for (var i = p.openElements.stackTop; i > 0; i--) {
|
| + var 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;
|
| + }
|
| + }
|
| +}
|
|
|