Skip to content

Commit 03afed4

Browse files
committed
Parse pug with Tokenizer
1 parent 184dc09 commit 03afed4

File tree

7 files changed

+123
-6
lines changed

7 files changed

+123
-6
lines changed

Diff for: .gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@
77
/npm-debug.log
88
/test.js
99
/test/fixtures/espree-v8/node_modules
10+
.yarn
11+
.yarnrc.yml
12+
yarn.lock

Diff for: package.json

+9-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@
1010
"index.*"
1111
],
1212
"peerDependencies": {
13-
"eslint": ">=5.0.0"
13+
"eslint": ">=5.0.0",
14+
"pug-lexer": ">=5.0.0"
15+
},
16+
"peerDependenciesMeta": {
17+
"pug-lexer": {
18+
"optional": true
19+
}
1420
},
1521
"dependencies": {
1622
"debug": "^4.1.1",
@@ -52,8 +58,10 @@
5258
"nyc": "^14.0.0",
5359
"opener": "^1.5.1",
5460
"prettier": "^2.3.1",
61+
"pug-lexer": "^5.0.1",
5562
"rimraf": "^2.6.3",
5663
"rollup": "^1.1.2",
64+
"rollup-plugin-commonjs": "^10.1.0",
5765
"rollup-plugin-node-resolve": "^4.0.0",
5866
"rollup-plugin-sourcemaps": "^0.4.2",
5967
"ts-node": "^8.1.0",

Diff for: rollup.config.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
import resolve from "rollup-plugin-node-resolve"
77
import sourcemaps from "rollup-plugin-sourcemaps"
8+
import commonjs from "rollup-plugin-commonjs"
89

910
const pkg = require("./package.json")
1011
const deps = new Set(
@@ -23,6 +24,6 @@ export default {
2324
* See LICENSE file in root directory for full license.
2425
*/`,
2526
},
26-
plugins: [sourcemaps(), resolve()],
27+
plugins: [sourcemaps(), resolve(), commonjs()],
2728
external: id => deps.has(id) || id.startsWith("lodash"),
2829
}

Diff for: src/index.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import * as path from "path"
77
import * as AST from "./ast"
88
import { LocationCalculatorForHtml } from "./common/location-calculator"
99
import { HTMLParser, HTMLTokenizer } from "./html"
10+
import { PugParser, PugTokenizer } from "./pug"
1011
import { parseScript, parseScriptElement } from "./script"
1112
import * as services from "./parser-services"
1213
import type { ParserOptions } from "./common/parser-options"
@@ -74,9 +75,15 @@ export function parseForESLint(
7475
ecmaVersion: options.ecmaVersion || DEFAULT_ECMA_VERSION,
7576
}
7677
const skipParsingScript = options.parser === false
77-
const tokenizer = new HTMLTokenizer(code, optionsForTemplate)
78-
const rootAST = new HTMLParser(tokenizer, optionsForTemplate).parse()
79-
78+
let tokenizer: HTMLTokenizer | PugTokenizer
79+
let rootAST: AST.VDocumentFragment
80+
if (/^\<template\s+lang\=["']pug["']\>/i.test(code)) {
81+
tokenizer = new PugTokenizer(code, optionsForTemplate)
82+
rootAST = new PugParser(tokenizer, optionsForTemplate).parse()
83+
} else {
84+
tokenizer = new HTMLTokenizer(code, optionsForTemplate)
85+
rootAST = new HTMLParser(tokenizer as HTMLTokenizer, optionsForTemplate).parse()
86+
}
8087
locationCalculator = new LocationCalculatorForHtml(
8188
tokenizer.gaps,
8289
tokenizer.lineTerminators,
@@ -90,7 +97,7 @@ export function parseForESLint(
9097
errors: rootAST.errors,
9198
}
9299
const templateBody =
93-
template != null && templateLang === "html"
100+
template != null && (templateLang === "html" || templateLang === "pug")
94101
? Object.assign(template, concreteInfo)
95102
: undefined
96103

Diff for: src/pug/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { Parser as PugParser } from "./parser"
2+
export { Tokenizer as PugTokenizer } from "./tokenizer"

Diff for: src/pug/parser.ts

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import type { Token } from "pug-lexer";
2+
import type { VDocumentFragment } from "../ast";
3+
import { ParseError } from "../ast";
4+
import type { ParserOptions } from "../common/parser-options";
5+
import { isSFCFile } from "../common/parser-options";
6+
import type { Tokenizer } from "./tokenizer";
7+
8+
/**
9+
* Parser for pug.
10+
*/
11+
export class Parser {
12+
private tokenizer: Tokenizer;
13+
// @ts-expect-error: should be used later
14+
private baseParserOptions: ParserOptions;
15+
// @ts-expect-error: should be used later
16+
private isSFC: boolean;
17+
private document: VDocumentFragment;
18+
19+
/**
20+
* The tokens.
21+
*/
22+
private get tokens(): Token[] {
23+
return this.tokenizer.tokens;
24+
}
25+
26+
/**
27+
* The comments.
28+
*/
29+
private get comments(): Token[] {
30+
return [];
31+
// return this.tokenizer.comments;
32+
}
33+
34+
/**
35+
* The syntax errors which are found in this parsing.
36+
*/
37+
private get errors(): ParseError[] {
38+
return [];
39+
// return this.tokenizer.errors;
40+
}
41+
42+
public constructor(tokenizer: Tokenizer, parserOptions: ParserOptions) {
43+
this.tokenizer = tokenizer;
44+
this.baseParserOptions = parserOptions;
45+
this.isSFC = isSFCFile(parserOptions);
46+
this.document = {
47+
type: "VDocumentFragment",
48+
range: [0, 0],
49+
loc: {
50+
start: { line: 1, column: 0 },
51+
end: { line: 1, column: 0 },
52+
},
53+
parent: null,
54+
children: [],
55+
tokens: this.tokens as any[],
56+
comments: this.comments as any[],
57+
errors: this.errors,
58+
};
59+
}
60+
61+
public parse(): VDocumentFragment {
62+
return this.document;
63+
}
64+
}

Diff for: src/pug/tokenizer.ts

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import type { Token } from "pug-lexer";
2+
import lex from "pug-lexer";
3+
import { debug } from "../common/debug";
4+
import type { ParserOptions } from "../common/parser-options";
5+
6+
/**
7+
* Tokenizer for pug.
8+
*/
9+
export class Tokenizer {
10+
// Reading
11+
public readonly text: string;
12+
public readonly gaps: number[];
13+
public readonly lineTerminators: number[];
14+
public readonly tokens: Token[];
15+
// @ts-expect-error: should be used later
16+
private readonly parserOptions: ParserOptions;
17+
18+
/**
19+
* Initialize this tokenizer.
20+
* @param text The source code to tokenize.
21+
* @param parserOptions The parser options.
22+
*/
23+
public constructor(text: string, parserOptions?: ParserOptions) {
24+
debug("[pug] the source code length: %d", text.length);
25+
this.text = text;
26+
this.gaps = [];
27+
this.lineTerminators = [];
28+
this.parserOptions = parserOptions || {};
29+
30+
this.tokens = lex(text);
31+
}
32+
}

0 commit comments

Comments
 (0)