From e47b73fb8eea2cb990a5e0f290514d7bbabdfbd7 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Fri, 4 Jul 2025 23:26:04 +0800 Subject: [PATCH 01/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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/32] 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", From a327579a7c8043fc454c1b5c5137ef3417a5a12e Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Tue, 8 Jul 2025 08:51:38 +0800 Subject: [PATCH 32/32] test: fix incorrect `fallback` --- test/test-utils.ts | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/test/test-utils.ts b/test/test-utils.ts index 7048f348..f5305181 100644 --- a/test/test-utils.ts +++ b/test/test-utils.ts @@ -8,6 +8,7 @@ import type { import type { ESLintProgram, Token } from "../src/ast" import type { ParserOptions } from "../src/common/parser-options" import * as escope from "eslint-scope" +import { getFallbackKeys } from "../src/ast" /** * Remove `parent` properties from the given AST. @@ -128,24 +129,4 @@ export function analyze( }) return result - - function getFallbackKeys(node: any) { - return Object.keys(node).filter(fallbackKeysFilter, node) - } - - function fallbackKeysFilter(key: string) { - const value = null - return ( - key !== "comments" && - key !== "leadingComments" && - key !== "loc" && - key !== "parent" && - key !== "range" && - key !== "tokens" && - key !== "trailingComments" && - typeof value === "object" && - // @ts-expect-error -- ignore - (typeof value.type === "string" || Array.isArray(value)) - ) - } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy