Skip to content

Commit

Permalink
refactor: Convert most of the parser to TS
Browse files Browse the repository at this point in the history
  • Loading branch information
fb55 committed Jan 7, 2022
1 parent 4385fde commit 347206c
Show file tree
Hide file tree
Showing 11 changed files with 468 additions and 358 deletions.
4 changes: 2 additions & 2 deletions packages/parse5-parser-stream/lib/index.ts
Expand Up @@ -7,7 +7,7 @@ export class ParserStream<T extends TreeAdapterTypeMap> extends Writable {
writeCallback: null | (() => void) = null;
pausedByScript = false;

parser: Parser;
parser: Parser<T>;
pendingHtmlInsertions: string[] = [];
document: T['document'];

Expand Down Expand Up @@ -70,7 +70,7 @@ export class ParserStream<T extends TreeAdapterTypeMap> extends Writable {
}
}

_scriptHandler(scriptElement: any) {
_scriptHandler(scriptElement: T['element']) {
if (this.listenerCount('script') > 0) {
this.pausedByScript = true;
this.emit('script', scriptElement, this._documentWrite, this._resume);
Expand Down
Expand Up @@ -22,7 +22,7 @@ export class ParserFeedbackSimulator {
}

getNextToken(): Token {
const token = this.tokenizer.getNextToken()!;
const token = this.tokenizer.getNextToken();

if (token.type === Tokenizer.START_TAG_TOKEN) {
this._handleStartTagToken(token);
Expand Down
2 changes: 1 addition & 1 deletion packages/parse5/lib/common/doctype.ts
Expand Up @@ -99,7 +99,7 @@ export function isConforming(token: DoctypeToken): boolean {
);
}

export function getDocumentMode(token: DoctypeToken): string | null {
export function getDocumentMode(token: DoctypeToken): DOCUMENT_MODE {
if (token.name !== VALID_DOCTYPE_NAME) {
return DOCUMENT_MODE.QUIRKS;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/parse5/lib/common/token.ts
Expand Up @@ -61,7 +61,7 @@ export interface CommentToken extends TokenBase {
data: string;
}

interface EOFToken extends TokenBase {
export interface EOFToken extends TokenBase {
readonly type: TokenType.EOF;
}

Expand Down
Expand Up @@ -40,7 +40,7 @@ export class ErrorReportingParserMixin extends ErrorReportingMixinBase {
},

_err(code, options) {
mxn.locBeforeToken = options && options.beforeToken;
mxn.locBeforeToken = options?.beforeToken;
mxn._reportError(code);
},
};
Expand Down
@@ -1,24 +1,31 @@
import { CommentToken, DoctypeToken, CharacterToken } from './../../common/token';
import { Mixin } from '../../utils/mixin.js';
import { Tokenizer } from '../../tokenizer/index.js';
import { LocationInfoTokenizerMixin } from './tokenizer-mixin.js';
import { LocationInfoOpenElementStackMixin } from './open-element-stack-mixin.js';
import * as HTML from '../../common/html.js';
import type { TreeAdapter, TreeAdapterTypeMap } from './../../tree-adapters/interface';
import type { Parser } from '../../parser/index.js';
import type { PositionTrackingPreprocessorMixin } from './../position-tracking/preprocessor-mixin';
import type { Token, Location, TagToken } from '../../common/token.js';

//Aliases
const $ = HTML.TAG_NAMES;

export class LocationInfoParserMixin extends Mixin {
constructor(parser) {
export class LocationInfoParserMixin<T extends TreeAdapterTypeMap> extends Mixin<Parser<T>> {
treeAdapter: TreeAdapter<T>;
posTracker: PositionTrackingPreprocessorMixin | null = null;
lastStartTagToken: null | TagToken = null;
lastFosterParentingLocation: null | ReturnType<Parser<T>['_findFosterParentingLocation']> = null;
currentToken: Token | null = null;

constructor(parser: Parser<T>) {
super(parser);

this.treeAdapter = parser.treeAdapter;
this.posTracker = null;
this.lastStartTagToken = null;
this.lastFosterParentingLocation = null;
this.currentToken = null;
}

_setStartLocation(element) {
_setStartLocation(element: T['element']) {
let loc = null;

if (this.lastStartTagToken) {
Expand All @@ -31,7 +38,7 @@ export class LocationInfoParserMixin extends Mixin {
this.treeAdapter.setNodeSourceCodeLocation(element, loc);
}

_setEndLocation(element, closingToken) {
_setEndLocation(element: T['element'], closingToken: TagToken) {
const loc = this.treeAdapter.getNodeSourceCodeLocation(element);

if (loc && closingToken.location) {
Expand All @@ -41,7 +48,7 @@ export class LocationInfoParserMixin extends Mixin {
// NOTE: For cases like <p> <p> </p> - First 'p' closes without a closing
// tag and for cases like <td> <p> </td> - 'p' closes without a closing tag.
const isClosingEndTag = closingToken.type === Tokenizer.END_TAG_TOKEN && tn === closingToken.tagName;
const endLoc = {};
const endLoc: Location = {};
if (isClosingEndTag) {
endLoc.endTag = { ...ctLoc };
endLoc.endLine = ctLoc.endLine;
Expand All @@ -57,9 +64,9 @@ export class LocationInfoParserMixin extends Mixin {
}
}

_getOverriddenMethods(mxn, orig) {
override _getOverriddenMethods(mxn: LocationInfoParserMixin<T>, orig: Parser<T>) {
return {
_bootstrap(document, fragmentContext) {
_bootstrap(this: Parser<T>, document, fragmentContext) {
orig._bootstrap.call(this, document, fragmentContext);

mxn.lastStartTagToken = null;
Expand All @@ -77,7 +84,7 @@ export class LocationInfoParserMixin extends Mixin {
});
},

_runParsingLoop(scriptHandler) {
_runParsingLoop(this: Parser<T>, scriptHandler) {
orig._runParsingLoop.call(this, scriptHandler);

// NOTE: generate location info for elements
Expand All @@ -88,12 +95,12 @@ export class LocationInfoParserMixin extends Mixin {
},

//Token processing
_processTokenInForeignContent(token) {
_processTokenInForeignContent(this: Parser<T>, token: Token) {
mxn.currentToken = token;
orig._processTokenInForeignContent.call(this, token);
},

_processToken(token) {
_processToken(this: Parser<T>, token: Token) {
mxn.currentToken = token;
orig._processToken.call(this, token);

Expand All @@ -116,7 +123,7 @@ export class LocationInfoParserMixin extends Mixin {
},

//Doctype
_setDocumentType(token) {
_setDocumentType(this: Parser<T>, token: DoctypeToken) {
orig._setDocumentType.call(this, token);

const documentChildren = this.treeAdapter.getChildNodes(this.document);
Expand All @@ -128,25 +135,25 @@ export class LocationInfoParserMixin extends Mixin {
},

//Elements
_attachElementToTree(element) {
_attachElementToTree(this: Parser<T>, element: T['element']) {
//NOTE: _attachElementToTree is called from _appendElement, _insertElement and _insertTemplate methods.
//So we will use token location stored in this methods for the element.
mxn._setStartLocation(element);
mxn.lastStartTagToken = null;
orig._attachElementToTree.call(this, element);
},

_appendElement(token, namespaceURI) {
_appendElement(this: Parser<T>, token: TagToken, namespaceURI: HTML.NAMESPACES) {
mxn.lastStartTagToken = token;
orig._appendElement.call(this, token, namespaceURI);
},

_insertElement(token, namespaceURI) {
_insertElement(this: Parser<T>, token: TagToken, namespaceURI: HTML.NAMESPACES) {
mxn.lastStartTagToken = token;
orig._insertElement.call(this, token, namespaceURI);
},

_insertTemplate(token) {
_insertTemplate(this: Parser<T>, token: TagToken) {
mxn.lastStartTagToken = token;
orig._insertTemplate.call(this, token);

Expand All @@ -155,13 +162,13 @@ export class LocationInfoParserMixin extends Mixin {
this.treeAdapter.setNodeSourceCodeLocation(tmplContent, null);
},

_insertFakeRootElement() {
_insertFakeRootElement(this: Parser<T>) {
orig._insertFakeRootElement.call(this);
this.treeAdapter.setNodeSourceCodeLocation(this.openElements.current, null);
},

//Comments
_appendCommentNode(token, parent) {
_appendCommentNode(this: Parser<T>, token: CommentToken, parent: T['parentNode']) {
orig._appendCommentNode.call(this, token, parent);

const children = this.treeAdapter.getChildNodes(parent);
Expand All @@ -171,15 +178,15 @@ export class LocationInfoParserMixin extends Mixin {
},

//Text
_findFosterParentingLocation() {
_findFosterParentingLocation(this: Parser<T>) {
//NOTE: store last foster parenting location, so we will be able to find inserted text
//in case of foster parenting
mxn.lastFosterParentingLocation = orig._findFosterParentingLocation.call(this);

return mxn.lastFosterParentingLocation;
},

_insertCharacters(token) {
_insertCharacters(this: Parser<T>, token: CharacterToken) {
orig._insertCharacters.call(this, token);

const hasFosterParent = this._shouldFosterParentOnInsertion();
Expand Down
12 changes: 6 additions & 6 deletions packages/parse5/lib/parser/formatting-element-list.ts
@@ -1,4 +1,4 @@
import type { Attribute, Token } from '../common/token.js';
import type { Attribute, TagToken } from '../common/token.js';
import type { TreeAdapterTypeMap } from './../tree-adapters/interface';

//Const
Expand All @@ -13,13 +13,13 @@ interface MarkerEntry {
type: EntryType.Marker;
}

interface ElementEntry<T extends TreeAdapterTypeMap> {
export interface ElementEntry<T extends TreeAdapterTypeMap> {
type: EntryType.Element;
element: T['element'];
token: Token;
token: TagToken;
}

type Entry<T extends TreeAdapterTypeMap> = MarkerEntry | ElementEntry<T>;
export type Entry<T extends TreeAdapterTypeMap> = MarkerEntry | ElementEntry<T>;

//List of formatting elements
export class FormattingElementList<T extends TreeAdapterTypeMap> {
Expand Down Expand Up @@ -90,7 +90,7 @@ export class FormattingElementList<T extends TreeAdapterTypeMap> {
this.length++;
}

pushElement(element: T['element'], token: Token) {
pushElement(element: T['element'], token: TagToken) {
this._ensureNoahArkCondition(element);

this.entries.push({
Expand All @@ -102,7 +102,7 @@ export class FormattingElementList<T extends TreeAdapterTypeMap> {
this.length++;
}

insertElementAfterBookmark(element: T['element'], token: Token) {
insertElementAfterBookmark(element: T['element'], token: TagToken) {
const bookmarkIdx = this.entries.lastIndexOf(this.bookmark!);

this.entries.splice(bookmarkIdx + 1, 0, {
Expand Down

0 comments on commit 347206c

Please sign in to comment.