From e47b73fb8eea2cb990a5e0f290514d7bbabdfbd7 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Fri, 4 Jul 2025 23:26:04 +0800 Subject: [PATCH 01/31] feat: move `parser-options` to `vitest` --- package.json | 1 + test/{parser-options.js => parser-options.test.ts} | 12 +++++------- vitest.config.ts | 7 +++++++ 3 files changed, 13 insertions(+), 7 deletions(-) rename test/{parser-options.js => parser-options.test.ts} (91%) create mode 100644 vitest.config.ts diff --git a/package.json b/package.json index 63586655..5f7b279a 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "rollup-plugin-sourcemaps": "^0.6.3", "ts-node": "^10.9.2", "typescript": "~5.7.3", + "vitest": "^3.2.4", "wait-on": "^6.0.0", "warun": "^1.0.0" }, diff --git a/test/parser-options.js b/test/parser-options.test.ts similarity index 91% rename from test/parser-options.js rename to test/parser-options.test.ts index 3c7e4e1b..12d82efd 100644 --- a/test/parser-options.js +++ b/test/parser-options.test.ts @@ -2,12 +2,10 @@ * @author Toru Nagashima * See LICENSE file in root directory for full license. */ -"use strict" -const assert = require("assert") -const { parseForESLint } = require("../src") -const eslint = require("eslint") -const Linter = eslint.Linter +import { describe, it, assert } from "vitest" +import { parseForESLint } from "../src" +import { Linter } from "eslint" describe("parserOptions", () => { describe("parser", () => { @@ -33,7 +31,7 @@ describe("parserOptions", () => { it("false then skip parsing '` - const config = { + const config: Linter.Config = { files: ["*.vue"], plugins: { vue: plugin, @@ -57,7 +55,7 @@ describe("parserOptions", () => { it("Fail in ` - const config = { + const config: Linter.Config = { files: ["*.vue"], plugins: { vue: plugin, diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 00000000..b4b08887 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,7 @@ +import { defineConfig} from 'vitest/config' + +export default defineConfig({ + test: { + include: ['test/parser-options.test.ts'] + } +}) \ No newline at end of file From 1cdfa2f9ee5d8367e6deb7eb5d47a3a62e7c1f70 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sat, 5 Jul 2025 00:13:02 +0800 Subject: [PATCH 02/31] feat: move `crlf` to `vitest` --- test/{crlf.js => crlf.test.ts} | 21 +++++++++++---------- vitest.config.ts | 10 +++++----- 2 files changed, 16 insertions(+), 15 deletions(-) rename test/{crlf.js => crlf.test.ts} (73%) diff --git a/test/crlf.js b/test/crlf.test.ts similarity index 73% rename from test/crlf.js rename to test/crlf.test.ts index d35ce260..c2ecb46d 100644 --- a/test/crlf.js +++ b/test/crlf.test.ts @@ -1,9 +1,10 @@ -const assert = require("assert") -const parser = require("../src") +import type { VElement, VText } from "../src/ast" +import { describe, it, assert } from "vitest" +import { parseForESLint } from "../src" describe("About CRLF tests", () => { it("should not contain CR in `" - const config = { + const config: eslint.Linter.Config = { languageOptions: { parser, parserOptions: { @@ -882,7 +889,7 @@ describe("Basic tests", async () => { it("should notify 1 no-undef error", () => { const code = "" - const config = { + const config: eslint.Linter.Config = { languageOptions: { parser, }, @@ -917,7 +924,7 @@ export default {} ` const result = parseForESLint(code, { sourceType: "module" }) - const comments = result.ast.comments + const comments = result.ast.comments! // Should have 2 comments assert.strictEqual(comments.length, 2) @@ -937,7 +944,7 @@ export default {} }) }) -function buildPlugins(rule) { +function buildPlugins(rule: Rule.RuleModule) { return { test: { rules: { diff --git a/vitest.config.ts b/vitest.config.ts index d1299b09..266ce87a 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -3,7 +3,7 @@ import { defineConfig } from "vitest/config" export default defineConfig({ test: { include: [ - "test/{parser-options,crlf,define-document-visitor,define-custom-blocks-visitor,parser-options-project,document-fragment,tokens,variables-references,ast}.test.ts", + "test/{parser-options,crlf,define-document-visitor,define-custom-blocks-visitor,parser-options-project,document-fragment,tokens,variables-references,ast,index}.test.ts", ], }, }) From 8099d38238e000ccf1d410d9797b681addbc86bc Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sat, 5 Jul 2025 22:25:12 +0800 Subject: [PATCH 16/31] refactor: move all test to `vitest` --- package.json | 6 +-- src/index.ts | 2 +- test/define-custom-blocks-visitor.test.ts | 1 + .../{integrations.js => integrations.test.ts} | 50 ++++++++--------- .../{eslint-compat.js => eslint-compat.ts} | 53 +++++++------------ test/parser-options-project.test.ts | 1 + vitest.config.ts | 6 +-- 7 files changed, 54 insertions(+), 65 deletions(-) rename test/{integrations.js => integrations.test.ts} (71%) rename test/lib/{eslint-compat.js => eslint-compat.ts} (67%) diff --git a/package.json b/package.json index 35877776..d0988bff 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ "@eslint/eslintrc": "^3.2.0", "@eslint/js": "^9.19.0", "@types/debug": "^4.1.7", - "@types/espree": "^10.1.0", "@types/estree": "^1.0.0", "@types/fs-extra": "^11.0.4", "@types/mocha": "^9.0.0", @@ -73,9 +72,8 @@ "lint": "eslint src test package.json", "pretest": "run-s build lint", "test": "npm run -s test:mocha", - "test:mocha": "mocha --require ts-node/register \"test/*.js\" --reporter dot --timeout 60000", - "test:cover": "nyc mocha \"test/*.js\" --reporter dot --timeout 60000", - "test:debug": "mocha --require ts-node/register/transpile-only \"test/*.js\" --reporter dot --timeout 60000", + "test:vitest": "vitest", + "test:cover": "vitest --coverage", "update-fixtures": "ts-node --transpile-only scripts/update-fixtures-ast.js && ts-node --transpile-only scripts/update-fixtures-document-fragment.js", "preversion": "npm test", "version": "npm run -s build", diff --git a/src/index.ts b/src/index.ts index 13cb5300..45d43d64 100644 --- a/src/index.ts +++ b/src/index.ts @@ -84,7 +84,7 @@ export function parseForESLint( * @param options The parser options. * @returns The parsing result. */ -export function parse(code: string, options: any): AST.ESLintProgram { +export function parse(code: string, options?: any): AST.ESLintProgram { return parseForESLint(code, options).ast } diff --git a/test/define-custom-blocks-visitor.test.ts b/test/define-custom-blocks-visitor.test.ts index 0da7e5cc..cd83bf2d 100644 --- a/test/define-custom-blocks-visitor.test.ts +++ b/test/define-custom-blocks-visitor.test.ts @@ -13,6 +13,7 @@ import { assert, describe, it } from "vitest" import { Linter } from "eslint" import { builtinRules } from "eslint/use-at-your-own-risk" import jsonParser from "jsonc-eslint-parser" +// @ts-expect-error -- ignore import * as espree from "espree" import * as parser from "../src" import type { Program } from "estree" diff --git a/test/integrations.js b/test/integrations.test.ts similarity index 71% rename from test/integrations.js rename to test/integrations.test.ts index 88e9c501..65dbfbb4 100644 --- a/test/integrations.js +++ b/test/integrations.test.ts @@ -2,16 +2,18 @@ // Requirements //------------------------------------------------------------------------------ -const assert = require("assert") -const path = require("path") -const fs = require("fs-extra") -const cp = require("child_process") -const eslintCompat = require("./lib/eslint-compat") +import { assert, beforeAll, describe, it } from "vitest" +import path from "path" +import fs from "fs-extra" +import cp from "child_process" +import eslintCompat from "./lib/eslint-compat" +import * as ESLintRaw from "eslint" //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ +// eslint-disable-next-line no-undef const FIXTURE_DIR = path.join(__dirname, "fixtures/integrations") //------------------------------------------------------------------------------ @@ -19,15 +21,19 @@ const FIXTURE_DIR = path.join(__dirname, "fixtures/integrations") //------------------------------------------------------------------------------ describe("Integration tests", () => { + beforeAll(async () => { + await import("ts-node/register") + }) for (const target of fs.readdirSync(FIXTURE_DIR)) { it(target, async () => { - let ESLint = eslintCompat(require("eslint")).ESLint + let ESLint = eslintCompat(ESLintRaw).ESLint if (fs.existsSync(path.join(FIXTURE_DIR, target, "package.json"))) { const originalCwd = process.cwd() try { process.chdir(path.join(FIXTURE_DIR, target)) cp.execSync("npm i", { stdio: "inherit" }) ESLint = eslintCompat( + // eslint-disable-next-line @typescript-eslint/no-require-imports require( path.join( FIXTURE_DIR, @@ -46,7 +52,7 @@ describe("Integration tests", () => { }) const report = await cli.lintFiles(["**/*.vue"]) - const outputPath = path.join(FIXTURE_DIR, target, `output.json`) + const outputPath = path.join(FIXTURE_DIR, target, "output.json") const expected = JSON.parse(fs.readFileSync(outputPath, "utf8")) try { assert.deepStrictEqual( @@ -59,7 +65,7 @@ describe("Integration tests", () => { const actualPath = path.join( FIXTURE_DIR, target, - `_actual.json`, + "_actual.json", ) fs.writeFileSync( actualPath, @@ -72,22 +78,18 @@ describe("Integration tests", () => { function normalizeReport(report, option = {}) { return report .filter((res) => res.messages.length) - .map((res) => { - return { - filePath: res.filePath - .replace(cwd, "") - .replace(/\\/gu, "/"), - messages: res.messages.map((msg) => { - return { - ruleId: msg.ruleId, - line: msg.line, - ...(option.withoutMessage - ? {} - : { message: msg.message }), - } - }), - } - }) + .map((res) => ({ + filePath: res.filePath + .replace(cwd, "") + .replace(/\\/gu, "/"), + messages: res.messages.map((msg) => ({ + ruleId: msg.ruleId, + line: msg.line, + ...(option.withoutMessage + ? {} + : { message: msg.message }), + })), + })) .sort((a, b) => a.filePath < b.filePath ? -1 diff --git a/test/lib/eslint-compat.js b/test/lib/eslint-compat.ts similarity index 67% rename from test/lib/eslint-compat.js rename to test/lib/eslint-compat.ts index 9077ec55..2f29fdba 100644 --- a/test/lib/eslint-compat.js +++ b/test/lib/eslint-compat.ts @@ -1,11 +1,6 @@ -"use strict" +import type { ESLint } from "eslint" -/** - * @typedef {import('eslint')} eslint - */ - -/** @param {eslint} eslint */ -module.exports = function compat(eslint) { +export default function compat(eslint: any) { return { ESLint: eslint.ESLint || getESLintClassForV6(eslint), RuleTester: eslint.RuleTester, @@ -13,15 +8,16 @@ module.exports = function compat(eslint) { } } -/** @returns {typeof eslint.ESLint} */ -function getESLintClassForV6(eslint) { +function getESLintClassForV6(eslint: any): ESLint { class ESLintForV6 { + public engine + static get version() { return eslint.CLIEngine.version } - /** @param {eslint.ESLint.Options} options */ - constructor(options) { + // eslint-disable-next-line @typescript-eslint/explicit-member-accessibility + constructor(options: ESLint.Options) { const { overrideConfig: { plugins, @@ -40,8 +36,7 @@ function getESLintClassForV6(eslint) { plugins: pluginsMap, ...otherOptions } = options || {} - /** @type {eslint.CLIEngine.Options} */ - const newOptions = { + const newOptions: CLIEngine.Options = { fix: Boolean(fix), reportUnusedDisableDirectives: reportUnusedDisableDirectives ? reportUnusedDisableDirectives !== "off" @@ -64,7 +59,7 @@ function getESLintClassForV6(eslint) { } return o }, - /** @type {NonNullable} */ {}, + {} satisfies NonNullable, ) : undefined, ...overrideConfig, @@ -76,41 +71,33 @@ function getESLintClassForV6(eslint) { } } - /** - * @param {Parameters} params - * @returns {ReturnType} - */ - async lintText(...params) { + async lintText( + ...params: Parameters + ): ReturnType { const result = this.engine.executeOnText( params[0], - params[1].filePath, + params[1]!.filePath, ) return result.results } - /** - * @param {Parameters} params - * @returns {ReturnType} - */ - async lintFiles(...params) { + async lintFiles( + ...params: Parameters + ): ReturnType { const result = this.engine.executeOnFiles( Array.isArray(params[0]) ? params[0] : [params[0]], ) return result.results } - /** - * @param {Parameters} params - * @returns {ReturnType} - */ - static async outputFixes(...params) { + static async outputFixes( + ...params: Parameters + ): ReturnType { return eslint.CLIEngine.outputFixes({ results: params[0], }) } } - /** @type {typeof eslint.ESLint} */ - const eslintClass = /** @type {any} */ ESLintForV6 - return eslintClass + return ESLintForV6 as any } diff --git a/test/parser-options-project.test.ts b/test/parser-options-project.test.ts index 257f4ded..77c8c51d 100644 --- a/test/parser-options-project.test.ts +++ b/test/parser-options-project.test.ts @@ -1,5 +1,6 @@ import { describe, it, assert } from "vitest" import { parseForESLint } from "../src" +// @ts-expect-error -- ignore import * as espree from "espree" import type { Linter } from "eslint" diff --git a/vitest.config.ts b/vitest.config.ts index 266ce87a..4aca483c 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -2,8 +2,8 @@ import { defineConfig } from "vitest/config" export default defineConfig({ test: { - include: [ - "test/{parser-options,crlf,define-document-visitor,define-custom-blocks-visitor,parser-options-project,document-fragment,tokens,variables-references,ast,index}.test.ts", - ], + reporters: "dot", + include: ["test/*.test.ts"], + teardownTimeout: 60000, }, }) From f3f67de3b4cf8da3a079522101f0d066bbf8b3bb Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sat, 5 Jul 2025 22:53:05 +0800 Subject: [PATCH 17/31] chore: enhance type definition --- test/integrations.test.ts | 8 ++++++-- test/lib/eslint-compat.ts | 33 +++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/test/integrations.test.ts b/test/integrations.test.ts index 65dbfbb4..e8604871 100644 --- a/test/integrations.test.ts +++ b/test/integrations.test.ts @@ -22,6 +22,7 @@ const FIXTURE_DIR = path.join(__dirname, "fixtures/integrations") describe("Integration tests", () => { beforeAll(async () => { + // @ts-expect-error -- ignore await import("ts-node/register") }) for (const target of fs.readdirSync(FIXTURE_DIR)) { @@ -75,8 +76,11 @@ describe("Integration tests", () => { throw e } - function normalizeReport(report, option = {}) { - return report + function normalizeReport( + result: ESLintRaw.ESLint.LintResult[], + option: { withoutMessage?: boolean } = {}, + ) { + return result .filter((res) => res.messages.length) .map((res) => ({ filePath: res.filePath diff --git a/test/lib/eslint-compat.ts b/test/lib/eslint-compat.ts index 2f29fdba..ae96362f 100644 --- a/test/lib/eslint-compat.ts +++ b/test/lib/eslint-compat.ts @@ -1,6 +1,10 @@ -import type { ESLint } from "eslint" +import type { ESLint, Linter, RuleTester } from "eslint" -export default function compat(eslint: any) { +export default function compat(eslint: any): { + ESLint: typeof ESLint + RuleTester: typeof RuleTester + Linter: typeof Linter +} { return { ESLint: eslint.ESLint || getESLintClassForV6(eslint), RuleTester: eslint.RuleTester, @@ -8,16 +12,17 @@ export default function compat(eslint: any) { } } -function getESLintClassForV6(eslint: any): ESLint { +function getESLintClassForV6(eslint: any): typeof ESLint { class ESLintForV6 { public engine + // eslint-disable-next-line @typescript-eslint/explicit-member-accessibility static get version() { return eslint.CLIEngine.version } // eslint-disable-next-line @typescript-eslint/explicit-member-accessibility - constructor(options: ESLint.Options) { + constructor(options: any) { const { overrideConfig: { plugins, @@ -29,14 +34,14 @@ function getESLintClassForV6(eslint: any): ESLint { plugins: [], globals: {}, rules: {}, - }, + } as any, overrideConfigFile, fix, reportUnusedDisableDirectives, plugins: pluginsMap, ...otherOptions } = options || {} - const newOptions: CLIEngine.Options = { + const newOptions = { fix: Boolean(fix), reportUnusedDisableDirectives: reportUnusedDisableDirectives ? reportUnusedDisableDirectives !== "off" @@ -59,7 +64,7 @@ function getESLintClassForV6(eslint: any): ESLint { } return o }, - {} satisfies NonNullable, + {} as Record, ) : undefined, ...overrideConfig, @@ -71,29 +76,33 @@ function getESLintClassForV6(eslint: any): ESLint { } } + // eslint-disable-next-line @typescript-eslint/explicit-member-accessibility async lintText( ...params: Parameters ): ReturnType { - const result = this.engine.executeOnText( + const result = await this.engine.executeOnText( params[0], params[1]!.filePath, ) return result.results } + // eslint-disable-next-line @typescript-eslint/explicit-member-accessibility async lintFiles( ...params: Parameters ): ReturnType { - const result = this.engine.executeOnFiles( + const result = await this.engine.executeOnFiles( Array.isArray(params[0]) ? params[0] : [params[0]], ) return result.results } + // eslint-disable-next-line @typescript-eslint/explicit-member-accessibility static async outputFixes( - ...params: Parameters - ): ReturnType { - return eslint.CLIEngine.outputFixes({ + ...params: Parameters + ): ReturnType { + // eslint-disable-next-line no-return-await + return await eslint.CLIEngine.outputFixes({ results: params[0], }) } From 3cd2989a882e3b44f248d2552891de36a7788374 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sat, 5 Jul 2025 22:58:20 +0800 Subject: [PATCH 18/31] chore: uninstall mocha --- package.json | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index d0988bff..7f5b9a75 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,6 @@ "@types/debug": "^4.1.7", "@types/estree": "^1.0.0", "@types/fs-extra": "^11.0.4", - "@types/mocha": "^9.0.0", "@types/node": "^18.8.4", "@types/semver": "^7.3.12", "@typescript-eslint/eslint-plugin": "^8.22.0", @@ -48,7 +47,6 @@ "eslint-plugin-unicorn": "^57.0.0", "fs-extra": "^10.0.0", "jsonc-eslint-parser": "^2.0.3", - "mocha": "^9.1.3", "npm-run-all": "^4.1.5", "nyc": "^15.1.0", "opener": "^1.5.2", @@ -67,12 +65,11 @@ "scripts": { "prebuild": "npm run -s clean", "build": "tsc --module es2015 && rollup -c -o index.js && dts-bundle --name vue-eslint-parser --main .temp/index.d.ts --out ../index.d.ts", - "clean": "rimraf .nyc_output .temp coverage index.*", + "clean": "rimraf .temp index.*", "coverage": "opener ./coverage/lcov-report/index.html", "lint": "eslint src test package.json", "pretest": "run-s build lint", - "test": "npm run -s test:mocha", - "test:vitest": "vitest", + "test": "vitest", "test:cover": "vitest --coverage", "update-fixtures": "ts-node --transpile-only scripts/update-fixtures-ast.js && ts-node --transpile-only scripts/update-fixtures-document-fragment.js", "preversion": "npm test", @@ -82,7 +79,6 @@ "watch": "run-p watch:*", "watch:tsc": "tsc --module es2015 --watch", "watch:rollup": "wait-on .temp/index.js && rollup -c -o index.js --watch", - "watch:test": "wait-on index.js && warun index.js \"test/*.js\" \"test/fixtures/ast/*/*.json\" \"test/fixtures/*\" --debounce 1000 --no-initial -- nyc mocha \"test/*.js\" --reporter dot --timeout 10000", "watch:update-ast": "wait-on index.js && warun index.js \"test/fixtures/ast/*/*.vue\" -- ts-node scripts/update-fixtures-ast.js", "watch:coverage-report": "wait-on coverage/lcov-report/index.html && opener coverage/lcov-report/index.html" }, From 94d42efbdbc0b3c6157d58037f8ffa2023f9458f Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sat, 5 Jul 2025 23:07:32 +0800 Subject: [PATCH 19/31] test: update --- package.json | 4 +++- vitest.config.ts | 6 +++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7f5b9a75..977a007d 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,8 @@ "@types/semver": "^7.3.12", "@typescript-eslint/eslint-plugin": "^8.22.0", "@typescript-eslint/parser": "^8.22.0", + "@vitest/coverage-v8": "^3.2.4", + "@vitest/ui": "^3.2.4", "chokidar": "^3.5.2", "cross-spawn": "^7.0.3", "dts-bundle": "^0.7.3", @@ -66,7 +68,7 @@ "prebuild": "npm run -s clean", "build": "tsc --module es2015 && rollup -c -o index.js && dts-bundle --name vue-eslint-parser --main .temp/index.d.ts --out ../index.d.ts", "clean": "rimraf .temp index.*", - "coverage": "opener ./coverage/lcov-report/index.html", + "coverage": "vitest --ui", "lint": "eslint src test package.json", "pretest": "run-s build lint", "test": "vitest", diff --git a/vitest.config.ts b/vitest.config.ts index 4aca483c..867408c9 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -3,7 +3,11 @@ import { defineConfig } from "vitest/config" export default defineConfig({ test: { reporters: "dot", - include: ["test/*.test.ts"], + include: ["test/**/*.test.ts"], teardownTimeout: 60000, + coverage: { + enabled: true, + include: ["src"], + }, }, }) From 736756749fa79de33177c7abb90a5d15d16f4837 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sat, 5 Jul 2025 23:15:18 +0800 Subject: [PATCH 20/31] chore: update --- .gitignore | 2 -- eslint.config.mjs | 2 -- package.json | 5 +---- test/index.test.ts | 2 ++ test/parser-options.test.ts | 5 +++-- 5 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 8bf60fc5..f46f6afb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,4 @@ -/.nyc_output /.temp -/coverage node_modules /test/temp /index.* diff --git a/eslint.config.mjs b/eslint.config.mjs index 5e81622f..635c3b42 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -22,9 +22,7 @@ const compat = new FlatCompat({ export default [ { ignores: [ - ".nyc_output", ".temp", - "coverage", "**/node_modules", "src/html/util/alternative-cr.ts", "src/html/util/attribute-names.ts", diff --git a/package.json b/package.json index 977a007d..933d18eb 100644 --- a/package.json +++ b/package.json @@ -50,8 +50,6 @@ "fs-extra": "^10.0.0", "jsonc-eslint-parser": "^2.0.3", "npm-run-all": "^4.1.5", - "nyc": "^15.1.0", - "opener": "^1.5.2", "prettier": "^3.4.2", "rimraf": "^3.0.2", "rollup": "^2.60.0", @@ -81,8 +79,7 @@ "watch": "run-p watch:*", "watch:tsc": "tsc --module es2015 --watch", "watch:rollup": "wait-on .temp/index.js && rollup -c -o index.js --watch", - "watch:update-ast": "wait-on index.js && warun index.js \"test/fixtures/ast/*/*.vue\" -- ts-node scripts/update-fixtures-ast.js", - "watch:coverage-report": "wait-on coverage/lcov-report/index.html && opener coverage/lcov-report/index.html" + "watch:update-ast": "wait-on index.js && warun index.js \"test/fixtures/ast/*/*.vue\" -- ts-node scripts/update-fixtures-ast.js" }, "repository": { "type": "git", diff --git a/test/index.test.ts b/test/index.test.ts index 9f108bfe..98fd6df4 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -11,6 +11,7 @@ import type { Rule } from "eslint" import path from "node:path" import { describe, it, assert, beforeEach, afterEach } from "vitest" +// @ts-expect-error -- ignore import * as tsParser from "@typescript-eslint/parser" import fs from "fs-extra" import * as eslint from "eslint" @@ -49,6 +50,7 @@ const BABEL_PARSER_OPTIONS = { describe("Basic tests", async () => { const ESLint = await eslint.loadESLint({ useFlatConfig: true }) const Linter = class extends eslint.Linter { + // eslint-disable-next-line @typescript-eslint/explicit-member-accessibility constructor() { super({ configType: "flat" }) } diff --git a/test/parser-options.test.ts b/test/parser-options.test.ts index 12d82efd..37aa60a9 100644 --- a/test/parser-options.test.ts +++ b/test/parser-options.test.ts @@ -5,13 +5,14 @@ import { describe, it, assert } from "vitest" import { parseForESLint } from "../src" +import type { ESLint } from "eslint" import { Linter } from "eslint" describe("parserOptions", () => { describe("parser", () => { const linter = new Linter({ configType: "flat" }) - const parser = { parseForESLint } - const plugin = { + const parser: Linter.Parser = { parseForESLint } + const plugin: ESLint.Plugin = { rules: { "template-test": { create(context) { From 7aa76c652bf85214e48ebe425fad5558e5f289eb Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sat, 5 Jul 2025 23:31:53 +0800 Subject: [PATCH 21/31] chore: update ci --- .github/workflows/CI.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index e1d1e9de..09e612c1 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -58,7 +58,7 @@ jobs: - name: Build run: npm run -s build - name: Test - run: npm run -s test:mocha + run: npm run -s test test-for-old-eslint: name: Test strategy: @@ -82,4 +82,4 @@ jobs: - name: Install ESLint v${{ matrix.eslint }} run: node scripts/ci-install-eslint ${{ matrix.eslint }} - name: Test - run: npm run -s test:debug + run: npm run -s test From dd1335a1d17e284eb0c89d330c71ce6acca09d7f Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sat, 5 Jul 2025 23:39:45 +0800 Subject: [PATCH 22/31] fix: update something maybe wrong --- test/ast.test.ts | 68 ++++++++++------------- test/define-custom-blocks-visitor.test.ts | 3 +- test/test-utils.ts | 1 + 3 files changed, 32 insertions(+), 40 deletions(-) diff --git a/test/ast.test.ts b/test/ast.test.ts index df310180..b402aa91 100644 --- a/test/ast.test.ts +++ b/test/ast.test.ts @@ -71,28 +71,23 @@ function getTree(source: string, parserOptions: any) { }, }), } - const result = linter.verify( - source, - { - files: ["**"], - plugins: { - test: { - rules: { - maketree, - }, + const result = linter.verify(source, { + files: ["**"], + plugins: { + test: { + rules: { + maketree, }, }, - languageOptions: { - parser, - ecmaVersion: parserOptions.ecmaVersion ?? "latest", - sourceType: parserOptions.sourceType ?? "module", - parserOptions, - }, - rules: { "test/maketree": "error" }, }, - undefined, - true, - ) + languageOptions: { + parser, + ecmaVersion: parserOptions.ecmaVersion ?? "latest", + sourceType: parserOptions.sourceType ?? "module", + parserOptions, + }, + rules: { "test/maketree": "error" }, + }) assert.deepStrictEqual(result, []) return root.children @@ -122,7 +117,7 @@ function validateParent(source: string, parserOptions: any) { ruleContext.sourceCode.parserServices.defineTemplateBodyVisitor({ "*"(node: Node) { if (stack.length >= 1) { - const parent = stack.at(-1) + const parent = stack.at(-1)! assert( node.parent === parent, `The parent of ${nodeToString( @@ -141,28 +136,23 @@ function validateParent(source: string, parserOptions: any) { }, }), } - const result = linter.verify( - source, - { - files: ["**"], - plugins: { - test: { - rules: { - validateparent, - }, + const result = linter.verify(source, { + files: ["**"], + plugins: { + test: { + rules: { + validateparent, }, }, - languageOptions: { - parser, - ecmaVersion: parserOptions.ecmaVersion ?? "latest", - sourceType: parserOptions.sourceType ?? "module", - parserOptions, - }, - rules: { "test/validateparent": "error" }, }, - undefined, - true, - ) + languageOptions: { + parser, + ecmaVersion: parserOptions.ecmaVersion ?? "latest", + sourceType: parserOptions.sourceType ?? "module", + parserOptions, + }, + rules: { "test/validateparent": "error" }, + }) assert.deepStrictEqual(result, []) } diff --git a/test/define-custom-blocks-visitor.test.ts b/test/define-custom-blocks-visitor.test.ts index cd83bf2d..97c7298d 100644 --- a/test/define-custom-blocks-visitor.test.ts +++ b/test/define-custom-blocks-visitor.test.ts @@ -461,7 +461,8 @@ describe("parserServices.defineCustomBlocksVisitor tests", () => { const linter = createLinter() const config = getConfig( (lang, block) => - (lang === "json" && lang === "json5") || + lang === "json" || + lang === "json5" || (!lang && block.name === "i18n"), ) diff --git a/test/test-utils.ts b/test/test-utils.ts index 993851fc..7048f348 100644 --- a/test/test-utils.ts +++ b/test/test-utils.ts @@ -144,6 +144,7 @@ export function analyze( key !== "tokens" && key !== "trailingComments" && typeof value === "object" && + // @ts-expect-error -- ignore (typeof value.type === "string" || Array.isArray(value)) ) } From f558d6a155e290ed75c3e8db4bc1187110aac319 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sat, 5 Jul 2025 23:59:29 +0800 Subject: [PATCH 23/31] chore: update, try fix ci --- .gitignore | 1 + eslint.config.mjs | 2 +- package.json | 2 +- tsconfig.json | 2 +- tsconfig.test.json | 7 +++++++ vitest.config.ts | 1 - 6 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 tsconfig.test.json diff --git a/.gitignore b/.gitignore index f46f6afb..1afb3f2f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /.temp node_modules +/coverage /test/temp /index.* /npm-debug.log diff --git a/eslint.config.mjs b/eslint.config.mjs index 635c3b42..f44e79b9 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -62,7 +62,7 @@ export default [ }, loggerFn: false, - project: "tsconfig.json", + project: ["tsconfig.json", "tsconfig.test.json"], }, }, diff --git a/package.json b/package.json index 933d18eb..2f33bb99 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "prebuild": "npm run -s clean", "build": "tsc --module es2015 && rollup -c -o index.js && dts-bundle --name vue-eslint-parser --main .temp/index.d.ts --out ../index.d.ts", "clean": "rimraf .temp index.*", - "coverage": "vitest --ui", + "coverage": "vitest --coverage --ui", "lint": "eslint src test package.json", "pretest": "run-s build lint", "test": "vitest", diff --git a/tsconfig.json b/tsconfig.json index 5fe9fd6e..c5dc0e4c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -37,5 +37,5 @@ "skipLibCheck": true }, - "include": ["src/**/*.ts", "test/**/*.ts", "vitest.config.ts"] + "include": ["src/**/*.ts"] } diff --git a/tsconfig.test.json b/tsconfig.test.json new file mode 100644 index 00000000..e507e28e --- /dev/null +++ b/tsconfig.test.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "moduleResolution": "Bundler" + }, + "include": ["test/**/*.ts", "vitest.config.ts"] +} diff --git a/vitest.config.ts b/vitest.config.ts index 867408c9..c00bfcdc 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -6,7 +6,6 @@ export default defineConfig({ include: ["test/**/*.test.ts"], teardownTimeout: 60000, coverage: { - enabled: true, include: ["src"], }, }, From 6c1b3a9c780b6023b3b814f111064bace5d7a5ec Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sun, 6 Jul 2025 00:15:36 +0800 Subject: [PATCH 24/31] chore: up --- package.json | 1 - test/define-custom-blocks-visitor.test.ts | 7 +++---- test/document-fragment.test.ts | 4 ++-- test/index.test.ts | 5 ++--- test/integrations.test.ts | 7 +++---- test/parser-options-project.test.ts | 1 - 6 files changed, 10 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 2f33bb99..852636c3 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "@eslint/js": "^9.19.0", "@types/debug": "^4.1.7", "@types/estree": "^1.0.0", - "@types/fs-extra": "^11.0.4", "@types/node": "^18.8.4", "@types/semver": "^7.3.12", "@typescript-eslint/eslint-plugin": "^8.22.0", diff --git a/test/define-custom-blocks-visitor.test.ts b/test/define-custom-blocks-visitor.test.ts index 97c7298d..f57ddf15 100644 --- a/test/define-custom-blocks-visitor.test.ts +++ b/test/define-custom-blocks-visitor.test.ts @@ -7,13 +7,12 @@ //------------------------------------------------------------------------------ import type { ESLint, Rule } from "eslint" -import type { VElement } from "../src/ast" +import type { Location, VElement } from "../src/ast" import type { CustomBlockContext } from "../src/sfc/custom-block" import { assert, describe, it } from "vitest" import { Linter } from "eslint" import { builtinRules } from "eslint/use-at-your-own-risk" import jsonParser from "jsonc-eslint-parser" -// @ts-expect-error -- ignore import * as espree from "espree" import * as parser from "../src" import type { Program } from "estree" @@ -55,7 +54,7 @@ const noParsingErrorRule: Rule.RuleModule = { create(context) { const parseError = context.getSourceCode().parserServices.parseError if (parseError) { - let loc = undefined + let loc: Location | undefined = undefined if ("column" in parseError && "lineNumber" in parseError) { loc = { line: parseError.lineNumber, @@ -79,7 +78,7 @@ const noParsingErrorRule2: Rule.RuleModule = { create(context: any) { const parseError = context.parserServices.parseError if (parseError) { - let loc = undefined + let loc: Location | undefined = undefined if ("column" in parseError && "lineNumber" in parseError) { loc = { line: parseError.lineNumber, diff --git a/test/document-fragment.test.ts b/test/document-fragment.test.ts index 7988e6fd..d3f8a740 100644 --- a/test/document-fragment.test.ts +++ b/test/document-fragment.test.ts @@ -3,8 +3,8 @@ //------------------------------------------------------------------------------ import type { VDocumentFragment } from "../src/ast" -import fs from "fs" -import path from "path" +import fs from "node:fs" +import path from "node:path" import { describe, it, assert } from "vitest" import * as parser from "../src" import { replacer } from "./test-utils" diff --git a/test/index.test.ts b/test/index.test.ts index 98fd6df4..852ec521 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -11,10 +11,9 @@ import type { Rule } from "eslint" import path from "node:path" import { describe, it, assert, beforeEach, afterEach } from "vitest" -// @ts-expect-error -- ignore -import * as tsParser from "@typescript-eslint/parser" +import tsParser from "@typescript-eslint/parser" import fs from "fs-extra" -import * as eslint from "eslint" +import eslint from "eslint" import { parse, parseForESLint } from "../src" import * as parser from "../src" import type { Node, VAttribute, VElement, VText } from "../src/ast" diff --git a/test/integrations.test.ts b/test/integrations.test.ts index e8604871..651e6616 100644 --- a/test/integrations.test.ts +++ b/test/integrations.test.ts @@ -3,11 +3,11 @@ //------------------------------------------------------------------------------ import { assert, beforeAll, describe, it } from "vitest" -import path from "path" -import fs from "fs-extra" +import path from "node:path" +import fs from "node:fs" import cp from "child_process" import eslintCompat from "./lib/eslint-compat" -import * as ESLintRaw from "eslint" +import ESLintRaw from "eslint" //------------------------------------------------------------------------------ // Helpers @@ -22,7 +22,6 @@ const FIXTURE_DIR = path.join(__dirname, "fixtures/integrations") describe("Integration tests", () => { beforeAll(async () => { - // @ts-expect-error -- ignore await import("ts-node/register") }) for (const target of fs.readdirSync(FIXTURE_DIR)) { diff --git a/test/parser-options-project.test.ts b/test/parser-options-project.test.ts index 77c8c51d..257f4ded 100644 --- a/test/parser-options-project.test.ts +++ b/test/parser-options-project.test.ts @@ -1,6 +1,5 @@ import { describe, it, assert } from "vitest" import { parseForESLint } from "../src" -// @ts-expect-error -- ignore import * as espree from "espree" import type { Linter } from "eslint" From a27eccc1c9a3de75a5a29318bac266f39712aa92 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sun, 6 Jul 2025 00:36:25 +0800 Subject: [PATCH 25/31] ci: try fix --- .github/workflows/CI.yml | 2 -- package.json | 4 ++-- scripts/ci-install-eslint.js | 3 +++ 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 09e612c1..6bb0a761 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -55,8 +55,6 @@ jobs: run: npm install -f - name: Install ESLint v${{ matrix.eslint }} run: node scripts/ci-install-eslint ${{ matrix.eslint }} - - name: Build - run: npm run -s build - name: Test run: npm run -s test test-for-old-eslint: diff --git a/package.json b/package.json index 852636c3..df18afcf 100644 --- a/package.json +++ b/package.json @@ -65,9 +65,9 @@ "prebuild": "npm run -s clean", "build": "tsc --module es2015 && rollup -c -o index.js && dts-bundle --name vue-eslint-parser --main .temp/index.d.ts --out ../index.d.ts", "clean": "rimraf .temp index.*", - "coverage": "vitest --coverage --ui", + "coverage": "vitest --coverage --ui", "lint": "eslint src test package.json", - "pretest": "run-s build lint", + "pretest": "npm run lint", "test": "vitest", "test:cover": "vitest --coverage", "update-fixtures": "ts-node --transpile-only scripts/update-fixtures-ast.js && ts-node --transpile-only scripts/update-fixtures-document-fragment.js", diff --git a/scripts/ci-install-eslint.js b/scripts/ci-install-eslint.js index c3626692..289481fc 100644 --- a/scripts/ci-install-eslint.js +++ b/scripts/ci-install-eslint.js @@ -1,6 +1,7 @@ "use strict" const { spawn } = require("child_process") +const semver = require("semver") function cd(path) { console.log("$ cd %s", path) @@ -30,6 +31,8 @@ function sh(command) { // Install ESLint of the requested version await sh(`npm install eslint@${requestedVersionSpec} -f`) + if (semver.compare(requestedVersionSpec, "9.0.0")) + await sh(`npm install @types/eslint -f`) // Install ESLint submodule of the requested version // const installedVersion = require("eslint/package.json").version From 5a219168a39d195a87643739cba4dd743bd7bb64 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sun, 6 Jul 2025 00:38:40 +0800 Subject: [PATCH 26/31] chore: up --- scripts/ci-install-eslint.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci-install-eslint.js b/scripts/ci-install-eslint.js index 289481fc..ab180f3b 100644 --- a/scripts/ci-install-eslint.js +++ b/scripts/ci-install-eslint.js @@ -31,7 +31,7 @@ function sh(command) { // Install ESLint of the requested version await sh(`npm install eslint@${requestedVersionSpec} -f`) - if (semver.compare(requestedVersionSpec, "9.0.0")) + if (semver.compare(requestedVersion, "9.0.0")) await sh(`npm install @types/eslint -f`) // Install ESLint submodule of the requested version From 50e1e69541804f6b6d8b5faf35a15006bfe7f6e0 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sun, 6 Jul 2025 00:41:40 +0800 Subject: [PATCH 27/31] ci: fix --- scripts/ci-install-eslint.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/ci-install-eslint.js b/scripts/ci-install-eslint.js index ab180f3b..fe2f96c3 100644 --- a/scripts/ci-install-eslint.js +++ b/scripts/ci-install-eslint.js @@ -1,7 +1,6 @@ "use strict" const { spawn } = require("child_process") -const semver = require("semver") function cd(path) { console.log("$ cd %s", path) @@ -31,8 +30,8 @@ function sh(command) { // Install ESLint of the requested version await sh(`npm install eslint@${requestedVersionSpec} -f`) - if (semver.compare(requestedVersion, "9.0.0")) - await sh(`npm install @types/eslint -f`) + if (Number(requestedVersion) < 9) + await sh(`npm install @types/eslint -D -f`) // Install ESLint submodule of the requested version // const installedVersion = require("eslint/package.json").version From 8acc52a9c9bd997fe25b23707010062870cda237 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sun, 6 Jul 2025 00:45:35 +0800 Subject: [PATCH 28/31] chore: use vite^6 for node18 test --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index df18afcf..b325e750 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "rollup-plugin-sourcemaps": "^0.6.3", "ts-node": "^10.9.2", "typescript": "~5.7.3", + "vite": "^6.3.5", "vitest": "^3.2.4", "wait-on": "^6.0.0", "warun": "^1.0.0" @@ -67,7 +68,6 @@ "clean": "rimraf .temp index.*", "coverage": "vitest --coverage --ui", "lint": "eslint src test package.json", - "pretest": "npm run lint", "test": "vitest", "test:cover": "vitest --coverage", "update-fixtures": "ts-node --transpile-only scripts/update-fixtures-ast.js && ts-node --transpile-only scripts/update-fixtures-document-fragment.js", From 52150d8d04a64a2ec58938f7af0d418fc93b47d5 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sun, 6 Jul 2025 00:47:37 +0800 Subject: [PATCH 29/31] chore: update timeout config --- vitest.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vitest.config.ts b/vitest.config.ts index c00bfcdc..f0cdca4d 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -4,7 +4,7 @@ export default defineConfig({ test: { reporters: "dot", include: ["test/**/*.test.ts"], - teardownTimeout: 60000, + testTimeout: 60000, coverage: { include: ["src"], }, From 2131857218c9282eb052ba4c0e896c9544cde334 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sun, 6 Jul 2025 01:02:37 +0800 Subject: [PATCH 30/31] chore: update --- eslint.config.mjs | 1 + tsconfig.json | 3 ++- tsconfig.test.json | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index f44e79b9..423872c5 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -24,6 +24,7 @@ export default [ ignores: [ ".temp", "**/node_modules", + "coverage", "src/html/util/alternative-cr.ts", "src/html/util/attribute-names.ts", "src/html/util/entities.ts", diff --git a/tsconfig.json b/tsconfig.json index c5dc0e4c..677d8fec 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -37,5 +37,6 @@ "skipLibCheck": true }, - "include": ["src/**/*.ts"] + "include": ["src/**/*.ts"], + "references": [{ "path": "./tsconfig.test.json" }] } diff --git a/tsconfig.test.json b/tsconfig.test.json index e507e28e..a5e080f7 100644 --- a/tsconfig.test.json +++ b/tsconfig.test.json @@ -1,6 +1,11 @@ { "extends": "./tsconfig.json", "compilerOptions": { + "composite": true, + "paths": { + "*": ["typings/*"] + }, + "module": "esnext", "moduleResolution": "Bundler" }, "include": ["test/**/*.ts", "vitest.config.ts"] From 11147906e194e36f6d29a7df83642ee87bcae85f Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sun, 6 Jul 2025 01:12:43 +0800 Subject: [PATCH 31/31] chore: flat diff --- .gitignore | 2 +- eslint.config.mjs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 1afb3f2f..387f51ab 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ /.temp -node_modules /coverage +node_modules /test/temp /index.* /npm-debug.log diff --git a/eslint.config.mjs b/eslint.config.mjs index 423872c5..a46acd53 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -23,8 +23,8 @@ export default [ { ignores: [ ".temp", - "**/node_modules", "coverage", + "**/node_modules", "src/html/util/alternative-cr.ts", "src/html/util/attribute-names.ts", "src/html/util/entities.ts",