From 62349931c04e663a6331c9d03133f44f5e873700 Mon Sep 17 00:00:00 2001 From: Toru Nagashima Date: Thu, 14 May 2020 20:31:50 +0900 Subject: [PATCH 001/151] =?UTF-8?q?=E2=9A=92=20remove=20outdated=20setting?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index e4ba81f2..72446f43 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,9 +1,3 @@ { - "eslint.validate": [ - "javascript", - {"language": "html", "autoFix": true}, - {"language": "vue", "autoFix": true}, - {"language": "typescript", "autoFix": true} - ], "typescript.tsdk": "node_modules/typescript/lib" } From 27a275f530b27e4714183c535d2e121aadf9e3bd Mon Sep 17 00:00:00 2001 From: Toru Nagashima Date: Thu, 14 May 2020 20:32:05 +0900 Subject: [PATCH 002/151] =?UTF-8?q?=E2=9C=A8=20use=20espree=20in=20eslint?= =?UTF-8?q?=20deps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/CI.yml | 4 +-- src/script/espree.ts | 69 ++++++++++++++++++++++++++++++++++++++++ src/script/index.ts | 18 ++--------- test/espree.js | 60 ++++++++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+), 18 deletions(-) create mode 100644 src/script/espree.ts create mode 100644 test/espree.js diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index c9b501be..d3f8df9a 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -1,7 +1,7 @@ name: CI on: push: - branches: [master] + branches: [master, try] pull_request: branches: [master] schedule: @@ -21,7 +21,7 @@ jobs: with: node-version: 14 - name: Install Packages - run: npm install + run: npm install && cd test/fixtures/eslint && npm install - name: Lint run: npm run -s lint diff --git a/src/script/espree.ts b/src/script/espree.ts new file mode 100644 index 00000000..4e25d07b --- /dev/null +++ b/src/script/espree.ts @@ -0,0 +1,69 @@ +import Module from "module" +import path from "path" +import { ESLintExtendedProgram, ESLintProgram } from "../ast" + +/** + * The interface of a result of ESLint custom parser. + */ +export type ESLintCustomParserResult = ESLintProgram | ESLintExtendedProgram + +/** + * The interface of ESLint custom parsers. + */ +export interface ESLintCustomParser { + parse(code: string, options: any): ESLintCustomParserResult + parseForESLint?(code: string, options: any): ESLintCustomParserResult +} + +const createRequire: (filename: string) => (filename: string) => any = + // Added in v12.2.0 + (Module as any).createRequire || + // Added in v10.12.0, but deprecated in v12.2.0. + Module.createRequireFromPath || + // Polyfill - This is not executed on the tests on node@>=10. + /* istanbul ignore next */ + (filename => { + const mod = new Module(filename) + + mod.filename = filename + mod.paths = (Module as any)._nodeModulePaths(path.dirname(filename)) + ;(mod as any)._compile("module.exports = require;", filename) + return mod.exports + }) + +let espreeCache: ESLintCustomParser | null = null + +function isLinterPath(p: string): boolean { + return ( + // ESLint 6 and above + p.includes( + `eslint${path.sep}lib${path.sep}linter${path.sep}linter.js`, + ) || + // ESLint 5 + p.includes(`eslint${path.sep}lib${path.sep}linter.js`) + ) +} + +/** + * Load `espree` from the loaded ESLint. + * If the loaded ESLint was not found, just returns `require("espree")`. + */ +export function getEspree(): ESLintCustomParser { + if (!espreeCache) { + // Lookup the loaded eslint + const linterPath = Object.keys(require.cache).find(isLinterPath) + if (linterPath) { + try { + espreeCache = createRequire(linterPath)("espree") + } catch { + // ignore + } + } + if (!espreeCache) { + //eslint-disable-next-line @mysticatea/ts/no-require-imports + espreeCache = require("espree") + } + } + + return espreeCache! +} diff --git a/src/script/index.ts b/src/script/index.ts index c5d9e2f8..bfa9100f 100644 --- a/src/script/index.ts +++ b/src/script/index.ts @@ -17,7 +17,6 @@ import { ESLintForOfStatement, ESLintFunctionExpression, ESLintPattern, - ESLintProgram, ESLintVariableDeclaration, ESLintUnaryExpression, HasLocation, @@ -39,6 +38,7 @@ import { analyzeExternalReferences, analyzeVariablesAndExternalReferences, } from "./scope-analyzer" +import { ESLintCustomParser, getEspree } from "./espree" // [1] = spacing before the aliases. // [2] = aliases. @@ -51,14 +51,6 @@ const DUMMY_PARENT: any = {} const IS_FUNCTION_EXPRESSION = /^\s*([\w$_]+|\([^)]*?\))\s*=>|^function\s*\(/u const IS_SIMPLE_PATH = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?'\]|\["[^"]*?"\]|\[\d+\]|\[[A-Za-z_$][\w$]*\])*$/u -/** - * The interface of ESLint custom parsers. - */ -interface ESLintCustomParser { - parse(code: string, options: any): ESLintCustomParserResult - parseForESLint?(code: string, options: any): ESLintCustomParserResult -} - /** * Do post-process of parsing an expression. * @@ -548,11 +540,6 @@ export interface ExpressionParseResult { variables: Variable[] } -/** - * The interface of a result of ESLint custom parser. - */ -export type ESLintCustomParserResult = ESLintProgram | ESLintExtendedProgram - /** * Parse the given source code. * @@ -568,8 +555,7 @@ export function parseScript( typeof parserOptions.parser === "string" ? // eslint-disable-next-line @mysticatea/ts/no-require-imports require(parserOptions.parser) - : // eslint-disable-next-line @mysticatea/ts/no-require-imports - require("espree") + : getEspree() const result: any = // eslint-disable-next-line @mysticatea/ts/unbound-method typeof parser.parseForESLint === "function" diff --git a/test/espree.js b/test/espree.js new file mode 100644 index 00000000..284da5dd --- /dev/null +++ b/test/espree.js @@ -0,0 +1,60 @@ +"use strict" + +const path = require("path") + +/** + * Spawn a child process to run `childMain()`. + */ +function parentMain() { + const { spawn } = require("child_process") + + describe("Loading espree from ESLint", () => { + it("should load espree from the ESLint location.", done => { + spawn(process.execPath, [__filename, "--child"], { + stdio: "inherit", + }) + .on("error", done) + .on("exit", code => + code + ? done(new Error(`Exited with non-zero: ${code}`)) + : done() + ) + }) + }) +} + +/** + * Check this parser loads the `espree` from the location of the loaded ESLint. + */ +function childMain() { + const assert = require("assert") + const { Linter } = require("./fixtures/eslint") + const linter = new Linter() + linter.defineParser("vue-eslint-parser", require("../src")) + + const beforeEsprees = Object.keys(require.cache).filter(isEspreePath) + + linter.verify( + "", + { parser: "vue-eslint-parser" }, + { filename: "a.vue" } + ) + + const afterEsprees = Object.keys(require.cache).filter(isEspreePath) + + assert.strictEqual( + afterEsprees.length, + beforeEsprees.length, + "espree should be loaded from the expected place" + ) +} + +function isEspreePath(p) { + return p.includes(`${path.sep}node_modules${path.sep}espree${path.sep}`) +} + +if (process.argv.includes("--child")) { + childMain() +} else { + parentMain() +} From c12da39d0d548123b784533645bc58499cbb864d Mon Sep 17 00:00:00 2001 From: Toru Nagashima Date: Thu, 14 May 2020 22:00:10 +0900 Subject: [PATCH 003/151] =?UTF-8?q?=E2=9A=92=20add=20funding=20field?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index cd43aff1..6574bd1f 100644 --- a/package.json +++ b/package.json @@ -82,5 +82,6 @@ "bugs": { "url": "https://github.com/mysticatea/vue-eslint-parser/issues" }, - "homepage": "https://github.com/mysticatea/vue-eslint-parser#readme" + "homepage": "https://github.com/mysticatea/vue-eslint-parser#readme", + "funding": "https://github.com/sponsors/mysticatea" } From c627e36c57ab6607c96f995e81b8ce693ac846ef Mon Sep 17 00:00:00 2001 From: Toru Nagashima Date: Fri, 15 May 2020 17:46:26 +0900 Subject: [PATCH 004/151] =?UTF-8?q?=F0=9F=94=96=207.1.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6574bd1f..db6f2cc7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-eslint-parser", - "version": "7.0.0", + "version": "7.1.0", "description": "The ESLint custom parser for `.vue` files.", "engines": { "node": ">=8.10" From ca614f466b315e9faea889ea6ccb00d94a19f564 Mon Sep 17 00:00:00 2001 From: Yosuke Ota Date: Mon, 12 Oct 2020 19:20:56 +0900 Subject: [PATCH 005/151] Fixed wrong location calculation when including CRLF. (#74) * Fixed wrong location calculation when including CRLF. * Fixed error --- src/common/location-calculator.ts | 43 +- src/script/index.ts | 30 +- test/ast.js | 19 + test/fixtures/ast/end-of-line01/ast.json | 2803 +++++++++++++++++ test/fixtures/ast/end-of-line01/source.vue | 17 + .../ast/end-of-line01/token-ranges.json | 80 + test/fixtures/ast/end-of-line01/tree.json | 311 ++ test/fixtures/ast/end-of-line02/ast.json | 2803 +++++++++++++++++ test/fixtures/ast/end-of-line02/source.vue | 17 + .../ast/end-of-line02/token-ranges.json | 80 + test/fixtures/ast/end-of-line02/tree.json | 311 ++ 11 files changed, 6494 insertions(+), 20 deletions(-) create mode 100644 test/fixtures/ast/end-of-line01/ast.json create mode 100644 test/fixtures/ast/end-of-line01/source.vue create mode 100644 test/fixtures/ast/end-of-line01/token-ranges.json create mode 100644 test/fixtures/ast/end-of-line01/tree.json create mode 100644 test/fixtures/ast/end-of-line02/ast.json create mode 100644 test/fixtures/ast/end-of-line02/source.vue create mode 100644 test/fixtures/ast/end-of-line02/token-ranges.json create mode 100644 test/fixtures/ast/end-of-line02/tree.json diff --git a/src/common/location-calculator.ts b/src/common/location-calculator.ts index fb33bef0..980e0174 100644 --- a/src/common/location-calculator.ts +++ b/src/common/location-calculator.ts @@ -23,17 +23,20 @@ export class LocationCalculator { private ltOffsets: number[] private baseOffset: number private baseIndexOfGap: number + private shiftOffset: number /** * Initialize this calculator. * @param gapOffsets The list of the offset of removed characters in tokenization phase. * @param ltOffsets The list of the offset of line terminators. * @param baseOffset The base offset to calculate locations. + * @param shiftOffset The shift offset to calculate locations. */ public constructor( gapOffsets: number[], ltOffsets: number[], baseOffset?: number, + shiftOffset: number = 0, ) { this.gapOffsets = gapOffsets this.ltOffsets = ltOffsets @@ -42,6 +45,7 @@ export class LocationCalculator { this.baseOffset === 0 ? 0 : sortedLastIndex(gapOffsets, this.baseOffset) + this.shiftOffset = shiftOffset } /** @@ -54,6 +58,21 @@ export class LocationCalculator { this.gapOffsets, this.ltOffsets, this.baseOffset + offset, + this.shiftOffset, + ) + } + + /** + * Get sub calculator that shifts the given offset. + * @param offset The shift of new sub calculator. + * @returns Sub calculator. + */ + public getSubCalculatorShift(offset: number): LocationCalculator { + return new LocationCalculator( + this.gapOffsets, + this.ltOffsets, + this.baseOffset, + this.shiftOffset + offset, ) } @@ -91,7 +110,7 @@ export class LocationCalculator { * @returns The location of the index. */ public getLocation(index: number): Location { - return this._getLocation(this.baseOffset + index) + return this._getLocation(this.baseOffset + index + this.shiftOffset) } /** @@ -100,7 +119,13 @@ export class LocationCalculator { * @returns The offset of the index. */ public getOffsetWithGap(index: number): number { - return this.baseOffset + index + this._getGap(index) + const shiftOffset = this.shiftOffset + return ( + this.baseOffset + + index + + shiftOffset + + this._getGap(index + shiftOffset) + ) } /** @@ -108,12 +133,13 @@ export class LocationCalculator { * @param node The node to modify their location. */ public fixLocation(node: T): T { + const shiftOffset = this.shiftOffset const range = node.range const loc = node.loc - const gap0 = this._getGap(range[0]) - const gap1 = this._getGap(range[1]) - const d0 = this.baseOffset + Math.max(0, gap0) - const d1 = this.baseOffset + Math.max(0, gap1) + const gap0 = this._getGap(range[0] + shiftOffset) + const gap1 = this._getGap(range[1] + shiftOffset) + const d0 = this.baseOffset + Math.max(0, gap0) + shiftOffset + const d1 = this.baseOffset + Math.max(0, gap1) + shiftOffset if (d0 !== 0) { range[0] += d0 @@ -138,8 +164,9 @@ export class LocationCalculator { * @param error The error to modify their location. */ public fixErrorLocation(error: ParseError) { - const gap = this._getGap(error.index) - const diff = this.baseOffset + Math.max(0, gap) + const shiftOffset = this.shiftOffset + const gap = this._getGap(error.index + shiftOffset) + const diff = this.baseOffset + Math.max(0, gap) + shiftOffset error.index += diff diff --git a/src/script/index.ts b/src/script/index.ts index bfa9100f..f073acd5 100644 --- a/src/script/index.ts +++ b/src/script/index.ts @@ -361,7 +361,7 @@ function parseExpressionBody( try { const ast = parseScriptFragment( `0(${code})`, - locationCalculator.getSubCalculatorAfter(-2), + locationCalculator.getSubCalculatorShift(-2), parserOptions, ).ast const tokens = ast.tokens || [] @@ -431,9 +431,12 @@ function parseFilter( // Parse the callee. if (calleeCode.trim()) { const spaces = /^\s*/u.exec(calleeCode)![0] + const subCalculator = locationCalculator.getSubCalculatorShift( + spaces.length, + ) const { ast } = parseScriptFragment( - `${spaces}"${calleeCode.trim()}"`, - locationCalculator, + `"${calleeCode.trim()}"`, + subCalculator, parserOptions, ) const statement = ast.body[0] as ESLintExpressionStatement @@ -455,12 +458,13 @@ function parseFilter( expression.callee = { type: "Identifier", parent: expression, - range: [callee.range[0], callee.range[1] - 2], + range: [ + callee.range[0], + subCalculator.getOffsetWithGap(calleeCode.trim().length), + ], loc: { start: callee.loc.start, - end: locationCalculator.getLocation( - callee.range[1] - callee.range[0] - 1, - ), + end: subCalculator.getLocation(calleeCode.trim().length), }, name: String(callee.value), } @@ -478,7 +482,9 @@ function parseFilter( if (argsCode != null) { const { ast } = parseScriptFragment( `0${argsCode}`, - locationCalculator.getSubCalculatorAfter(paren - 1), + locationCalculator + .getSubCalculatorAfter(paren) + .getSubCalculatorShift(-1), parserOptions, ) const statement = ast.body[0] as ESLintExpressionStatement @@ -684,7 +690,7 @@ export function parseExpression( // Parse a filter const retF = parseFilter( filterCode, - locationCalculator.getSubCalculatorAfter(prevLoc + 1), + locationCalculator.getSubCalculatorShift(prevLoc + 1), parserOptions, ) if (retF) { @@ -731,7 +737,7 @@ export function parseVForExpression( const replaced = processedCode !== code const ast = parseScriptFragment( `for(let ${processedCode});`, - locationCalculator.getSubCalculatorAfter(-8), + locationCalculator.getSubCalculatorShift(-8), parserOptions, ).ast const tokens = ast.tokens || [] @@ -829,7 +835,7 @@ function parseVOnExpressionBody( try { const ast = parseScriptFragment( `void function($event){${code}}`, - locationCalculator.getSubCalculatorAfter(-22), + locationCalculator.getSubCalculatorShift(-22), parserOptions, ).ast const references = analyzeExternalReferences(ast, parserOptions) @@ -905,7 +911,7 @@ export function parseSlotScopeExpression( try { const ast = parseScriptFragment( `void function(${code}) {}`, - locationCalculator.getSubCalculatorAfter(-14), + locationCalculator.getSubCalculatorShift(-14), parserOptions, ).ast const statement = ast.body[0] as ESLintExpressionStatement diff --git a/test/ast.js b/test/ast.js index 34900a9b..3f2d15a6 100644 --- a/test/ast.js +++ b/test/ast.js @@ -198,6 +198,25 @@ describe("Template AST", () => { assert.strictEqual(actualText, expectedText) }) + it("should have correct range on windows(CRLF).", () => { + const sourceForWin = source.replace(/\r?\n/gu, "\r\n") + const actualForWin = parser.parseForESLint( + sourceForWin, + Object.assign({ filePath: sourcePath }, PARSER_OPTIONS) + ) + + const resultPath = path.join(ROOT, `${name}/token-ranges.json`) + const expectedText = fs.readFileSync(resultPath, "utf8") + const tokens = getAllTokens(actualForWin.ast).map(t => + sourceForWin + .slice(t.range[0], t.range[1]) + .replace(/\r?\n/gu, "\n") + ) + const actualText = JSON.stringify(tokens, null, 4) + + assert.strictEqual(actualText, expectedText) + }) + it("should have correct location.", () => { const lines = source.match(/[^\r\n]*(?:\r?\n|$)/gu) || [] lines.push(String.fromCodePoint(0)) diff --git a/test/fixtures/ast/end-of-line01/ast.json b/test/fixtures/ast/end-of-line01/ast.json new file mode 100644 index 00000000..94e76dd0 --- /dev/null +++ b/test/fixtures/ast/end-of-line01/ast.json @@ -0,0 +1,2803 @@ +{ + "type": "Program", + "start": 191, + "end": 204, + "loc": { + "start": { + "line": 16, + "column": 0 + }, + "end": { + "line": 16, + "column": 11 + } + }, + "range": [ + 192, + 203 + ], + "body": [ + { + "type": "VariableDeclaration", + "start": 192, + "end": 203, + "loc": { + "start": { + "line": 16, + "column": 0 + }, + "end": { + "line": 16, + "column": 11 + } + }, + "range": [ + 192, + 203 + ], + "declarations": [ + { + "type": "VariableDeclarator", + "start": 196, + "end": 203, + "loc": { + "start": { + "line": 16, + "column": 4 + }, + "end": { + "line": 16, + "column": 11 + } + }, + "range": [ + 196, + 203 + ], + "id": { + "type": "Identifier", + "start": 196, + "end": 197, + "loc": { + "start": { + "line": 16, + "column": 4 + }, + "end": { + "line": 16, + "column": 5 + } + }, + "range": [ + 196, + 197 + ], + "name": "a" + }, + "init": { + "type": "Identifier", + "start": 200, + "end": 203, + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 11 + } + }, + "range": [ + 200, + 203 + ], + "name": "foo" + } + } + ], + "kind": "var" + } + ], + "sourceType": "script", + "comments": [], + "tokens": [ + { + "type": "Punctuator", + "range": [ + 183, + 191 + ], + "loc": { + "start": { + "line": 15, + "column": 0 + }, + "end": { + "line": 15, + "column": 8 + } + }, + "value": "" + } + ], + "templateBody": { + "type": "VElement", + "range": [ + 0, + 182 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 14, + "column": 11 + } + }, + "name": "template", + "rawName": "template", + "namespace": "http://www.w3.org/1999/xhtml", + "startTag": { + "type": "VStartTag", + "range": [ + 0, + 10 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "selfClosing": false, + "attributes": [] + }, + "children": [ + { + "type": "VText", + "range": [ + 10, + 13 + ], + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 2, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "VElement", + "range": [ + 13, + 44 + ], + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 4, + "column": 9 + } + }, + "name": "div", + "rawName": "div", + "namespace": "http://www.w3.org/1999/xhtml", + "startTag": { + "type": "VStartTag", + "range": [ + 13, + 38 + ], + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 4, + "column": 3 + } + }, + "selfClosing": false, + "attributes": [ + { + "type": "VAttribute", + "range": [ + 22, + 34 + ], + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 16 + } + }, + "directive": true, + "key": { + "type": "VDirectiveKey", + "range": [ + 22, + 28 + ], + "loc": { + "start": { + "line": 3, + "column": 4 + }, + "end": { + "line": 3, + "column": 10 + } + }, + "name": { + "type": "VIdentifier", + "range": [ + 22, + 23 + ], + "loc": { + "start": { + "column": 4, + "line": 3 + }, + "end": { + "column": 5, + "line": 3 + } + }, + "name": "on", + "rawName": "@" + }, + "argument": { + "type": "VIdentifier", + "range": [ + 23, + 28 + ], + "loc": { + "start": { + "column": 5, + "line": 3 + }, + "end": { + "column": 10, + "line": 3 + } + }, + "name": "click", + "rawName": "click" + }, + "modifiers": [] + }, + "value": { + "type": "VExpressionContainer", + "range": [ + 29, + 34 + ], + "loc": { + "start": { + "line": 3, + "column": 11 + }, + "end": { + "line": 3, + "column": 16 + } + }, + "expression": { + "type": "VOnExpression", + "range": [ + 30, + 33 + ], + "loc": { + "start": { + "line": 3, + "column": 12 + }, + "end": { + "line": 3, + "column": 15 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 30, + "end": 33, + "loc": { + "start": { + "line": 3, + "column": 12 + }, + "end": { + "line": 3, + "column": 15 + } + }, + "range": [ + 30, + 33 + ], + "expression": { + "type": "AssignmentExpression", + "start": 30, + "end": 33, + "loc": { + "start": { + "line": 3, + "column": 12 + }, + "end": { + "line": 3, + "column": 15 + } + }, + "range": [ + 30, + 33 + ], + "operator": "=", + "left": { + "type": "Identifier", + "start": 30, + "end": 31, + "loc": { + "start": { + "line": 3, + "column": 12 + }, + "end": { + "line": 3, + "column": 13 + } + }, + "range": [ + 30, + 31 + ], + "name": "a" + }, + "right": { + "type": "Identifier", + "start": 32, + "end": 33, + "loc": { + "start": { + "line": 3, + "column": 14 + }, + "end": { + "line": 3, + "column": 15 + } + }, + "range": [ + 32, + 33 + ], + "name": "b" + } + } + } + ] + }, + "references": [ + { + "id": { + "type": "Identifier", + "start": 30, + "end": 31, + "loc": { + "start": { + "line": 3, + "column": 12 + }, + "end": { + "line": 3, + "column": 13 + } + }, + "range": [ + 30, + 31 + ], + "name": "a" + }, + "mode": "w" + }, + { + "id": { + "type": "Identifier", + "start": 32, + "end": 33, + "loc": { + "start": { + "line": 3, + "column": 14 + }, + "end": { + "line": 3, + "column": 15 + } + }, + "range": [ + 32, + 33 + ], + "name": "b" + }, + "mode": "r" + } + ] + } + } + ] + }, + "children": [], + "endTag": { + "type": "VEndTag", + "range": [ + 38, + 44 + ], + "loc": { + "start": { + "line": 4, + "column": 3 + }, + "end": { + "line": 4, + "column": 9 + } + } + }, + "variables": [] + }, + { + "type": "VText", + "range": [ + 44, + 47 + ], + "loc": { + "start": { + "line": 4, + "column": 9 + }, + "end": { + "line": 5, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "VElement", + "range": [ + 47, + 83 + ], + "loc": { + "start": { + "line": 5, + "column": 2 + }, + "end": { + "line": 7, + "column": 9 + } + }, + "name": "div", + "rawName": "div", + "namespace": "http://www.w3.org/1999/xhtml", + "startTag": { + "type": "VStartTag", + "range": [ + 47, + 77 + ], + "loc": { + "start": { + "line": 5, + "column": 2 + }, + "end": { + "line": 7, + "column": 3 + } + }, + "selfClosing": false, + "attributes": [ + { + "type": "VAttribute", + "range": [ + 56, + 73 + ], + "loc": { + "start": { + "line": 6, + "column": 4 + }, + "end": { + "line": 6, + "column": 21 + } + }, + "directive": true, + "key": { + "type": "VDirectiveKey", + "range": [ + 56, + 67 + ], + "loc": { + "start": { + "line": 6, + "column": 4 + }, + "end": { + "line": 6, + "column": 15 + } + }, + "name": { + "type": "VIdentifier", + "range": [ + 56, + 57 + ], + "loc": { + "start": { + "column": 4, + "line": 6 + }, + "end": { + "column": 5, + "line": 6 + } + }, + "name": "bind", + "rawName": ":" + }, + "argument": { + "type": "VIdentifier", + "range": [ + 57, + 67 + ], + "loc": { + "start": { + "column": 5, + "line": 6 + }, + "end": { + "column": 15, + "line": 6 + } + }, + "name": "data-click", + "rawName": "data-click" + }, + "modifiers": [] + }, + "value": { + "type": "VExpressionContainer", + "range": [ + 68, + 73 + ], + "loc": { + "start": { + "line": 6, + "column": 16 + }, + "end": { + "line": 6, + "column": 21 + } + }, + "expression": { + "type": "AssignmentExpression", + "start": 69, + "end": 72, + "loc": { + "start": { + "line": 6, + "column": 17 + }, + "end": { + "line": 6, + "column": 20 + } + }, + "range": [ + 69, + 72 + ], + "operator": "=", + "left": { + "type": "Identifier", + "start": 69, + "end": 70, + "loc": { + "start": { + "line": 6, + "column": 17 + }, + "end": { + "line": 6, + "column": 18 + } + }, + "range": [ + 69, + 70 + ], + "name": "a" + }, + "right": { + "type": "Identifier", + "start": 71, + "end": 72, + "loc": { + "start": { + "line": 6, + "column": 19 + }, + "end": { + "line": 6, + "column": 20 + } + }, + "range": [ + 71, + 72 + ], + "name": "b" + } + }, + "references": [ + { + "id": { + "type": "Identifier", + "start": 69, + "end": 70, + "loc": { + "start": { + "line": 6, + "column": 17 + }, + "end": { + "line": 6, + "column": 18 + } + }, + "range": [ + 69, + 70 + ], + "name": "a" + }, + "mode": "w" + }, + { + "id": { + "type": "Identifier", + "start": 71, + "end": 72, + "loc": { + "start": { + "line": 6, + "column": 19 + }, + "end": { + "line": 6, + "column": 20 + } + }, + "range": [ + 71, + 72 + ], + "name": "b" + }, + "mode": "r" + } + ] + } + } + ] + }, + "children": [], + "endTag": { + "type": "VEndTag", + "range": [ + 77, + 83 + ], + "loc": { + "start": { + "line": 7, + "column": 3 + }, + "end": { + "line": 7, + "column": 9 + } + } + }, + "variables": [] + }, + { + "type": "VText", + "range": [ + 83, + 86 + ], + "loc": { + "start": { + "line": 7, + "column": 9 + }, + "end": { + "line": 8, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "VElement", + "range": [ + 86, + 129 + ], + "loc": { + "start": { + "line": 8, + "column": 2 + }, + "end": { + "line": 10, + "column": 9 + } + }, + "name": "div", + "rawName": "div", + "namespace": "http://www.w3.org/1999/xhtml", + "startTag": { + "type": "VStartTag", + "range": [ + 86, + 123 + ], + "loc": { + "start": { + "line": 8, + "column": 2 + }, + "end": { + "line": 10, + "column": 3 + } + }, + "selfClosing": false, + "attributes": [ + { + "type": "VAttribute", + "range": [ + 95, + 119 + ], + "loc": { + "start": { + "line": 9, + "column": 4 + }, + "end": { + "line": 9, + "column": 28 + } + }, + "directive": true, + "key": { + "type": "VDirectiveKey", + "range": [ + 95, + 104 + ], + "loc": { + "start": { + "line": 9, + "column": 4 + }, + "end": { + "line": 9, + "column": 13 + } + }, + "name": { + "type": "VIdentifier", + "range": [ + 95, + 96 + ], + "loc": { + "start": { + "column": 4, + "line": 9 + }, + "end": { + "column": 5, + "line": 9 + } + }, + "name": "bind", + "rawName": ":" + }, + "argument": { + "type": "VIdentifier", + "range": [ + 96, + 104 + ], + "loc": { + "start": { + "column": 5, + "line": 9 + }, + "end": { + "column": 13, + "line": 9 + } + }, + "name": "data-foo", + "rawName": "data-foo" + }, + "modifiers": [] + }, + "value": { + "type": "VExpressionContainer", + "range": [ + 105, + 119 + ], + "loc": { + "start": { + "line": 9, + "column": 14 + }, + "end": { + "line": 9, + "column": 28 + } + }, + "expression": { + "type": "LogicalExpression", + "start": 106, + "end": 110, + "loc": { + "start": { + "line": 9, + "column": 15 + }, + "end": { + "line": 9, + "column": 27 + } + }, + "range": [ + 106, + 118 + ], + "left": { + "type": "Identifier", + "start": 106, + "end": 107, + "loc": { + "start": { + "line": 9, + "column": 15 + }, + "end": { + "line": 9, + "column": 16 + } + }, + "range": [ + 106, + 107 + ], + "name": "c" + }, + "operator": "&&", + "right": { + "type": "Identifier", + "start": 117, + "end": 118, + "loc": { + "start": { + "line": 9, + "column": 26 + }, + "end": { + "line": 9, + "column": 27 + } + }, + "range": [ + 117, + 118 + ], + "name": "d" + } + }, + "references": [ + { + "id": { + "type": "Identifier", + "start": 106, + "end": 107, + "loc": { + "start": { + "line": 9, + "column": 15 + }, + "end": { + "line": 9, + "column": 16 + } + }, + "range": [ + 106, + 107 + ], + "name": "c" + }, + "mode": "r" + }, + { + "id": { + "type": "Identifier", + "start": 117, + "end": 118, + "loc": { + "start": { + "line": 9, + "column": 26 + }, + "end": { + "line": 9, + "column": 27 + } + }, + "range": [ + 117, + 118 + ], + "name": "d" + }, + "mode": "r" + } + ] + } + } + ] + }, + "children": [], + "endTag": { + "type": "VEndTag", + "range": [ + 123, + 129 + ], + "loc": { + "start": { + "line": 10, + "column": 3 + }, + "end": { + "line": 10, + "column": 9 + } + } + }, + "variables": [] + }, + { + "type": "VText", + "range": [ + 129, + 132 + ], + "loc": { + "start": { + "line": 10, + "column": 9 + }, + "end": { + "line": 11, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "VElement", + "range": [ + 132, + 170 + ], + "loc": { + "start": { + "line": 11, + "column": 2 + }, + "end": { + "line": 13, + "column": 9 + } + }, + "name": "div", + "rawName": "div", + "namespace": "http://www.w3.org/1999/xhtml", + "startTag": { + "type": "VStartTag", + "range": [ + 132, + 164 + ], + "loc": { + "start": { + "line": 11, + "column": 2 + }, + "end": { + "line": 13, + "column": 3 + } + }, + "selfClosing": false, + "attributes": [ + { + "type": "VAttribute", + "range": [ + 141, + 160 + ], + "loc": { + "start": { + "line": 12, + "column": 4 + }, + "end": { + "line": 12, + "column": 23 + } + }, + "directive": true, + "key": { + "type": "VDirectiveKey", + "range": [ + 141, + 145 + ], + "loc": { + "start": { + "line": 12, + "column": 4 + }, + "end": { + "line": 12, + "column": 8 + } + }, + "name": { + "type": "VIdentifier", + "range": [ + 141, + 142 + ], + "loc": { + "start": { + "column": 4, + "line": 12 + }, + "end": { + "column": 5, + "line": 12 + } + }, + "name": "on", + "rawName": "@" + }, + "argument": { + "type": "VIdentifier", + "range": [ + 142, + 145 + ], + "loc": { + "start": { + "column": 5, + "line": 12 + }, + "end": { + "column": 8, + "line": 12 + } + }, + "name": "foo", + "rawName": "foo" + }, + "modifiers": [] + }, + "value": { + "type": "VExpressionContainer", + "range": [ + 146, + 160 + ], + "loc": { + "start": { + "line": 12, + "column": 9 + }, + "end": { + "line": 12, + "column": 23 + } + }, + "expression": { + "type": "VOnExpression", + "range": [ + 147, + 159 + ], + "loc": { + "start": { + "line": 12, + "column": 10 + }, + "end": { + "line": 12, + "column": 22 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 147, + "end": 151, + "loc": { + "start": { + "line": 12, + "column": 10 + }, + "end": { + "line": 12, + "column": 22 + } + }, + "range": [ + 147, + 159 + ], + "expression": { + "type": "LogicalExpression", + "start": 147, + "end": 151, + "loc": { + "start": { + "line": 12, + "column": 10 + }, + "end": { + "line": 12, + "column": 22 + } + }, + "range": [ + 147, + 159 + ], + "left": { + "type": "Identifier", + "start": 147, + "end": 148, + "loc": { + "start": { + "line": 12, + "column": 10 + }, + "end": { + "line": 12, + "column": 11 + } + }, + "range": [ + 147, + 148 + ], + "name": "c" + }, + "operator": "&&", + "right": { + "type": "Identifier", + "start": 158, + "end": 159, + "loc": { + "start": { + "line": 12, + "column": 21 + }, + "end": { + "line": 12, + "column": 22 + } + }, + "range": [ + 158, + 159 + ], + "name": "d" + } + } + } + ] + }, + "references": [ + { + "id": { + "type": "Identifier", + "start": 147, + "end": 148, + "loc": { + "start": { + "line": 12, + "column": 10 + }, + "end": { + "line": 12, + "column": 11 + } + }, + "range": [ + 147, + 148 + ], + "name": "c" + }, + "mode": "r" + }, + { + "id": { + "type": "Identifier", + "start": 158, + "end": 159, + "loc": { + "start": { + "line": 12, + "column": 21 + }, + "end": { + "line": 12, + "column": 22 + } + }, + "range": [ + 158, + 159 + ], + "name": "d" + }, + "mode": "r" + } + ] + } + } + ] + }, + "children": [], + "endTag": { + "type": "VEndTag", + "range": [ + 164, + 170 + ], + "loc": { + "start": { + "line": 13, + "column": 3 + }, + "end": { + "line": 13, + "column": 9 + } + } + }, + "variables": [] + }, + { + "type": "VText", + "range": [ + 170, + 171 + ], + "loc": { + "start": { + "line": 13, + "column": 9 + }, + "end": { + "line": 14, + "column": 0 + } + }, + "value": "\n" + } + ], + "endTag": { + "type": "VEndTag", + "range": [ + 171, + 182 + ], + "loc": { + "start": { + "line": 14, + "column": 0 + }, + "end": { + "line": 14, + "column": 11 + } + } + }, + "variables": [], + "tokens": [ + { + "type": "HTMLTagOpen", + "range": [ + 0, + 9 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 9 + } + }, + "value": "template" + }, + { + "type": "HTMLTagClose", + "range": [ + 9, + 10 + ], + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 10, + 13 + ], + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 2, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "HTMLTagOpen", + "range": [ + 13, + 17 + ], + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 6 + } + }, + "value": "div" + }, + { + "type": "Punctuator", + "range": [ + 22, + 23 + ], + "loc": { + "start": { + "column": 4, + "line": 3 + }, + "end": { + "column": 5, + "line": 3 + } + }, + "value": "@" + }, + { + "type": "HTMLIdentifier", + "range": [ + 23, + 28 + ], + "loc": { + "start": { + "column": 5, + "line": 3 + }, + "end": { + "column": 10, + "line": 3 + } + }, + "value": "click" + }, + { + "type": "HTMLAssociation", + "range": [ + 28, + 29 + ], + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 11 + } + }, + "value": "" + }, + { + "type": "Punctuator", + "range": [ + 29, + 30 + ], + "loc": { + "start": { + "line": 3, + "column": 11 + }, + "end": { + "line": 3, + "column": 12 + } + }, + "value": "\"" + }, + { + "type": "Identifier", + "value": "a", + "start": 30, + "end": 31, + "loc": { + "start": { + "line": 3, + "column": 12 + }, + "end": { + "line": 3, + "column": 13 + } + }, + "range": [ + 30, + 31 + ] + }, + { + "type": "Punctuator", + "value": "=", + "start": 31, + "end": 32, + "loc": { + "start": { + "line": 3, + "column": 13 + }, + "end": { + "line": 3, + "column": 14 + } + }, + "range": [ + 31, + 32 + ] + }, + { + "type": "Identifier", + "value": "b", + "start": 32, + "end": 33, + "loc": { + "start": { + "line": 3, + "column": 14 + }, + "end": { + "line": 3, + "column": 15 + } + }, + "range": [ + 32, + 33 + ] + }, + { + "type": "Punctuator", + "range": [ + 33, + 34 + ], + "loc": { + "start": { + "line": 3, + "column": 15 + }, + "end": { + "line": 3, + "column": 16 + } + }, + "value": "\"" + }, + { + "type": "HTMLTagClose", + "range": [ + 37, + 38 + ], + "loc": { + "start": { + "line": 4, + "column": 2 + }, + "end": { + "line": 4, + "column": 3 + } + }, + "value": "" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 38, + 43 + ], + "loc": { + "start": { + "line": 4, + "column": 3 + }, + "end": { + "line": 4, + "column": 8 + } + }, + "value": "div" + }, + { + "type": "HTMLTagClose", + "range": [ + 43, + 44 + ], + "loc": { + "start": { + "line": 4, + "column": 8 + }, + "end": { + "line": 4, + "column": 9 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 44, + 47 + ], + "loc": { + "start": { + "line": 4, + "column": 9 + }, + "end": { + "line": 5, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "HTMLTagOpen", + "range": [ + 47, + 51 + ], + "loc": { + "start": { + "line": 5, + "column": 2 + }, + "end": { + "line": 5, + "column": 6 + } + }, + "value": "div" + }, + { + "type": "Punctuator", + "range": [ + 56, + 57 + ], + "loc": { + "start": { + "column": 4, + "line": 6 + }, + "end": { + "column": 5, + "line": 6 + } + }, + "value": ":" + }, + { + "type": "HTMLIdentifier", + "range": [ + 57, + 67 + ], + "loc": { + "start": { + "column": 5, + "line": 6 + }, + "end": { + "column": 15, + "line": 6 + } + }, + "value": "data-click" + }, + { + "type": "HTMLAssociation", + "range": [ + 67, + 68 + ], + "loc": { + "start": { + "line": 6, + "column": 15 + }, + "end": { + "line": 6, + "column": 16 + } + }, + "value": "" + }, + { + "type": "Punctuator", + "range": [ + 68, + 69 + ], + "loc": { + "start": { + "line": 6, + "column": 16 + }, + "end": { + "line": 6, + "column": 17 + } + }, + "value": "\"" + }, + { + "type": "Identifier", + "value": "a", + "start": 69, + "end": 70, + "loc": { + "start": { + "line": 6, + "column": 17 + }, + "end": { + "line": 6, + "column": 18 + } + }, + "range": [ + 69, + 70 + ] + }, + { + "type": "Punctuator", + "value": "=", + "start": 70, + "end": 71, + "loc": { + "start": { + "line": 6, + "column": 18 + }, + "end": { + "line": 6, + "column": 19 + } + }, + "range": [ + 70, + 71 + ] + }, + { + "type": "Identifier", + "value": "b", + "start": 71, + "end": 72, + "loc": { + "start": { + "line": 6, + "column": 19 + }, + "end": { + "line": 6, + "column": 20 + } + }, + "range": [ + 71, + 72 + ] + }, + { + "type": "Punctuator", + "range": [ + 72, + 73 + ], + "loc": { + "start": { + "line": 6, + "column": 20 + }, + "end": { + "line": 6, + "column": 21 + } + }, + "value": "\"" + }, + { + "type": "HTMLTagClose", + "range": [ + 76, + 77 + ], + "loc": { + "start": { + "line": 7, + "column": 2 + }, + "end": { + "line": 7, + "column": 3 + } + }, + "value": "" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 77, + 82 + ], + "loc": { + "start": { + "line": 7, + "column": 3 + }, + "end": { + "line": 7, + "column": 8 + } + }, + "value": "div" + }, + { + "type": "HTMLTagClose", + "range": [ + 82, + 83 + ], + "loc": { + "start": { + "line": 7, + "column": 8 + }, + "end": { + "line": 7, + "column": 9 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 83, + 86 + ], + "loc": { + "start": { + "line": 7, + "column": 9 + }, + "end": { + "line": 8, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "HTMLTagOpen", + "range": [ + 86, + 90 + ], + "loc": { + "start": { + "line": 8, + "column": 2 + }, + "end": { + "line": 8, + "column": 6 + } + }, + "value": "div" + }, + { + "type": "Punctuator", + "range": [ + 95, + 96 + ], + "loc": { + "start": { + "column": 4, + "line": 9 + }, + "end": { + "column": 5, + "line": 9 + } + }, + "value": ":" + }, + { + "type": "HTMLIdentifier", + "range": [ + 96, + 104 + ], + "loc": { + "start": { + "column": 5, + "line": 9 + }, + "end": { + "column": 13, + "line": 9 + } + }, + "value": "data-foo" + }, + { + "type": "HTMLAssociation", + "range": [ + 104, + 105 + ], + "loc": { + "start": { + "line": 9, + "column": 13 + }, + "end": { + "line": 9, + "column": 14 + } + }, + "value": "" + }, + { + "type": "Punctuator", + "range": [ + 105, + 106 + ], + "loc": { + "start": { + "line": 9, + "column": 14 + }, + "end": { + "line": 9, + "column": 15 + } + }, + "value": "\"" + }, + { + "type": "Identifier", + "value": "c", + "start": 106, + "end": 107, + "loc": { + "start": { + "line": 9, + "column": 15 + }, + "end": { + "line": 9, + "column": 16 + } + }, + "range": [ + 106, + 107 + ] + }, + { + "type": "Punctuator", + "value": "&&", + "start": 107, + "end": 109, + "loc": { + "start": { + "line": 9, + "column": 16 + }, + "end": { + "line": 9, + "column": 26 + } + }, + "range": [ + 107, + 117 + ] + }, + { + "type": "Identifier", + "value": "d", + "start": 117, + "end": 118, + "loc": { + "start": { + "line": 9, + "column": 26 + }, + "end": { + "line": 9, + "column": 27 + } + }, + "range": [ + 117, + 118 + ] + }, + { + "type": "Punctuator", + "range": [ + 118, + 119 + ], + "loc": { + "start": { + "line": 9, + "column": 27 + }, + "end": { + "line": 9, + "column": 28 + } + }, + "value": "\"" + }, + { + "type": "HTMLTagClose", + "range": [ + 122, + 123 + ], + "loc": { + "start": { + "line": 10, + "column": 2 + }, + "end": { + "line": 10, + "column": 3 + } + }, + "value": "" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 123, + 128 + ], + "loc": { + "start": { + "line": 10, + "column": 3 + }, + "end": { + "line": 10, + "column": 8 + } + }, + "value": "div" + }, + { + "type": "HTMLTagClose", + "range": [ + 128, + 129 + ], + "loc": { + "start": { + "line": 10, + "column": 8 + }, + "end": { + "line": 10, + "column": 9 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 129, + 132 + ], + "loc": { + "start": { + "line": 10, + "column": 9 + }, + "end": { + "line": 11, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "HTMLTagOpen", + "range": [ + 132, + 136 + ], + "loc": { + "start": { + "line": 11, + "column": 2 + }, + "end": { + "line": 11, + "column": 6 + } + }, + "value": "div" + }, + { + "type": "Punctuator", + "range": [ + 141, + 142 + ], + "loc": { + "start": { + "column": 4, + "line": 12 + }, + "end": { + "column": 5, + "line": 12 + } + }, + "value": "@" + }, + { + "type": "HTMLIdentifier", + "range": [ + 142, + 145 + ], + "loc": { + "start": { + "column": 5, + "line": 12 + }, + "end": { + "column": 8, + "line": 12 + } + }, + "value": "foo" + }, + { + "type": "HTMLAssociation", + "range": [ + 145, + 146 + ], + "loc": { + "start": { + "line": 12, + "column": 8 + }, + "end": { + "line": 12, + "column": 9 + } + }, + "value": "" + }, + { + "type": "Punctuator", + "range": [ + 146, + 147 + ], + "loc": { + "start": { + "line": 12, + "column": 9 + }, + "end": { + "line": 12, + "column": 10 + } + }, + "value": "\"" + }, + { + "type": "Identifier", + "value": "c", + "start": 147, + "end": 148, + "loc": { + "start": { + "line": 12, + "column": 10 + }, + "end": { + "line": 12, + "column": 11 + } + }, + "range": [ + 147, + 148 + ] + }, + { + "type": "Punctuator", + "value": "&&", + "start": 148, + "end": 150, + "loc": { + "start": { + "line": 12, + "column": 11 + }, + "end": { + "line": 12, + "column": 21 + } + }, + "range": [ + 148, + 158 + ] + }, + { + "type": "Identifier", + "value": "d", + "start": 158, + "end": 159, + "loc": { + "start": { + "line": 12, + "column": 21 + }, + "end": { + "line": 12, + "column": 22 + } + }, + "range": [ + 158, + 159 + ] + }, + { + "type": "Punctuator", + "range": [ + 159, + 160 + ], + "loc": { + "start": { + "line": 12, + "column": 22 + }, + "end": { + "line": 12, + "column": 23 + } + }, + "value": "\"" + }, + { + "type": "HTMLTagClose", + "range": [ + 163, + 164 + ], + "loc": { + "start": { + "line": 13, + "column": 2 + }, + "end": { + "line": 13, + "column": 3 + } + }, + "value": "" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 164, + 169 + ], + "loc": { + "start": { + "line": 13, + "column": 3 + }, + "end": { + "line": 13, + "column": 8 + } + }, + "value": "div" + }, + { + "type": "HTMLTagClose", + "range": [ + 169, + 170 + ], + "loc": { + "start": { + "line": 13, + "column": 8 + }, + "end": { + "line": 13, + "column": 9 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 170, + 171 + ], + "loc": { + "start": { + "line": 13, + "column": 9 + }, + "end": { + "line": 14, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 171, + 181 + ], + "loc": { + "start": { + "line": 14, + "column": 0 + }, + "end": { + "line": 14, + "column": 10 + } + }, + "value": "template" + }, + { + "type": "HTMLTagClose", + "range": [ + 181, + 182 + ], + "loc": { + "start": { + "line": 14, + "column": 10 + }, + "end": { + "line": 14, + "column": 11 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 182, + 183 + ], + "loc": { + "start": { + "line": 14, + "column": 11 + }, + "end": { + "line": 15, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLTagOpen", + "range": [ + 183, + 190 + ], + "loc": { + "start": { + "line": 15, + "column": 0 + }, + "end": { + "line": 15, + "column": 7 + } + }, + "value": "script" + }, + { + "type": "HTMLTagClose", + "range": [ + 190, + 191 + ], + "loc": { + "start": { + "line": 15, + "column": 7 + }, + "end": { + "line": 15, + "column": 8 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 191, + 192 + ], + "loc": { + "start": { + "line": 15, + "column": 8 + }, + "end": { + "line": 16, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLRawText", + "range": [ + 192, + 195 + ], + "loc": { + "start": { + "line": 16, + "column": 0 + }, + "end": { + "line": 16, + "column": 3 + } + }, + "value": "var" + }, + { + "type": "HTMLWhitespace", + "range": [ + 195, + 196 + ], + "loc": { + "start": { + "line": 16, + "column": 3 + }, + "end": { + "line": 16, + "column": 4 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 196, + 197 + ], + "loc": { + "start": { + "line": 16, + "column": 4 + }, + "end": { + "line": 16, + "column": 5 + } + }, + "value": "a" + }, + { + "type": "HTMLWhitespace", + "range": [ + 197, + 198 + ], + "loc": { + "start": { + "line": 16, + "column": 5 + }, + "end": { + "line": 16, + "column": 6 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 198, + 199 + ], + "loc": { + "start": { + "line": 16, + "column": 6 + }, + "end": { + "line": 16, + "column": 7 + } + }, + "value": "=" + }, + { + "type": "HTMLWhitespace", + "range": [ + 199, + 200 + ], + "loc": { + "start": { + "line": 16, + "column": 7 + }, + "end": { + "line": 16, + "column": 8 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 200, + 203 + ], + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 11 + } + }, + "value": "foo" + }, + { + "type": "HTMLWhitespace", + "range": [ + 203, + 204 + ], + "loc": { + "start": { + "line": 16, + "column": 11 + }, + "end": { + "line": 17, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 204, + 212 + ], + "loc": { + "start": { + "line": 17, + "column": 0 + }, + "end": { + "line": 17, + "column": 8 + } + }, + "value": "script" + }, + { + "type": "HTMLTagClose", + "range": [ + 212, + 213 + ], + "loc": { + "start": { + "line": 17, + "column": 8 + }, + "end": { + "line": 17, + "column": 9 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 213, + 214 + ], + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 18, + "column": 0 + } + }, + "value": "\n" + } + ], + "comments": [], + "errors": [] + } +} \ No newline at end of file diff --git a/test/fixtures/ast/end-of-line01/source.vue b/test/fixtures/ast/end-of-line01/source.vue new file mode 100644 index 00000000..4f0ac53a --- /dev/null +++ b/test/fixtures/ast/end-of-line01/source.vue @@ -0,0 +1,17 @@ + + diff --git a/test/fixtures/ast/end-of-line01/token-ranges.json b/test/fixtures/ast/end-of-line01/token-ranges.json new file mode 100644 index 00000000..6b841cd8 --- /dev/null +++ b/test/fixtures/ast/end-of-line01/token-ranges.json @@ -0,0 +1,80 @@ +[ + "", + "", + "\n ", + "", + "", + "\n ", + "", + "", + "\n ", + "", + "", + "\n ", + "", + "", + "\n", + "", + "\n", + "", + "\n", + "var", + " ", + "a", + " ", + "=", + " ", + "foo", + "\n", + "", + "\n" +] \ No newline at end of file diff --git a/test/fixtures/ast/end-of-line01/tree.json b/test/fixtures/ast/end-of-line01/tree.json new file mode 100644 index 00000000..a68b9b28 --- /dev/null +++ b/test/fixtures/ast/end-of-line01/tree.json @@ -0,0 +1,311 @@ +[ + { + "type": "VElement", + "text": "", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + } + ] + } +] \ No newline at end of file diff --git a/test/fixtures/ast/end-of-line02/ast.json b/test/fixtures/ast/end-of-line02/ast.json new file mode 100644 index 00000000..86473657 --- /dev/null +++ b/test/fixtures/ast/end-of-line02/ast.json @@ -0,0 +1,2803 @@ +{ + "type": "Program", + "start": 8, + "end": 21, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 11 + } + }, + "range": [ + 9, + 20 + ], + "body": [ + { + "type": "VariableDeclaration", + "start": 9, + "end": 20, + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 11 + } + }, + "range": [ + 9, + 20 + ], + "declarations": [ + { + "type": "VariableDeclarator", + "start": 13, + "end": 20, + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 11 + } + }, + "range": [ + 13, + 20 + ], + "id": { + "type": "Identifier", + "start": 13, + "end": 14, + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 5 + } + }, + "range": [ + 13, + 14 + ], + "name": "a" + }, + "init": { + "type": "Identifier", + "start": 17, + "end": 20, + "loc": { + "start": { + "line": 2, + "column": 8 + }, + "end": { + "line": 2, + "column": 11 + } + }, + "range": [ + 17, + 20 + ], + "name": "foo" + } + } + ], + "kind": "var" + } + ], + "sourceType": "script", + "comments": [], + "tokens": [ + { + "type": "Punctuator", + "range": [ + 0, + 8 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 8 + } + }, + "value": "" + } + ], + "templateBody": { + "type": "VElement", + "range": [ + 31, + 213 + ], + "loc": { + "start": { + "line": 4, + "column": 0 + }, + "end": { + "line": 17, + "column": 11 + } + }, + "name": "template", + "rawName": "template", + "namespace": "http://www.w3.org/1999/xhtml", + "startTag": { + "type": "VStartTag", + "range": [ + 31, + 41 + ], + "loc": { + "start": { + "line": 4, + "column": 0 + }, + "end": { + "line": 4, + "column": 10 + } + }, + "selfClosing": false, + "attributes": [] + }, + "children": [ + { + "type": "VText", + "range": [ + 41, + 44 + ], + "loc": { + "start": { + "line": 4, + "column": 10 + }, + "end": { + "line": 5, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "VElement", + "range": [ + 44, + 75 + ], + "loc": { + "start": { + "line": 5, + "column": 2 + }, + "end": { + "line": 7, + "column": 9 + } + }, + "name": "div", + "rawName": "div", + "namespace": "http://www.w3.org/1999/xhtml", + "startTag": { + "type": "VStartTag", + "range": [ + 44, + 69 + ], + "loc": { + "start": { + "line": 5, + "column": 2 + }, + "end": { + "line": 7, + "column": 3 + } + }, + "selfClosing": false, + "attributes": [ + { + "type": "VAttribute", + "range": [ + 53, + 65 + ], + "loc": { + "start": { + "line": 6, + "column": 4 + }, + "end": { + "line": 6, + "column": 16 + } + }, + "directive": true, + "key": { + "type": "VDirectiveKey", + "range": [ + 53, + 59 + ], + "loc": { + "start": { + "line": 6, + "column": 4 + }, + "end": { + "line": 6, + "column": 10 + } + }, + "name": { + "type": "VIdentifier", + "range": [ + 53, + 54 + ], + "loc": { + "start": { + "column": 4, + "line": 6 + }, + "end": { + "column": 5, + "line": 6 + } + }, + "name": "on", + "rawName": "@" + }, + "argument": { + "type": "VIdentifier", + "range": [ + 54, + 59 + ], + "loc": { + "start": { + "column": 5, + "line": 6 + }, + "end": { + "column": 10, + "line": 6 + } + }, + "name": "click", + "rawName": "click" + }, + "modifiers": [] + }, + "value": { + "type": "VExpressionContainer", + "range": [ + 60, + 65 + ], + "loc": { + "start": { + "line": 6, + "column": 11 + }, + "end": { + "line": 6, + "column": 16 + } + }, + "expression": { + "type": "VOnExpression", + "range": [ + 61, + 64 + ], + "loc": { + "start": { + "line": 6, + "column": 12 + }, + "end": { + "line": 6, + "column": 15 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 61, + "end": 64, + "loc": { + "start": { + "line": 6, + "column": 12 + }, + "end": { + "line": 6, + "column": 15 + } + }, + "range": [ + 61, + 64 + ], + "expression": { + "type": "AssignmentExpression", + "start": 61, + "end": 64, + "loc": { + "start": { + "line": 6, + "column": 12 + }, + "end": { + "line": 6, + "column": 15 + } + }, + "range": [ + 61, + 64 + ], + "operator": "=", + "left": { + "type": "Identifier", + "start": 61, + "end": 62, + "loc": { + "start": { + "line": 6, + "column": 12 + }, + "end": { + "line": 6, + "column": 13 + } + }, + "range": [ + 61, + 62 + ], + "name": "a" + }, + "right": { + "type": "Identifier", + "start": 63, + "end": 64, + "loc": { + "start": { + "line": 6, + "column": 14 + }, + "end": { + "line": 6, + "column": 15 + } + }, + "range": [ + 63, + 64 + ], + "name": "b" + } + } + } + ] + }, + "references": [ + { + "id": { + "type": "Identifier", + "start": 61, + "end": 62, + "loc": { + "start": { + "line": 6, + "column": 12 + }, + "end": { + "line": 6, + "column": 13 + } + }, + "range": [ + 61, + 62 + ], + "name": "a" + }, + "mode": "w" + }, + { + "id": { + "type": "Identifier", + "start": 63, + "end": 64, + "loc": { + "start": { + "line": 6, + "column": 14 + }, + "end": { + "line": 6, + "column": 15 + } + }, + "range": [ + 63, + 64 + ], + "name": "b" + }, + "mode": "r" + } + ] + } + } + ] + }, + "children": [], + "endTag": { + "type": "VEndTag", + "range": [ + 69, + 75 + ], + "loc": { + "start": { + "line": 7, + "column": 3 + }, + "end": { + "line": 7, + "column": 9 + } + } + }, + "variables": [] + }, + { + "type": "VText", + "range": [ + 75, + 78 + ], + "loc": { + "start": { + "line": 7, + "column": 9 + }, + "end": { + "line": 8, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "VElement", + "range": [ + 78, + 121 + ], + "loc": { + "start": { + "line": 8, + "column": 2 + }, + "end": { + "line": 10, + "column": 9 + } + }, + "name": "div", + "rawName": "div", + "namespace": "http://www.w3.org/1999/xhtml", + "startTag": { + "type": "VStartTag", + "range": [ + 78, + 115 + ], + "loc": { + "start": { + "line": 8, + "column": 2 + }, + "end": { + "line": 10, + "column": 3 + } + }, + "selfClosing": false, + "attributes": [ + { + "type": "VAttribute", + "range": [ + 87, + 111 + ], + "loc": { + "start": { + "line": 9, + "column": 4 + }, + "end": { + "line": 9, + "column": 28 + } + }, + "directive": true, + "key": { + "type": "VDirectiveKey", + "range": [ + 87, + 96 + ], + "loc": { + "start": { + "line": 9, + "column": 4 + }, + "end": { + "line": 9, + "column": 13 + } + }, + "name": { + "type": "VIdentifier", + "range": [ + 87, + 88 + ], + "loc": { + "start": { + "column": 4, + "line": 9 + }, + "end": { + "column": 5, + "line": 9 + } + }, + "name": "bind", + "rawName": ":" + }, + "argument": { + "type": "VIdentifier", + "range": [ + 88, + 96 + ], + "loc": { + "start": { + "column": 5, + "line": 9 + }, + "end": { + "column": 13, + "line": 9 + } + }, + "name": "data-foo", + "rawName": "data-foo" + }, + "modifiers": [] + }, + "value": { + "type": "VExpressionContainer", + "range": [ + 97, + 111 + ], + "loc": { + "start": { + "line": 9, + "column": 14 + }, + "end": { + "line": 9, + "column": 28 + } + }, + "expression": { + "type": "LogicalExpression", + "start": 98, + "end": 102, + "loc": { + "start": { + "line": 9, + "column": 15 + }, + "end": { + "line": 9, + "column": 27 + } + }, + "range": [ + 98, + 110 + ], + "left": { + "type": "Identifier", + "start": 98, + "end": 99, + "loc": { + "start": { + "line": 9, + "column": 15 + }, + "end": { + "line": 9, + "column": 16 + } + }, + "range": [ + 98, + 99 + ], + "name": "c" + }, + "operator": "&&", + "right": { + "type": "Identifier", + "start": 109, + "end": 110, + "loc": { + "start": { + "line": 9, + "column": 26 + }, + "end": { + "line": 9, + "column": 27 + } + }, + "range": [ + 109, + 110 + ], + "name": "d" + } + }, + "references": [ + { + "id": { + "type": "Identifier", + "start": 98, + "end": 99, + "loc": { + "start": { + "line": 9, + "column": 15 + }, + "end": { + "line": 9, + "column": 16 + } + }, + "range": [ + 98, + 99 + ], + "name": "c" + }, + "mode": "r" + }, + { + "id": { + "type": "Identifier", + "start": 109, + "end": 110, + "loc": { + "start": { + "line": 9, + "column": 26 + }, + "end": { + "line": 9, + "column": 27 + } + }, + "range": [ + 109, + 110 + ], + "name": "d" + }, + "mode": "r" + } + ] + } + } + ] + }, + "children": [], + "endTag": { + "type": "VEndTag", + "range": [ + 115, + 121 + ], + "loc": { + "start": { + "line": 10, + "column": 3 + }, + "end": { + "line": 10, + "column": 9 + } + } + }, + "variables": [] + }, + { + "type": "VText", + "range": [ + 121, + 124 + ], + "loc": { + "start": { + "line": 10, + "column": 9 + }, + "end": { + "line": 11, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "VElement", + "range": [ + 124, + 160 + ], + "loc": { + "start": { + "line": 11, + "column": 2 + }, + "end": { + "line": 13, + "column": 9 + } + }, + "name": "div", + "rawName": "div", + "namespace": "http://www.w3.org/1999/xhtml", + "startTag": { + "type": "VStartTag", + "range": [ + 124, + 154 + ], + "loc": { + "start": { + "line": 11, + "column": 2 + }, + "end": { + "line": 13, + "column": 3 + } + }, + "selfClosing": false, + "attributes": [ + { + "type": "VAttribute", + "range": [ + 133, + 150 + ], + "loc": { + "start": { + "line": 12, + "column": 4 + }, + "end": { + "line": 12, + "column": 21 + } + }, + "directive": true, + "key": { + "type": "VDirectiveKey", + "range": [ + 133, + 144 + ], + "loc": { + "start": { + "line": 12, + "column": 4 + }, + "end": { + "line": 12, + "column": 15 + } + }, + "name": { + "type": "VIdentifier", + "range": [ + 133, + 134 + ], + "loc": { + "start": { + "column": 4, + "line": 12 + }, + "end": { + "column": 5, + "line": 12 + } + }, + "name": "bind", + "rawName": ":" + }, + "argument": { + "type": "VIdentifier", + "range": [ + 134, + 144 + ], + "loc": { + "start": { + "column": 5, + "line": 12 + }, + "end": { + "column": 15, + "line": 12 + } + }, + "name": "data-click", + "rawName": "data-click" + }, + "modifiers": [] + }, + "value": { + "type": "VExpressionContainer", + "range": [ + 145, + 150 + ], + "loc": { + "start": { + "line": 12, + "column": 16 + }, + "end": { + "line": 12, + "column": 21 + } + }, + "expression": { + "type": "AssignmentExpression", + "start": 146, + "end": 149, + "loc": { + "start": { + "line": 12, + "column": 17 + }, + "end": { + "line": 12, + "column": 20 + } + }, + "range": [ + 146, + 149 + ], + "operator": "=", + "left": { + "type": "Identifier", + "start": 146, + "end": 147, + "loc": { + "start": { + "line": 12, + "column": 17 + }, + "end": { + "line": 12, + "column": 18 + } + }, + "range": [ + 146, + 147 + ], + "name": "a" + }, + "right": { + "type": "Identifier", + "start": 148, + "end": 149, + "loc": { + "start": { + "line": 12, + "column": 19 + }, + "end": { + "line": 12, + "column": 20 + } + }, + "range": [ + 148, + 149 + ], + "name": "b" + } + }, + "references": [ + { + "id": { + "type": "Identifier", + "start": 146, + "end": 147, + "loc": { + "start": { + "line": 12, + "column": 17 + }, + "end": { + "line": 12, + "column": 18 + } + }, + "range": [ + 146, + 147 + ], + "name": "a" + }, + "mode": "w" + }, + { + "id": { + "type": "Identifier", + "start": 148, + "end": 149, + "loc": { + "start": { + "line": 12, + "column": 19 + }, + "end": { + "line": 12, + "column": 20 + } + }, + "range": [ + 148, + 149 + ], + "name": "b" + }, + "mode": "r" + } + ] + } + } + ] + }, + "children": [], + "endTag": { + "type": "VEndTag", + "range": [ + 154, + 160 + ], + "loc": { + "start": { + "line": 13, + "column": 3 + }, + "end": { + "line": 13, + "column": 9 + } + } + }, + "variables": [] + }, + { + "type": "VText", + "range": [ + 160, + 163 + ], + "loc": { + "start": { + "line": 13, + "column": 9 + }, + "end": { + "line": 14, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "VElement", + "range": [ + 163, + 201 + ], + "loc": { + "start": { + "line": 14, + "column": 2 + }, + "end": { + "line": 16, + "column": 9 + } + }, + "name": "div", + "rawName": "div", + "namespace": "http://www.w3.org/1999/xhtml", + "startTag": { + "type": "VStartTag", + "range": [ + 163, + 195 + ], + "loc": { + "start": { + "line": 14, + "column": 2 + }, + "end": { + "line": 16, + "column": 3 + } + }, + "selfClosing": false, + "attributes": [ + { + "type": "VAttribute", + "range": [ + 172, + 191 + ], + "loc": { + "start": { + "line": 15, + "column": 4 + }, + "end": { + "line": 15, + "column": 23 + } + }, + "directive": true, + "key": { + "type": "VDirectiveKey", + "range": [ + 172, + 176 + ], + "loc": { + "start": { + "line": 15, + "column": 4 + }, + "end": { + "line": 15, + "column": 8 + } + }, + "name": { + "type": "VIdentifier", + "range": [ + 172, + 173 + ], + "loc": { + "start": { + "column": 4, + "line": 15 + }, + "end": { + "column": 5, + "line": 15 + } + }, + "name": "on", + "rawName": "@" + }, + "argument": { + "type": "VIdentifier", + "range": [ + 173, + 176 + ], + "loc": { + "start": { + "column": 5, + "line": 15 + }, + "end": { + "column": 8, + "line": 15 + } + }, + "name": "foo", + "rawName": "foo" + }, + "modifiers": [] + }, + "value": { + "type": "VExpressionContainer", + "range": [ + 177, + 191 + ], + "loc": { + "start": { + "line": 15, + "column": 9 + }, + "end": { + "line": 15, + "column": 23 + } + }, + "expression": { + "type": "VOnExpression", + "range": [ + 178, + 190 + ], + "loc": { + "start": { + "line": 15, + "column": 10 + }, + "end": { + "line": 15, + "column": 22 + } + }, + "body": [ + { + "type": "ExpressionStatement", + "start": 178, + "end": 182, + "loc": { + "start": { + "line": 15, + "column": 10 + }, + "end": { + "line": 15, + "column": 22 + } + }, + "range": [ + 178, + 190 + ], + "expression": { + "type": "LogicalExpression", + "start": 178, + "end": 182, + "loc": { + "start": { + "line": 15, + "column": 10 + }, + "end": { + "line": 15, + "column": 22 + } + }, + "range": [ + 178, + 190 + ], + "left": { + "type": "Identifier", + "start": 178, + "end": 179, + "loc": { + "start": { + "line": 15, + "column": 10 + }, + "end": { + "line": 15, + "column": 11 + } + }, + "range": [ + 178, + 179 + ], + "name": "c" + }, + "operator": "&&", + "right": { + "type": "Identifier", + "start": 189, + "end": 190, + "loc": { + "start": { + "line": 15, + "column": 21 + }, + "end": { + "line": 15, + "column": 22 + } + }, + "range": [ + 189, + 190 + ], + "name": "d" + } + } + } + ] + }, + "references": [ + { + "id": { + "type": "Identifier", + "start": 178, + "end": 179, + "loc": { + "start": { + "line": 15, + "column": 10 + }, + "end": { + "line": 15, + "column": 11 + } + }, + "range": [ + 178, + 179 + ], + "name": "c" + }, + "mode": "r" + }, + { + "id": { + "type": "Identifier", + "start": 189, + "end": 190, + "loc": { + "start": { + "line": 15, + "column": 21 + }, + "end": { + "line": 15, + "column": 22 + } + }, + "range": [ + 189, + 190 + ], + "name": "d" + }, + "mode": "r" + } + ] + } + } + ] + }, + "children": [], + "endTag": { + "type": "VEndTag", + "range": [ + 195, + 201 + ], + "loc": { + "start": { + "line": 16, + "column": 3 + }, + "end": { + "line": 16, + "column": 9 + } + } + }, + "variables": [] + }, + { + "type": "VText", + "range": [ + 201, + 202 + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 17, + "column": 0 + } + }, + "value": "\n" + } + ], + "endTag": { + "type": "VEndTag", + "range": [ + 202, + 213 + ], + "loc": { + "start": { + "line": 17, + "column": 0 + }, + "end": { + "line": 17, + "column": 11 + } + } + }, + "variables": [], + "tokens": [ + { + "type": "HTMLTagOpen", + "range": [ + 0, + 7 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 7 + } + }, + "value": "script" + }, + { + "type": "HTMLTagClose", + "range": [ + 7, + 8 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 8 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 8, + 9 + ], + "loc": { + "start": { + "line": 1, + "column": 8 + }, + "end": { + "line": 2, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLRawText", + "range": [ + 9, + 12 + ], + "loc": { + "start": { + "line": 2, + "column": 0 + }, + "end": { + "line": 2, + "column": 3 + } + }, + "value": "var" + }, + { + "type": "HTMLWhitespace", + "range": [ + 12, + 13 + ], + "loc": { + "start": { + "line": 2, + "column": 3 + }, + "end": { + "line": 2, + "column": 4 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 13, + 14 + ], + "loc": { + "start": { + "line": 2, + "column": 4 + }, + "end": { + "line": 2, + "column": 5 + } + }, + "value": "a" + }, + { + "type": "HTMLWhitespace", + "range": [ + 14, + 15 + ], + "loc": { + "start": { + "line": 2, + "column": 5 + }, + "end": { + "line": 2, + "column": 6 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 15, + 16 + ], + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 7 + } + }, + "value": "=" + }, + { + "type": "HTMLWhitespace", + "range": [ + 16, + 17 + ], + "loc": { + "start": { + "line": 2, + "column": 7 + }, + "end": { + "line": 2, + "column": 8 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 17, + 20 + ], + "loc": { + "start": { + "line": 2, + "column": 8 + }, + "end": { + "line": 2, + "column": 11 + } + }, + "value": "foo" + }, + { + "type": "HTMLWhitespace", + "range": [ + 20, + 21 + ], + "loc": { + "start": { + "line": 2, + "column": 11 + }, + "end": { + "line": 3, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 21, + 29 + ], + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 8 + } + }, + "value": "script" + }, + { + "type": "HTMLTagClose", + "range": [ + 29, + 30 + ], + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 9 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 30, + 31 + ], + "loc": { + "start": { + "line": 3, + "column": 9 + }, + "end": { + "line": 4, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLTagOpen", + "range": [ + 31, + 40 + ], + "loc": { + "start": { + "line": 4, + "column": 0 + }, + "end": { + "line": 4, + "column": 9 + } + }, + "value": "template" + }, + { + "type": "HTMLTagClose", + "range": [ + 40, + 41 + ], + "loc": { + "start": { + "line": 4, + "column": 9 + }, + "end": { + "line": 4, + "column": 10 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 41, + 44 + ], + "loc": { + "start": { + "line": 4, + "column": 10 + }, + "end": { + "line": 5, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "HTMLTagOpen", + "range": [ + 44, + 48 + ], + "loc": { + "start": { + "line": 5, + "column": 2 + }, + "end": { + "line": 5, + "column": 6 + } + }, + "value": "div" + }, + { + "type": "Punctuator", + "range": [ + 53, + 54 + ], + "loc": { + "start": { + "column": 4, + "line": 6 + }, + "end": { + "column": 5, + "line": 6 + } + }, + "value": "@" + }, + { + "type": "HTMLIdentifier", + "range": [ + 54, + 59 + ], + "loc": { + "start": { + "column": 5, + "line": 6 + }, + "end": { + "column": 10, + "line": 6 + } + }, + "value": "click" + }, + { + "type": "HTMLAssociation", + "range": [ + 59, + 60 + ], + "loc": { + "start": { + "line": 6, + "column": 10 + }, + "end": { + "line": 6, + "column": 11 + } + }, + "value": "" + }, + { + "type": "Punctuator", + "range": [ + 60, + 61 + ], + "loc": { + "start": { + "line": 6, + "column": 11 + }, + "end": { + "line": 6, + "column": 12 + } + }, + "value": "\"" + }, + { + "type": "Identifier", + "value": "a", + "start": 61, + "end": 62, + "loc": { + "start": { + "line": 6, + "column": 12 + }, + "end": { + "line": 6, + "column": 13 + } + }, + "range": [ + 61, + 62 + ] + }, + { + "type": "Punctuator", + "value": "=", + "start": 62, + "end": 63, + "loc": { + "start": { + "line": 6, + "column": 13 + }, + "end": { + "line": 6, + "column": 14 + } + }, + "range": [ + 62, + 63 + ] + }, + { + "type": "Identifier", + "value": "b", + "start": 63, + "end": 64, + "loc": { + "start": { + "line": 6, + "column": 14 + }, + "end": { + "line": 6, + "column": 15 + } + }, + "range": [ + 63, + 64 + ] + }, + { + "type": "Punctuator", + "range": [ + 64, + 65 + ], + "loc": { + "start": { + "line": 6, + "column": 15 + }, + "end": { + "line": 6, + "column": 16 + } + }, + "value": "\"" + }, + { + "type": "HTMLTagClose", + "range": [ + 68, + 69 + ], + "loc": { + "start": { + "line": 7, + "column": 2 + }, + "end": { + "line": 7, + "column": 3 + } + }, + "value": "" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 69, + 74 + ], + "loc": { + "start": { + "line": 7, + "column": 3 + }, + "end": { + "line": 7, + "column": 8 + } + }, + "value": "div" + }, + { + "type": "HTMLTagClose", + "range": [ + 74, + 75 + ], + "loc": { + "start": { + "line": 7, + "column": 8 + }, + "end": { + "line": 7, + "column": 9 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 75, + 78 + ], + "loc": { + "start": { + "line": 7, + "column": 9 + }, + "end": { + "line": 8, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "HTMLTagOpen", + "range": [ + 78, + 82 + ], + "loc": { + "start": { + "line": 8, + "column": 2 + }, + "end": { + "line": 8, + "column": 6 + } + }, + "value": "div" + }, + { + "type": "Punctuator", + "range": [ + 87, + 88 + ], + "loc": { + "start": { + "column": 4, + "line": 9 + }, + "end": { + "column": 5, + "line": 9 + } + }, + "value": ":" + }, + { + "type": "HTMLIdentifier", + "range": [ + 88, + 96 + ], + "loc": { + "start": { + "column": 5, + "line": 9 + }, + "end": { + "column": 13, + "line": 9 + } + }, + "value": "data-foo" + }, + { + "type": "HTMLAssociation", + "range": [ + 96, + 97 + ], + "loc": { + "start": { + "line": 9, + "column": 13 + }, + "end": { + "line": 9, + "column": 14 + } + }, + "value": "" + }, + { + "type": "Punctuator", + "range": [ + 97, + 98 + ], + "loc": { + "start": { + "line": 9, + "column": 14 + }, + "end": { + "line": 9, + "column": 15 + } + }, + "value": "\"" + }, + { + "type": "Identifier", + "value": "c", + "start": 98, + "end": 99, + "loc": { + "start": { + "line": 9, + "column": 15 + }, + "end": { + "line": 9, + "column": 16 + } + }, + "range": [ + 98, + 99 + ] + }, + { + "type": "Punctuator", + "value": "&&", + "start": 99, + "end": 101, + "loc": { + "start": { + "line": 9, + "column": 16 + }, + "end": { + "line": 9, + "column": 26 + } + }, + "range": [ + 99, + 109 + ] + }, + { + "type": "Identifier", + "value": "d", + "start": 109, + "end": 110, + "loc": { + "start": { + "line": 9, + "column": 26 + }, + "end": { + "line": 9, + "column": 27 + } + }, + "range": [ + 109, + 110 + ] + }, + { + "type": "Punctuator", + "range": [ + 110, + 111 + ], + "loc": { + "start": { + "line": 9, + "column": 27 + }, + "end": { + "line": 9, + "column": 28 + } + }, + "value": "\"" + }, + { + "type": "HTMLTagClose", + "range": [ + 114, + 115 + ], + "loc": { + "start": { + "line": 10, + "column": 2 + }, + "end": { + "line": 10, + "column": 3 + } + }, + "value": "" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 115, + 120 + ], + "loc": { + "start": { + "line": 10, + "column": 3 + }, + "end": { + "line": 10, + "column": 8 + } + }, + "value": "div" + }, + { + "type": "HTMLTagClose", + "range": [ + 120, + 121 + ], + "loc": { + "start": { + "line": 10, + "column": 8 + }, + "end": { + "line": 10, + "column": 9 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 121, + 124 + ], + "loc": { + "start": { + "line": 10, + "column": 9 + }, + "end": { + "line": 11, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "HTMLTagOpen", + "range": [ + 124, + 128 + ], + "loc": { + "start": { + "line": 11, + "column": 2 + }, + "end": { + "line": 11, + "column": 6 + } + }, + "value": "div" + }, + { + "type": "Punctuator", + "range": [ + 133, + 134 + ], + "loc": { + "start": { + "column": 4, + "line": 12 + }, + "end": { + "column": 5, + "line": 12 + } + }, + "value": ":" + }, + { + "type": "HTMLIdentifier", + "range": [ + 134, + 144 + ], + "loc": { + "start": { + "column": 5, + "line": 12 + }, + "end": { + "column": 15, + "line": 12 + } + }, + "value": "data-click" + }, + { + "type": "HTMLAssociation", + "range": [ + 144, + 145 + ], + "loc": { + "start": { + "line": 12, + "column": 15 + }, + "end": { + "line": 12, + "column": 16 + } + }, + "value": "" + }, + { + "type": "Punctuator", + "range": [ + 145, + 146 + ], + "loc": { + "start": { + "line": 12, + "column": 16 + }, + "end": { + "line": 12, + "column": 17 + } + }, + "value": "\"" + }, + { + "type": "Identifier", + "value": "a", + "start": 146, + "end": 147, + "loc": { + "start": { + "line": 12, + "column": 17 + }, + "end": { + "line": 12, + "column": 18 + } + }, + "range": [ + 146, + 147 + ] + }, + { + "type": "Punctuator", + "value": "=", + "start": 147, + "end": 148, + "loc": { + "start": { + "line": 12, + "column": 18 + }, + "end": { + "line": 12, + "column": 19 + } + }, + "range": [ + 147, + 148 + ] + }, + { + "type": "Identifier", + "value": "b", + "start": 148, + "end": 149, + "loc": { + "start": { + "line": 12, + "column": 19 + }, + "end": { + "line": 12, + "column": 20 + } + }, + "range": [ + 148, + 149 + ] + }, + { + "type": "Punctuator", + "range": [ + 149, + 150 + ], + "loc": { + "start": { + "line": 12, + "column": 20 + }, + "end": { + "line": 12, + "column": 21 + } + }, + "value": "\"" + }, + { + "type": "HTMLTagClose", + "range": [ + 153, + 154 + ], + "loc": { + "start": { + "line": 13, + "column": 2 + }, + "end": { + "line": 13, + "column": 3 + } + }, + "value": "" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 154, + 159 + ], + "loc": { + "start": { + "line": 13, + "column": 3 + }, + "end": { + "line": 13, + "column": 8 + } + }, + "value": "div" + }, + { + "type": "HTMLTagClose", + "range": [ + 159, + 160 + ], + "loc": { + "start": { + "line": 13, + "column": 8 + }, + "end": { + "line": 13, + "column": 9 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 160, + 163 + ], + "loc": { + "start": { + "line": 13, + "column": 9 + }, + "end": { + "line": 14, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "HTMLTagOpen", + "range": [ + 163, + 167 + ], + "loc": { + "start": { + "line": 14, + "column": 2 + }, + "end": { + "line": 14, + "column": 6 + } + }, + "value": "div" + }, + { + "type": "Punctuator", + "range": [ + 172, + 173 + ], + "loc": { + "start": { + "column": 4, + "line": 15 + }, + "end": { + "column": 5, + "line": 15 + } + }, + "value": "@" + }, + { + "type": "HTMLIdentifier", + "range": [ + 173, + 176 + ], + "loc": { + "start": { + "column": 5, + "line": 15 + }, + "end": { + "column": 8, + "line": 15 + } + }, + "value": "foo" + }, + { + "type": "HTMLAssociation", + "range": [ + 176, + 177 + ], + "loc": { + "start": { + "line": 15, + "column": 8 + }, + "end": { + "line": 15, + "column": 9 + } + }, + "value": "" + }, + { + "type": "Punctuator", + "range": [ + 177, + 178 + ], + "loc": { + "start": { + "line": 15, + "column": 9 + }, + "end": { + "line": 15, + "column": 10 + } + }, + "value": "\"" + }, + { + "type": "Identifier", + "value": "c", + "start": 178, + "end": 179, + "loc": { + "start": { + "line": 15, + "column": 10 + }, + "end": { + "line": 15, + "column": 11 + } + }, + "range": [ + 178, + 179 + ] + }, + { + "type": "Punctuator", + "value": "&&", + "start": 179, + "end": 181, + "loc": { + "start": { + "line": 15, + "column": 11 + }, + "end": { + "line": 15, + "column": 21 + } + }, + "range": [ + 179, + 189 + ] + }, + { + "type": "Identifier", + "value": "d", + "start": 189, + "end": 190, + "loc": { + "start": { + "line": 15, + "column": 21 + }, + "end": { + "line": 15, + "column": 22 + } + }, + "range": [ + 189, + 190 + ] + }, + { + "type": "Punctuator", + "range": [ + 190, + 191 + ], + "loc": { + "start": { + "line": 15, + "column": 22 + }, + "end": { + "line": 15, + "column": 23 + } + }, + "value": "\"" + }, + { + "type": "HTMLTagClose", + "range": [ + 194, + 195 + ], + "loc": { + "start": { + "line": 16, + "column": 2 + }, + "end": { + "line": 16, + "column": 3 + } + }, + "value": "" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 195, + 200 + ], + "loc": { + "start": { + "line": 16, + "column": 3 + }, + "end": { + "line": 16, + "column": 8 + } + }, + "value": "div" + }, + { + "type": "HTMLTagClose", + "range": [ + 200, + 201 + ], + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 9 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 201, + 202 + ], + "loc": { + "start": { + "line": 16, + "column": 9 + }, + "end": { + "line": 17, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 202, + 212 + ], + "loc": { + "start": { + "line": 17, + "column": 0 + }, + "end": { + "line": 17, + "column": 10 + } + }, + "value": "template" + }, + { + "type": "HTMLTagClose", + "range": [ + 212, + 213 + ], + "loc": { + "start": { + "line": 17, + "column": 10 + }, + "end": { + "line": 17, + "column": 11 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 213, + 214 + ], + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 18, + "column": 0 + } + }, + "value": "\n" + } + ], + "comments": [], + "errors": [] + } +} \ No newline at end of file diff --git a/test/fixtures/ast/end-of-line02/source.vue b/test/fixtures/ast/end-of-line02/source.vue new file mode 100644 index 00000000..6c27e7dd --- /dev/null +++ b/test/fixtures/ast/end-of-line02/source.vue @@ -0,0 +1,17 @@ + + diff --git a/test/fixtures/ast/end-of-line02/token-ranges.json b/test/fixtures/ast/end-of-line02/token-ranges.json new file mode 100644 index 00000000..be779652 --- /dev/null +++ b/test/fixtures/ast/end-of-line02/token-ranges.json @@ -0,0 +1,80 @@ +[ + "", + "", + "\n", + "var", + " ", + "a", + " ", + "=", + " ", + "foo", + "\n", + "", + "\n", + "", + "\n ", + "", + "", + "\n ", + "", + "", + "\n ", + "", + "", + "\n ", + "", + "", + "\n", + "", + "\n" +] \ No newline at end of file diff --git a/test/fixtures/ast/end-of-line02/tree.json b/test/fixtures/ast/end-of-line02/tree.json new file mode 100644 index 00000000..d1a52306 --- /dev/null +++ b/test/fixtures/ast/end-of-line02/tree.json @@ -0,0 +1,311 @@ +[ + { + "type": "VElement", + "text": "", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + } + ] + } +] \ No newline at end of file From f7d69af9ba51f831008a863877458d6297a6dc68 Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Mon, 12 Oct 2020 19:34:34 +0900 Subject: [PATCH 006/151] 7.1.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index db6f2cc7..fbb1f013 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-eslint-parser", - "version": "7.1.0", + "version": "7.1.1", "description": "The ESLint custom parser for `.vue` files.", "engines": { "node": ">=8.10" From 9a04a8e68834516c039c41d24d01dcdd274a0ff6 Mon Sep 17 00:00:00 2001 From: Yosuke Ota Date: Tue, 13 Oct 2020 18:20:22 +0900 Subject: [PATCH 007/151] Move repo (#83) --- README.md | 8 ++++---- package.json | 6 +++--- test/index.js | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 3fd432b1..825afc74 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ [![npm version](https://img.shields.io/npm/v/vue-eslint-parser.svg)](https://www.npmjs.com/package/vue-eslint-parser) [![Downloads/month](https://img.shields.io/npm/dm/vue-eslint-parser.svg)](http://www.npmtrends.com/vue-eslint-parser) -[![Build Status](https://github.com/mysticatea/vue-eslint-parser/workflows/CI/badge.svg)](https://github.com/mysticatea/vue-eslint-parser/actions) -[![Coverage Status](https://codecov.io/gh/mysticatea/vue-eslint-parser/branch/master/graph/badge.svg)](https://codecov.io/gh/mysticatea/vue-eslint-parser) -[![Dependency Status](https://david-dm.org/mysticatea/vue-eslint-parser.svg)](https://david-dm.org/mysticatea/vue-eslint-parser) +[![Build Status](https://github.com/vuejs/vue-eslint-parser/workflows/CI/badge.svg)](https://github.com/vuejs/vue-eslint-parser/actions) +[![Coverage Status](https://codecov.io/gh/vuejs/vue-eslint-parser/branch/master/graph/badge.svg)](https://codecov.io/gh/vuejs/vue-eslint-parser) +[![Dependency Status](https://david-dm.org/vuejs/vue-eslint-parser.svg)](https://david-dm.org/vuejs/vue-eslint-parser) The ESLint custom parser for `.vue` files. @@ -114,7 +114,7 @@ Please disable those rules for `.vue` files as necessary. ## 📰 Changelog -- [GitHub Releases](https://github.com/mysticatea/vue-eslint-parser/releases) +- [GitHub Releases](https://github.com/vuejs/vue-eslint-parser/releases) ## 🍻 Contributing diff --git a/package.json b/package.json index fbb1f013..87599abc 100644 --- a/package.json +++ b/package.json @@ -74,14 +74,14 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/mysticatea/vue-eslint-parser.git" + "url": "git+https://github.com/vuejs/vue-eslint-parser.git" }, "keywords": [], "author": "Toru Nagashima", "license": "MIT", "bugs": { - "url": "https://github.com/mysticatea/vue-eslint-parser/issues" + "url": "https://github.com/vuejs/vue-eslint-parser/issues" }, - "homepage": "https://github.com/mysticatea/vue-eslint-parser#readme", + "homepage": "https://github.com/vuejs/vue-eslint-parser#readme", "funding": "https://github.com/sponsors/mysticatea" } diff --git a/test/index.js b/test/index.js index 185115c2..1ffbe1df 100644 --- a/test/index.js +++ b/test/index.js @@ -529,7 +529,7 @@ describe("Basic tests", () => { }) }) - describe("https://github.com/mysticatea/vue-eslint-parser/issues/21", () => { + describe("https://github.com/vuejs/vue-eslint-parser/issues/21", () => { it("should make the correct location of decorators", () => { const code = fs.readFileSync( path.join(FIXTURE_DIR, "issue21.vue"), From 707476366cc06ac4a1a1025921c234d4c17f32e8 Mon Sep 17 00:00:00 2001 From: Yosuke Ota Date: Sat, 7 Nov 2020 01:00:25 +0900 Subject: [PATCH 008/151] Update the CI workflow. (#86) * Fix the CI workflow. * fix --- .github/workflows/CI.yml | 21 +++++++++++++++++++++ package.json | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index d3f8df9a..91907760 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -77,6 +77,27 @@ jobs: run: npm run -s build - name: Test run: npm run -s test:mocha + + test-cov: + name: Test and Send Coverage + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Checkout submodules + run: git submodule update --init + - name: Install Node.js v14 + uses: actions/setup-node@v1 + with: + node-version: 14 + - name: Install Packages + run: npm install + - name: Install ESLint v7 + run: node scripts/ci-install-eslint 7 + - name: Build + run: npm run -s build + - name: Test + run: npm run -s test:mocha - name: Send Coverage run: npm run -s codecov env: diff --git a/package.json b/package.json index 87599abc..1a4d11a6 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "clean": "rimraf .nyc_output .temp coverage index.*", "codecov": "codecov", "coverage": "opener ./coverage/lcov-report/index.html", - "lint": "node -e \"if(process.env.ESLINT=='5')process.exit(1)\" && eslint src test --ext .js,.ts || node -e \"if(process.env.ESLINT!='5')process.exit(1)\"", + "lint": "eslint src test --ext .js,.ts", "setup": "git submodule update --init && cd test/fixtures/eslint && npm install", "pretest": "run-s build lint", "test": "npm run -s test:mocha", From bd916f576ac8b22d25780da8a21b855d338ce9a9 Mon Sep 17 00:00:00 2001 From: Yosuke Ota Date: Sat, 7 Nov 2020 01:00:48 +0900 Subject: [PATCH 009/151] Fix type of VDirectiveKey (#85) --- src/ast/nodes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ast/nodes.ts b/src/ast/nodes.ts index 3de03e7e..0945ae6c 100644 --- a/src/ast/nodes.ts +++ b/src/ast/nodes.ts @@ -767,7 +767,7 @@ export interface VIdentifier extends HasLocation, HasParent { */ export interface VDirectiveKey extends HasLocation, HasParent { type: "VDirectiveKey" - parent: VAttribute + parent: VDirective name: VIdentifier argument: VExpressionContainer | VIdentifier | null modifiers: VIdentifier[] From 237eac44c5d38138767f3b0dbcccf43d2e1dbdcf Mon Sep 17 00:00:00 2001 From: Yosuke Ota Date: Wed, 18 Nov 2020 11:44:16 +0900 Subject: [PATCH 010/151] Fix the wrong location when using with `@typescript-eslint/scope-manager` (#87) * Fix the wrong location when using with `@typescript-eslint/scope-manager` * Update * update --- .eslintrc.yml | 6 +++++- package.json | 7 ++++--- src/ast/nodes.ts | 9 ++++++--- src/common/location-calculator.ts | 11 ++++++++++- src/external/token-store/utils.ts | 6 +++--- src/html/tokenizer.ts | 8 ++++---- src/script/espree.ts | 13 +++++++------ src/script/index.ts | 24 +++++++++++++++++++----- test/fixtures/ts-scope-manager.vue | 11 +++++++++++ test/index.js | 23 +++++++++++++++++++++++ 10 files changed, 92 insertions(+), 26 deletions(-) create mode 100644 test/fixtures/ts-scope-manager.vue diff --git a/.eslintrc.yml b/.eslintrc.yml index 8f89e2f3..28a03e19 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -1,8 +1,12 @@ extends: - plugin:@mysticatea/es2015 - plugin:@mysticatea/+node - +globals: { + root: "off" +} overrides: + - files: "**/*.ts" + parser: "@typescript-eslint/parser" - files: "typings/**" rules: node/no-missing-import: diff --git a/package.json b/package.json index 1a4d11a6..a90d248e 100644 --- a/package.json +++ b/package.json @@ -21,13 +21,13 @@ "lodash": "^4.17.15" }, "devDependencies": { - "@mysticatea/eslint-plugin": "^11.0.0", + "@mysticatea/eslint-plugin": "^13.0.0", "@types/debug": "0.0.30", "@types/estree": "0.0.38", "@types/lodash": "^4.14.120", "@types/mocha": "^5.2.4", "@types/node": "^10.12.21", - "@typescript-eslint/parser": "^2.31.0", + "@typescript-eslint/parser": "^4.7.0", "babel-eslint": "^10.0.1", "chokidar": "^2.0.4", "codecov": "^3.1.0", @@ -44,7 +44,7 @@ "rollup-plugin-node-resolve": "^4.0.0", "rollup-plugin-sourcemaps": "^0.4.2", "ts-node": "^8.1.0", - "typescript": "~3.4.4", + "typescript": "~4.0.5", "wait-on": "^3.2.0", "warun": "^1.0.0" }, @@ -59,6 +59,7 @@ "pretest": "run-s build lint", "test": "npm run -s test:mocha", "test:mocha": "nyc mocha \"test/*.js\" --reporter dot --timeout 10000", + "test:debug": "mocha --inspect --require ts-node/register \"test/*.js\" --reporter dot --timeout 10000", "preupdate-fixtures": "npm run -s build", "update-fixtures": "node scripts/update-fixtures-ast.js && node scripts/update-fixtures-document-fragment.js", "preversion": "npm test", diff --git a/src/ast/nodes.ts b/src/ast/nodes.ts index 0945ae6c..eca0b327 100644 --- a/src/ast/nodes.ts +++ b/src/ast/nodes.ts @@ -280,7 +280,8 @@ export interface ESLintImportDeclaration extends HasLocation, HasParent { specifiers: ( | ESLintImportSpecifier | ESLintImportDefaultSpecifier - | ESLintImportNamespaceSpecifier)[] + | ESLintImportNamespaceSpecifier + )[] source: ESLintLiteral } @@ -375,7 +376,8 @@ export interface ESLintObjectExpression extends HasLocation, HasParent { properties: ( | ESLintProperty | ESLintSpreadElement - | ESLintLegacySpreadProperty)[] + | ESLintLegacySpreadProperty + )[] } export interface ESLintProperty extends HasLocation, HasParent { @@ -570,7 +572,8 @@ export interface ESLintObjectPattern extends HasLocation, HasParent { properties: ( | ESLintAssignmentProperty | ESLintRestElement - | ESLintLegacyRestProperty)[] + | ESLintLegacyRestProperty + )[] } export interface ESLintAssignmentProperty extends ESLintProperty { diff --git a/src/common/location-calculator.ts b/src/common/location-calculator.ts index 980e0174..497bd194 100644 --- a/src/common/location-calculator.ts +++ b/src/common/location-calculator.ts @@ -36,7 +36,7 @@ export class LocationCalculator { gapOffsets: number[], ltOffsets: number[], baseOffset?: number, - shiftOffset: number = 0, + shiftOffset = 0, ) { this.gapOffsets = gapOffsets this.ltOffsets = ltOffsets @@ -76,6 +76,15 @@ export class LocationCalculator { ) } + /** + * Calculate the location of the given index. + * @param index The index to calculate their location. + * @returns The location of the index. + */ + public getLocFromIndex(index: number): Location { + return this._getLocation(index) + } + /** * Calculate the location of the given offset. * @param offset The offset to calculate their location. diff --git a/src/external/token-store/utils.ts b/src/external/token-store/utils.ts index fd42a8f3..d8e35831 100644 --- a/src/external/token-store/utils.ts +++ b/src/external/token-store/utils.ts @@ -26,9 +26,9 @@ function getStartLocation(token: { range: number[] }): number { */ export function search(tokens: HasLocation[], location: number): number { return sortedIndexBy( - tokens, - {range: [location]}, - getStartLocation + tokens as { range: number[] }[], + { range: [location] }, + getStartLocation, ) } diff --git a/src/html/tokenizer.ts b/src/html/tokenizer.ts index b6e0c5e5..440cc0c4 100644 --- a/src/html/tokenizer.ts +++ b/src/html/tokenizer.ts @@ -527,7 +527,7 @@ export class Tokenizer { "Invalid state: the provisional token was not found.", ) - const token = this.provisionalToken as Token + const token = this.provisionalToken this.provisionalToken = null if (token.range[0] < token.range[1]) { @@ -542,10 +542,10 @@ export class Tokenizer { assert(this.currentToken != null) assert(this.provisionalToken != null) - const token = this.currentToken as Token + const token = this.currentToken debug("[html] rollback token: %d %s", token.range[0], token.type) - this.currentToken = this.provisionalToken as Token + this.currentToken = this.provisionalToken this.provisionalToken = null } @@ -1808,7 +1808,7 @@ export class Tokenizer { // The this.buffer.length is not new length since it includes surrogate pairs. // Calculate new length. - const token = this.currentToken as Token + const token = this.currentToken const len0 = token.value.length for (const cp1 of this.buffer) { this.appendTokenValue(cp1, null) diff --git a/src/script/espree.ts b/src/script/espree.ts index 4e25d07b..3765ff0a 100644 --- a/src/script/espree.ts +++ b/src/script/espree.ts @@ -15,19 +15,20 @@ export interface ESLintCustomParser { parseForESLint?(code: string, options: any): ESLintCustomParserResult } -const createRequire: (filename: string) => (filename: string) => any = +const createRequire: (filename: string) => (modname: string) => any = // Added in v12.2.0 (Module as any).createRequire || // Added in v10.12.0, but deprecated in v12.2.0. + // eslint-disable-next-line @mysticatea/node/no-deprecated-api Module.createRequireFromPath || // Polyfill - This is not executed on the tests on node@>=10. /* istanbul ignore next */ - (filename => { - const mod = new Module(filename) + (modname => { + const mod = new Module(modname) - mod.filename = filename - mod.paths = (Module as any)._nodeModulePaths(path.dirname(filename)) - ;(mod as any)._compile("module.exports = require;", filename) + mod.filename = modname + mod.paths = (Module as any)._nodeModulePaths(path.dirname(modname)) + ;(mod as any)._compile("module.exports = require;", modname) return mod.exports }) diff --git a/src/script/index.ts b/src/script/index.ts index f073acd5..10dd70a9 100644 --- a/src/script/index.ts +++ b/src/script/index.ts @@ -31,6 +31,8 @@ import { VForExpression, VOnExpression, VSlotScopeExpression, + OffsetRange, + LocationRange, } from "../ast" import { debug } from "../common/debug" import { LocationCalculator } from "../common/location-calculator" @@ -66,7 +68,7 @@ function postprocess( ): void { // There are cases which the same node instance appears twice in the tree. // E.g. `let {a} = {}` // This `a` appears twice at `Property#key` and `Property#value`. - const traversed = new Set() + const traversed = new Set() traverseNodes(result.ast, { visitorKeys: result.visitorKeys, @@ -78,9 +80,22 @@ function postprocess( // `babel-eslint@8` has shared `Node#range` with multiple nodes. // See also: https://github.com/vuejs/eslint-plugin-vue/issues/208 - if (!traversed.has(node.range)) { - traversed.add(node.range) + if (traversed.has(node.range)) { + if (!traversed.has(node.loc)) { + // However, `Node#loc` may not be shared. + // See also: https://github.com/vuejs/vue-eslint-parser/issues/84 + node.loc.start = locationCalculator.getLocFromIndex( + node.range[0], + ) + node.loc.end = locationCalculator.getLocFromIndex( + node.range[1], + ) + traversed.add(node.loc) + } + } else { locationCalculator.fixLocation(node) + traversed.add(node.range) + traversed.add(node.loc) } } }, @@ -139,7 +154,7 @@ function normalizeLeft( */ function getCommaTokenBeforeNode(tokens: Token[], node: Node): Token | null { let tokenIndex = sortedIndexBy( - tokens, + tokens as { range: OffsetRange }[], { range: node.range }, t => t.range[0], ) @@ -563,7 +578,6 @@ export function parseScript( require(parserOptions.parser) : getEspree() const result: any = - // eslint-disable-next-line @mysticatea/ts/unbound-method typeof parser.parseForESLint === "function" ? parser.parseForESLint(code, parserOptions) : parser.parse(code, parserOptions) diff --git a/test/fixtures/ts-scope-manager.vue b/test/fixtures/ts-scope-manager.vue new file mode 100644 index 00000000..f3685675 --- /dev/null +++ b/test/fixtures/ts-scope-manager.vue @@ -0,0 +1,11 @@ + + + diff --git a/test/index.js b/test/index.js index 1ffbe1df..0e2dc894 100644 --- a/test/index.js +++ b/test/index.js @@ -340,6 +340,29 @@ describe("Basic tests", () => { }) }) + describe("About fixtures/ts-scope-manager.vue", () => { + it("should calculate the correct location with '@typescript-eslint/parser'", () => { + const cli = new CLIEngine({ + cwd: FIXTURE_DIR, + envs: ["es6", "node"], + parser: PARSER_PATH, + parserOptions: { + parser: "@typescript-eslint/parser", + }, + rules: { "no-unused-vars": ["error"] }, + useEslintrc: false, + }) + const report = cli.executeOnFiles(["ts-scope-manager.vue"]) + const messages = report.results[0].messages + + assert.strictEqual(messages.length, 1) + assert.deepStrictEqual(messages[0].line, 8) + assert.deepStrictEqual(messages[0].column, 8) + assert.deepStrictEqual(messages[0].endLine, 8) + assert.deepStrictEqual(messages[0].endColumn, 14) + }) + }) + describe("About fixtures/svg-attrs.vue", () => { it("parses attributes with colons", () => { const cli = new CLIEngine({ From 505677510a33253db66d3dc68a8fe0917fdeb4f1 Mon Sep 17 00:00:00 2001 From: Yosuke Ota Date: Thu, 3 Dec 2020 10:45:22 +0900 Subject: [PATCH 011/151] Add parserOptions.vueFeatures.interpolationAsNonHTML option (#88) * Change the parsing in the interpolation not to handle `<` as the tag. * Update --- README.md | 27 + scripts/update-fixtures-ast.js | 9 +- src/ast/errors.ts | 1 + src/common/parser-options.ts | 34 + src/html/parser.ts | 5 +- src/html/tokenizer.ts | 82 +- src/index.ts | 7 +- src/script/index.ts | 21 +- src/script/scope-analyzer.ts | 10 +- src/template/index.ts | 11 +- test/ast.js | 28 +- .../ast.json | 273 ++++ .../parser-options.json | 5 + .../source.vue | 3 + .../token-ranges.json | 11 + .../tree.json | 23 + .../ast.json | 675 ++++++++ .../parser-options.json | 5 + .../source.vue | 3 + .../token-ranges.json | 18 + .../tree.json | 72 + .../ast.json | 1373 +++++++++++++++++ .../parser-options.json | 5 + .../source.vue | 5 + .../token-ranges.json | 34 + .../tree.json | 148 ++ test/fixtures/ast/mustache-in-lt-gt/ast.json | 650 ++++++++ .../fixtures/ast/mustache-in-lt-gt/source.vue | 5 + .../ast/mustache-in-lt-gt/token-ranges.json | 23 + test/fixtures/ast/mustache-in-lt-gt/tree.json | 67 + 30 files changed, 3596 insertions(+), 37 deletions(-) create mode 100644 src/common/parser-options.ts create mode 100644 test/fixtures/ast/mustache-errors-opt-interpolation-as-non-html/ast.json create mode 100644 test/fixtures/ast/mustache-errors-opt-interpolation-as-non-html/parser-options.json create mode 100644 test/fixtures/ast/mustache-errors-opt-interpolation-as-non-html/source.vue create mode 100644 test/fixtures/ast/mustache-errors-opt-interpolation-as-non-html/token-ranges.json create mode 100644 test/fixtures/ast/mustache-errors-opt-interpolation-as-non-html/tree.json create mode 100644 test/fixtures/ast/mustache-in-escape-opt-interpolation-as-non-html/ast.json create mode 100644 test/fixtures/ast/mustache-in-escape-opt-interpolation-as-non-html/parser-options.json create mode 100644 test/fixtures/ast/mustache-in-escape-opt-interpolation-as-non-html/source.vue create mode 100644 test/fixtures/ast/mustache-in-escape-opt-interpolation-as-non-html/token-ranges.json create mode 100644 test/fixtures/ast/mustache-in-escape-opt-interpolation-as-non-html/tree.json create mode 100644 test/fixtures/ast/mustache-in-lt-gt-opt-interpolation-as-non-html/ast.json create mode 100644 test/fixtures/ast/mustache-in-lt-gt-opt-interpolation-as-non-html/parser-options.json create mode 100644 test/fixtures/ast/mustache-in-lt-gt-opt-interpolation-as-non-html/source.vue create mode 100644 test/fixtures/ast/mustache-in-lt-gt-opt-interpolation-as-non-html/token-ranges.json create mode 100644 test/fixtures/ast/mustache-in-lt-gt-opt-interpolation-as-non-html/tree.json create mode 100644 test/fixtures/ast/mustache-in-lt-gt/ast.json create mode 100644 test/fixtures/ast/mustache-in-lt-gt/source.vue create mode 100644 test/fixtures/ast/mustache-in-lt-gt/token-ranges.json create mode 100644 test/fixtures/ast/mustache-in-lt-gt/tree.json diff --git a/README.md b/README.md index 825afc74..f5e5bda6 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,33 @@ For example: If the `parserOptions.parser` is `false`, the `vue-eslint-parser` skips parsing `\n \n\n", + "children": [ + { + "type": "VText", + "text": "\n", + "children": [] + }, + { + "type": "VElement", + "text": "\n\n \n\n\n
\n \n \n\n", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + }, + { + "type": "VText", + "text": "\n", + "children": [] + }, + { + "type": "VElement", + "text": "\n \n", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + }, + { + "type": "VText", + "text": "\n ", + "children": [] + }, + { + "type": "VElement", + "text": "", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + } + ] + }, + { + "type": "VText", + "text": "\n", + "children": [] + }, + { + "type": "VEndTag", + "text": "", + "children": [] + } + ] + }, + { + "type": "VText", + "text": "\n", + "children": [] + }, + { + "type": "VElement", + "text": "\n
\n \n \n", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + }, + { + "type": "VText", + "text": "\n ", + "children": [] + }, + { + "type": "VElement", + "text": "
", + "children": [ + { + "type": "VStartTag", + "text": "
", + "children": [] + }, + { + "type": "VEndTag", + "text": "
", + "children": [] + } + ] + }, + { + "type": "VText", + "text": "\n ", + "children": [] + }, + { + "type": "VElement", + "text": "", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + } + ] + }, + { + "type": "VText", + "text": "\n ", + "children": [] + }, + { + "type": "VElement", + "text": "", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + } + ] + }, + { + "type": "VText", + "text": "\n", + "children": [] + }, + { + "type": "VEndTag", + "text": "", + "children": [] + } + ] + }, + { + "type": "VText", + "text": "\n", + "children": [] + }, + { + "type": "VEndTag", + "text": "", + "children": [] + } + ] + } + ] + } +] \ No newline at end of file diff --git a/test/fixtures/document-fragment/template-tag-is-absent/token-ranges.json b/test/fixtures/document-fragment/template-tag-is-absent/token-ranges.json new file mode 100644 index 00000000..9cb40b9c --- /dev/null +++ b/test/fixtures/document-fragment/template-tag-is-absent/token-ranges.json @@ -0,0 +1,46 @@ +[ + "", + "\n ", + "", + "", + "\n", + "", + "\n", + "", + "\n", + "export", + " ", + "default", + " ", + "{", + "\n ", + "name:", + " ", + "'test'", + "\n", + "}", + "\n", + "", + "\n", + "", + "\n", + "a", + " ", + "{", + "\n ", + "color:", + " ", + "pink;", + "\n", + "}", + "\n", + "" +] \ No newline at end of file diff --git a/test/fixtures/document-fragment/template-tag-is-absent/tree.json b/test/fixtures/document-fragment/template-tag-is-absent/tree.json new file mode 100644 index 00000000..a1131305 --- /dev/null +++ b/test/fixtures/document-fragment/template-tag-is-absent/tree.json @@ -0,0 +1,102 @@ +[ + { + "type": "VDocumentFragment", + "text": "\n\n", + "children": [ + { + "type": "VElement", + "text": "", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + } + ] + }, + { + "type": "VText", + "text": "\n", + "children": [] + }, + { + "type": "VElement", + "text": "", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + } + ] + }, + { + "type": "VText", + "text": "\n", + "children": [] + }, + { + "type": "VElement", + "text": "", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + } + ] + } + ] + } +] \ No newline at end of file diff --git a/test/fixtures/document-fragment/template-tag-is-present/document-fragment.json b/test/fixtures/document-fragment/template-tag-is-present/document-fragment.json index 37b74e40..52c22960 100644 --- a/test/fixtures/document-fragment/template-tag-is-present/document-fragment.json +++ b/test/fixtures/document-fragment/template-tag-is-present/document-fragment.json @@ -339,7 +339,7 @@ "value": "\n " }, { - "type": "HTMLText", + "type": "HTMLRawText", "range": [ 11, 14 diff --git a/test/fixtures/document-fragment/template-tag-is-present/token-ranges.json b/test/fixtures/document-fragment/template-tag-is-present/token-ranges.json new file mode 100644 index 00000000..37f86b4a --- /dev/null +++ b/test/fixtures/document-fragment/template-tag-is-present/token-ranges.json @@ -0,0 +1,43 @@ +[ + "", + "\n ", + "doc", + "\n", + "", + "\n", + "", + "\n", + "export", + " ", + "default", + " ", + "{", + "\n ", + "name:", + " ", + "'test'", + "\n", + "}", + "\n", + "", + "\n", + "", + "\n", + "a", + " ", + "{", + "\n ", + "color:", + " ", + "pink;", + "\n", + "}", + "\n", + "" +] \ No newline at end of file diff --git a/test/fixtures/document-fragment/template-tag-is-present/tree.json b/test/fixtures/document-fragment/template-tag-is-present/tree.json new file mode 100644 index 00000000..6743799a --- /dev/null +++ b/test/fixtures/document-fragment/template-tag-is-present/tree.json @@ -0,0 +1,81 @@ +[ + { + "type": "VDocumentFragment", + "text": "\n doc\n\n\n", + "children": [ + { + "type": "VElement", + "text": "\n doc\n", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + }, + { + "type": "VText", + "text": "\n doc\n", + "children": [] + }, + { + "type": "VEndTag", + "text": "", + "children": [] + } + ] + }, + { + "type": "VText", + "text": "\n", + "children": [] + }, + { + "type": "VElement", + "text": "", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + } + ] + }, + { + "type": "VText", + "text": "\n", + "children": [] + }, + { + "type": "VElement", + "text": "", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + } + ] + } + ] + } +] \ No newline at end of file diff --git a/test/fixtures/document-fragment/textarea-custom-block/document-fragment.json b/test/fixtures/document-fragment/textarea-custom-block/document-fragment.json new file mode 100644 index 00000000..a03221b9 --- /dev/null +++ b/test/fixtures/document-fragment/textarea-custom-block/document-fragment.json @@ -0,0 +1,977 @@ +{ + "type": "VDocumentFragment", + "range": [ + 0, + 117 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 8, + "column": 0 + } + }, + "children": [ + { + "type": "VElement", + "range": [ + 0, + 52 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 11 + } + }, + "name": "textarea", + "rawName": "textarea", + "namespace": "http://www.w3.org/1999/xhtml", + "startTag": { + "type": "VStartTag", + "range": [ + 0, + 10 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "selfClosing": false, + "attributes": [] + }, + "children": [ + { + "type": "VText", + "range": [ + 10, + 41 + ], + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 3, + "column": 0 + } + }, + "value": "\n < custom block >
\n" + } + ], + "endTag": { + "type": "VEndTag", + "range": [ + 41, + 52 + ], + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 11 + } + } + }, + "variables": [] + }, + { + "type": "VText", + "range": [ + 52, + 54 + ], + "loc": { + "start": { + "line": 3, + "column": 11 + }, + "end": { + "line": 5, + "column": 0 + } + }, + "value": "\n\n" + }, + { + "type": "VElement", + "range": [ + 54, + 116 + ], + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 7, + "column": 11 + } + }, + "name": "textarea", + "rawName": "textarea", + "namespace": "http://www.w3.org/1999/xhtml", + "startTag": { + "type": "VStartTag", + "range": [ + 54, + 76 + ], + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 22 + } + }, + "selfClosing": false, + "attributes": [ + { + "type": "VAttribute", + "range": [ + 64, + 75 + ], + "loc": { + "start": { + "line": 5, + "column": 10 + }, + "end": { + "line": 5, + "column": 21 + } + }, + "directive": false, + "key": { + "type": "VIdentifier", + "range": [ + 64, + 68 + ], + "loc": { + "start": { + "line": 5, + "column": 10 + }, + "end": { + "line": 5, + "column": 14 + } + }, + "name": "lang", + "rawName": "lang" + }, + "value": { + "type": "VLiteral", + "range": [ + 69, + 75 + ], + "loc": { + "start": { + "line": 5, + "column": 15 + }, + "end": { + "line": 5, + "column": 21 + } + }, + "value": "html" + } + } + ] + }, + "children": [ + { + "type": "VText", + "range": [ + 76, + 100 + ], + "loc": { + "start": { + "line": 5, + "column": 22 + }, + "end": { + "line": 6, + "column": 23 + } + }, + "value": "\n < not RCDATA > " + }, + { + "type": "VElement", + "range": [ + 100, + 104 + ], + "loc": { + "start": { + "line": 6, + "column": 23 + }, + "end": { + "line": 6, + "column": 27 + } + }, + "name": "br", + "rawName": "br", + "namespace": "http://www.w3.org/1999/xhtml", + "startTag": { + "type": "VStartTag", + "range": [ + 100, + 104 + ], + "loc": { + "start": { + "line": 6, + "column": 23 + }, + "end": { + "line": 6, + "column": 27 + } + }, + "selfClosing": false, + "attributes": [] + }, + "children": [], + "endTag": null, + "variables": [] + }, + { + "type": "VText", + "range": [ + 104, + 105 + ], + "loc": { + "start": { + "line": 6, + "column": 27 + }, + "end": { + "line": 7, + "column": 0 + } + }, + "value": "\n" + } + ], + "endTag": { + "type": "VEndTag", + "range": [ + 105, + 116 + ], + "loc": { + "start": { + "line": 7, + "column": 0 + }, + "end": { + "line": 7, + "column": 11 + } + } + }, + "variables": [] + }, + { + "type": "VText", + "range": [ + 116, + 117 + ], + "loc": { + "start": { + "line": 7, + "column": 11 + }, + "end": { + "line": 8, + "column": 0 + } + }, + "value": "\n" + } + ], + "tokens": [ + { + "type": "HTMLTagOpen", + "range": [ + 0, + 9 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 9 + } + }, + "value": "textarea" + }, + { + "type": "HTMLTagClose", + "range": [ + 9, + 10 + ], + "loc": { + "start": { + "line": 1, + "column": 9 + }, + "end": { + "line": 1, + "column": 10 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 10, + 13 + ], + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 2, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "HTMLRawText", + "range": [ + 13, + 17 + ], + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 6 + } + }, + "value": "<" + }, + { + "type": "HTMLWhitespace", + "range": [ + 17, + 18 + ], + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 7 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 18, + 24 + ], + "loc": { + "start": { + "line": 2, + "column": 7 + }, + "end": { + "line": 2, + "column": 13 + } + }, + "value": "custom" + }, + { + "type": "HTMLWhitespace", + "range": [ + 24, + 25 + ], + "loc": { + "start": { + "line": 2, + "column": 13 + }, + "end": { + "line": 2, + "column": 14 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 25, + 30 + ], + "loc": { + "start": { + "line": 2, + "column": 14 + }, + "end": { + "line": 2, + "column": 19 + } + }, + "value": "block" + }, + { + "type": "HTMLWhitespace", + "range": [ + 30, + 31 + ], + "loc": { + "start": { + "line": 2, + "column": 19 + }, + "end": { + "line": 2, + "column": 20 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 31, + 35 + ], + "loc": { + "start": { + "line": 2, + "column": 20 + }, + "end": { + "line": 2, + "column": 24 + } + }, + "value": ">" + }, + { + "type": "HTMLWhitespace", + "range": [ + 35, + 36 + ], + "loc": { + "start": { + "line": 2, + "column": 24 + }, + "end": { + "line": 2, + "column": 25 + } + }, + "value": " " + }, + { + "type": "HTMLRawText", + "range": [ + 36, + 40 + ], + "loc": { + "start": { + "line": 2, + "column": 25 + }, + "end": { + "line": 2, + "column": 29 + } + }, + "value": "
" + }, + { + "type": "HTMLWhitespace", + "range": [ + 40, + 41 + ], + "loc": { + "start": { + "line": 2, + "column": 29 + }, + "end": { + "line": 3, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 41, + 51 + ], + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 10 + } + }, + "value": "textarea" + }, + { + "type": "HTMLTagClose", + "range": [ + 51, + 52 + ], + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 11 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 52, + 54 + ], + "loc": { + "start": { + "line": 3, + "column": 11 + }, + "end": { + "line": 5, + "column": 0 + } + }, + "value": "\n\n" + }, + { + "type": "HTMLTagOpen", + "range": [ + 54, + 63 + ], + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 9 + } + }, + "value": "textarea" + }, + { + "type": "HTMLIdentifier", + "range": [ + 64, + 68 + ], + "loc": { + "start": { + "line": 5, + "column": 10 + }, + "end": { + "line": 5, + "column": 14 + } + }, + "value": "lang" + }, + { + "type": "HTMLAssociation", + "range": [ + 68, + 69 + ], + "loc": { + "start": { + "line": 5, + "column": 14 + }, + "end": { + "line": 5, + "column": 15 + } + }, + "value": "" + }, + { + "type": "HTMLLiteral", + "range": [ + 69, + 75 + ], + "loc": { + "start": { + "line": 5, + "column": 15 + }, + "end": { + "line": 5, + "column": 21 + } + }, + "value": "html" + }, + { + "type": "HTMLTagClose", + "range": [ + 75, + 76 + ], + "loc": { + "start": { + "line": 5, + "column": 21 + }, + "end": { + "line": 5, + "column": 22 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 76, + 79 + ], + "loc": { + "start": { + "line": 5, + "column": 22 + }, + "end": { + "line": 6, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "HTMLText", + "range": [ + 79, + 83 + ], + "loc": { + "start": { + "line": 6, + "column": 2 + }, + "end": { + "line": 6, + "column": 6 + } + }, + "value": "<" + }, + { + "type": "HTMLWhitespace", + "range": [ + 83, + 84 + ], + "loc": { + "start": { + "line": 6, + "column": 6 + }, + "end": { + "line": 6, + "column": 7 + } + }, + "value": " " + }, + { + "type": "HTMLText", + "range": [ + 84, + 87 + ], + "loc": { + "start": { + "line": 6, + "column": 7 + }, + "end": { + "line": 6, + "column": 10 + } + }, + "value": "not" + }, + { + "type": "HTMLWhitespace", + "range": [ + 87, + 88 + ], + "loc": { + "start": { + "line": 6, + "column": 10 + }, + "end": { + "line": 6, + "column": 11 + } + }, + "value": " " + }, + { + "type": "HTMLText", + "range": [ + 88, + 94 + ], + "loc": { + "start": { + "line": 6, + "column": 11 + }, + "end": { + "line": 6, + "column": 17 + } + }, + "value": "RCDATA" + }, + { + "type": "HTMLWhitespace", + "range": [ + 94, + 95 + ], + "loc": { + "start": { + "line": 6, + "column": 17 + }, + "end": { + "line": 6, + "column": 18 + } + }, + "value": " " + }, + { + "type": "HTMLText", + "range": [ + 95, + 99 + ], + "loc": { + "start": { + "line": 6, + "column": 18 + }, + "end": { + "line": 6, + "column": 22 + } + }, + "value": ">" + }, + { + "type": "HTMLWhitespace", + "range": [ + 99, + 100 + ], + "loc": { + "start": { + "line": 6, + "column": 22 + }, + "end": { + "line": 6, + "column": 23 + } + }, + "value": " " + }, + { + "type": "HTMLTagOpen", + "range": [ + 100, + 103 + ], + "loc": { + "start": { + "line": 6, + "column": 23 + }, + "end": { + "line": 6, + "column": 26 + } + }, + "value": "br" + }, + { + "type": "HTMLTagClose", + "range": [ + 103, + 104 + ], + "loc": { + "start": { + "line": 6, + "column": 26 + }, + "end": { + "line": 6, + "column": 27 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 104, + 105 + ], + "loc": { + "start": { + "line": 6, + "column": 27 + }, + "end": { + "line": 7, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 105, + 115 + ], + "loc": { + "start": { + "line": 7, + "column": 0 + }, + "end": { + "line": 7, + "column": 10 + } + }, + "value": "textarea" + }, + { + "type": "HTMLTagClose", + "range": [ + 115, + 116 + ], + "loc": { + "start": { + "line": 7, + "column": 10 + }, + "end": { + "line": 7, + "column": 11 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 116, + 117 + ], + "loc": { + "start": { + "line": 7, + "column": 11 + }, + "end": { + "line": 8, + "column": 0 + } + }, + "value": "\n" + } + ], + "comments": [], + "errors": [] +} \ No newline at end of file diff --git a/test/fixtures/document-fragment/textarea-custom-block/source.vue b/test/fixtures/document-fragment/textarea-custom-block/source.vue new file mode 100644 index 00000000..66a4da98 --- /dev/null +++ b/test/fixtures/document-fragment/textarea-custom-block/source.vue @@ -0,0 +1,7 @@ + + + diff --git a/test/fixtures/document-fragment/textarea-custom-block/token-ranges.json b/test/fixtures/document-fragment/textarea-custom-block/token-ranges.json new file mode 100644 index 00000000..cefee57b --- /dev/null +++ b/test/fixtures/document-fragment/textarea-custom-block/token-ranges.json @@ -0,0 +1,38 @@ +[ + "", + "\n ", + "<", + " ", + "custom", + " ", + "block", + " ", + ">", + " ", + "
", + "\n", + "
", + "\n\n", + "", + "\n ", + "<", + " ", + "not", + " ", + "RCDATA", + " ", + ">", + " ", + "", + "\n", + "", + "\n" +] \ No newline at end of file diff --git a/test/fixtures/document-fragment/textarea-custom-block/tree.json b/test/fixtures/document-fragment/textarea-custom-block/tree.json new file mode 100644 index 00000000..b69d234f --- /dev/null +++ b/test/fixtures/document-fragment/textarea-custom-block/tree.json @@ -0,0 +1,93 @@ +[ + { + "type": "VDocumentFragment", + "text": "\n\n\n", + "children": [ + { + "type": "VElement", + "text": "", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + } + ] + }, + { + "type": "VText", + "text": "\n\n", + "children": [] + }, + { + "type": "VElement", + "text": "", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + } + ] + }, + { + "type": "VText", + "text": "\n", + "children": [] + } + ] + } +] \ No newline at end of file diff --git a/test/fixtures/document-fragment/textarea-in-html/document-fragment.json b/test/fixtures/document-fragment/textarea-in-html/document-fragment.json new file mode 100644 index 00000000..e87cf382 --- /dev/null +++ b/test/fixtures/document-fragment/textarea-in-html/document-fragment.json @@ -0,0 +1,444 @@ +{ + "type": "VDocumentFragment", + "range": [ + 0, + 58 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 11 + } + }, + "children": [ + { + "type": "VElement", + "range": [ + 0, + 58 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 11 + } + }, + "name": "textarea", + "rawName": "textarea", + "namespace": "http://www.w3.org/1999/xhtml", + "startTag": { + "type": "VStartTag", + "range": [ + 0, + 22 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 22 + } + }, + "selfClosing": false, + "attributes": [ + { + "type": "VAttribute", + "range": [ + 10, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 21 + } + }, + "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, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 15 + }, + "end": { + "line": 1, + "column": 21 + } + }, + "value": "html" + } + } + ] + }, + "children": [ + { + "type": "VText", + "range": [ + 22, + 47 + ], + "loc": { + "start": { + "line": 1, + "column": 22 + }, + "end": { + "line": 3, + "column": 0 + } + }, + "value": "\n < RCDATA >
\n" + } + ], + "endTag": { + "type": "VEndTag", + "range": [ + 47, + 58 + ], + "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": "textarea" + }, + { + "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, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 15 + }, + "end": { + "line": 1, + "column": 21 + } + }, + "value": "html" + }, + { + "type": "HTMLTagClose", + "range": [ + 21, + 22 + ], + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 1, + "column": 22 + } + }, + "value": "" + }, + { + "type": "HTMLWhitespace", + "range": [ + 22, + 25 + ], + "loc": { + "start": { + "line": 1, + "column": 22 + }, + "end": { + "line": 2, + "column": 2 + } + }, + "value": "\n " + }, + { + "type": "HTMLRCDataText", + "range": [ + 25, + 29 + ], + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 6 + } + }, + "value": "<" + }, + { + "type": "HTMLWhitespace", + "range": [ + 29, + 30 + ], + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 7 + } + }, + "value": " " + }, + { + "type": "HTMLRCDataText", + "range": [ + 30, + 36 + ], + "loc": { + "start": { + "line": 2, + "column": 7 + }, + "end": { + "line": 2, + "column": 13 + } + }, + "value": "RCDATA" + }, + { + "type": "HTMLWhitespace", + "range": [ + 36, + 37 + ], + "loc": { + "start": { + "line": 2, + "column": 13 + }, + "end": { + "line": 2, + "column": 14 + } + }, + "value": " " + }, + { + "type": "HTMLRCDataText", + "range": [ + 37, + 41 + ], + "loc": { + "start": { + "line": 2, + "column": 14 + }, + "end": { + "line": 2, + "column": 18 + } + }, + "value": ">" + }, + { + "type": "HTMLWhitespace", + "range": [ + 41, + 42 + ], + "loc": { + "start": { + "line": 2, + "column": 18 + }, + "end": { + "line": 2, + "column": 19 + } + }, + "value": " " + }, + { + "type": "HTMLRCDataText", + "range": [ + 42, + 46 + ], + "loc": { + "start": { + "line": 2, + "column": 19 + }, + "end": { + "line": 2, + "column": 23 + } + }, + "value": "
" + }, + { + "type": "HTMLWhitespace", + "range": [ + 46, + 47 + ], + "loc": { + "start": { + "line": 2, + "column": 23 + }, + "end": { + "line": 3, + "column": 0 + } + }, + "value": "\n" + }, + { + "type": "HTMLEndTagOpen", + "range": [ + 47, + 57 + ], + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 10 + } + }, + "value": "textarea" + }, + { + "type": "HTMLTagClose", + "range": [ + 57, + 58 + ], + "loc": { + "start": { + "line": 3, + "column": 10 + }, + "end": { + "line": 3, + "column": 11 + } + }, + "value": "" + } + ], + "comments": [], + "errors": [] +} \ No newline at end of file diff --git a/test/fixtures/document-fragment/textarea-in-html/source.html b/test/fixtures/document-fragment/textarea-in-html/source.html new file mode 100644 index 00000000..cbad1a36 --- /dev/null +++ b/test/fixtures/document-fragment/textarea-in-html/source.html @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/test/fixtures/document-fragment/textarea-in-html/token-ranges.json b/test/fixtures/document-fragment/textarea-in-html/token-ranges.json new file mode 100644 index 00000000..762c1a1b --- /dev/null +++ b/test/fixtures/document-fragment/textarea-in-html/token-ranges.json @@ -0,0 +1,18 @@ +[ + "", + "\n ", + "<", + " ", + "RCDATA", + " ", + ">", + " ", + "
", + "\n", + "
" +] \ No newline at end of file diff --git a/test/fixtures/document-fragment/textarea-in-html/tree.json b/test/fixtures/document-fragment/textarea-in-html/tree.json new file mode 100644 index 00000000..ab6b3002 --- /dev/null +++ b/test/fixtures/document-fragment/textarea-in-html/tree.json @@ -0,0 +1,46 @@ +[ + { + "type": "VDocumentFragment", + "text": "", + "children": [ + { + "type": "VElement", + "text": "", + "children": [ + { + "type": "VStartTag", + "text": "", + "children": [] + } + ] + } + ] + } +] \ No newline at end of file From 45f8900cb31d372d3531226309373b853986a27d Mon Sep 17 00:00:00 2001 From: Yosuke Ota Date: Mon, 14 Dec 2020 14:03:48 +0900 Subject: [PATCH 015/151] Add defineCustomBlocksVisitor to parserServices (#91) * Add defineCustomBlocksVisitor to parserServices * fix * Update * Add testcase * ignore not SFC --- README.md | 1 + package.json | 4 +- src/common/fix-locations.ts | 67 ++ src/common/parser-options.ts | 9 + src/html/parser.ts | 6 +- src/index.ts | 12 +- src/parser-services.ts | 196 ++++++ src/script/index.ts | 69 +- src/sfc/custom-block/index.ts | 383 +++++++++++ test/define-custom-blocks-visitor.js | 625 ++++++++++++++++++ .../empty-custom-block/document-fragment.json | 189 ++++++ .../empty-custom-block/source.vue | 1 + .../empty-custom-block/token-ranges.json | 7 + .../empty-custom-block/tree.json | 29 + test/index.js | 2 +- 15 files changed, 1525 insertions(+), 75 deletions(-) create mode 100644 src/common/fix-locations.ts create mode 100644 src/sfc/custom-block/index.ts create mode 100644 test/define-custom-blocks-visitor.js create mode 100644 test/fixtures/document-fragment/empty-custom-block/document-fragment.json create mode 100644 test/fixtures/document-fragment/empty-custom-block/source.vue create mode 100644 test/fixtures/document-fragment/empty-custom-block/token-ranges.json create mode 100644 test/fixtures/document-fragment/empty-custom-block/tree.json diff --git a/README.md b/README.md index 6ef377a6..c2e06a24 100644 --- a/README.md +++ b/README.md @@ -173,6 +173,7 @@ But, it cannot be parsed with Vue 2. - `defineTemplateBodyVisitor(templateVisitor, scriptVisitor)` ... returns ESLint visitor to traverse `