diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 69cac752d..1ae716ca8 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -26,12 +26,35 @@ jobs: - name: Lint run: npm run lint + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-node@v6 + with: + node-version: lts/* + + - name: Install Packages + run: npm install + + - name: Build + run: npm run build + + - name: Cache dist + uses: actions/upload-artifact@v5 + with: + retention-days: 3 + name: dist + path: dist + test: name: Test strategy: matrix: node: [18, 20, 21, 'lts/*'] runs-on: ubuntu-latest + needs: + - build steps: - name: Checkout uses: actions/checkout@v5 @@ -41,12 +64,18 @@ jobs: node-version: ${{ matrix.node }} - name: Install Packages run: npm install + - name: Restore dist cache + uses: actions/download-artifact@v6 + with: + name: dist - name: Test run: npm test test-with-eslint-v8: name: Test with ESLint v8 runs-on: ubuntu-latest + needs: + - build steps: - name: Checkout uses: actions/checkout@v5 @@ -58,12 +87,18 @@ jobs: run: npm install - name: Install ESLint v8 run: npm install --save-dev eslint@8 --force + - name: Restore dist cache + uses: actions/download-artifact@v6 + with: + name: dist - name: Test run: npm test test-without-eslint-stylistic: name: Test without ESLint Stylistic runs-on: ubuntu-latest + needs: + - build steps: - name: Checkout uses: actions/checkout@v5 @@ -73,6 +108,10 @@ jobs: run: npm install - name: Uninstall @stylistic/eslint-plugin run: npm uninstall @stylistic/eslint-plugin + - name: Restore dist cache + uses: actions/download-artifact@v6 + with: + name: dist - name: Test run: npm test @@ -82,6 +121,8 @@ jobs: matrix: stylistic: [2, 3, 4] runs-on: ubuntu-latest + needs: + - build steps: - name: Checkout uses: actions/checkout@v5 @@ -91,12 +132,18 @@ jobs: run: npm install - name: Install @stylistic/eslint-plugin v${{ matrix.stylistic }} run: npm install -D @stylistic/eslint-plugin@${{ matrix.stylistic }} --force + - name: Restore dist cache + uses: actions/download-artifact@v6 + with: + name: dist - name: Test run: npm test test-with-typescript-eslint-v7: name: Test with typescript-eslint v7 runs-on: ubuntu-latest + needs: + - build steps: - name: Checkout uses: actions/checkout@v5 @@ -106,5 +153,9 @@ jobs: run: npm install - name: Install @typescript-eslint/parser v7 run: npm install -D @typescript-eslint/parser@7 --force + - name: Restore dist cache + uses: actions/download-artifact@v6 + with: + name: dist - name: Test run: npm test diff --git a/.gitignore b/.gitignore index d6fadf92c..5a7a63a56 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ yarn-error.log /docs/.vitepress/cache typings/eslint/lib/rules eslint-typegen.d.ts +dist diff --git a/docs/.vitepress/theme/components/eslint-code-block.vue b/docs/.vitepress/theme/components/eslint-code-block.vue index 12cd1ff8b..29d7cf0eb 100644 --- a/docs/.vitepress/theme/components/eslint-code-block.vue +++ b/docs/.vitepress/theme/components/eslint-code-block.vue @@ -142,7 +142,7 @@ export default { this.height = `${Math.max(120, 20 * (1 + lines))}px` // Load linter. const [plugin, { Linter }, vueEslintParser, globals] = await Promise.all([ - import('../../../..'), + import('../../../../lib/index'), import('eslint'), import('vue-eslint-parser'), import('globals') diff --git a/lib/index.js b/lib/index.js deleted file mode 100644 index 788f5de9e..000000000 --- a/lib/index.js +++ /dev/null @@ -1,6 +0,0 @@ -'use strict' - -const configs = require('./configs') -const plugin = require('./plugin') - -module.exports = Object.assign(plugin, { configs }) diff --git a/lib/index.ts b/lib/index.ts new file mode 100644 index 000000000..a52f8d635 --- /dev/null +++ b/lib/index.ts @@ -0,0 +1,4 @@ +import configs from './configs/index.js' +import plugin from './plugin.js' + +export default Object.assign(plugin, { configs }) diff --git a/lib/meta.js b/lib/meta.js deleted file mode 100644 index d70069950..000000000 --- a/lib/meta.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict' -const { name, version } = require('../package.json') -module.exports = { name, version } diff --git a/lib/meta.ts b/lib/meta.ts new file mode 100644 index 000000000..aa5e07211 --- /dev/null +++ b/lib/meta.ts @@ -0,0 +1,3 @@ +import pkg from '../package.json' with { type: 'json' } + +export default { name: pkg.name, version: pkg.version } diff --git a/lib/plugin.js b/lib/plugin.js index 7bedbbdf5..dce33001b 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -6,7 +6,7 @@ 'use strict' const plugin = { - meta: require('./meta'), + meta: require('./meta.ts').default, rules: { 'array-bracket-newline': require('./rules/array-bracket-newline'), 'array-bracket-spacing': require('./rules/array-bracket-spacing'), @@ -258,8 +258,8 @@ const plugin = { 'valid-v-text': require('./rules/valid-v-text') }, processors: { - '.vue': require('./processor'), - vue: require('./processor') + '.vue': require('./processor.ts').default, + vue: require('./processor.ts').default } } diff --git a/lib/processor.js b/lib/processor.ts similarity index 73% rename from lib/processor.js rename to lib/processor.ts index b7268fab9..270036172 100644 --- a/lib/processor.js +++ b/lib/processor.ts @@ -1,44 +1,34 @@ /** * @author Toru Nagashima */ -'use strict' +import type { Linter } from 'eslint' +import meta from './meta.ts' -/** - * @typedef {import('eslint').Linter.LintMessage} LintMessage - */ -/** - * @typedef {object} GroupState - * @property {Set} GroupState.disableAllKeys - * @property {Map} GroupState.disableRuleKeys - */ +type LintMessage = Linter.LintMessage + +interface GroupState { + disableAllKeys: Set + disableRuleKeys: Map +} -module.exports = { - /** @param {string} code */ - preprocess(code) { +export default { + preprocess(code: string): string[] { return [code] }, - /** - * @param {LintMessage[][]} messages - * @returns {LintMessage[]} - */ - postprocess(messages) { + postprocess(messages: LintMessage[][]): LintMessage[] { const state = { - /** @type {GroupState} */ block: { - disableAllKeys: new Set(), - disableRuleKeys: new Map() - }, - /** @type {GroupState} */ + disableAllKeys: new Set(), + disableRuleKeys: new Map() + } satisfies GroupState, line: { - disableAllKeys: new Set(), - disableRuleKeys: new Map() - } + disableAllKeys: new Set(), + disableRuleKeys: new Map() + } satisfies GroupState } - /** @type {string[]} */ - const usedDisableDirectiveKeys = [] - /** @type {Map} */ - const unusedDisableDirectiveReports = new Map() + const usedDisableDirectiveKeys: string[] = [] + const unusedDisableDirectiveReports = new Map() // Filter messages which are in disabled area. const filteredMessages = messages[0].filter((message) => { @@ -136,15 +126,14 @@ module.exports = { supportsAutofix: true, - meta: require('./meta') + meta } -/** - * @param {Map} disableRuleKeys - * @param {string} rule - * @param {string} key - */ -function addDisableRule(disableRuleKeys, rule, key) { +function addDisableRule( + disableRuleKeys: GroupState['disableRuleKeys'], + rule: string, + key: string +): void { let keys = disableRuleKeys.get(rule) if (keys) { keys.push(key) @@ -154,11 +143,7 @@ function addDisableRule(disableRuleKeys, rule, key) { } } -/** - * @param {LintMessage} message - * @returns {string} message key - */ -function messageToKey(message) { +function messageToKey(message: LintMessage): string { return `line:${message.line},column${ // -1 because +1 by ESLint's `report-translator`. message.column - 1 @@ -167,11 +152,11 @@ function messageToKey(message) { /** * Compares the locations of two objects in a source file - * @param {Position} itemA The first object - * @param {Position} itemB The second object - * @returns {number} A value less than 1 if itemA appears before itemB in the source file, greater than 1 if + * @param itemA The first object + * @param itemB The second object + * @returns A value less than 1 if itemA appears before itemB in the source file, greater than 1 if * itemA appears after itemB in the source file, or 0 if itemA and itemB have the same location. */ -function compareLocations(itemA, itemB) { +function compareLocations(itemA: Position, itemB: Position): number { return itemA.line - itemB.line || itemA.column - itemB.column } diff --git a/package.json b/package.json index 593c90043..f4ba47968 100644 --- a/package.json +++ b/package.json @@ -2,8 +2,8 @@ "name": "eslint-plugin-vue", "version": "10.6.2", "description": "Official ESLint plugin for Vue.js", - "main": "lib/index.js", - "types": "lib/index.d.ts", + "main": "dist/index.js", + "types": "dist/index.d.ts", "scripts": { "new": "node tools/new-rule.js", "start": "npm run test:base -- --watch", @@ -22,15 +22,16 @@ "update": "node ./tools/update.js", "update-resources": "node ./tools/update-resources.js", "typegen": "node ./tools/generate-typegen.mjs", + "build": "npm run typegen && tsdown", "docs:watch": "vitepress dev docs", "predocs:build": "npm run update", "docs:build": "vitepress build docs", "generate:version": "env-cmd -e version npm run update && npm run lint:fix", "changeset:version": "changeset version && npm run generate:version && git add --all", - "changeset:publish": "npm run typegen && changeset publish" + "changeset:publish": "npm run build && changeset publish" }, "files": [ - "lib" + "dist" ], "homepage": "https://eslint.vuejs.org", "keywords": [ @@ -117,6 +118,7 @@ "markdownlint-cli": "^0.42.0", "pathe": "^1.1.2", "prettier": "^3.7.0", + "tsdown": "^0.17.0", "typescript": "^5.7.2", "vite-plugin-eslint4b": "^0.5.1", "vitepress": "^1.4.1", diff --git a/tools/generate-typegen.mjs b/tools/generate-typegen.mjs index 1f3b4a129..b247c5552 100644 --- a/tools/generate-typegen.mjs +++ b/tools/generate-typegen.mjs @@ -1,6 +1,6 @@ import fs from 'node:fs/promises' import { pluginsToRulesDTS } from 'eslint-typegen/core' -import plugin from '../lib/index.js' +import plugin from '../lib/index.ts' const dts = await pluginsToRulesDTS( { diff --git a/tools/update-lib-plugin.js b/tools/update-lib-plugin.js index b9fa03870..8d6d46488 100644 --- a/tools/update-lib-plugin.js +++ b/tools/update-lib-plugin.js @@ -24,15 +24,15 @@ const content = `/* 'use strict' const plugin = { - meta: require('./meta'), + meta: require('./meta.ts').default, rules: { ${rules .map((rule) => `'${rule.name}': require('./rules/${rule.name}')`) .join(',\n')} }, processors: { - '.vue': require('./processor'), - 'vue': require('./processor') + '.vue': require('./processor.ts').default, + 'vue': require('./processor.ts').default } } diff --git a/tsconfig.json b/tsconfig.json index 2008bef78..5c6bfa7ff 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,8 @@ { "compilerOptions": { - "target": "ES2019", - "module": "node16", - "moduleResolution": "Node16", + "target": "esnext", + "module": "preserve", + "moduleResolution": "bundler", "lib": ["es2020"], "types": [ "vitest/globals" @@ -20,11 +20,14 @@ "noFallthroughCasesInSwitch": true, "esModuleInterop": true, "resolveJsonModule": true, + "isolatedModules": true, + "noUncheckedSideEffectImports": true, "baseUrl": ".", "paths": { "*": ["typings/*"] }, - "skipLibCheck": true + "skipLibCheck": true, + "allowImportingTsExtensions": true }, "include": [ "lib/**/*", diff --git a/tsdown.config.ts b/tsdown.config.ts new file mode 100644 index 000000000..3016d5017 --- /dev/null +++ b/tsdown.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from 'tsdown' + +export default defineConfig({ + entry: ['lib/index.ts'], + format: ['cjs'], + copy: ['lib/index.d.ts', 'lib/eslint-typegen.d.ts', 'lib/removed-rules.js'], + dts: false, + external: ['typescript'], + unbundle: true, + fixedExtension: false +})