Skip to content
This repository was archived by the owner on Mar 24, 2022. It is now read-only.

Commit b82e3e9

Browse files
committed
refactor: Start moving LocationInfoParserMixin into parser
1 parent 269ef1c commit b82e3e9

3 files changed

Lines changed: 57 additions & 131 deletions

File tree

Lines changed: 2 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,17 @@
1-
import { CommentToken, DoctypeToken, CharacterToken } from '../../common/token';
21
import { Mixin } from '../../utils/mixin.js';
3-
import { TAG_NAMES as $, NAMESPACES as NS } from '../../common/html.js';
2+
import { TAG_NAMES as $ } from '../../common/html.js';
43
import type { TreeAdapterTypeMap, ElementLocation } from '../../tree-adapters/interface';
54
import type { Parser } from '../../parser/index.js';
6-
import { TokenType, Token, TagToken } from '../../common/token.js';
5+
import { TokenType, Token } from '../../common/token.js';
76

87
export class LocationInfoParserMixin<T extends TreeAdapterTypeMap> extends Mixin<Parser<T>> {
9-
lastStartTagToken: null | TagToken = null;
108
lastFosterParentingLocation: null | ReturnType<Parser<T>['_findFosterParentingLocation']> = null;
119
currentToken: Token | null = null;
1210

1311
constructor(private parser: Parser<T>) {
1412
super(parser);
1513
}
1614

17-
_setStartLocation(element: T['element']) {
18-
let loc = null;
19-
20-
if (this.lastStartTagToken) {
21-
loc = {
22-
...this.lastStartTagToken.location!,
23-
startTag: this.lastStartTagToken.location!,
24-
};
25-
}
26-
27-
this.parser.treeAdapter.setNodeSourceCodeLocation(element, loc);
28-
}
29-
3015
_setEndLocation(element: T['element'], closingToken: Token) {
3116
const loc = this.parser.treeAdapter.getNodeSourceCodeLocation(element);
3217

@@ -58,7 +43,6 @@ export class LocationInfoParserMixin<T extends TreeAdapterTypeMap> extends Mixin
5843
_bootstrap(this: Parser<T>, document: T['document'], fragmentContext: T['element'] | null) {
5944
orig._bootstrap.call(this, document, fragmentContext);
6045

61-
mxn.lastStartTagToken = null;
6246
mxn.lastFosterParentingLocation = null;
6347
mxn.currentToken = null;
6448

@@ -101,100 +85,6 @@ export class LocationInfoParserMixin<T extends TreeAdapterTypeMap> extends Mixin
10185
}
10286
}
10387
},
104-
105-
//Doctype
106-
_setDocumentType(this: Parser<T>, token: DoctypeToken) {
107-
orig._setDocumentType.call(this, token);
108-
109-
const documentChildren = this.treeAdapter.getChildNodes(this.document);
110-
const docTypeNode = documentChildren.find((node) => this.treeAdapter.isDocumentTypeNode(node));
111-
112-
if (docTypeNode) {
113-
this.treeAdapter.setNodeSourceCodeLocation(docTypeNode, token.location!);
114-
}
115-
},
116-
117-
//Elements
118-
_attachElementToTree(this: Parser<T>, element: T['element']) {
119-
//NOTE: _attachElementToTree is called from _appendElement, _insertElement and _insertTemplate methods.
120-
//So we will use token location stored in this methods for the element.
121-
mxn._setStartLocation(element);
122-
mxn.lastStartTagToken = null;
123-
orig._attachElementToTree.call(this, element);
124-
},
125-
126-
_appendElement(this: Parser<T>, token: TagToken, namespaceURI: NS) {
127-
mxn.lastStartTagToken = token;
128-
orig._appendElement.call(this, token, namespaceURI);
129-
},
130-
131-
_insertElement(this: Parser<T>, token: TagToken, namespaceURI: NS) {
132-
mxn.lastStartTagToken = token;
133-
orig._insertElement.call(this, token, namespaceURI);
134-
},
135-
136-
_insertTemplate(this: Parser<T>, token: TagToken) {
137-
mxn.lastStartTagToken = token;
138-
orig._insertTemplate.call(this, token);
139-
140-
const tmplContent = this.treeAdapter.getTemplateContent(this.openElements.current);
141-
142-
this.treeAdapter.setNodeSourceCodeLocation(tmplContent, null);
143-
},
144-
145-
_insertFakeRootElement(this: Parser<T>) {
146-
orig._insertFakeRootElement.call(this);
147-
this.treeAdapter.setNodeSourceCodeLocation(this.openElements.current, null);
148-
},
149-
150-
//Comments
151-
_appendCommentNode(this: Parser<T>, token: CommentToken, parent: T['parentNode']) {
152-
orig._appendCommentNode.call(this, token, parent);
153-
154-
const children = this.treeAdapter.getChildNodes(parent);
155-
const commentNode = children[children.length - 1];
156-
157-
this.treeAdapter.setNodeSourceCodeLocation(commentNode, token.location!);
158-
},
159-
160-
//Text
161-
_findFosterParentingLocation(this: Parser<T>) {
162-
//NOTE: store last foster parenting location, so we will be able to find inserted text
163-
//in case of foster parenting
164-
mxn.lastFosterParentingLocation = orig._findFosterParentingLocation.call(this);
165-
166-
return mxn.lastFosterParentingLocation;
167-
},
168-
169-
_insertCharacters(this: Parser<T>, token: CharacterToken) {
170-
orig._insertCharacters.call(this, token);
171-
172-
const hasFosterParent = this._shouldFosterParentOnInsertion();
173-
174-
const parent =
175-
(hasFosterParent && mxn.lastFosterParentingLocation!.parent) ||
176-
this.openElements.currentTmplContent ||
177-
this.openElements.current;
178-
179-
const siblings = this.treeAdapter.getChildNodes(parent);
180-
181-
const textNodeIdx =
182-
hasFosterParent && mxn.lastFosterParentingLocation!.beforeElement
183-
? siblings.indexOf(mxn.lastFosterParentingLocation!.beforeElement) - 1
184-
: siblings.length - 1;
185-
186-
const textNode = siblings[textNodeIdx];
187-
188-
//NOTE: if we have location assigned by another token, then just update end position
189-
const tnLoc = this.treeAdapter.getNodeSourceCodeLocation(textNode);
190-
191-
if (tnLoc) {
192-
const { endLine, endCol, endOffset } = token.location!;
193-
this.treeAdapter.updateNodeSourceCodeLocation(textNode, { endLine, endCol, endOffset });
194-
} else {
195-
this.treeAdapter.setNodeSourceCodeLocation(textNode, token.location!);
196-
}
197-
},
19888
};
19989
}
20090
}

