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/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/docs/developer-guide/index.md b/docs/developer-guide/index.md index 2e1bb7da9..9bfc68007 100644 --- a/docs/developer-guide/index.md +++ b/docs/developer-guide/index.md @@ -8,6 +8,15 @@ If you think you’ve found a bug in ESLint, please [create a new issue](https:/ Please include as much detail as possible to help us properly address your issue. If we need to triage issues and constantly ask people for more detail, that’s time taken away from actually fixing issues. Help us be as efficient as possible by including a lot of detail in your issues. +## :seedling: Project Setup + +To develop locally, fork the eslint-plugin-vue repository and clone it in your local machine. Use the [npm](https://www.npmjs.com/) package manager to install and link dependencies and the LTS version of [Node.js](https://nodejs.org/). + +To develop and test the `eslint-plugin-vue` package: + +1. Run `npm install` in the project's root folder. +2. Run `npm test` to make sure everything is set up correctly. + ## :sparkles: Proposing a new rule or a rule change In order to add a new rule or a rule change, you should: diff --git a/docs/rules/index.md b/docs/rules/index.md index 6423ef365..34462fba0 100644 --- a/docs/rules/index.md +++ b/docs/rules/index.md @@ -327,6 +327,7 @@ The following rules extend the rules provided by ESLint itself and apply them to | [vue/no-implicit-coercion] | Disallow shorthand type conversions in ``, options: [{ alphabetical: true }], errors: [ - 'Attribute "v-bind" should go before "v-on:click".', - 'Attribute "v-if" should go before "v-on:click".' + { + message: 'Attribute "v-bind" should go before "v-on:click".', + line: 5, + column: 11, + endLine: 5, + endColumn: 21 + }, + { + message: 'Attribute "v-if" should go before "v-on:click".', + line: 6, + column: 11, + endLine: 6, + endColumn: 19 + } ] }, { @@ -1428,7 +1652,15 @@ tester.run('attributes-order', rule, { v-bind:value="a"> `, - errors: ['Attribute "v-model" should go before "v-custom-directive".'] + errors: [ + { + message: 'Attribute "v-model" should go before "v-custom-directive".', + line: 6, + column: 11, + endLine: 6, + endColumn: 22 + } + ] }, { filename: 'test.vue', @@ -1450,7 +1682,15 @@ tester.run('attributes-order', rule, { v-model="c"> `, - errors: ['Attribute "v-bind:id" should go before "v-model".'] + errors: [ + { + message: 'Attribute "v-bind:id" should go before "v-model".', + line: 7, + column: 11, + endLine: 7, + endColumn: 24 + } + ] }, // omit order @@ -1473,7 +1713,15 @@ tester.run('attributes-order', rule, { `, options: [{ order: ['LIST_RENDERING', 'CONDITIONALS'] }], - errors: ['Attribute "v-for" should go before "v-if".'] + errors: [ + { + message: 'Attribute "v-for" should go before "v-if".', + line: 6, + column: 11, + endLine: 6, + endColumn: 29 + } + ] }, { filename: 'test.vue', @@ -1494,7 +1742,15 @@ tester.run('attributes-order', rule, { `, options: [{ order: ['LIST_RENDERING', 'CONDITIONALS'] }], - errors: ['Attribute "v-for" should go before "v-if".'] + errors: [ + { + message: 'Attribute "v-for" should go before "v-if".', + line: 6, + column: 11, + endLine: 6, + endColumn: 29 + } + ] }, // slot @@ -1523,7 +1779,11 @@ tester.run('attributes-order', rule, { ], errors: [ { - message: 'Attribute "bar" should go before "v-slot".' + message: 'Attribute "bar" should go before "v-slot".', + line: 1, + column: 43, + endLine: 1, + endColumn: 52 } ] }, @@ -1553,7 +1813,11 @@ tester.run('attributes-order', rule, { ], errors: [ { - message: 'Attribute "ref" should go before "bar".' + message: 'Attribute "ref" should go before "bar".', + line: 1, + column: 26, + endLine: 1, + endColumn: 35 } ] }, @@ -1579,8 +1843,20 @@ tester.run('attributes-order', rule, { @click="handleClick"/> `, errors: [ - 'Attribute "v-if" should go before "v-bind".', - 'Attribute "ref" should go before "v-model".' + { + message: 'Attribute "v-if" should go before "v-bind".', + line: 5, + column: 11, + endLine: 5, + endColumn: 22 + }, + { + message: 'Attribute "ref" should go before "v-model".', + line: 7, + column: 11, + endLine: 7, + endColumn: 20 + } ] }, @@ -1598,7 +1874,15 @@ tester.run('attributes-order', rule, { v-bind="object" @click="handleClick"/> `, - errors: ['Attribute "v-bind" should go before "@click".'] + errors: [ + { + message: 'Attribute "v-bind" should go before "@click".', + line: 5, + column: 11, + endLine: 5, + endColumn: 26 + } + ] }, { @@ -1619,7 +1903,15 @@ tester.run('attributes-order', rule, { @click="handleClick" @input="handleInput"/> `, - errors: ['Attribute "v-bind" should go before "@click".'] + errors: [ + { + message: 'Attribute "v-bind" should go before "@click".', + line: 6, + column: 11, + endLine: 6, + endColumn: 26 + } + ] }, { @@ -1641,7 +1933,15 @@ tester.run('attributes-order', rule, { v-bind="object"/> `, options: [{ order: ['UNIQUE', 'EVENTS', 'OTHER_ATTR'] }], - errors: ['Attribute "@input" should go before "v-bind".'] + errors: [ + { + message: 'Attribute "@input" should go before "v-bind".', + line: 7, + column: 11, + endLine: 7, + endColumn: 31 + } + ] }, { @@ -1661,7 +1961,15 @@ tester.run('attributes-order', rule, { attr="foo"/> `, options: [{ order: ['UNIQUE', 'EVENTS', 'OTHER_ATTR'] }], - errors: ['Attribute "@click" should go before "v-bind".'] + errors: [ + { + message: 'Attribute "@click" should go before "v-bind".', + line: 5, + column: 11, + endLine: 5, + endColumn: 31 + } + ] }, { @@ -1681,7 +1989,15 @@ tester.run('attributes-order', rule, { :prop-three="c"/> `, options: [{ order: ['ATTR_STATIC', 'ATTR_DYNAMIC'] }], - errors: ['Attribute "prop-two" should go before "v-bind:prop-one".'] + errors: [ + { + message: 'Attribute "prop-two" should go before "v-bind:prop-one".', + line: 5, + column: 11, + endLine: 5, + endColumn: 23 + } + ] }, { @@ -1722,8 +2038,20 @@ tester.run('attributes-order', rule, { } ], errors: [ - 'Attribute "v-model" should go before ":prop-one".', - 'Attribute ":prop-three" should go before "prop-two".' + { + message: 'Attribute "v-model" should go before ":prop-one".', + line: 5, + column: 11, + endLine: 5, + endColumn: 26 + }, + { + message: 'Attribute ":prop-three" should go before "prop-two".', + line: 7, + column: 11, + endLine: 7, + endColumn: 26 + } ] }, @@ -1765,7 +2093,15 @@ tester.run('attributes-order', rule, { ] } ], - errors: ['Attribute "v-model" should go before ":prop-one".'] + errors: [ + { + message: 'Attribute "v-model" should go before ":prop-one".', + line: 5, + column: 11, + endLine: 5, + endColumn: 26 + } + ] } ] }) diff --git a/tests/lib/rules/block-lang.js b/tests/lib/rules/block-lang.js index 5f7851b54..af8b837d6 100644 --- a/tests/lib/rules/block-lang.js +++ b/tests/lib/rules/block-lang.js @@ -42,9 +42,12 @@ tester.run('block-lang', rule, { options: [{ script: { lang: 'ts' } }], errors: [ { - message: `Only "ts" can be used for the 'lang' attribute of '` }, + { + 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 index 5bcb325a5..1f3b4a129 100644 --- a/tools/generate-typegen.mjs +++ b/tools/generate-typegen.mjs @@ -2,8 +2,13 @@ import fs from 'node:fs/promises' import { pluginsToRulesDTS } from 'eslint-typegen/core' import plugin from '../lib/index.js' -const dts = await pluginsToRulesDTS({ - vue: plugin -}) +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