From 39aef90255d9e093f6d37d0a4bdad99cd54b134a Mon Sep 17 00:00:00 2001 From: Shinigami92 Date: Mon, 23 Aug 2021 18:07:43 +0200 Subject: [PATCH 1/8] Parse pug with Tokenizer --- .gitignore | 3 +++ package.json | 10 ++++++- rollup.config.js | 3 ++- src/index.ts | 15 ++++++++--- src/pug/index.ts | 2 ++ src/pug/parser.ts | 64 ++++++++++++++++++++++++++++++++++++++++++++ src/pug/tokenizer.ts | 32 ++++++++++++++++++++++ 7 files changed, 123 insertions(+), 6 deletions(-) create mode 100644 src/pug/index.ts create mode 100644 src/pug/parser.ts create mode 100644 src/pug/tokenizer.ts diff --git a/.gitignore b/.gitignore index 6ea559ee..de0f22fd 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ /npm-debug.log /test.js /test/fixtures/espree-v8/node_modules +.yarn +.yarnrc.yml +yarn.lock \ No newline at end of file diff --git a/package.json b/package.json index 50dc44cb..fee5973e 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,13 @@ "index.*" ], "peerDependencies": { - "eslint": ">=5.0.0" + "eslint": ">=5.0.0", + "pug-lexer": ">=5.0.0" + }, + "peerDependenciesMeta": { + "pug-lexer": { + "optional": true + } }, "dependencies": { "debug": "^4.1.1", @@ -52,8 +58,10 @@ "nyc": "^14.0.0", "opener": "^1.5.1", "prettier": "^2.3.1", + "pug-lexer": "^5.0.1", "rimraf": "^2.6.3", "rollup": "^1.1.2", + "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-node-resolve": "^4.0.0", "rollup-plugin-sourcemaps": "^0.4.2", "ts-node": "^8.1.0", diff --git a/rollup.config.js b/rollup.config.js index ccd8c5ff..3c623e44 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -5,6 +5,7 @@ */ import resolve from "rollup-plugin-node-resolve" import sourcemaps from "rollup-plugin-sourcemaps" +import commonjs from "rollup-plugin-commonjs" const pkg = require("./package.json") const deps = new Set( @@ -23,6 +24,6 @@ export default { * See LICENSE file in root directory for full license. */`, }, - plugins: [sourcemaps(), resolve()], + plugins: [sourcemaps(), resolve(), commonjs()], external: id => deps.has(id) || id.startsWith("lodash"), } diff --git a/src/index.ts b/src/index.ts index 6bf09da3..acc16c2e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,6 +7,7 @@ import * as path from "path" import * as AST from "./ast" import { LocationCalculatorForHtml } from "./common/location-calculator" import { HTMLParser, HTMLTokenizer } from "./html" +import { PugParser, PugTokenizer } from "./pug" import { parseScript, parseScriptElement } from "./script" import * as services from "./parser-services" import type { ParserOptions } from "./common/parser-options" @@ -87,9 +88,15 @@ export function parseForESLint( ecmaVersion: options.ecmaVersion || DEFAULT_ECMA_VERSION, } const skipParsingScript = options.parser === false - const tokenizer = new HTMLTokenizer(code, optionsForTemplate) - const rootAST = new HTMLParser(tokenizer, optionsForTemplate).parse() - + let tokenizer: HTMLTokenizer | PugTokenizer + let rootAST: AST.VDocumentFragment + if (/^\/i.test(code)) { + tokenizer = new PugTokenizer(code, optionsForTemplate) + rootAST = new PugParser(tokenizer, optionsForTemplate).parse() + } else { + tokenizer = new HTMLTokenizer(code, optionsForTemplate) + rootAST = new HTMLParser(tokenizer as HTMLTokenizer, optionsForTemplate).parse() + } locationCalculator = new LocationCalculatorForHtml( tokenizer.gaps, tokenizer.lineTerminators, @@ -103,7 +110,7 @@ export function parseForESLint( errors: rootAST.errors, } const templateBody = - template != null && templateLang === "html" + template != null && (templateLang === "html" || templateLang === "pug") ? Object.assign(template, concreteInfo) : undefined diff --git a/src/pug/index.ts b/src/pug/index.ts new file mode 100644 index 00000000..e2e3cee8 --- /dev/null +++ b/src/pug/index.ts @@ -0,0 +1,2 @@ +export { Parser as PugParser } from "./parser" +export { Tokenizer as PugTokenizer } from "./tokenizer" diff --git a/src/pug/parser.ts b/src/pug/parser.ts new file mode 100644 index 00000000..f91b4266 --- /dev/null +++ b/src/pug/parser.ts @@ -0,0 +1,64 @@ +import type { Token } from "pug-lexer"; +import type { VDocumentFragment } from "../ast"; +import { ParseError } from "../ast"; +import type { ParserOptions } from "../common/parser-options"; +import { isSFCFile } from "../common/parser-options"; +import type { Tokenizer } from "./tokenizer"; + +/** + * Parser for pug. + */ +export class Parser { + private tokenizer: Tokenizer; + // @ts-expect-error: should be used later + private baseParserOptions: ParserOptions; + // @ts-expect-error: should be used later + private isSFC: boolean; + private document: VDocumentFragment; + + /** + * The tokens. + */ + private get tokens(): Token[] { + return this.tokenizer.tokens; + } + + /** + * The comments. + */ + private get comments(): Token[] { + return []; + // return this.tokenizer.comments; + } + + /** + * The syntax errors which are found in this parsing. + */ + private get errors(): ParseError[] { + return []; + // return this.tokenizer.errors; + } + + public constructor(tokenizer: Tokenizer, parserOptions: ParserOptions) { + this.tokenizer = tokenizer; + this.baseParserOptions = parserOptions; + this.isSFC = isSFCFile(parserOptions); + this.document = { + type: "VDocumentFragment", + range: [0, 0], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 0 }, + }, + parent: null, + children: [], + tokens: this.tokens as any[], + comments: this.comments as any[], + errors: this.errors, + }; + } + + public parse(): VDocumentFragment { + return this.document; + } +} diff --git a/src/pug/tokenizer.ts b/src/pug/tokenizer.ts new file mode 100644 index 00000000..7cfe261d --- /dev/null +++ b/src/pug/tokenizer.ts @@ -0,0 +1,32 @@ +import type { Token } from "pug-lexer"; +import lex from "pug-lexer"; +import { debug } from "../common/debug"; +import type { ParserOptions } from "../common/parser-options"; + +/** + * Tokenizer for pug. + */ +export class Tokenizer { + // Reading + public readonly text: string; + public readonly gaps: number[]; + public readonly lineTerminators: number[]; + public readonly tokens: Token[]; + // @ts-expect-error: should be used later + private readonly parserOptions: ParserOptions; + + /** + * Initialize this tokenizer. + * @param text The source code to tokenize. + * @param parserOptions The parser options. + */ + public constructor(text: string, parserOptions?: ParserOptions) { + debug("[pug] the source code length: %d", text.length); + this.text = text; + this.gaps = []; + this.lineTerminators = []; + this.parserOptions = parserOptions || {}; + + this.tokens = lex(text); + } +} From 6c9c1fa02574af4c15ba110a229992828f52d177 Mon Sep 17 00:00:00 2001 From: Christopher Quadflieg Date: Thu, 26 Aug 2021 13:19:49 +0200 Subject: [PATCH 2/8] Remove PugParser and PugTokenizer --- src/index.ts | 13 +++------ src/pug/index.ts | 2 -- src/pug/parser.ts | 64 -------------------------------------------- src/pug/tokenizer.ts | 32 ---------------------- 4 files changed, 3 insertions(+), 108 deletions(-) delete mode 100644 src/pug/index.ts delete mode 100644 src/pug/parser.ts delete mode 100644 src/pug/tokenizer.ts diff --git a/src/index.ts b/src/index.ts index acc16c2e..888d82fb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,6 @@ import * as path from "path" import * as AST from "./ast" import { LocationCalculatorForHtml } from "./common/location-calculator" import { HTMLParser, HTMLTokenizer } from "./html" -import { PugParser, PugTokenizer } from "./pug" import { parseScript, parseScriptElement } from "./script" import * as services from "./parser-services" import type { ParserOptions } from "./common/parser-options" @@ -88,15 +87,9 @@ export function parseForESLint( ecmaVersion: options.ecmaVersion || DEFAULT_ECMA_VERSION, } const skipParsingScript = options.parser === false - let tokenizer: HTMLTokenizer | PugTokenizer - let rootAST: AST.VDocumentFragment - if (/^\/i.test(code)) { - tokenizer = new PugTokenizer(code, optionsForTemplate) - rootAST = new PugParser(tokenizer, optionsForTemplate).parse() - } else { - tokenizer = new HTMLTokenizer(code, optionsForTemplate) - rootAST = new HTMLParser(tokenizer as HTMLTokenizer, optionsForTemplate).parse() - } + const tokenizer = new HTMLTokenizer(code, optionsForTemplate) + const rootAST = new HTMLParser(tokenizer, optionsForTemplate).parse() + locationCalculator = new LocationCalculatorForHtml( tokenizer.gaps, tokenizer.lineTerminators, diff --git a/src/pug/index.ts b/src/pug/index.ts deleted file mode 100644 index e2e3cee8..00000000 --- a/src/pug/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { Parser as PugParser } from "./parser" -export { Tokenizer as PugTokenizer } from "./tokenizer" diff --git a/src/pug/parser.ts b/src/pug/parser.ts deleted file mode 100644 index f91b4266..00000000 --- a/src/pug/parser.ts +++ /dev/null @@ -1,64 +0,0 @@ -import type { Token } from "pug-lexer"; -import type { VDocumentFragment } from "../ast"; -import { ParseError } from "../ast"; -import type { ParserOptions } from "../common/parser-options"; -import { isSFCFile } from "../common/parser-options"; -import type { Tokenizer } from "./tokenizer"; - -/** - * Parser for pug. - */ -export class Parser { - private tokenizer: Tokenizer; - // @ts-expect-error: should be used later - private baseParserOptions: ParserOptions; - // @ts-expect-error: should be used later - private isSFC: boolean; - private document: VDocumentFragment; - - /** - * The tokens. - */ - private get tokens(): Token[] { - return this.tokenizer.tokens; - } - - /** - * The comments. - */ - private get comments(): Token[] { - return []; - // return this.tokenizer.comments; - } - - /** - * The syntax errors which are found in this parsing. - */ - private get errors(): ParseError[] { - return []; - // return this.tokenizer.errors; - } - - public constructor(tokenizer: Tokenizer, parserOptions: ParserOptions) { - this.tokenizer = tokenizer; - this.baseParserOptions = parserOptions; - this.isSFC = isSFCFile(parserOptions); - this.document = { - type: "VDocumentFragment", - range: [0, 0], - loc: { - start: { line: 1, column: 0 }, - end: { line: 1, column: 0 }, - }, - parent: null, - children: [], - tokens: this.tokens as any[], - comments: this.comments as any[], - errors: this.errors, - }; - } - - public parse(): VDocumentFragment { - return this.document; - } -} diff --git a/src/pug/tokenizer.ts b/src/pug/tokenizer.ts deleted file mode 100644 index 7cfe261d..00000000 --- a/src/pug/tokenizer.ts +++ /dev/null @@ -1,32 +0,0 @@ -import type { Token } from "pug-lexer"; -import lex from "pug-lexer"; -import { debug } from "../common/debug"; -import type { ParserOptions } from "../common/parser-options"; - -/** - * Tokenizer for pug. - */ -export class Tokenizer { - // Reading - public readonly text: string; - public readonly gaps: number[]; - public readonly lineTerminators: number[]; - public readonly tokens: Token[]; - // @ts-expect-error: should be used later - private readonly parserOptions: ParserOptions; - - /** - * Initialize this tokenizer. - * @param text The source code to tokenize. - * @param parserOptions The parser options. - */ - public constructor(text: string, parserOptions?: ParserOptions) { - debug("[pug] the source code length: %d", text.length); - this.text = text; - this.gaps = []; - this.lineTerminators = []; - this.parserOptions = parserOptions || {}; - - this.tokens = lex(text); - } -} From 9a2d5b1a3dd1b510a533f7076d7bf218446015d4 Mon Sep 17 00:00:00 2001 From: Christopher Quadflieg Date: Thu, 26 Aug 2021 13:52:34 +0200 Subject: [PATCH 3/8] wip: parse pug content --- src/html/parser.ts | 10 ++++++++++ src/index.ts | 2 ++ test/fixtures/ast/pug/source.vue | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/html/parser.ts b/src/html/parser.ts index 538e5f24..aae7a99b 100644 --- a/src/html/parser.ts +++ b/src/html/parser.ts @@ -51,6 +51,8 @@ import { getScriptParser, getParserLangFromSFC, } from "../common/parser-options" +// import type { Token } from "pug-lexer"; +import lex from "pug-lexer"; const DIRECTIVE_NAME = /^(?:v-|[.:@#]).*[^.:@#]$/u const DT_DD = /^d[dt]$/u @@ -300,6 +302,14 @@ export class Parser { } this.postProcessesForScript = [] + // Process pug + const match = /(?.*)<\/template>/isu.exec(this.text) + if (match && match.groups && match.groups.content) { + const pugTokens = lex(match.groups.content) + console.log(pugTokens); + + } + return doc } diff --git a/src/index.ts b/src/index.ts index 888d82fb..7d0c92ff 100644 --- a/src/index.ts +++ b/src/index.ts @@ -106,6 +106,8 @@ export function parseForESLint( template != null && (templateLang === "html" || templateLang === "pug") ? Object.assign(template, concreteInfo) : undefined + // if (templateLang === "pug") + // console.log(templateBody) const scriptParser = getScriptParser(options.parser, () => getParserLangFromSFC(rootAST), diff --git a/test/fixtures/ast/pug/source.vue b/test/fixtures/ast/pug/source.vue index ab1c2e5e..3cabe675 100644 --- a/test/fixtures/ast/pug/source.vue +++ b/test/fixtures/ast/pug/source.vue @@ -1,3 +1,3 @@ From 9991b20d70c8edc46cf649157f8e273b0e0b861e Mon Sep 17 00:00:00 2001 From: Shinigami92 Date: Tue, 7 Sep 2021 13:41:39 +0200 Subject: [PATCH 4/8] Add pugTokens to doc --- src/ast/nodes.ts | 2 ++ src/html/parser.ts | 14 +++++++------- src/index.ts | 2 -- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ast/nodes.ts b/src/ast/nodes.ts index a6c1c647..98b63063 100644 --- a/src/ast/nodes.ts +++ b/src/ast/nodes.ts @@ -3,6 +3,7 @@ * @copyright 2017 Toru Nagashima. All rights reserved. * See LICENSE file in root directory for full license. */ +import type { Token as PugToken } from "pug-lexer" import type { ScopeManager } from "eslint-scope" import type { ParseError } from "./errors" import type { HasLocation } from "./locations" @@ -860,6 +861,7 @@ export interface VDocumentFragment type: "VDocumentFragment" parent: null children: (VElement | VText | VExpressionContainer | VStyleElement)[] + pugTokens?: PugToken[] } /** diff --git a/src/html/parser.ts b/src/html/parser.ts index aae7a99b..645ac9f3 100644 --- a/src/html/parser.ts +++ b/src/html/parser.ts @@ -302,13 +302,13 @@ export class Parser { } this.postProcessesForScript = [] - // Process pug - const match = /(?.*)<\/template>/isu.exec(this.text) - if (match && match.groups && match.groups.content) { - const pugTokens = lex(match.groups.content) - console.log(pugTokens); - - } + try { + // Process pug + const match = /(?.*)<\/template>/isu.exec(this.text) + if (match && match.groups && match.groups.content) { + doc.pugTokens = lex(match.groups.content) + } + } catch {} return doc } diff --git a/src/index.ts b/src/index.ts index 7d0c92ff..888d82fb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -106,8 +106,6 @@ export function parseForESLint( template != null && (templateLang === "html" || templateLang === "pug") ? Object.assign(template, concreteInfo) : undefined - // if (templateLang === "pug") - // console.log(templateBody) const scriptParser = getScriptParser(options.parser, () => getParserLangFromSFC(rootAST), From e6070d2371abbbe2ee2fa23bda77f177c7aaa80d Mon Sep 17 00:00:00 2001 From: Shinigami92 Date: Tue, 7 Sep 2021 13:45:50 +0200 Subject: [PATCH 5/8] Clean commented import --- src/html/parser.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/html/parser.ts b/src/html/parser.ts index 645ac9f3..56d1cef4 100644 --- a/src/html/parser.ts +++ b/src/html/parser.ts @@ -51,7 +51,6 @@ import { getScriptParser, getParserLangFromSFC, } from "../common/parser-options" -// import type { Token } from "pug-lexer"; import lex from "pug-lexer"; const DIRECTIVE_NAME = /^(?:v-|[.:@#]).*[^.:@#]$/u From dfe02ac21c34ae925b068a86596e49de5aa5c5d9 Mon Sep 17 00:00:00 2001 From: Shinigami92 Date: Tue, 7 Sep 2021 14:28:58 +0200 Subject: [PATCH 6/8] Format --- src/html/parser.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/html/parser.ts b/src/html/parser.ts index 56d1cef4..f7906b8a 100644 --- a/src/html/parser.ts +++ b/src/html/parser.ts @@ -51,7 +51,7 @@ import { getScriptParser, getParserLangFromSFC, } from "../common/parser-options" -import lex from "pug-lexer"; +import lex from "pug-lexer" const DIRECTIVE_NAME = /^(?:v-|[.:@#]).*[^.:@#]$/u const DT_DD = /^d[dt]$/u @@ -303,11 +303,14 @@ export class Parser { try { // Process pug - const match = /(?.*)<\/template>/isu.exec(this.text) + const match = + /(?.*)<\/template>/isu.exec( + this.text + ) if (match && match.groups && match.groups.content) { doc.pugTokens = lex(match.groups.content) } - } catch {} + } catch { /* ignore */ } return doc } From 13c482e47c581dd0a8bb8fc96f8b5758009eec8f Mon Sep 17 00:00:00 2001 From: Shinigami92 Date: Tue, 7 Sep 2021 14:33:48 +0200 Subject: [PATCH 7/8] Format --- src/html/parser.ts | 6 ++++-- src/index.ts | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/html/parser.ts b/src/html/parser.ts index f7906b8a..e022b5e4 100644 --- a/src/html/parser.ts +++ b/src/html/parser.ts @@ -305,12 +305,14 @@ export class Parser { // Process pug const match = /(?.*)<\/template>/isu.exec( - this.text + this.text, ) if (match && match.groups && match.groups.content) { doc.pugTokens = lex(match.groups.content) } - } catch { /* ignore */ } + } catch { + /* ignore */ + } return doc } diff --git a/src/index.ts b/src/index.ts index 888d82fb..8a90776c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -103,7 +103,8 @@ export function parseForESLint( errors: rootAST.errors, } const templateBody = - template != null && (templateLang === "html" || templateLang === "pug") + template != null && + (templateLang === "html" || templateLang === "pug") ? Object.assign(template, concreteInfo) : undefined From 2710dc177d8bb536fa01a910f2911718a9440ee8 Mon Sep 17 00:00:00 2001 From: Shinigami92 Date: Tue, 7 Sep 2021 14:58:33 +0200 Subject: [PATCH 8/8] Update tests --- test/fixtures/ast/pug/ast.json | 527 +++++++++++++++++++++++- test/fixtures/ast/pug/token-ranges.json | 20 +- test/fixtures/ast/pug/tree.json | 57 ++- 3 files changed, 601 insertions(+), 3 deletions(-) diff --git a/test/fixtures/ast/pug/ast.json b/test/fixtures/ast/pug/ast.json index 0905cb4d..4be2cf1e 100644 --- a/test/fixtures/ast/pug/ast.json +++ b/test/fixtures/ast/pug/ast.json @@ -19,5 +19,530 @@ "body": [], "sourceType": "script", "comments": [], - "tokens": [] + "tokens": [], + "templateBody": { + "type": "VElement", + "range": [ + 0, + 57 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 11 + } + }, + "name": "template", + "rawName": "template", + "namespace": "http://www.w3.org/1999/xhtml", + "startTag": { + "type": "VStartTag", + "range": [ + 0, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 21 + } + }, + "selfClosing": false, + "attributes": [ + { + "type": "VAttribute", + "range": [ + 10, + 20 + ], + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 20 + } + }, + "directive": false, + "key": { + "type": "VIdentifier", + "range": [ + 10, + 14 + ], + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 14 + } + }, + "name": "lang", + "rawName": "lang" + }, + "value": { + "type": "VLiteral", + "range": [ + 15, + 20 + ], + "loc": { + "start": { + "line": 1, + "column": 15 + }, + "end": { + "line": 1, + "column": 20 + } + }, + "value": "pug" + } + } + ] + }, + "children": [ + { + "type": "VText", + "range": [ + 21, + 24 + ], + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 2, + "column": 2 + } + }, + "value": "\np " + }, + { + "type": "VExpressionContainer", + "range": [ + 24, + 38 + ], + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 16 + } + }, + "expression": { + "type": "Identifier", + "start": 27, + "end": 35, + "loc": { + "start": { + "line": 2, + "column": 5 + }, + "end": { + "line": 2, + "column": 13 + } + }, + "range": [ + 27, + 35 + ], + "name": "greeting" + }, + "references": [ + { + "id": { + "type": "Identifier", + "start": 27, + "end": 35, + "loc": { + "start": { + "line": 2, + "column": 5 + }, + "end": { + "line": 2, + "column": 13 + } + }, + "range": [ + 27, + 35 + ], + "name": "greeting" + }, + "mode": "r" + } + ] + }, + { + "type": "VText", + "range": [ + 38, + 46 + ], + "loc": { + "start": { + "line": 2, + "column": 16 + }, + "end": { + "line": 3, + "column": 0 + } + }, + "value": " World!\n" + } + ], + "endTag": { + "type": "VEndTag", + "range": [ + 46, + 57 + ], + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 11 + } + } + }, + "variables": [], + "tokens": [ + { + "type": "HTMLTagOpen", + "range": [ + 0, + 9 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 9 + } + }, + "value": "template" + }, + { + "type": "HTMLIdentifier", + "range": [ + 10, + 14 + ], + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 14 + } + }, + "value": "lang" + }, + { + "type": "HTMLAssociation", + "range": [ + 14, + 15 + ], + "loc": { + "start": { + "line": 1, + "column": 14 + }, + "end": { + "line": 1, + "column": 15 + } + }, + "value": "" + }, + { + "type": "HTMLLiteral", + "range": [ + 15, + 20 + ], + "loc": { + "start": { + "line": 1, + "column": 15 + }, + "end": { + "line": 1, + "column": 20 + } + }, + "value": "pug" + }, + { + "type": "HTMLTagClose", + "range": [ + 20, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 20 + }, + "end": { + "line": 1, + "column": 21 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 21, + 22 + ], + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 2, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLRawText", + "range": [ + 22, + 23 + ], + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 1 + } + }, + "value": "p" + }, + { + "type": "HTMLWhitespace", + "range": [ + 23, + 24 + ], + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 2, + "column": 2 + } + }, + "value": " " + }, + { + "type": "VExpressionStart", + "range": [ + 24, + 26 + ], + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 4 + } + }, + "value": "{{" + }, + { + "type": "Identifier", + "value": "greeting", + "start": 27, + "end": 35, + "loc": { + "start": { + "line": 2, + "column": 5 + }, + "end": { + "line": 2, + "column": 13 + } + }, + "range": [ + 27, + 35 + ] + }, + { + "type": "VExpressionEnd", + "range": [ + 36, + 38 + ], + "loc": { + "start": { + "line": 2, + "column": 14 + }, + "end": { + "line": 2, + "column": 16 + } + }, + "value": "}}" + }, + { + "type": "HTMLWhitespace", + "range": [ + 38, + 39 + ], + "loc": { + "start": { + "line": 2, + "column": 16 + }, + "end": { + "line": 2, + "column": 17 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 39, + 45 + ], + "loc": { + "start": { + "line": 2, + "column": 17 + }, + "end": { + "line": 2, + "column": 23 + } + }, + "value": "World!" + }, + { + "type": "HTMLWhitespace", + "range": [ + 45, + 46 + ], + "loc": { + "start": { + "line": 2, + "column": 23 + }, + "end": { + "line": 3, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 46, + 56 + ], + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 10 + } + }, + "value": "template" + }, + { + "type": "HTMLTagClose", + "range": [ + 56, + 57 + ], + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 11 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 57, + 58 + ], + "loc": { + "start": { + "line": 3, + "column": 11 + }, + "end": { + "line": 4, + "column": 0 + } + }, + "value": "\n" + } + ], + "comments": [], + "errors": [] + } } \ No newline at end of file diff --git a/test/fixtures/ast/pug/token-ranges.json b/test/fixtures/ast/pug/token-ranges.json index 0637a088..a99867e3 100644 --- a/test/fixtures/ast/pug/token-ranges.json +++ b/test/fixtures/ast/pug/token-ranges.json @@ -1 +1,19 @@ -[] \ No newline at end of file +[ + "", + "\n", + "p", + " ", + "{{", + "greeting", + "}}", + " ", + "World!", + "\n", + "", + "\n" +] \ No newline at end of file diff --git a/test/fixtures/ast/pug/tree.json b/test/fixtures/ast/pug/tree.json index 0637a088..4cb94d09 100644 --- a/test/fixtures/ast/pug/tree.json +++ b/test/fixtures/ast/pug/tree.json @@ -1 +1,56 @@ -[] \ No newline at end of file +[ + { + "type": "VElement", + "text": "", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + } + ] + } +] \ No newline at end of file