packages/parse5/lib/parser/index.ts

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
CharacterToken,
2626
TagToken,
2727
DoctypeToken,
28+
LocationWithAttributes,
2829
} from '../common/token.js';
2930

3031
//Misc constants
@@ -407,9 +408,25 @@ export class Parser<T extends TreeAdapterTypeMap> {
407408
const systemId = token.systemId || '';
408409

409410
this.treeAdapter.setDocumentType(this.document, name, publicId, systemId);
411+
412+
if (token.location) {
413+
const documentChildren = this.treeAdapter.getChildNodes(this.document);
414+
const docTypeNode = documentChildren.find((node) => this.treeAdapter.isDocumentTypeNode(node));
415+
416+
if (docTypeNode) {
417+
this.treeAdapter.setNodeSourceCodeLocation(docTypeNode, token.location);
418+
}
419+
}
410420
}
411421

412-
_attachElementToTree(element: T['element']) {
422+
_attachElementToTree(element: T['element'], location: LocationWithAttributes | null) {
423+
const loc = location && {
424+
...location,
425+
startTag: location,
426+
};
427+
428+
this.treeAdapter.setNodeSourceCodeLocation(element, loc);
429+
413430
if (this._shouldFosterParentOnInsertion()) {
414431
this._fosterParentElement(element);
415432
} else {
@@ -422,20 +439,20 @@ export class Parser<T extends TreeAdapterTypeMap> {
422439
_appendElement(token: TagToken, namespaceURI: NS) {
423440
const element = this.treeAdapter.createElement(token.tagName, namespaceURI, token.attrs);
424441

425-
this._attachElementToTree(element);
442+
this._attachElementToTree(element, token.location);
426443
}
427444

428445
_insertElement(token: TagToken, namespaceURI: NS) {
429446
const element = this.treeAdapter.createElement(token.tagName, namespaceURI, token.attrs);
430447

431-
this._attachElementToTree(element);
448+
this._attachElementToTree(element, token.location);
432449
this.openElements.push(element);
433450
}
434451

435452
_insertFakeElement(tagName: string) {
436453
const element = this.treeAdapter.createElement(tagName, NS.HTML, []);
437454

438-
this._attachElementToTree(element);
455+
this._attachElementToTree(element, null);
439456
this.openElements.push(element);
440457
}
441458

@@ -444,12 +461,14 @@ export class Parser<T extends TreeAdapterTypeMap> {
444461
const content = this.treeAdapter.createDocumentFragment();
445462

446463
this.treeAdapter.setTemplateContent(tmpl, content);
447-
this._attachElementToTree(tmpl);
464+
this._attachElementToTree(tmpl, token.location);
448465
this.openElements.push(tmpl);
466+
this.treeAdapter.setNodeSourceCodeLocation(content, null);
449467
}
450468

451469
_insertFakeRootElement() {
452470
const element = this.treeAdapter.createElement($.HTML, NS.HTML, []);
471+
this.treeAdapter.setNodeSourceCodeLocation(element, null);
453472

454473
this.treeAdapter.appendChild(this.openElements.current, element);
455474
this.openElements.push(element);
@@ -459,16 +478,42 @@ export class Parser<T extends TreeAdapterTypeMap> {
459478
const commentNode = this.treeAdapter.createCommentNode(token.data);
460479

461480
this.treeAdapter.appendChild(parent, commentNode);
481+
this.treeAdapter.setNodeSourceCodeLocation(commentNode, token.location);
462482
}
463483

464484
_insertCharacters(token: CharacterToken) {
485+
let parent;
486+
let beforeElement;
487+
465488
if (this._shouldFosterParentOnInsertion()) {
466-
this._fosterParentText(token.chars);
489+
({ parent, beforeElement } = this._findFosterParentingLocation());
490+
491+
if (beforeElement) {
492+
this.treeAdapter.insertTextBefore(parent, token.chars, beforeElement);
493+
} else {
494+
this.treeAdapter.insertText(parent, token.chars);
495+
}
467496
} else {
468-
const parent = this.openElements.currentTmplContent || this.openElements.current;
497+
parent = this.openElements.currentTmplContent || this.openElements.current;
469498

470499
this.treeAdapter.insertText(parent, token.chars);
471500
}
501+
502+
if (!token.location) return;
503+
504+
const siblings = this.treeAdapter.getChildNodes(parent);
505+
const textNodeIdx = beforeElement ? siblings.lastIndexOf(beforeElement) : siblings.length;
506+
const textNode = siblings[textNodeIdx - 1];
507+
508+
//NOTE: if we have location assigned by another token, then just update end position
509+
const tnLoc = this.treeAdapter.getNodeSourceCodeLocation(textNode);
510+
511+
if (tnLoc) {
512+
const { endLine, endCol, endOffset } = token.location;
513+
this.treeAdapter.updateNodeSourceCodeLocation(textNode, { endLine, endCol, endOffset });
514+
} else {
515+
this.treeAdapter.setNodeSourceCodeLocation(textNode, token.location);
516+
}
472517
}
473518

474519
_adoptNodes(donor: T['parentNode'], recipient: T['parentNode']) {
@@ -748,16 +793,6 @@ export class Parser<T extends TreeAdapterTypeMap> {
748793
}
749794
}
750795

751-
_fosterParentText(chars: string) {
752-
const location = this._findFosterParentingLocation();
753-
754-
if (location.beforeElement) {
755-
this.treeAdapter.insertTextBefore(location.parent, chars, location.beforeElement);
756-
} else {
757-
this.treeAdapter.insertText(location.parent, chars);
758-
}
759-
}
760-
761796
//Special elements
762797
_isSpecialElement(element: T['element']): boolean {
763798
const tn = this.treeAdapter.getTagName(element);

packages/parse5/lib/tree-adapters/default.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,13 +152,14 @@ export function setDocumentType(document: Document, name: string, publicId: stri
152152
doctypeNode.publicId = publicId;
153153
doctypeNode.systemId = systemId;
154154
} else {
155-
appendChild(document, {
155+
const node: DocumentType = {
156156
nodeName: NodeType.DocumentType,
157157
name,
158158
publicId,
159159
systemId,
160160
parentNode: null,
161-
} as DocumentType);
161+
};
162+
appendChild(document, node);
162163
}
163164
}
164165

0 commit comments

Comments
 (0)