Brunobkr/llama.cpp_AlgMor24_github
ΩFFFΣLLIa • llama.cpp • AlgMor24 ██████╗ ███████╗███████╗███████╗██╗ ██╗ ██╗ █████╗ ██╔═══██╗██╔════╝██╔════╝██╔════╝██║ ██║ ██║██╔══██╗ ██║ ██║█████╗ █████╗ █████╗ ██║ ██║ ██║███████║ ██║ ██║██╔══╝ ██╔══╝ ██╔══╝ ██║ ██║ ██║██╔══██║ ╚██████╔╝██║ ██║ ███████╗███████╗███████╗██║██║ ██║ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝╚══════╝╚══════╝╚═╝╚═╝ ╚═╝ High-Performance LLM / VLM Inference & Autonomous Agentic Ecosystem… See the full description on the dataset page: https://huggingface.co/datasets/Brunobkr/llama.cpp_AlgMor24_github.
03.1k
1import { Tokenizer, TokenizerMode } from '../tokenizer/index.js';2import { OpenElementStack } from './open-element-stack.js';3import { FormattingElementList, EntryType } from './formatting-element-list.js';4import { defaultTreeAdapter } from '../tree-adapters/default.js';5import * as doctype from '../common/doctype.js';6import * as foreignContent from '../common/foreign-content.js';7import { ERR } from '../common/error-codes.js';8import * as unicode from '../common/unicode.js';9import { TAG_ID as $, TAG_NAMES as TN, NS, ATTRS, SPECIAL_ELEMENTS, DOCUMENT_MODE, NUMBERED_HEADERS, getTagID, } from '../common/html.js';10import { TokenType, getTokenAttr, } from '../common/token.js';11//Misc constants12const HIDDEN_INPUT_TYPE = 'hidden';13//Adoption agency loops iteration count14const AA_OUTER_LOOP_ITER = 8;15const AA_INNER_LOOP_ITER = 3;16//Insertion modes17var InsertionMode;18(function (InsertionMode) {19 InsertionMode[InsertionMode["INITIAL"] = 0] = "INITIAL";20 InsertionMode[InsertionMode["BEFORE_HTML"] = 1] = "BEFORE_HTML";21 InsertionMode[InsertionMode["BEFORE_HEAD"] = 2] = "BEFORE_HEAD";22 InsertionMode[InsertionMode["IN_HEAD"] = 3] = "IN_HEAD";23 InsertionMode[InsertionMode["IN_HEAD_NO_SCRIPT"] = 4] = "IN_HEAD_NO_SCRIPT";24 InsertionMode[InsertionMode["AFTER_HEAD"] = 5] = "AFTER_HEAD";25 InsertionMode[InsertionMode["IN_BODY"] = 6] = "IN_BODY";26 InsertionMode[InsertionMode["TEXT"] = 7] = "TEXT";27 InsertionMode[InsertionMode["IN_TABLE"] = 8] = "IN_TABLE";28 InsertionMode[InsertionMode["IN_TABLE_TEXT"] = 9] = "IN_TABLE_TEXT";29 InsertionMode[InsertionMode["IN_CAPTION"] = 10] = "IN_CAPTION";30 InsertionMode[InsertionMode["IN_COLUMN_GROUP"] = 11] = "IN_COLUMN_GROUP";31 InsertionMode[InsertionMode["IN_TABLE_BODY"] = 12] = "IN_TABLE_BODY";32 InsertionMode[InsertionMode["IN_ROW"] = 13] = "IN_ROW";33 InsertionMode[InsertionMode["IN_CELL"] = 14] = "IN_CELL";34 InsertionMode[InsertionMode["IN_SELECT"] = 15] = "IN_SELECT";35 InsertionMode[InsertionMode["IN_SELECT_IN_TABLE"] = 16] = "IN_SELECT_IN_TABLE";36 InsertionMode[InsertionMode["IN_TEMPLATE"] = 17] = "IN_TEMPLATE";37 InsertionMode[InsertionMode["AFTER_BODY"] = 18] = "AFTER_BODY";38 InsertionMode[InsertionMode["IN_FRAMESET"] = 19] = "IN_FRAMESET";39 InsertionMode[InsertionMode["AFTER_FRAMESET"] = 20] = "AFTER_FRAMESET";40 InsertionMode[InsertionMode["AFTER_AFTER_BODY"] = 21] = "AFTER_AFTER_BODY";41 InsertionMode[InsertionMode["AFTER_AFTER_FRAMESET"] = 22] = "AFTER_AFTER_FRAMESET";42})(InsertionMode || (InsertionMode = {}));43const BASE_LOC = {44 startLine: -1,45 startCol: -1,46 startOffset: -1,47 endLine: -1,48 endCol: -1,49 endOffset: -1,50};51const TABLE_STRUCTURE_TAGS = new Set([$.TABLE, $.TBODY, $.TFOOT, $.THEAD, $.TR]);52const defaultParserOptions = {53 scriptingEnabled: true,54 sourceCodeLocationInfo: false,55 treeAdapter: defaultTreeAdapter,56 onParseError: null,57};58//Parser59export class Parser {60 constructor(options, document, 61 /** @internal */62 fragmentContext = null, 63 /** @internal */64 scriptHandler = null) {65 this.fragmentContext = fragmentContext;66 this.scriptHandler = scriptHandler;67 this.currentToken = null;68 this.stopped = false;69 /** @internal */70 this.insertionMode = InsertionMode.INITIAL;71 /** @internal */72 this.originalInsertionMode = InsertionMode.INITIAL;73 /** @internal */74 this.headElement = null;75 /** @internal */76 this.formElement = null;77 /** Indicates that the current node is not an element in the HTML namespace */78 this.currentNotInHTML = false;79 /**80 * The template insertion mode stack is maintained from the left.81 * Ie. the topmost element will always have index 0.82 *83 * @internal84 */85 this.tmplInsertionModeStack = [];86 /** @internal */87 this.pendingCharacterTokens = [];88 /** @internal */89 this.hasNonWhitespacePendingCharacterToken = false;90 /** @internal */91 this.framesetOk = true;92 /** @internal */93 this.skipNextNewLine = false;94 /** @internal */95 this.fosterParentingEnabled = false;96 this.options = {97 ...defaultParserOptions,98 ...options,99 };100 this.treeAdapter = this.options.treeAdapter;101 this.onParseError = this.options.onParseError;102 // Always enable location info if we report parse errors.103 if (this.onParseError) {104 this.options.sourceCodeLocationInfo = true;105 }106 this.document = document !== null && document !== void 0 ? document : this.treeAdapter.createDocument();107 this.tokenizer = new Tokenizer(this.options, this);108 this.activeFormattingElements = new FormattingElementList(this.treeAdapter);109 this.fragmentContextID = fragmentContext ? getTagID(this.treeAdapter.getTagName(fragmentContext)) : $.UNKNOWN;110 this._setContextModes(fragmentContext !== null && fragmentContext !== void 0 ? fragmentContext : this.document, this.fragmentContextID);111 this.openElements = new OpenElementStack(this.document, this.treeAdapter, this);112 }113 // API114 static parse(html, options) {115 const parser = new this(options);116 parser.tokenizer.write(html, true);117 return parser.document;118 }119 static getFragmentParser(fragmentContext, options) {120 const opts = {121 ...defaultParserOptions,122 ...options,123 };124 //NOTE: use a <template> element as the fragment context if no context element was provided,125 //so we will parse in a "forgiving" manner126 fragmentContext !== null && fragmentContext !== void 0 ? fragmentContext : (fragmentContext = opts.treeAdapter.createElement(TN.TEMPLATE, NS.HTML, []));127 //NOTE: create a fake element which will be used as the `document` for fragment parsing.128 //This is important for jsdom, where a new `document` cannot be created. This led to129 //fragment parsing messing with the main `document`.130 const documentMock = opts.treeAdapter.createElement('documentmock', NS.HTML, []);131 const parser = new this(opts, documentMock, fragmentContext);132 if (parser.fragmentContextID === $.TEMPLATE) {133 parser.tmplInsertionModeStack.unshift(InsertionMode.IN_TEMPLATE);134 }135 parser._initTokenizerForFragmentParsing();136 parser._insertFakeRootElement();137 parser._resetInsertionMode();138 parser._findFormInFragmentContext();139 return parser;140 }141 getFragment() {142 const rootElement = this.treeAdapter.getFirstChild(this.document);143 const fragment = this.treeAdapter.createDocumentFragment();144 this._adoptNodes(rootElement, fragment);145 return fragment;146 }147 //Errors148 /** @internal */149 _err(token, code, beforeToken) {150 var _a;151 if (!this.onParseError)152 return;153 const loc = (_a = token.location) !== null && _a !== void 0 ? _a : BASE_LOC;154 const err = {155 code,156 startLine: loc.startLine,157 startCol: loc.startCol,158 startOffset: loc.startOffset,159 endLine: beforeToken ? loc.startLine : loc.endLine,160 endCol: beforeToken ? loc.startCol : loc.endCol,161 endOffset: beforeToken ? loc.startOffset : loc.endOffset,162 };163 this.onParseError(err);164 }165 //Stack events166 /** @internal */167 onItemPush(node, tid, isTop) {168 var _a, _b;169 (_b = (_a = this.treeAdapter).onItemPush) === null || _b === void 0 ? void 0 : _b.call(_a, node);170 if (isTop && this.openElements.stackTop > 0)171 this._setContextModes(node, tid);172 }173 /** @internal */174 onItemPop(node, isTop) {175 var _a, _b;176 if (this.options.sourceCodeLocationInfo) {177 this._setEndLocation(node, this.currentToken);178 }179 (_b = (_a = this.treeAdapter).onItemPop) === null || _b === void 0 ? void 0 : _b.call(_a, node, this.openElements.current);180 if (isTop) {181 let current;182 let currentTagId;183 if (this.openElements.stackTop === 0 && this.fragmentContext) {184 current = this.fragmentContext;185 currentTagId = this.fragmentContextID;186 }187 else {188 ({ current, currentTagId } = this.openElements);189 }190 this._setContextModes(current, currentTagId);191 }192 }193 _setContextModes(current, tid) {194 const isHTML = current === this.document || (current && this.treeAdapter.getNamespaceURI(current) === NS.HTML);195 this.currentNotInHTML = !isHTML;196 this.tokenizer.inForeignNode =197 !isHTML && current !== undefined && tid !== undefined && !this._isIntegrationPoint(tid, current);198 }199 /** @protected */200 _switchToTextParsing(currentToken, nextTokenizerState) {201 this._insertElement(currentToken, NS.HTML);202 this.tokenizer.state = nextTokenizerState;203 this.originalInsertionMode = this.insertionMode;204 this.insertionMode = InsertionMode.TEXT;205 }206 switchToPlaintextParsing() {207 this.insertionMode = InsertionMode.TEXT;208 this.originalInsertionMode = InsertionMode.IN_BODY;209 this.tokenizer.state = TokenizerMode.PLAINTEXT;210 }211 //Fragment parsing212 /** @protected */213 _getAdjustedCurrentElement() {214 return this.openElements.stackTop === 0 && this.fragmentContext215 ? this.fragmentContext216 : this.openElements.current;217 }218 /** @protected */219 _findFormInFragmentContext() {220 let node = this.fragmentContext;221 while (node) {222 if (this.treeAdapter.getTagName(node) === TN.FORM) {223 this.formElement = node;224 break;225 }226 node = this.treeAdapter.getParentNode(node);227 }228 }229 _initTokenizerForFragmentParsing() {230 if (!this.fragmentContext || this.treeAdapter.getNamespaceURI(this.fragmentContext) !== NS.HTML) {231 return;232 }233 switch (this.fragmentContextID) {234 case $.TITLE:235 case $.TEXTAREA: {236 this.tokenizer.state = TokenizerMode.RCDATA;237 break;238 }239 case $.STYLE:240 case $.XMP:241 case $.IFRAME:242 case $.NOEMBED:243 case $.NOFRAMES:244 case $.NOSCRIPT: {245 this.tokenizer.state = TokenizerMode.RAWTEXT;246 break;247 }248 case $.SCRIPT: {249 this.tokenizer.state = TokenizerMode.SCRIPT_DATA;250 break;251 }252 case $.PLAINTEXT: {253 this.tokenizer.state = TokenizerMode.PLAINTEXT;254 break;255 }256 default:257 // Do nothing258 }259 }260 //Tree mutation261 /** @protected */262 _setDocumentType(token) {263 const name = token.name || '';264 const publicId = token.publicId || '';265 const systemId = token.systemId || '';266 this.treeAdapter.setDocumentType(this.document, name, publicId, systemId);267 if (token.location) {268 const documentChildren = this.treeAdapter.getChildNodes(this.document);269 const docTypeNode = documentChildren.find((node) => this.treeAdapter.isDocumentTypeNode(node));270 if (docTypeNode) {271 this.treeAdapter.setNodeSourceCodeLocation(docTypeNode, token.location);272 }273 }274 }275 /** @protected */276 _attachElementToTree(element, location) {277 if (this.options.sourceCodeLocationInfo) {278 const loc = location && {279 ...location,280 startTag: location,281 };282 this.treeAdapter.setNodeSourceCodeLocation(element, loc);283 }284 if (this._shouldFosterParentOnInsertion()) {285 this._fosterParentElement(element);286 }287 else {288 const parent = this.openElements.currentTmplContentOrNode;289 this.treeAdapter.appendChild(parent !== null && parent !== void 0 ? parent : this.document, element);290 }291 }292 /**293 * For self-closing tags. Add an element to the tree, but skip adding it294 * to the stack.295 */296 /** @protected */297 _appendElement(token, namespaceURI) {298 const element = this.treeAdapter.createElement(token.tagName, namespaceURI, token.attrs);299 this._attachElementToTree(element, token.location);300 }301 /** @protected */302 _insertElement(token, namespaceURI) {303 const element = this.treeAdapter.createElement(token.tagName, namespaceURI, token.attrs);304 this._attachElementToTree(element, token.location);305 this.openElements.push(element, token.tagID);306 }307 /** @protected */308 _insertFakeElement(tagName, tagID) {309 const element = this.treeAdapter.createElement(tagName, NS.HTML, []);310 this._attachElementToTree(element, null);311 this.openElements.push(element, tagID);312 }313 /** @protected */314 _insertTemplate(token) {315 const tmpl = this.treeAdapter.createElement(token.tagName, NS.HTML, token.attrs);316 const content = this.treeAdapter.createDocumentFragment();317 this.treeAdapter.setTemplateContent(tmpl, content);318 this._attachElementToTree(tmpl, token.location);319 this.openElements.push(tmpl, token.tagID);320 if (this.options.sourceCodeLocationInfo)321 this.treeAdapter.setNodeSourceCodeLocation(content, null);322 }323 /** @protected */324 _insertFakeRootElement() {325 const element = this.treeAdapter.createElement(TN.HTML, NS.HTML, []);326 if (this.options.sourceCodeLocationInfo)327 this.treeAdapter.setNodeSourceCodeLocation(element, null);328 this.treeAdapter.appendChild(this.openElements.current, element);329 this.openElements.push(element, $.HTML);330 }331 /** @protected */332 _appendCommentNode(token, parent) {333 const commentNode = this.treeAdapter.createCommentNode(token.data);334 this.treeAdapter.appendChild(parent, commentNode);335 if (this.options.sourceCodeLocationInfo) {336 this.treeAdapter.setNodeSourceCodeLocation(commentNode, token.location);337 }338 }339 /** @protected */340 _insertCharacters(token) {341 let parent;342 let beforeElement;343 if (this._shouldFosterParentOnInsertion()) {344 ({ parent, beforeElement } = this._findFosterParentingLocation());345 if (beforeElement) {346 this.treeAdapter.insertTextBefore(parent, token.chars, beforeElement);347 }348 else {349 this.treeAdapter.insertText(parent, token.chars);350 }351 }352 else {353 parent = this.openElements.currentTmplContentOrNode;354 this.treeAdapter.insertText(parent, token.chars);355 }356 if (!token.location)357 return;358 const siblings = this.treeAdapter.getChildNodes(parent);359 const textNodeIdx = beforeElement ? siblings.lastIndexOf(beforeElement) : siblings.length;360 const textNode = siblings[textNodeIdx - 1];361 //NOTE: if we have a location assigned by another token, then just update the end position362 const tnLoc = this.treeAdapter.getNodeSourceCodeLocation(textNode);363 if (tnLoc) {364 const { endLine, endCol, endOffset } = token.location;365 this.treeAdapter.updateNodeSourceCodeLocation(textNode, { endLine, endCol, endOffset });366 }367 else if (this.options.sourceCodeLocationInfo) {368 this.treeAdapter.setNodeSourceCodeLocation(textNode, token.location);369 }370 }371 /** @protected */372 _adoptNodes(donor, recipient) {373 for (let child = this.treeAdapter.getFirstChild(donor); child; child = this.treeAdapter.getFirstChild(donor)) {374 this.treeAdapter.detachNode(child);375 this.treeAdapter.appendChild(recipient, child);376 }377 }378 /** @protected */379 _setEndLocation(element, closingToken) {380 if (this.treeAdapter.getNodeSourceCodeLocation(element) && closingToken.location) {381 const ctLoc = closingToken.location;382 const tn = this.treeAdapter.getTagName(element);383 const endLoc = 384 // NOTE: For cases like <p> <p> </p> - First 'p' closes without a closing385 // tag and for cases like <td> <p> </td> - 'p' closes without a closing tag.386 closingToken.type === TokenType.END_TAG && tn === closingToken.tagName387 ? {388 endTag: { ...ctLoc },389 endLine: ctLoc.endLine,390 endCol: ctLoc.endCol,391 endOffset: ctLoc.endOffset,392 }393 : {394 endLine: ctLoc.startLine,395 endCol: ctLoc.startCol,396 endOffset: ctLoc.startOffset,397 };398 this.treeAdapter.updateNodeSourceCodeLocation(element, endLoc);399 }400 }401 //Token processing402 shouldProcessStartTagTokenInForeignContent(token) {403 // Check that neither current === document, or ns === NS.HTML404 if (!this.currentNotInHTML)405 return false;406 let current;407 let currentTagId;408 if (this.openElements.stackTop === 0 && this.fragmentContext) {409 current = this.fragmentContext;410 currentTagId = this.fragmentContextID;411 }412 else {413 ({ current, currentTagId } = this.openElements);414 }415 if (token.tagID === $.SVG &&416 this.treeAdapter.getTagName(current) === TN.ANNOTATION_XML &&417 this.treeAdapter.getNamespaceURI(current) === NS.MATHML) {418 return false;419 }420 return (421 // Check that `current` is not an integration point for HTML or MathML elements.422 this.tokenizer.inForeignNode ||423 // If it _is_ an integration point, then we might have to check that it is not an HTML424 // integration point.425 ((token.tagID === $.MGLYPH || token.tagID === $.MALIGNMARK) &&426 currentTagId !== undefined &&427 !this._isIntegrationPoint(currentTagId, current, NS.HTML)));428 }429 /** @protected */430 _processToken(token) {431 switch (token.type) {432 case TokenType.CHARACTER: {433 this.onCharacter(token);434 break;435 }436 case TokenType.NULL_CHARACTER: {437 this.onNullCharacter(token);438 break;439 }440 case TokenType.COMMENT: {441 this.onComment(token);442 break;443 }444 case TokenType.DOCTYPE: {445 this.onDoctype(token);446 break;447 }448 case TokenType.START_TAG: {449 this._processStartTag(token);450 break;451 }452 case TokenType.END_TAG: {453 this.onEndTag(token);454 break;455 }456 case TokenType.EOF: {457 this.onEof(token);458 break;459 }460 case TokenType.WHITESPACE_CHARACTER: {461 this.onWhitespaceCharacter(token);462 break;463 }464 }465 }466 //Integration points467 /** @protected */468 _isIntegrationPoint(tid, element, foreignNS) {469 const ns = this.treeAdapter.getNamespaceURI(element);470 const attrs = this.treeAdapter.getAttrList(element);471 return foreignContent.isIntegrationPoint(tid, ns, attrs, foreignNS);472 }473 //Active formatting elements reconstruction474 /** @protected */475 _reconstructActiveFormattingElements() {476 const listLength = this.activeFormattingElements.entries.length;477 if (listLength) {478 const endIndex = this.activeFormattingElements.entries.findIndex((entry) => entry.type === EntryType.Marker || this.openElements.contains(entry.element));479 const unopenIdx = endIndex === -1 ? listLength - 1 : endIndex - 1;480 for (let i = unopenIdx; i >= 0; i--) {481 const entry = this.activeFormattingElements.entries[i];482 this._insertElement(entry.token, this.treeAdapter.getNamespaceURI(entry.element));483 entry.element = this.openElements.current;484 }485 }486 }487 //Close elements488 /** @protected */489 _closeTableCell() {490 this.openElements.generateImpliedEndTags();491 this.openElements.popUntilTableCellPopped();492 this.activeFormattingElements.clearToLastMarker();493 this.insertionMode = InsertionMode.IN_ROW;494 }495 /** @protected */496 _closePElement() {497 this.openElements.generateImpliedEndTagsWithExclusion($.P);498 this.openElements.popUntilTagNamePopped($.P);499 }500 //Insertion modes501 /** @protected */502 _resetInsertionMode() {503 for (let i = this.openElements.stackTop; i >= 0; i--) {504 //Insertion mode reset map505 switch (i === 0 && this.fragmentContext ? this.fragmentContextID : this.openElements.tagIDs[i]) {506 case $.TR: {507 this.insertionMode = InsertionMode.IN_ROW;508 return;509 }510 case $.TBODY:511 case $.THEAD:512 case $.TFOOT: {513 this.insertionMode = InsertionMode.IN_TABLE_BODY;514 return;515 }516 case $.CAPTION: {517 this.insertionMode = InsertionMode.IN_CAPTION;518 return;519 }520 case $.COLGROUP: {521 this.insertionMode = InsertionMode.IN_COLUMN_GROUP;522 return;523 }524 case $.TABLE: {525 this.insertionMode = InsertionMode.IN_TABLE;526 return;527 }528 case $.BODY: {529 this.insertionMode = InsertionMode.IN_BODY;530 return;531 }532 case $.FRAMESET: {533 this.insertionMode = InsertionMode.IN_FRAMESET;534 return;535 }536 case $.SELECT: {537 this._resetInsertionModeForSelect(i);538 return;539 }540 case $.TEMPLATE: {541 this.insertionMode = this.tmplInsertionModeStack[0];542 return;543 }544 case $.HTML: {545 this.insertionMode = this.headElement ? InsertionMode.AFTER_HEAD : InsertionMode.BEFORE_HEAD;546 return;547 }548 case $.TD:549 case $.TH: {550 if (i > 0) {551 this.insertionMode = InsertionMode.IN_CELL;552 return;553 }554 break;555 }556 case $.HEAD: {557 if (i > 0) {558 this.insertionMode = InsertionMode.IN_HEAD;559 return;560 }561 break;562 }563 }564 }565 this.insertionMode = InsertionMode.IN_BODY;566 }567 /** @protected */568 _resetInsertionModeForSelect(selectIdx) {569 if (selectIdx > 0) {570 for (let i = selectIdx - 1; i > 0; i--) {571 const tn = this.openElements.tagIDs[i];572 if (tn === $.TEMPLATE) {573 break;574 }575 else if (tn === $.TABLE) {576 this.insertionMode = InsertionMode.IN_SELECT_IN_TABLE;577 return;578 }579 }580 }581 this.insertionMode = InsertionMode.IN_SELECT;582 }583 //Foster parenting584 /** @protected */585 _isElementCausesFosterParenting(tn) {586 return TABLE_STRUCTURE_TAGS.has(tn);587 }588 /** @protected */589 _shouldFosterParentOnInsertion() {590 return (this.fosterParentingEnabled &&591 this.openElements.currentTagId !== undefined &&592 this._isElementCausesFosterParenting(this.openElements.currentTagId));593 }594 /** @protected */595 _findFosterParentingLocation() {596 for (let i = this.openElements.stackTop; i >= 0; i--) {597 const openElement = this.openElements.items[i];598 switch (this.openElements.tagIDs[i]) {599 case $.TEMPLATE: {600 if (this.treeAdapter.getNamespaceURI(openElement) === NS.HTML) {601 return { parent: this.treeAdapter.getTemplateContent(openElement), beforeElement: null };602 }603 break;604 }605 case $.TABLE: {606 const parent = this.treeAdapter.getParentNode(openElement);607 if (parent) {608 return { parent, beforeElement: openElement };609 }610 return { parent: this.openElements.items[i - 1], beforeElement: null };611 }612 default:613 // Do nothing614 }615 }616 return { parent: this.openElements.items[0], beforeElement: null };617 }618 /** @protected */619 _fosterParentElement(element) {620 const location = this._findFosterParentingLocation();621 if (location.beforeElement) {622 this.treeAdapter.insertBefore(location.parent, element, location.beforeElement);623 }624 else {625 this.treeAdapter.appendChild(location.parent, element);626 }627 }628 //Special elements629 /** @protected */630 _isSpecialElement(element, id) {631 const ns = this.treeAdapter.getNamespaceURI(element);632 return SPECIAL_ELEMENTS[ns].has(id);633 }634 /** @internal */635 onCharacter(token) {636 this.skipNextNewLine = false;637 if (this.tokenizer.inForeignNode) {638 characterInForeignContent(this, token);639 return;640 }641 switch (this.insertionMode) {642 case InsertionMode.INITIAL: {643 tokenInInitialMode(this, token);644 break;645 }646 case InsertionMode.BEFORE_HTML: {647 tokenBeforeHtml(this, token);648 break;649 }650 case InsertionMode.BEFORE_HEAD: {651 tokenBeforeHead(this, token);652 break;653 }654 case InsertionMode.IN_HEAD: {655 tokenInHead(this, token);656 break;657 }658 case InsertionMode.IN_HEAD_NO_SCRIPT: {659 tokenInHeadNoScript(this, token);660 break;661 }662 case InsertionMode.AFTER_HEAD: {663 tokenAfterHead(this, token);664 break;665 }666 case InsertionMode.IN_BODY:667 case InsertionMode.IN_CAPTION:668 case InsertionMode.IN_CELL:669 case InsertionMode.IN_TEMPLATE: {670 characterInBody(this, token);671 break;672 }673 case InsertionMode.TEXT:674 case InsertionMode.IN_SELECT:675 case InsertionMode.IN_SELECT_IN_TABLE: {676 this._insertCharacters(token);677 break;678 }679 case InsertionMode.IN_TABLE:680 case InsertionMode.IN_TABLE_BODY:681 case InsertionMode.IN_ROW: {682 characterInTable(this, token);683 break;684 }685 case InsertionMode.IN_TABLE_TEXT: {686 characterInTableText(this, token);687 break;688 }689 case InsertionMode.IN_COLUMN_GROUP: {690 tokenInColumnGroup(this, token);691 break;692 }693 case InsertionMode.AFTER_BODY: {694 tokenAfterBody(this, token);695 break;696 }697 case InsertionMode.AFTER_AFTER_BODY: {698 tokenAfterAfterBody(this, token);699 break;700 }701 default:702 // Do nothing703 }704 }705 /** @internal */706 onNullCharacter(token) {707 this.skipNextNewLine = false;708 if (this.tokenizer.inForeignNode) {709 nullCharacterInForeignContent(this, token);710 return;711 }712 switch (this.insertionMode) {713 case InsertionMode.INITIAL: {714 tokenInInitialMode(this, token);715 break;716 }717 case InsertionMode.BEFORE_HTML: {718 tokenBeforeHtml(this, token);719 break;720 }721 case InsertionMode.BEFORE_HEAD: {722 tokenBeforeHead(this, token);723 break;724 }725 case InsertionMode.IN_HEAD: {726 tokenInHead(this, token);727 break;728 }729 case InsertionMode.IN_HEAD_NO_SCRIPT: {730 tokenInHeadNoScript(this, token);731 break;732 }733 case InsertionMode.AFTER_HEAD: {734 tokenAfterHead(this, token);735 break;736 }737 case InsertionMode.TEXT: {738 this._insertCharacters(token);739 break;740 }741 case InsertionMode.IN_TABLE:742 case InsertionMode.IN_TABLE_BODY:743 case InsertionMode.IN_ROW: {744 characterInTable(this, token);745 break;746 }747 case InsertionMode.IN_COLUMN_GROUP: {748 tokenInColumnGroup(this, token);749 break;750 }751 case InsertionMode.AFTER_BODY: {752 tokenAfterBody(this, token);753 break;754 }755 case InsertionMode.AFTER_AFTER_BODY: {756 tokenAfterAfterBody(this, token);757 break;758 }759 default:760 // Do nothing761 }762 }763 /** @internal */764 onComment(token) {765 this.skipNextNewLine = false;766 if (this.currentNotInHTML) {767 appendComment(this, token);768 return;769 }770 switch (this.insertionMode) {771 case InsertionMode.INITIAL:772 case InsertionMode.BEFORE_HTML:773 case InsertionMode.BEFORE_HEAD:774 case InsertionMode.IN_HEAD:775 case InsertionMode.IN_HEAD_NO_SCRIPT:776 case InsertionMode.AFTER_HEAD:777 case InsertionMode.IN_BODY:778 case InsertionMode.IN_TABLE:779 case InsertionMode.IN_CAPTION:780 case InsertionMode.IN_COLUMN_GROUP:781 case InsertionMode.IN_TABLE_BODY:782 case InsertionMode.IN_ROW:783 case InsertionMode.IN_CELL:784 case InsertionMode.IN_SELECT:785 case InsertionMode.IN_SELECT_IN_TABLE:786 case InsertionMode.IN_TEMPLATE:787 case InsertionMode.IN_FRAMESET:788 case InsertionMode.AFTER_FRAMESET: {789 appendComment(this, token);790 break;791 }792 case InsertionMode.IN_TABLE_TEXT: {793 tokenInTableText(this, token);794 break;795 }796 case InsertionMode.AFTER_BODY: {797 appendCommentToRootHtmlElement(this, token);798 break;799 }800 case InsertionMode.AFTER_AFTER_BODY:801 case InsertionMode.AFTER_AFTER_FRAMESET: {802 appendCommentToDocument(this, token);803 break;804 }805 default:806 // Do nothing807 }808 }809 /** @internal */810 onDoctype(token) {811 this.skipNextNewLine = false;812 switch (this.insertionMode) {813 case InsertionMode.INITIAL: {814 doctypeInInitialMode(this, token);815 break;816 }817 case InsertionMode.BEFORE_HEAD:818 case InsertionMode.IN_HEAD:819 case InsertionMode.IN_HEAD_NO_SCRIPT:820 case InsertionMode.AFTER_HEAD: {821 this._err(token, ERR.misplacedDoctype);822 break;823 }824 case InsertionMode.IN_TABLE_TEXT: {825 tokenInTableText(this, token);826 break;827 }828 default:829 // Do nothing830 }831 }832 /** @internal */833 onStartTag(token) {834 this.skipNextNewLine = false;835 this.currentToken = token;836 this._processStartTag(token);837 if (token.selfClosing && !token.ackSelfClosing) {838 this._err(token, ERR.nonVoidHtmlElementStartTagWithTrailingSolidus);839 }840 }841 /**842 * Processes a given start tag.843 *844 * `onStartTag` checks if a self-closing tag was recognized. When a token845 * is moved inbetween multiple insertion modes, this check for self-closing846 * could lead to false positives. To avoid this, `_processStartTag` is used847 * for nested calls.848 *849 * @param token The token to process.850 * @protected851 */852 _processStartTag(token) {853 if (this.shouldProcessStartTagTokenInForeignContent(token)) {854 startTagInForeignContent(this, token);855 }856 else {857 this._startTagOutsideForeignContent(token);858 }859 }860 /** @protected */861 _startTagOutsideForeignContent(token) {862 switch (this.insertionMode) {863 case InsertionMode.INITIAL: {864 tokenInInitialMode(this, token);865 break;866 }867 case InsertionMode.BEFORE_HTML: {868 startTagBeforeHtml(this, token);869 break;870 }871 case InsertionMode.BEFORE_HEAD: {872 startTagBeforeHead(this, token);873 break;874 }875 case InsertionMode.IN_HEAD: {876 startTagInHead(this, token);877 break;878 }879 case InsertionMode.IN_HEAD_NO_SCRIPT: {880 startTagInHeadNoScript(this, token);881 break;882 }883 case InsertionMode.AFTER_HEAD: {884 startTagAfterHead(this, token);885 break;886 }887 case InsertionMode.IN_BODY: {888 startTagInBody(this, token);889 break;890 }891 case InsertionMode.IN_TABLE: {892 startTagInTable(this, token);893 break;894 }895 case InsertionMode.IN_TABLE_TEXT: {896 tokenInTableText(this, token);897 break;898 }899 case InsertionMode.IN_CAPTION: {900 startTagInCaption(this, token);901 break;902 }903 case InsertionMode.IN_COLUMN_GROUP: {904 startTagInColumnGroup(this, token);905 break;906 }907 case InsertionMode.IN_TABLE_BODY: {908 startTagInTableBody(this, token);909 break;910 }911 case InsertionMode.IN_ROW: {912 startTagInRow(this, token);913 break;914 }915 case InsertionMode.IN_CELL: {916 startTagInCell(this, token);917 break;918 }919 case InsertionMode.IN_SELECT: {920 startTagInSelect(this, token);921 break;922 }923 case InsertionMode.IN_SELECT_IN_TABLE: {924 startTagInSelectInTable(this, token);925 break;926 }927 case InsertionMode.IN_TEMPLATE: {928 startTagInTemplate(this, token);929 break;930 }931 case InsertionMode.AFTER_BODY: {932 startTagAfterBody(this, token);933 break;934 }935 case InsertionMode.IN_FRAMESET: {936 startTagInFrameset(this, token);937 break;938 }939 case InsertionMode.AFTER_FRAMESET: {940 startTagAfterFrameset(this, token);941 break;942 }943 case InsertionMode.AFTER_AFTER_BODY: {944 startTagAfterAfterBody(this, token);945 break;946 }947 case InsertionMode.AFTER_AFTER_FRAMESET: {948 startTagAfterAfterFrameset(this, token);949 break;950 }951 default:952 // Do nothing953 }954 }955 /** @internal */956 onEndTag(token) {957 this.skipNextNewLine = false;958 this.currentToken = token;959 if (this.currentNotInHTML) {960 endTagInForeignContent(this, token);961 }962 else {963 this._endTagOutsideForeignContent(token);964 }965 }966 /** @protected */967 _endTagOutsideForeignContent(token) {968 switch (this.insertionMode) {969 case InsertionMode.INITIAL: {970 tokenInInitialMode(this, token);971 break;972 }973 case InsertionMode.BEFORE_HTML: {974 endTagBeforeHtml(this, token);975 break;976 }977 case InsertionMode.BEFORE_HEAD: {978 endTagBeforeHead(this, token);979 break;980 }981 case InsertionMode.IN_HEAD: {982 endTagInHead(this, token);983 break;984 }985 case InsertionMode.IN_HEAD_NO_SCRIPT: {986 endTagInHeadNoScript(this, token);987 break;988 }989 case InsertionMode.AFTER_HEAD: {990 endTagAfterHead(this, token);991 break;992 }993 case InsertionMode.IN_BODY: {994 endTagInBody(this, token);995 break;996 }997 case InsertionMode.TEXT: {998 endTagInText(this, token);999 break;1000 }1001 case InsertionMode.IN_TABLE: {1002 endTagInTable(this, token);1003 break;1004 }1005 case InsertionMode.IN_TABLE_TEXT: {1006 tokenInTableText(this, token);1007 break;1008 }1009 case InsertionMode.IN_CAPTION: {1010 endTagInCaption(this, token);1011 break;1012 }1013 case InsertionMode.IN_COLUMN_GROUP: {1014 endTagInColumnGroup(this, token);1015 break;1016 }1017 case InsertionMode.IN_TABLE_BODY: {1018 endTagInTableBody(this, token);1019 break;1020 }1021 case InsertionMode.IN_ROW: {1022 endTagInRow(this, token);1023 break;1024 }1025 case InsertionMode.IN_CELL: {1026 endTagInCell(this, token);1027 break;1028 }1029 case InsertionMode.IN_SELECT: {1030 endTagInSelect(this, token);1031 break;1032 }1033 case InsertionMode.IN_SELECT_IN_TABLE: {1034 endTagInSelectInTable(this, token);1035 break;1036 }1037 case InsertionMode.IN_TEMPLATE: {1038 endTagInTemplate(this, token);1039 break;1040 }1041 case InsertionMode.AFTER_BODY: {1042 endTagAfterBody(this, token);1043 break;1044 }1045 case InsertionMode.IN_FRAMESET: {1046 endTagInFrameset(this, token);1047 break;1048 }1049 case InsertionMode.AFTER_FRAMESET: {1050 endTagAfterFrameset(this, token);1051 break;1052 }1053 case InsertionMode.AFTER_AFTER_BODY: {1054 tokenAfterAfterBody(this, token);1055 break;1056 }1057 default:1058 // Do nothing1059 }1060 }1061 /** @internal */1062 onEof(token) {1063 switch (this.insertionMode) {1064 case InsertionMode.INITIAL: {1065 tokenInInitialMode(this, token);1066 break;1067 }1068 case InsertionMode.BEFORE_HTML: {1069 tokenBeforeHtml(this, token);1070 break;1071 }1072 case InsertionMode.BEFORE_HEAD: {1073 tokenBeforeHead(this, token);1074 break;1075 }1076 case InsertionMode.IN_HEAD: {1077 tokenInHead(this, token);1078 break;1079 }1080 case InsertionMode.IN_HEAD_NO_SCRIPT: {1081 tokenInHeadNoScript(this, token);1082 break;1083 }1084 case InsertionMode.AFTER_HEAD: {1085 tokenAfterHead(this, token);1086 break;1087 }1088 case InsertionMode.IN_BODY:1089 case InsertionMode.IN_TABLE:1090 case InsertionMode.IN_CAPTION:1091 case InsertionMode.IN_COLUMN_GROUP:1092 case InsertionMode.IN_TABLE_BODY:1093 case InsertionMode.IN_ROW:1094 case InsertionMode.IN_CELL:1095 case InsertionMode.IN_SELECT:1096 case InsertionMode.IN_SELECT_IN_TABLE: {1097 eofInBody(this, token);1098 break;1099 }1100 case InsertionMode.TEXT: {1101 eofInText(this, token);1102 break;1103 }1104 case InsertionMode.IN_TABLE_TEXT: {1105 tokenInTableText(this, token);1106 break;1107 }1108 case InsertionMode.IN_TEMPLATE: {1109 eofInTemplate(this, token);1110 break;1111 }1112 case InsertionMode.AFTER_BODY:1113 case InsertionMode.IN_FRAMESET:1114 case InsertionMode.AFTER_FRAMESET:1115 case InsertionMode.AFTER_AFTER_BODY:1116 case InsertionMode.AFTER_AFTER_FRAMESET: {1117 stopParsing(this, token);1118 break;1119 }1120 default:1121 // Do nothing1122 }1123 }1124 /** @internal */1125 onWhitespaceCharacter(token) {1126 if (this.skipNextNewLine) {1127 this.skipNextNewLine = false;1128 if (token.chars.charCodeAt(0) === unicode.CODE_POINTS.LINE_FEED) {1129 if (token.chars.length === 1) {1130 return;1131 }1132 token.chars = token.chars.substr(1);1133 }1134 }1135 if (this.tokenizer.inForeignNode) {1136 this._insertCharacters(token);1137 return;1138 }1139 switch (this.insertionMode) {1140 case InsertionMode.IN_HEAD:1141 case InsertionMode.IN_HEAD_NO_SCRIPT:1142 case InsertionMode.AFTER_HEAD:1143 case InsertionMode.TEXT:1144 case InsertionMode.IN_COLUMN_GROUP:1145 case InsertionMode.IN_SELECT:1146 case InsertionMode.IN_SELECT_IN_TABLE:1147 case InsertionMode.IN_FRAMESET:1148 case InsertionMode.AFTER_FRAMESET: {1149 this._insertCharacters(token);1150 break;1151 }1152 case InsertionMode.IN_BODY:1153 case InsertionMode.IN_CAPTION:1154 case InsertionMode.IN_CELL:1155 case InsertionMode.IN_TEMPLATE:1156 case InsertionMode.AFTER_BODY:1157 case InsertionMode.AFTER_AFTER_BODY:1158 case InsertionMode.AFTER_AFTER_FRAMESET: {1159 whitespaceCharacterInBody(this, token);1160 break;1161 }1162 case InsertionMode.IN_TABLE:1163 case InsertionMode.IN_TABLE_BODY:1164 case InsertionMode.IN_ROW: {1165 characterInTable(this, token);1166 break;1167 }1168 case InsertionMode.IN_TABLE_TEXT: {1169 whitespaceCharacterInTableText(this, token);1170 break;1171 }1172 default:1173 // Do nothing1174 }1175 }1176}1177//Adoption agency algorithm1178//(see: http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#adoptionAgency)1179//------------------------------------------------------------------1180//Steps 5-8 of the algorithm1181function aaObtainFormattingElementEntry(p, token) {1182 let formattingElementEntry = p.activeFormattingElements.getElementEntryInScopeWithTagName(token.tagName);1183 if (formattingElementEntry) {1184 if (!p.openElements.contains(formattingElementEntry.element)) {1185 p.activeFormattingElements.removeEntry(formattingElementEntry);1186 formattingElementEntry = null;1187 }1188 else if (!p.openElements.hasInScope(token.tagID)) {1189 formattingElementEntry = null;1190 }1191 }1192 else {1193 genericEndTagInBody(p, token);1194 }1195 return formattingElementEntry;1196}1197//Steps 9 and 10 of the algorithm1198function aaObtainFurthestBlock(p, formattingElementEntry) {1199 let furthestBlock = null;1200 let idx = p.openElements.stackTop;