diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 000000000..e5b6d8d6a --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,8 @@ +# Changesets + +Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works +with multi-package repos, or single-package repos to help you version and publish your code. You can +find the full documentation for it [in our repository](https://github.com/changesets/changesets) + +We have a quick list of common questions to get you started engaging with this project in +[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) diff --git a/.changeset/beige-teams-camp.md b/.changeset/beige-teams-camp.md new file mode 100644 index 000000000..49c2a317b --- /dev/null +++ b/.changeset/beige-teams-camp.md @@ -0,0 +1,5 @@ +--- +'eslint-plugin-vue': minor +--- + +Added `ignoreParents` option to [`vue/no-deprecated-slot-attribute`](https://eslint.vuejs.org/rules/no-deprecated-slot-attribute.html) diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 000000000..43b72b358 --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://unpkg.com/@changesets/config/schema.json", + "changelog": [ + "@svitejs/changesets-changelog-github-compact", + { + "repo": "vuejs/eslint-plugin-vue" + } + ], + "commit": false, + "linked": [], + "access": "public", + "baseBranch": "master", + "bumpVersionsWithWorkspaceProtocolOnly": true, + "ignore": [] +} diff --git a/.changeset/eight-camels-refuse.md b/.changeset/eight-camels-refuse.md new file mode 100644 index 000000000..527b123e4 --- /dev/null +++ b/.changeset/eight-camels-refuse.md @@ -0,0 +1,5 @@ +--- +"eslint-plugin-vue": patch +--- + +Resolved TypeScript compatibility issues introduced by eslint-typegen diff --git a/.changeset/strong-masks-fetch.md b/.changeset/strong-masks-fetch.md new file mode 100644 index 000000000..b7b3b22a0 --- /dev/null +++ b/.changeset/strong-masks-fetch.md @@ -0,0 +1,5 @@ +--- +'eslint-plugin-vue': patch +--- + +Fixed inconsistent quotes in [`vue/block-lang`](https://eslint.vuejs.org/rules/block-lang.html) error messages diff --git a/.changeset/true-pumas-open.md b/.changeset/true-pumas-open.md new file mode 100644 index 000000000..7a49b0f25 --- /dev/null +++ b/.changeset/true-pumas-open.md @@ -0,0 +1,5 @@ +--- +'eslint-plugin-vue': minor +--- + +Added new [`vue/no-negated-condition`](https://eslint.vuejs.org/rules/no-negated-condition.html) rule diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 57aa5876d..90bd33ad5 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -46,7 +46,7 @@ jobs: with: node-version: ${{ matrix.node }} - name: Install Packages - run: npm install -f + run: npm install - name: Install ESLint v${{ matrix.eslint }} run: npm install --save-dev eslint@${{ matrix.eslint }} -f - name: Test @@ -61,8 +61,23 @@ jobs: - name: Install Node.js uses: actions/setup-node@v4 - name: Install Packages - run: npm install -f + run: npm install - name: Uninstall @stylistic/eslint-plugin run: npm uninstall -D @stylistic/eslint-plugin - name: Test run: npm test + + test-with-typescript-eslint-v7: + name: Test with typescript-eslint v7 + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Node.js + uses: actions/setup-node@v4 + - name: Install Packages + run: npm install + - name: Install @typescript-eslint/parser@7 + run: npm install -D @typescript-eslint/parser@7 -f + - name: Test + run: npm test diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml new file mode 100644 index 000000000..3653780d5 --- /dev/null +++ b/.github/workflows/Release.yml @@ -0,0 +1,35 @@ +name: Release + +on: + push: + branches: + - master + +permissions: {} + +jobs: + release: + # prevents this action from running on forks + if: github.repository == 'vuejs/eslint-plugin-vue' + permissions: + contents: write # to create release (changesets/action) + pull-requests: write # to create pull request (changesets/action) + name: Release + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + - name: Setup Node.js + uses: actions/setup-node@v4 + - name: Install Dependencies + run: npm install + + - name: Create Release Pull Request or Publish to npm + id: changesets + uses: changesets/action@v1 + with: + version: npm run changeset:version + publish: npm run changeset:publish + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/check-for-resources-update.yml b/.github/workflows/check-for-resources-update.yml index 613125fc3..31f881b1d 100644 --- a/.github/workflows/check-for-resources-update.yml +++ b/.github/workflows/check-for-resources-update.yml @@ -5,12 +5,13 @@ on: - cron: 0 0 * * 0 # At 00:00 on Sunday, see https://crontab.guru/#0_0_*_*_0 permissions: - contents: write - pull-requests: write + contents: write + pull-requests: write jobs: check-for-resources-update: runs-on: ubuntu-latest + if: ${{ github.repository == 'vuejs/eslint-plugin-vue' }} steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.gitignore b/.gitignore index 797d0cbcd..d6fadf92c 100644 --- a/.gitignore +++ b/.gitignore @@ -8,8 +8,9 @@ yarn.lock yarn-error.log /docs/.vitepress/dist -/docs/.vitepress/build-system/shim/eslint.mjs -/docs/.vitepress/build-system/shim/assert.mjs +/docs/.vitepress/build-system/shim/vue-eslint-parser.mjs +/docs/.vitepress/build-system/shim/@typescript-eslint/parser.mjs /docs/.vitepress/.temp /docs/.vitepress/cache typings/eslint/lib/rules +eslint-typegen.d.ts diff --git a/.markdownlintignore b/.markdownlintignore index 3c3629e64..e7becf85b 100644 --- a/.markdownlintignore +++ b/.markdownlintignore @@ -1 +1,2 @@ node_modules +CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..d48439d99 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,29 @@ +# eslint-plugin-vue + +## 10.3.0 + +### Minor Changes + +- Added [`@typescript-eslint/parser`](https://typescript-eslint.io/packages/parser) as an optional peer dependency ([#2775](https://github.com/vuejs/eslint-plugin-vue/pull/2775)) + +- Add TypeScript IntelliSense support via [eslint-typegen](https://github.com/antfu/eslint-typegen) ([#2770](https://github.com/vuejs/eslint-plugin-vue/pull/2770)) + +- [`vue/no-deprecated-slot-attribute`](https://eslint.vuejs.org/rules/no-deprecated-slot-attribute.html) `ignore` option now supports regex patterns ([#2773](https://github.com/vuejs/eslint-plugin-vue/pull/2773)) + +### Patch Changes + +- Fixed false negatives when using typescript-eslint v8 in [`vue/script-indent`](https://eslint.vuejs.org/rules/script-indent.html) rule ([#2775](https://github.com/vuejs/eslint-plugin-vue/pull/2775)) + +- Update resources ([#2752](https://github.com/vuejs/eslint-plugin-vue/pull/2752)) + +- [`vue/no-restricted-html-elements`](https://eslint.vuejs.org/rules/no-restricted-html-elements.html) now also checks SVG and MathML elements ([#2755](https://github.com/vuejs/eslint-plugin-vue/pull/2755)) + +## 10.2.0 + +### Minor Changes + +- [vue/no-restricted-html-elements](https://eslint.vuejs.org/rules/no-restricted-html-elements.html) now accepts multiple elements in each entry. ([#2750](https://github.com/vuejs/eslint-plugin-vue/pull/2750)) + +### Patch Changes + +- Updates resources ([#2747](https://github.com/vuejs/eslint-plugin-vue/pull/2747)) diff --git a/README.md b/README.md index 95e0c08be..bdeb5e167 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![NPM version](https://img.shields.io/npm/v/eslint-plugin-vue.svg?style=flat)](https://npmjs.org/package/eslint-plugin-vue) [![NPM downloads](https://img.shields.io/npm/dm/eslint-plugin-vue.svg?style=flat)](https://npmjs.org/package/eslint-plugin-vue) -[![CircleCI](https://img.shields.io/circleci/project/github/vuejs/eslint-plugin-vue/master.svg?style=flat)](https://circleci.com/gh/vuejs/eslint-plugin-vue) +[![CI](https://img.shields.io/github/actions/workflow/status/vuejs/eslint-plugin-vue/CI.yml?style=flat&label=CI)](https://github.com/vuejs/eslint-plugin-vue/actions/workflows/CI.yml) [![License](https://img.shields.io/github/license/vuejs/eslint-plugin-vue.svg?style=flat)](https://github.com/vuejs/eslint-plugin-vue/blob/master/LICENSE) > Official ESLint plugin for Vue.js diff --git a/docs/.vitepress/build-system/build.mts b/docs/.vitepress/build-system/build.mts index 9dce53faf..edda69143 100644 --- a/docs/.vitepress/build-system/build.mts +++ b/docs/.vitepress/build-system/build.mts @@ -9,14 +9,38 @@ import { fileURLToPath } from 'url' const dirname = path.dirname(fileURLToPath(import.meta.url)) build( - path.join(dirname, './src/eslint.mjs'), - path.join(dirname, './shim/eslint.mjs'), - ['path', 'assert', 'util', 'esquery'] + path.join( + dirname, + '../../../node_modules/@typescript-eslint/parser/dist/index.js' + ), + path.join(dirname, './shim/@typescript-eslint/parser.mjs'), + [ + 'util', + 'node:util', + 'path', + 'node:path', + 'fs', + 'node:fs', + 'semver', + 'fast-glob', + 'debug' + ] ) + build( - path.join(dirname, '../../../node_modules/assert'), - path.join(dirname, './shim/assert.mjs'), - ['path'] + path.join(dirname, '../../../node_modules/vue-eslint-parser/index.js'), + path.join(dirname, './shim/vue-eslint-parser.mjs'), + [ + 'path', + 'debug', + 'semver', + 'assert', + 'module', + 'events', + 'esquery', + 'fs', + 'eslint' + ] ) function build(input: string, out: string, injects: string[] = []) { @@ -42,16 +66,22 @@ function bundle(entryPoint: string, externals: string[]) { } function transform(code: string, injects: string[]) { + const normalizeInjects = [ + ...new Set(injects.map((inject) => inject.replace(/^node:/u, ''))) + ] const newCode = code.replace(/"[a-z]+" = "[a-z]+";/u, '') return ` -${injects +${normalizeInjects .map( (inject) => - `import $inject_${inject.replace(/-/gu, '_')}$ from '${inject}';` + `import $inject_${inject.replace(/[\-:]/gu, '_')}$ from '${inject}';` ) .join('\n')} const $_injects_$ = {${injects - .map((inject) => `${inject.replace(/-/gu, '_')}:$inject_${inject}$`) + .map( + (inject) => + `"${inject}":$inject_${inject.replace(/^node:/u, '').replace(/[\-:]/gu, '_')}$` + ) .join(',\n')}}; function require(module, ...args) { return $_injects_$[module] || {} diff --git a/docs/.vitepress/build-system/shim/globby.mjs b/docs/.vitepress/build-system/shim/empty.mjs similarity index 100% rename from docs/.vitepress/build-system/shim/globby.mjs rename to docs/.vitepress/build-system/shim/empty.mjs diff --git a/docs/.vitepress/build-system/shim/eslint/use-at-your-own-risk.mjs b/docs/.vitepress/build-system/shim/eslint/use-at-your-own-risk.mjs deleted file mode 100644 index 0db0b01c2..000000000 --- a/docs/.vitepress/build-system/shim/eslint/use-at-your-own-risk.mjs +++ /dev/null @@ -1,3 +0,0 @@ -export default { - /* empty */ -} diff --git a/docs/.vitepress/build-system/shim/esquery.mjs b/docs/.vitepress/build-system/shim/esquery.mjs deleted file mode 100644 index 5652b09f1..000000000 --- a/docs/.vitepress/build-system/shim/esquery.mjs +++ /dev/null @@ -1,5 +0,0 @@ -import esquery from '../../../../node_modules/esquery/dist/esquery.esm.js' - -export const { parse, match, traverse, matches, query } = esquery - -export { default } from '../../../../node_modules/esquery/dist/esquery.esm.js' diff --git a/docs/.vitepress/build-system/shim/path.mjs b/docs/.vitepress/build-system/shim/path.mjs deleted file mode 100644 index 544792b00..000000000 --- a/docs/.vitepress/build-system/shim/path.mjs +++ /dev/null @@ -1,38 +0,0 @@ -// @ts-nocheck -export const sep = '/' -export function basename(path, ext) { - const b = (/[^\/]*$/u.exec(path) || [''])[0] - return ext && b.endsWith(ext) ? b.slice(0, -ext.length) : b -} -export function extname(path) { - return (/[^.\/]*$/u.exec(path) || [''])[0] -} -export function isAbsolute() { - return false -} -export function join(...args) { - return args.length > 0 ? normalize(args.join('/')) : '.' -} - -function normalize(path) { - const result = [] - for (const part of path.replace(/\/+/gu, '/').split('/')) { - if (part === '..') { - if (result[0] && result[0] !== '..' && result[0] !== '.') result.shift() - } else if (part === '.' && result.length > 0) { - // noop - } else { - result.unshift(part) - } - } - return result.reverse().join('/') -} -const posix = { - sep, - basename, - extname, - isAbsolute, - join -} -posix.posix = posix -export default posix diff --git a/docs/.vitepress/build-system/src/eslint.mjs b/docs/.vitepress/build-system/src/eslint.mjs deleted file mode 100644 index ed193b58b..000000000 --- a/docs/.vitepress/build-system/src/eslint.mjs +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-nocheck -/* eslint-disable unicorn/prefer-export-from -- exporting as named and default is less duplication without `export…from` */ - -import { Linter } from '../../../../node_modules/eslint/lib/linter/linter.js' -import SourceCode from '../../../../node_modules/eslint/lib/source-code/source-code.js' - -export { Linter, SourceCode } -export default { Linter, SourceCode } diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index afa635d7e..7d198d588 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -3,6 +3,7 @@ import { defineConfig } from 'vitepress' import path from 'pathe' import { fileURLToPath } from 'url' import { viteCommonjs, vitePluginRequireResolve } from './vite-plugin.mjs' +import eslint4b, { requireESLintUseAtYourOwnRisk4b } from 'vite-plugin-eslint4b' // Pre-build cjs packages that cannot be bundled well. import './build-system/build.mjs' @@ -142,24 +143,30 @@ export default async () => { vite: { publicDir: path.resolve(dirname, './public'), - plugins: [vitePluginRequireResolve(), viteCommonjs()], + plugins: [ + vitePluginRequireResolve(), + viteCommonjs(), + eslint4b() as any, + requireESLintUseAtYourOwnRisk4b() + ], resolve: { alias: { - 'eslint/use-at-your-own-risk': path.join( + 'vue-eslint-parser': path.join( + dirname, + './build-system/shim/vue-eslint-parser.mjs' + ), + '@typescript-eslint/parser': path.join( dirname, - './build-system/shim/eslint/use-at-your-own-risk.mjs' + './build-system/shim/@typescript-eslint/parser.mjs' ), - eslint: path.join(dirname, './build-system/shim/eslint.mjs'), - assert: path.join(dirname, './build-system/shim/assert.mjs'), - path: path.join(dirname, './build-system/shim/path.mjs'), tslib: path.join(dirname, '../../node_modules/tslib/tslib.es6.js'), - esquery: path.join(dirname, './build-system/shim/esquery.mjs'), - globby: path.join(dirname, './build-system/shim/globby.mjs') + globby: path.join(dirname, './build-system/shim/empty.mjs'), + 'fast-glob': path.join(dirname, './build-system/shim/empty.mjs'), + module: path.join(dirname, './build-system/shim/empty.mjs') } }, define: { - 'process.env.NODE_DEBUG': 'false', 'require.cache': '{}' } }, diff --git a/docs/.vitepress/theme/components/eslint-code-block.vue b/docs/.vitepress/theme/components/eslint-code-block.vue index 77d4fd7cf..12cd1ff8b 100644 --- a/docs/.vitepress/theme/components/eslint-code-block.vue +++ b/docs/.vitepress/theme/components/eslint-code-block.vue @@ -8,8 +8,6 @@ class="eslint-code-block" :filename="filename" :language="language" - :preprocess="preprocess" - :postprocess="postprocess" dark :format="format" :fix="fix" @@ -20,8 +18,6 @@ +``` + + + +The rule applies to both JavaScript and TypeScript props: + + + +```vue + +``` + + + +## :wrench: Options + +```js +{ + "vue/define-props-destructuring": ["error", { + "destructure": "always" | "never" + }] +} +``` + +- `destructure` - Sets the destructuring preference for props + - `"always"` (default) - Requires destructuring when using `defineProps` and warns against using `withDefaults` with destructuring + - `"never"` - Requires using a variable to store props and prohibits destructuring + +### `"destructure": "never"` + + + +```vue + +``` + + + +## :books: Further Reading + +- [Reactive Props Destructure](https://vuejs.org/guide/components/props.html#reactive-props-destructure) + +## :rocket: Version + +This rule was introduced in eslint-plugin-vue v10.1.0 + +## :mag: Implementation + +- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/define-props-destructuring.js) +- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/define-props-destructuring.js) diff --git a/docs/rules/eqeqeq.md b/docs/rules/eqeqeq.md index 392deff7f..fb0133251 100644 --- a/docs/rules/eqeqeq.md +++ b/docs/rules/eqeqeq.md @@ -11,6 +11,7 @@ since: v5.2.0 > Require the use of `===` and `!==` in ` `, errors: [ - 'Expected 1 line break after opening tag (`
`), but no line breaks found.', - 'Expected 1 line break before closing tag (`
`), but no line breaks found.' + { + message: + 'Expected 1 line break after opening tag (`
`), but no line breaks found.', + line: 3, + column: 16, + endLine: 3, + endColumn: 16 + }, + { + message: + 'Expected 1 line break before closing tag (`
`), but no line breaks found.', + line: 4, + column: 25, + endLine: 4, + endColumn: 25 + } ] }, { @@ -457,8 +499,22 @@ multiline content `, errors: [ - 'Expected 1 line break after opening tag (`
`), but no line breaks found.', - 'Expected 1 line break before closing tag (`
`), but no line breaks found.' + { + message: + 'Expected 1 line break after opening tag (`
`), but no line breaks found.', + line: 3, + column: 16, + endLine: 3, + endColumn: 16 + }, + { + message: + 'Expected 1 line break before closing tag (`
`), but no line breaks found.', + line: 4, + column: 23, + endLine: 4, + endColumn: 23 + } ] }, // one error @@ -479,7 +535,14 @@ content `, errors: [ - 'Expected 1 line break after opening tag (`
`), but no line breaks found.' + { + message: + 'Expected 1 line break after opening tag (`
`), but no line breaks found.', + line: 3, + column: 16, + endLine: 3, + endColumn: 16 + } ] }, { @@ -499,7 +562,14 @@ content `, errors: [ - 'Expected 1 line break before closing tag (`
`), but no line breaks found.' + { + message: + 'Expected 1 line break before closing tag (`
`), but no line breaks found.', + line: 5, + column: 18, + endLine: 5, + endColumn: 18 + } ] }, // multi @@ -519,12 +589,54 @@ content `, errors: [ - 'Expected 1 line break after opening tag (``), but no line breaks found.' + { + message: + 'Expected 1 line break after opening tag (``), but no line breaks found.', + line: 3, + column: 35, + endLine: 3, + endColumn: 35 + } ] }, // multi line breaks @@ -548,8 +660,22 @@ content `, errors: [ - 'Expected 1 line break after opening tag (`
`), but 2 line breaks found.', - 'Expected 1 line break before closing tag (`
`), but 2 line breaks found.' + { + message: + 'Expected 1 line break after opening tag (`
`), but 2 line breaks found.', + line: 3, + column: 16, + endLine: 5, + endColumn: 13 + }, + { + message: + 'Expected 1 line break before closing tag (`
`), but 2 line breaks found.', + line: 6, + column: 20, + endLine: 8, + endColumn: 11 + } ] }, // allowEmptyLines @@ -575,7 +701,14 @@ content `, options: [{ allowEmptyLines: true, ignoreWhenEmpty: false }], errors: [ - 'Expected 1 line break after opening tag (`
`), but no line breaks found.' + { + message: + 'Expected 1 line break after opening tag (`
`), but no line breaks found.', + line: 8, + column: 27, + endLine: 8, + endColumn: 27 + } ] }, { @@ -607,8 +740,22 @@ content `, options: [{ allowEmptyLines: true }], errors: [ - 'Expected 1 line break after opening tag (`
`), but no line breaks found.', - 'Expected 1 line break before closing tag (`
`), but no line breaks found.' + { + message: + 'Expected 1 line break after opening tag (`
`), but no line breaks found.', + line: 9, + column: 16, + endLine: 9, + endColumn: 16 + }, + { + message: + 'Expected 1 line break before closing tag (`
`), but no line breaks found.', + line: 10, + column: 20, + endLine: 10, + endColumn: 20 + } ] }, // mustache @@ -628,8 +775,22 @@ content `, errors: [ - 'Expected 1 line break after opening tag (`
`), but no line breaks found.', - 'Expected 1 line break before closing tag (`
`), but no line breaks found.' + { + message: + 'Expected 1 line break after opening tag (`
`), but no line breaks found.', + line: 3, + column: 16, + endLine: 3, + endColumn: 16 + }, + { + message: + 'Expected 1 line break before closing tag (`
`), but no line breaks found.', + line: 4, + column: 23, + endLine: 4, + endColumn: 23 + } ] }, // mix @@ -651,8 +812,22 @@ content `, errors: [ - 'Expected 1 line break after opening tag (`
`), but no line breaks found.', - 'Expected 1 line break before closing tag (`
`), but no line breaks found.' + { + message: + 'Expected 1 line break after opening tag (`
`), but no line breaks found.', + line: 3, + column: 16, + endLine: 3, + endColumn: 16 + }, + { + message: + 'Expected 1 line break before closing tag (`
`), but no line breaks found.', + line: 5, + column: 27, + endLine: 5, + endColumn: 27 + } ] }, // start tag @@ -672,8 +847,22 @@ content `, errors: [ - 'Expected 1 line break after opening tag (`
`), but no line breaks found.', - 'Expected 1 line break before closing tag (`
`), but no line breaks found.' + { + message: + 'Expected 1 line break after opening tag (`
`), but no line breaks found.', + line: 4, + column: 14, + endLine: 4, + endColumn: 14 + }, + { + message: + 'Expected 1 line break before closing tag (`
`), but no line breaks found.', + line: 4, + column: 21, + endLine: 4, + endColumn: 21 + } ] }, { @@ -692,8 +881,22 @@ content `, errors: [ - 'Expected 1 line break after opening tag (`
`), but no line breaks found.', - 'Expected 1 line break before closing tag (`
`), but no line breaks found.' + { + message: + 'Expected 1 line break after opening tag (`
`), but no line breaks found.', + line: 4, + column: 18, + endLine: 4, + endColumn: 18 + }, + { + message: + 'Expected 1 line break before closing tag (`
`), but no line breaks found.', + line: 4, + column: 25, + endLine: 4, + endColumn: 25 + } ] }, { @@ -712,7 +915,14 @@ content `, options: [{ ignoreWhenEmpty: false }], errors: [ - 'Expected 1 line break after opening tag (`
`), but no line breaks found.' + { + message: + 'Expected 1 line break after opening tag (`
`), but no line breaks found.', + line: 4, + column: 14, + endLine: 4, + endColumn: 14 + } ] } ] diff --git a/tests/lib/rules/multiline-ternary.js b/tests/lib/rules/multiline-ternary.js index 87e3fe485..118cf6353 100644 --- a/tests/lib/rules/multiline-ternary.js +++ b/tests/lib/rules/multiline-ternary.js @@ -4,9 +4,8 @@ */ 'use strict' -const { RuleTester, ESLint } = require('../../eslint-compat') +const { RuleTester } = require('../../eslint-compat') const rule = require('../../../lib/rules/multiline-ternary') -const semver = require('semver') const tester = new RuleTester({ languageOptions: { @@ -80,8 +79,7 @@ tester.run('multiline-ternary', rule, {
`, - output: semver.gte(ESLint.version, '7.1.0') - ? ` + output: ` - ` - : null, + `, options: ['always-multiline'], errors: [ { message: 'Expected newline between consequent and alternate of ternary expression.', line: 5, - column: 15 + column: 15, + endLine: 5, + endColumn: 30 } ] }, @@ -113,23 +112,23 @@ tester.run('multiline-ternary', rule, {
`, - output: semver.gte(ESLint.version, '7.1.0') - ? ` + output: ` - ` - : null, + `, options: ['never'], errors: [ { message: 'Unexpected newline between test and consequent of ternary expression.', line: 4, - column: 21 + column: 21, + endLine: 4, + endColumn: 44 } ] }, @@ -143,8 +142,7 @@ tester.run('multiline-ternary', rule, {
`, - output: semver.gte(ESLint.version, '7.1.0') - ? ` + output: ` - ` - : null, + `, errors: [ { message: 'Expected newline between test and consequent of ternary expression.', line: 4, - column: 21 + column: 21, + endLine: 4, + endColumn: 44 }, { message: 'Expected newline between consequent and alternate of ternary expression.', line: 4, - column: 47 + column: 47, + endLine: 4, + endColumn: 62 } ] }, @@ -180,8 +181,7 @@ tester.run('multiline-ternary', rule, {
`, - output: semver.gte(ESLint.version, '7.1.0') - ? ` + output: ` - ` - : null, + `, errors: [ { message: 'Expected newline between test and consequent of ternary expression.', line: 4, - column: 21 + column: 21, + endLine: 4, + endColumn: 44 }, { message: 'Expected newline between consequent and alternate of ternary expression.', line: 4, - column: 47 + column: 47, + endLine: 4, + endColumn: 62 } ] }, @@ -220,8 +223,7 @@ tester.run('multiline-ternary', rule, { } `, - output: semver.gte(ESLint.version, '7.1.0') - ? ` + output: ` `, options: [{ allowlist: ['@@'] }] + }, + // regex + { + code: ` + + `, + options: [{ allowlist: [String.raw`/\d+/g`] }] + }, + { + code: ` + + `, + options: [{ allowlist: [String.raw`/\$\w+/`] }] + }, + { + code: ` + + `, + options: [{ allowlist: [String.raw`/\d+/`, 'foo'] }] } ], invalid: [ @@ -316,6 +342,40 @@ tester.run('no-bare-strings-in-template', rule, { endColumn: 34 } ] + }, + { + code: ` + + `, + options: [{ allowlist: [String.raw`/^\d+$/g`] }], + errors: [ + { + messageId: 'unexpected', + line: 3, + column: 13, + endLine: 3, + endColumn: 37 + } + ] + }, + { + code: ` + + `, + options: [{ allowlist: [String.raw`/\d+/`, 'foo'] }], + errors: [ + { + messageId: 'unexpected', + line: 3, + column: 13, + endLine: 3, + endColumn: 22 + } + ] } ] }) diff --git a/tests/lib/rules/no-deprecated-slot-attribute.js b/tests/lib/rules/no-deprecated-slot-attribute.js index 2fd5fa401..01b8f31df 100644 --- a/tests/lib/rules/no-deprecated-slot-attribute.js +++ b/tests/lib/rules/no-deprecated-slot-attribute.js @@ -55,6 +55,42 @@ tester.run('no-deprecated-slot-attribute', rule, { `, options: [{ ignore: ['one', 'two', 'my-component'] }] + }, + { + code: ``, + options: [{ ignore: ['/one/', '/^Two$/i', '/^my-.*/i'] }] + }, + { + code: ``, + options: [{ ignoreParents: ['LinkList'] }] + }, + { + code: ``, + options: [{ ignoreParents: ['/^Link/'] }] } ], invalid: [ @@ -74,7 +110,10 @@ tester.run('no-deprecated-slot-attribute', rule, { errors: [ { message: '`slot` attributes are deprecated.', - line: 4 + line: 4, + column: 21, + endLine: 4, + endColumn: 25 } ] }, @@ -94,7 +133,10 @@ tester.run('no-deprecated-slot-attribute', rule, { errors: [ { message: '`slot` attributes are deprecated.', - line: 4 + line: 4, + column: 21, + endLine: 4, + endColumn: 25 } ] }, @@ -114,7 +156,10 @@ tester.run('no-deprecated-slot-attribute', rule, { errors: [ { message: '`slot` attributes are deprecated.', - line: 4 + line: 4, + column: 21, + endLine: 4, + endColumn: 25 } ] }, @@ -134,7 +179,10 @@ tester.run('no-deprecated-slot-attribute', rule, { errors: [ { message: '`slot` attributes are deprecated.', - line: 4 + line: 4, + column: 21, + endLine: 4, + endColumn: 25 } ] }, @@ -154,7 +202,10 @@ tester.run('no-deprecated-slot-attribute', rule, { errors: [ { message: '`slot` attributes are deprecated.', - line: 4 + line: 4, + column: 21, + endLine: 4, + endColumn: 25 } ] }, @@ -173,23 +224,38 @@ tester.run('no-deprecated-slot-attribute', rule, { errors: [ { message: '`slot` attributes are deprecated.', - line: 4 + line: 4, + column: 21, + endLine: 4, + endColumn: 25 }, { message: '`slot` attributes are deprecated.', - line: 5 + line: 5, + column: 21, + endLine: 5, + endColumn: 25 }, { message: '`slot` attributes are deprecated.', - line: 6 + line: 6, + column: 21, + endLine: 6, + endColumn: 25 }, { message: '`slot` attributes are deprecated.', - line: 7 + line: 7, + column: 21, + endLine: 7, + endColumn: 25 }, { message: '`slot` attributes are deprecated.', - line: 8 + line: 8, + column: 21, + endLine: 8, + endColumn: 25 } ] }, @@ -209,7 +275,10 @@ tester.run('no-deprecated-slot-attribute', rule, { errors: [ { message: '`slot` attributes are deprecated.', - line: 4 + line: 4, + column: 21, + endLine: 4, + endColumn: 32 } ] }, @@ -224,7 +293,10 @@ tester.run('no-deprecated-slot-attribute', rule, { errors: [ { message: '`slot` attributes are deprecated.', - line: 4 + line: 4, + column: 21, + endLine: 4, + endColumn: 26 } ] }, @@ -244,7 +316,10 @@ tester.run('no-deprecated-slot-attribute', rule, { errors: [ { message: '`slot` attributes are deprecated.', - line: 4 + line: 4, + column: 21, + endLine: 4, + endColumn: 26 } ] }, @@ -259,7 +334,10 @@ tester.run('no-deprecated-slot-attribute', rule, { errors: [ { message: '`slot` attributes are deprecated.', - line: 4 + line: 4, + column: 21, + endLine: 4, + endColumn: 26 } ] }, @@ -274,7 +352,10 @@ tester.run('no-deprecated-slot-attribute', rule, { errors: [ { message: '`slot` attributes are deprecated.', - line: 4 + line: 4, + column: 21, + endLine: 4, + endColumn: 26 } ] }, @@ -289,7 +370,10 @@ tester.run('no-deprecated-slot-attribute', rule, { errors: [ { message: '`slot` attributes are deprecated.', - line: 4 + line: 4, + column: 21, + endLine: 4, + endColumn: 26 } ] }, @@ -304,7 +388,10 @@ tester.run('no-deprecated-slot-attribute', rule, { errors: [ { message: '`slot` attributes are deprecated.', - line: 4 + line: 4, + column: 21, + endLine: 4, + endColumn: 26 } ] }, @@ -324,7 +411,10 @@ tester.run('no-deprecated-slot-attribute', rule, { errors: [ { message: '`slot` attributes are deprecated.', - line: 4 + line: 4, + column: 21, + endLine: 4, + endColumn: 26 } ] }, @@ -344,7 +434,10 @@ tester.run('no-deprecated-slot-attribute', rule, { errors: [ { message: '`slot` attributes are deprecated.', - line: 4 + line: 4, + column: 14, + endLine: 4, + endColumn: 18 } ] }, @@ -364,7 +457,10 @@ tester.run('no-deprecated-slot-attribute', rule, { errors: [ { message: '`slot` attributes are deprecated.', - line: 4 + line: 4, + column: 14, + endLine: 4, + endColumn: 19 } ] }, @@ -385,7 +481,15 @@ tester.run('no-deprecated-slot-attribute', rule, { `, - errors: ['`slot` attributes are deprecated.'] + errors: [ + { + message: '`slot` attributes are deprecated.', + line: 4, + column: 21, + endLine: 4, + endColumn: 25 + } + ] }, { code: ` @@ -404,7 +508,15 @@ tester.run('no-deprecated-slot-attribute', rule, { `, - errors: ['`slot` attributes are deprecated.'] + errors: [ + { + message: '`slot` attributes are deprecated.', + line: 4, + column: 21, + endLine: 4, + endColumn: 25 + } + ] }, { code: ` @@ -423,7 +535,15 @@ tester.run('no-deprecated-slot-attribute', rule, { `, - errors: ['`slot` attributes are deprecated.'] + errors: [ + { + message: '`slot` attributes are deprecated.', + line: 4, + column: 21, + endLine: 4, + endColumn: 25 + } + ] }, { // https://github.com/vuejs/eslint-plugin-vue/issues/1499 @@ -458,11 +578,17 @@ tester.run('no-deprecated-slot-attribute', rule, { errors: [ { message: '`slot` attributes are deprecated.', - line: 4 + line: 4, + column: 21, + endLine: 4, + endColumn: 25 }, { message: '`slot` attributes are deprecated.', - line: 9 + line: 9, + column: 23, + endLine: 9, + endColumn: 27 } ] }, @@ -490,8 +616,20 @@ tester.run('no-deprecated-slot-attribute', rule, { `, errors: [ - '`slot` attributes are deprecated.', - '`slot` attributes are deprecated.' + { + message: '`slot` attributes are deprecated.', + line: 4, + column: 37, + endLine: 4, + endColumn: 41 + }, + { + message: '`slot` attributes are deprecated.', + line: 7, + column: 37, + endLine: 7, + endColumn: 42 + } ] }, { @@ -508,8 +646,20 @@ tester.run('no-deprecated-slot-attribute', rule, { `, output: null, errors: [ - '`slot` attributes are deprecated.', - '`slot` attributes are deprecated.' + { + message: '`slot` attributes are deprecated.', + line: 4, + column: 21, + endLine: 4, + endColumn: 25 + }, + { + message: '`slot` attributes are deprecated.', + line: 7, + column: 21, + endLine: 7, + endColumn: 25 + } ] }, { @@ -554,8 +704,20 @@ tester.run('no-deprecated-slot-attribute', rule, { `, output: null, errors: [ - '`slot` attributes are deprecated.', - '`slot` attributes are deprecated.' + { + message: '`slot` attributes are deprecated.', + line: 4, + column: 37, + endLine: 4, + endColumn: 42 + }, + { + message: '`slot` attributes are deprecated.', + line: 7, + column: 37, + endLine: 7, + endColumn: 42 + } ] }, { @@ -582,8 +744,20 @@ tester.run('no-deprecated-slot-attribute', rule, { `, errors: [ - '`slot` attributes are deprecated.', - '`slot` attributes are deprecated.' + { + message: '`slot` attributes are deprecated.', + line: 4, + column: 37, + endLine: 4, + endColumn: 42 + }, + { + message: '`slot` attributes are deprecated.', + line: 7, + column: 37, + endLine: 7, + endColumn: 42 + } ] }, { @@ -610,8 +784,20 @@ tester.run('no-deprecated-slot-attribute', rule, { `, errors: [ - '`slot` attributes are deprecated.', - '`slot` attributes are deprecated.' + { + message: '`slot` attributes are deprecated.', + line: 4, + column: 41, + endLine: 4, + endColumn: 46 + }, + { + message: '`slot` attributes are deprecated.', + line: 7, + column: 37, + endLine: 7, + endColumn: 42 + } ] }, { @@ -642,7 +828,175 @@ tester.run('no-deprecated-slot-attribute', rule, { ignore: ['one'] } ], - errors: ['`slot` attributes are deprecated.'] + errors: [ + { + message: '`slot` attributes are deprecated.', + line: 7, + column: 16, + endLine: 7, + endColumn: 20 + } + ] + }, + { + code: ` + `, + output: ` + `, + options: [ + { + ignore: ['/one/'] + } + ], + errors: [ + { + message: '`slot` attributes are deprecated.', + line: 7, + endLine: 7, + column: 16, + endColumn: 20 + } + ] + }, + { + code: ` + `, + output: ` + `, + options: [ + { + ignore: ['/^one$/'] + } + ], + errors: [ + { + message: '`slot` attributes are deprecated.', + line: 7, + endLine: 7, + column: 16, + endColumn: 20 + } + ] + }, + { + code: ` + `, + output: ` + `, + options: [ + { + ignoreParents: ['my-component'] + } + ], + errors: [ + { + message: '`slot` attributes are deprecated.', + line: 9, + column: 16, + endLine: 9, + endColumn: 20 + } + ] + }, + { + code: ` + `, + output: ` + `, + options: [ + { + ignoreParents: ['/component$/'] + } + ], + errors: [ + { + message: '`slot` attributes are deprecated.', + line: 9, + column: 16, + endLine: 9, + endColumn: 20 + } + ] }, { code: ` @@ -667,7 +1021,15 @@ tester.run('no-deprecated-slot-attribute', rule, { `, - errors: ['`slot` attributes are deprecated.'] + errors: [ + { + message: '`slot` attributes are deprecated.', + line: 6, + column: 13, + endLine: 6, + endColumn: 18 + } + ] }, { code: ` @@ -680,7 +1042,15 @@ tester.run('no-deprecated-slot-attribute', rule, { `, output: null, - errors: ['`slot` attributes are deprecated.'] + errors: [ + { + message: '`slot` attributes are deprecated.', + line: 4, + column: 16, + endLine: 4, + endColumn: 20 + } + ] } ] }) diff --git a/tests/lib/rules/no-dupe-keys.js b/tests/lib/rules/no-dupe-keys.js index 124442ec2..2df95908c 100644 --- a/tests/lib/rules/no-dupe-keys.js +++ b/tests/lib/rules/no-dupe-keys.js @@ -466,7 +466,7 @@ ruleTester.run('no-dupe-keys', rule, { { filename: 'test.vue', code: ` - + `, @@ -475,7 +475,7 @@ ruleTester.run('no-dupe-keys', rule, { { filename: 'test.vue', code: ` - + `, @@ -500,6 +500,17 @@ ruleTester.run('no-dupe-keys', rule, { parser: require('vue-eslint-parser'), parserOptions: { parser: require.resolve('@typescript-eslint/parser') } } + }, + { + filename: 'test.vue', + code: ` + + `, + languageOptions: { parser: require('vue-eslint-parser') } } ], @@ -1105,6 +1116,24 @@ ruleTester.run('no-dupe-keys', rule, { line: 5 } ] + }, + { + filename: 'test.vue', + code: ` + + `, + languageOptions: { parser: require('vue-eslint-parser') }, + errors: [ + { + message: + "Duplicate key 'bar'. May cause name collision in script or template tag.", + line: 5 + } + ] } ] }) diff --git a/tests/lib/rules/no-export-in-script-setup.js b/tests/lib/rules/no-export-in-script-setup.js index 8703dc74a..bf24b8682 100644 --- a/tests/lib/rules/no-export-in-script-setup.js +++ b/tests/lib/rules/no-export-in-script-setup.js @@ -92,20 +92,62 @@ ruleTester.run('no-export-in-script-setup', rule, { export * from 'foo' export default {} export class A {} + export const test = '123' + export function foo() {} + const a = 1 + export { a } + export { fao } from 'bar' `, errors: [ { message: '` `, + ` + + `, + ` + + `, ` ` + }, + { + filename: 'multiple-scripts-setup-first.vue', + code: ` + + + + + + ` + }, + { + filename: 'multiple-scripts-setup-last.vue', + code: ` + + + + + + ` } ], invalid: [ @@ -420,6 +454,60 @@ tester.run('prefer-use-template-ref', rule, { column: 28 } ] + }, + { + filename: 'multiple-scripts-setup-first.vue', + code: ` + + + + + + `, + errors: [ + { + messageId: 'preferUseTemplateRef', + data: { + name: 'ref' + }, + line: 8, + column: 20 + } + ] + }, + { + filename: 'multiple-scripts-setup-last.vue', + code: ` + + + + + + `, + errors: [ + { + messageId: 'preferUseTemplateRef', + data: { + name: 'ref' + }, + line: 12, + column: 20 + } + ] } ] }) diff --git a/tests/lib/rules/require-default-prop.js b/tests/lib/rules/require-default-prop.js index e352eddf3..43160dfda 100644 --- a/tests/lib/rules/require-default-prop.js +++ b/tests/lib/rules/require-default-prop.js @@ -388,6 +388,31 @@ ruleTester.run('require-default-prop', rule, { parser: require('vue-eslint-parser'), ...languageOptions } + }, + { + filename: 'test.vue', + code: ` + + `, + languageOptions: { + parser: require('vue-eslint-parser'), + ...languageOptions + } + }, + { + filename: 'test.vue', + code: ` + + `, + languageOptions: { + parser: require('vue-eslint-parser'), + ...languageOptions, + parserOptions: { parser: require.resolve('@typescript-eslint/parser') } + } } ], @@ -700,6 +725,26 @@ ruleTester.run('require-default-prop', rule, { line: 3 } ] + }, + { + // https://github.com/vuejs/eslint-plugin-vue/issues/2725 + filename: 'type-with-props-destructure.vue', + code: ` + + `, + languageOptions: { + parser: require('vue-eslint-parser'), + ...languageOptions, + parserOptions: { parser: require.resolve('@typescript-eslint/parser') } + }, + errors: [ + { + message: "Prop 'foo' requires default value to be set.", + line: 3 + } + ] } ] }) diff --git a/tests/lib/rules/require-explicit-slots.js b/tests/lib/rules/require-explicit-slots.js index f99614119..afee739a6 100644 --- a/tests/lib/rules/require-explicit-slots.js +++ b/tests/lib/rules/require-explicit-slots.js @@ -6,6 +6,9 @@ const RuleTester = require('../../eslint-compat').RuleTester const rule = require('../../../lib/rules/require-explicit-slots') +const { + getTypeScriptFixtureTestOptions +} = require('../../test-utils/typescript') const tester = new RuleTester({ languageOptions: { @@ -276,6 +279,21 @@ tester.run('require-explicit-slots', rule, { }) ` }, + { + filename: 'test.vue', + code: ` + + `, + ...getTypeScriptFixtureTestOptions() + }, { filename: 'test.vue', code: ` @@ -656,6 +674,28 @@ tester.run('require-explicit-slots', rule, { } ] }, + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + message: 'Slots must be explicitly defined.', + line: 5, + column: 11 + } + ], + ...getTypeScriptFixtureTestOptions() + }, { // ignore attribute binding except string literal filename: 'test.vue', diff --git a/tests/lib/utils/regexp.js b/tests/lib/utils/regexp.js index 830fa2a11..e27a0596f 100644 --- a/tests/lib/utils/regexp.js +++ b/tests/lib/utils/regexp.js @@ -1,6 +1,10 @@ 'use strict' -const { escape, toRegExp } = require('../../../lib/utils/regexp') +const { + escape, + toRegExp, + toRegExpGroupMatcher +} = require('../../../lib/utils/regexp') const assert = require('assert') const ESCAPED = '\\^\\$\\.\\*\\+\\?\\(\\)\\[\\]\\{\\}\\|\\\\' @@ -35,4 +39,120 @@ describe('toRegExp()', () => { assert.deepEqual(toRegExp(`${/^bar/i}`), /^bar/i) assert.deepEqual(toRegExp(`${/[\sA-Z]+/u}`), /[\sA-Z]+/u) }) + + it('should handle simple patterns', () => { + const regex = toRegExp('foo') + assert.strictEqual(regex.test('foo'), true) + assert.strictEqual(regex.test('bar'), false) + assert.strictEqual(regex.test('foobar'), false) + assert.strictEqual(regex.test('afoo'), false) + assert.strictEqual(regex.test('afoobar'), false) + assert.strictEqual(regex.test('Foo'), false) + }) + + it('should handle simple patterns with added flags', () => { + const regex = toRegExp('foo', { add: 'i' }) + assert.strictEqual(regex.test('foo'), true) + assert.strictEqual(regex.test('bar'), false) + assert.strictEqual(regex.test('foobar'), false) + assert.strictEqual(regex.test('afoo'), false) + assert.strictEqual(regex.test('afoobar'), false) + assert.strictEqual(regex.test('Foo'), true) + }) + + it('should handle regexp patterns', () => { + const regex = toRegExp('/^foo/') + assert.strictEqual(regex.test('foo'), true) + assert.strictEqual(regex.test('bar'), false) + assert.strictEqual(regex.test('foobar'), true) + assert.strictEqual(regex.test('afoo'), false) + assert.strictEqual(regex.test('afoobar'), false) + assert.strictEqual(regex.test('Foo'), false) + }) + + it('should handle regexp patterns with attached flags', () => { + const regex = toRegExp('/^foo/i') + assert.strictEqual(regex.test('foo'), true) + assert.strictEqual(regex.test('bar'), false) + assert.strictEqual(regex.test('foobar'), true) + assert.strictEqual(regex.test('afoo'), false) + assert.strictEqual(regex.test('afoobar'), false) + assert.strictEqual(regex.test('Foo'), true) + }) + + it('should handle regexp patterns with added flags', () => { + const regex = toRegExp('/^foo/', { add: 'i' }) + assert.deepEqual(regex, /^foo/i) + assert.strictEqual(regex.test('foo'), true) + assert.strictEqual(regex.test('bar'), false) + assert.strictEqual(regex.test('foobar'), true) + assert.strictEqual(regex.test('afoo'), false) + assert.strictEqual(regex.test('afoobar'), false) + assert.strictEqual(regex.test('Foo'), true) + }) + + it('should handle regexp patterns with removed flags', () => { + const regex = toRegExp('/^foo/i', { remove: 'i' }) + assert.deepEqual(regex, /^foo/) + assert.strictEqual(regex.test('foo'), true) + assert.strictEqual(regex.test('bar'), false) + assert.strictEqual(regex.test('foobar'), true) + assert.strictEqual(regex.test('afoo'), false) + assert.strictEqual(regex.test('afoobar'), false) + assert.strictEqual(regex.test('Foo'), false) + }) +}) + +describe('toRegExpGroupMatcher()', () => { + it('should return a function missing input', () => { + const groupMatcher = toRegExpGroupMatcher() + assert.strictEqual(groupMatcher(''), false) + assert.strictEqual(groupMatcher('foo'), false) + assert.strictEqual(groupMatcher('bar'), false) + }) + + it('should return a function for empty array', () => { + const groupMatcher = toRegExpGroupMatcher([]) + assert.strictEqual(groupMatcher(''), false) + assert.strictEqual(groupMatcher('foo'), false) + assert.strictEqual(groupMatcher('bar'), false) + }) + + it('should return a function for single simple pattern', () => { + const groupMatcher = toRegExpGroupMatcher(['foo']) + assert.strictEqual(groupMatcher(''), false) + assert.strictEqual(groupMatcher('foo'), true) + assert.strictEqual(groupMatcher('foo', 'early'), true) + assert.strictEqual(groupMatcher('late', 'matches', 'foo'), true) + assert.strictEqual(groupMatcher('foobar'), false) + assert.strictEqual(groupMatcher('afoo', 'fooa', 'afooa', 'bar'), false) + }) + + it('should return a function for multiple simple patterns', () => { + const groupMatcher = toRegExpGroupMatcher(['foo', 'bar']) + assert.strictEqual(groupMatcher('foo'), true) + assert.strictEqual(groupMatcher('bar', 'early'), true) + assert.strictEqual(groupMatcher('late', 'matches', 'foo'), true) + assert.strictEqual(groupMatcher('foobar'), false) + assert.strictEqual(groupMatcher('afoo', 'fooa', 'afooa'), false) + }) + + it('should return a function for single regexp pattern', () => { + const groupMatcher = toRegExpGroupMatcher(['/^foo/g']) + assert.strictEqual(groupMatcher(''), false) + assert.strictEqual(groupMatcher('foo'), true) + assert.strictEqual(groupMatcher('fooa', 'early'), true) + assert.strictEqual(groupMatcher('late', 'matches', 'fooa'), true) + assert.strictEqual(groupMatcher('barfoo'), false) + assert.strictEqual(groupMatcher('afoo', 'afooa', 'bar'), false) + }) + + it('should return a function for multiple regexp patterns', () => { + const groupMatcher = toRegExpGroupMatcher(['/^foo/', '/bar$/gi']) + assert.strictEqual(groupMatcher('foo'), true) + assert.strictEqual(groupMatcher('Bar', 'early'), true) + assert.strictEqual(groupMatcher('late', 'matches', 'foo'), true) + assert.strictEqual(groupMatcher('barfoo'), false) + assert.strictEqual(groupMatcher('afoo', 'afooa', 'bara'), false) + }) }) diff --git a/tools/generate-typegen.mjs b/tools/generate-typegen.mjs new file mode 100644 index 000000000..1f3b4a129 --- /dev/null +++ b/tools/generate-typegen.mjs @@ -0,0 +1,14 @@ +import fs from 'node:fs/promises' +import { pluginsToRulesDTS } from 'eslint-typegen/core' +import plugin from '../lib/index.js' + +const dts = await pluginsToRulesDTS( + { + vue: plugin + }, + { + includeAugmentation: false + } +) + +await fs.writeFile('lib/eslint-typegen.d.ts', dts) 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