diff --git a/.changeset/great-ravens-happen.md b/.changeset/great-ravens-happen.md
new file mode 100644
index 000000000..eea070fd5
--- /dev/null
+++ b/.changeset/great-ravens-happen.md
@@ -0,0 +1,5 @@
+---
+"eslint-plugin-vue": minor
+---
+
+Added [`@stylistic/eslint-plugin`](https://eslint.style/) as optional peer dependency
diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml
index 90bd33ad5..fede1a47a 100644
--- a/.github/workflows/CI.yml
+++ b/.github/workflows/CI.yml
@@ -31,12 +31,6 @@ jobs:
strategy:
matrix:
node: [18, 20, 21, 'lts/*']
- eslint: [9]
- include:
- # On old ESLint version
- - node: 18
- eslint: 8
-
runs-on: ubuntu-latest
steps:
- name: Checkout
@@ -47,8 +41,23 @@ jobs:
node-version: ${{ matrix.node }}
- name: Install Packages
run: npm install
- - name: Install ESLint v${{ matrix.eslint }}
- run: npm install --save-dev eslint@${{ matrix.eslint }} -f
+ - name: Test
+ run: npm test
+
+ test-with-eslint-v8:
+ name: Test with ESLint v8
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Install Node.js v18
+ uses: actions/setup-node@v4
+ with:
+ node-version: 18
+ - name: Install Packages
+ run: npm install
+ - name: Install ESLint v8
+ run: npm install --save-dev eslint@8 --force
- name: Test
run: npm test
@@ -63,7 +72,25 @@ jobs:
- name: Install Packages
run: npm install
- name: Uninstall @stylistic/eslint-plugin
- run: npm uninstall -D @stylistic/eslint-plugin
+ run: npm uninstall @stylistic/eslint-plugin
+ - name: Test
+ run: npm test
+
+ test-with-old-eslint-stylistic:
+ name: Test with old ESLint Stylistic
+ strategy:
+ matrix:
+ stylistic: [2, 3, 4]
+ 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 @stylistic/eslint-plugin v${{ matrix.stylistic }}
+ run: npm install -D @stylistic/eslint-plugin@${{ matrix.stylistic }} --force
- name: Test
run: npm test
@@ -77,7 +104,7 @@ jobs:
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: Install @typescript-eslint/parser v7
+ run: npm install -D @typescript-eslint/parser@7 --force
- name: Test
run: npm test
diff --git a/package.json b/package.json
index 404e07f32..5266cc3b6 100644
--- a/package.json
+++ b/package.json
@@ -58,11 +58,15 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"peerDependencies": {
+ "@stylistic/eslint-plugin": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0",
+ "@typescript-eslint/parser": "^7.0.0 || ^8.0.0",
"eslint": "^8.57.0 || ^9.0.0",
- "vue-eslint-parser": "^10.0.0",
- "@typescript-eslint/parser": "^7.0.0 || ^8.0.0"
+ "vue-eslint-parser": "^10.0.0"
},
"peerDependenciesMeta": {
+ "@stylistic/eslint-plugin": {
+ "optional": true
+ },
"@typescript-eslint/parser": {
"optional": true
}
@@ -78,7 +82,7 @@
"devDependencies": {
"@changesets/cli": "^2.29.2",
"@ota-meshi/site-kit-eslint-editor-vue": "^0.2.4",
- "@stylistic/eslint-plugin": "^2.12.1",
+ "@stylistic/eslint-plugin": "^5.2.2",
"@svitejs/changesets-changelog-github-compact": "^1.2.0",
"@types/eslint": "^8.56.2",
"@types/natural-compare": "^1.4.3",
diff --git a/tests/lib/rules/comma-style.js b/tests/lib/rules/comma-style.js
index 82c8e4044..e41ba9b44 100644
--- a/tests/lib/rules/comma-style.js
+++ b/tests/lib/rules/comma-style.js
@@ -3,8 +3,10 @@
*/
'use strict'
+const semver = require('semver')
const { RuleTester } = require('../../eslint-compat')
const rule = require('../../../lib/rules/comma-style')
+const { eslintStylisticVersion } = require('../../test-utils/eslint-stylistic')
const tester = new RuleTester({
languageOptions: { parser: require('vue-eslint-parser'), ecmaVersion: 2018 }
@@ -34,13 +36,6 @@ tester.run('comma-style', rule, {
`,
options: ['first', { exceptions: { ArrowFunctionExpression: false } }]
},
- `
-
-
-
- `,
{
code: `
@@ -173,3 +168,53 @@ tester.run('comma-style', rule, {
}
]
})
+
+if (
+ eslintStylisticVersion === undefined ||
+ semver.lt(eslintStylisticVersion, '3.0.0') ||
+ semver.satisfies(process.version, '<19.0.0 || ^21.0.0')
+) {
+ tester.run('comma-style', rule, {
+ valid: [
+ `
+
+
+
+ `
+ ],
+ invalid: []
+ })
+} else {
+ tester.run('comma-style', rule, {
+ valid: [],
+ invalid: [
+ {
+ code: `
+
+
+
+ `,
+ output: `
+
+
+
+ `,
+ errors: [
+ {
+ message: "',' should be placed last.",
+ line: 5,
+ column: 13,
+ endLine: 5,
+ endColumn: 14
+ }
+ ]
+ }
+ ]
+ })
+}
diff --git a/tests/lib/rules/func-call-spacing.js b/tests/lib/rules/func-call-spacing.js
index 7f06f72fc..6dfd86837 100644
--- a/tests/lib/rules/func-call-spacing.js
+++ b/tests/lib/rules/func-call-spacing.js
@@ -3,13 +3,54 @@
*/
'use strict'
+const semver = require('semver')
const { RuleTester } = require('../../eslint-compat')
const rule = require('../../../lib/rules/func-call-spacing')
+const { eslintStylisticVersion } = require('../../test-utils/eslint-stylistic')
const tester = new RuleTester({
languageOptions: { parser: require('vue-eslint-parser'), ecmaVersion: 2020 }
})
+/**
+ * @param {number} line
+ * @param {number} column
+ * @param {'unexpected' | 'missing'} errorType
+ * @returns {{line: number, column: number, endLine: number, endColumn: number}}
+ */
+function getErrorPosition(line, column, errorType) {
+ if (
+ eslintStylisticVersion !== undefined &&
+ semver.lt(eslintStylisticVersion, '3.0.0')
+ ) {
+ return {
+ line,
+ column: column - 3,
+ endLine: undefined,
+ endColumn: undefined
+ }
+ }
+
+ if (
+ eslintStylisticVersion === undefined ||
+ semver.satisfies(process.version, '<19.0.0 || ^21.0.0')
+ ) {
+ return {
+ line,
+ column: errorType === 'unexpected' ? column : column - 1,
+ endLine: line,
+ endColumn: column
+ }
+ }
+
+ return {
+ line,
+ column,
+ endLine: line,
+ endColumn: errorType === 'unexpected' ? column + 1 : column
+ }
+}
+
tester.run('func-call-spacing', rule, {
valid: [
`
@@ -61,7 +102,7 @@ tester.run('func-call-spacing', rule, {
errors: [
{
message: 'Unexpected whitespace between function name and paren.',
- line: 3
+ ...getErrorPosition(3, 23, 'unexpected')
}
]
},
@@ -80,7 +121,7 @@ tester.run('func-call-spacing', rule, {
errors: [
{
message: 'Missing space between function name and paren.',
- line: 3
+ ...getErrorPosition(3, 23, 'missing')
}
]
},
@@ -102,7 +143,7 @@ tester.run('func-call-spacing', rule, {
errors: [
{
message: 'Unexpected whitespace between function name and paren.',
- line: 4
+ ...getErrorPosition(4, 27, 'unexpected')
}
]
}
diff --git a/tests/test-utils/eslint-stylistic.js b/tests/test-utils/eslint-stylistic.js
new file mode 100644
index 000000000..81fc774f3
--- /dev/null
+++ b/tests/test-utils/eslint-stylistic.js
@@ -0,0 +1,16 @@
+const { existsSync, readFileSync } = require('node:fs')
+const path = require('node:path')
+
+const eslintStylisticPackagePath = path.join(
+ __dirname,
+ '../..',
+ 'node_modules',
+ '@stylistic',
+ 'eslint-plugin',
+ 'package.json'
+)
+const eslintStylisticVersion = existsSync(eslintStylisticPackagePath)
+ ? JSON.parse(readFileSync(eslintStylisticPackagePath, 'utf8')).version
+ : undefined
+
+module.exports = { eslintStylisticVersion }