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/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/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/.changeset/purple-lights-invite.md b/.changeset/purple-lights-invite.md new file mode 100644 index 000000000..80aa90b8d --- /dev/null +++ b/.changeset/purple-lights-invite.md @@ -0,0 +1,5 @@ +--- +'eslint-plugin-vue': minor +--- + +Added `ignorePattern` option to [`vue/no-v-html`](https://eslint.vuejs.org/rules/no-v-html.html) diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index e695f422a..000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,124 +0,0 @@ -workflows: - version: 2 - node-multi-build: - jobs: - - eslint-v6 - - eslint-v7 - - ts-eslint-v4 - - node-v12 - - node-v14 - - node-v16 - - lint - -version: 2 -jobs: - node-base: &node-base - docker: - - image: node - steps: - - run: - name: Versions - command: npm version - - checkout - # - restore_cache: - # keys: - # - v2-npm-lock-{{ .Branch }}-{{ .Environment.CIRCLE_JOB }}-{{ checksum "package.json" }} - - run: - name: Install dependencies - command: npm install --legacy-peer-deps - - run: - name: Test - command: npm test - # - save_cache: - # key: v2-npm-lock-{{ .Branch }}-{{ .Environment.CIRCLE_JOB }}-{{ checksum "package.json" }} - # paths: - # - node_modules - - eslint-v6: - docker: - - image: node:12 - steps: - - run: - name: Versions - command: npm version - - checkout - - run: - name: Install eslint@6 - command: | - npm install --save-exact eslint@6.8.0 - - run: - name: Install dependencies - command: npm install - - run: - name: Test - command: npm test - eslint-v7: - docker: - - image: node:14 - steps: - - run: - name: Versions - command: npm version - - checkout - - run: - name: Install eslint@7 - command: | - npm install eslint@7 - - run: - name: Install dependencies - command: npm install - - run: - name: Test - command: npm test - ts-eslint-v4: - docker: - - image: node:14 - steps: - - run: - name: Versions - command: npm version - - checkout - - run: - name: Install @typescript-eslint/parser@4 eslint@7 - command: | - npm install @typescript-eslint/parser@^4 eslint@7 - - run: - name: Install dependencies - command: npm install - - run: - name: Test - command: npm test - node-v12: - <<: *node-base - docker: - - image: node:12 - node-v14: - <<: *node-base - docker: - - image: node:14 - node-v16: - <<: *node-base - docker: - - image: node:16 - - lint: - docker: - - image: node:14 - steps: - - run: - name: Versions - command: npm version - - checkout - - restore_cache: - keys: - - v2-npm-lock-{{ .Branch }}-{{ .Environment.CIRCLE_JOB }}-{{ checksum "package.json" }} - - run: - name: Install dependencies - command: npm install - - save_cache: - key: v2-npm-lock-{{ .Branch }}-{{ .Environment.CIRCLE_JOB }}-{{ checksum "package.json" }} - paths: - - node_modules - - run: - name: Lint - command: npm run lint diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 1905aa4a8..000000000 --- a/.eslintignore +++ /dev/null @@ -1,8 +0,0 @@ -/.nyc_output -/coverage -/node_modules -/tests/fixtures -/tests/integrations/eslint-plugin-import - -!.vuepress -/docs/.vuepress/dist diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 3229de98d..000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,158 +0,0 @@ -'use strict' - -module.exports = { - root: true, - parserOptions: { - ecmaVersion: 2018 - }, - env: { - es6: true, - node: true, - mocha: true - }, - extends: [ - 'plugin:eslint-plugin/recommended', - 'prettier', - 'plugin:node-dependencies/recommended', - 'plugin:jsonc/recommended-with-jsonc' - ], - plugins: ['eslint-plugin', 'prettier'], - rules: { - 'accessor-pairs': 2, - camelcase: [2, { properties: 'never' }], - 'constructor-super': 2, - eqeqeq: [2, 'allow-null'], - 'handle-callback-err': [2, '^(err|error)$'], - 'jsx-quotes': [2, 'prefer-single'], - 'new-cap': [2, { newIsCap: true, capIsNew: false }], - 'new-parens': 2, - 'no-array-constructor': 2, - 'no-caller': 2, - 'no-class-assign': 2, - 'no-cond-assign': 2, - 'no-const-assign': 2, - 'no-control-regex': 2, - 'no-delete-var': 2, - 'no-dupe-args': 2, - 'no-dupe-class-members': 2, - 'no-dupe-keys': 2, - 'no-duplicate-case': 2, - 'no-empty-character-class': 2, - 'no-empty-pattern': 2, - 'no-eval': 2, - 'no-ex-assign': 2, - 'no-extend-native': 2, - 'no-extra-bind': 2, - 'no-extra-boolean-cast': 2, - 'no-extra-parens': [2, 'functions'], - 'no-fallthrough': 2, - 'no-floating-decimal': 2, - 'no-func-assign': 2, - 'no-implied-eval': 2, - 'no-inner-declarations': [2, 'functions'], - 'no-invalid-regexp': 2, - 'no-irregular-whitespace': 2, - 'no-iterator': 2, - 'no-label-var': 2, - 'no-labels': [2, { allowLoop: false, allowSwitch: false }], - 'no-lone-blocks': 2, - 'no-multi-spaces': [2, { ignoreEOLComments: true }], - 'no-multi-str': 2, - 'no-native-reassign': 2, - 'no-negated-in-lhs': 2, - 'no-new-object': 2, - 'no-new-require': 2, - 'no-new-symbol': 2, - 'no-new-wrappers': 2, - 'no-obj-calls': 2, - 'no-octal': 2, - 'no-octal-escape': 2, - 'no-path-concat': 2, - 'no-proto': 2, - 'no-redeclare': 2, - 'no-regex-spaces': 2, - 'no-return-assign': [2, 'except-parens'], - 'no-self-assign': 2, - 'no-self-compare': 2, - 'no-sequences': 2, - 'no-shadow-restricted-names': 2, - 'no-sparse-arrays': 2, - 'no-this-before-super': 2, - 'no-throw-literal': 2, - 'no-undef': 2, - 'no-undef-init': 2, - 'no-unexpected-multiline': 2, - 'no-unmodified-loop-condition': 2, - 'no-unneeded-ternary': [2, { defaultAssignment: false }], - 'no-unreachable': 2, - 'no-unsafe-finally': 2, - 'no-unused-vars': [2, { vars: 'all', args: 'none' }], - 'no-useless-call': 2, - 'no-useless-computed-key': 2, - 'no-useless-constructor': 2, - 'no-useless-escape': 0, - 'no-with': 2, - 'one-var': [2, { initialized: 'never' }], - 'use-isnan': 2, - 'valid-typeof': 2, - 'wrap-iife': [2, 'any'], - yoda: [2, 'never'], - 'prefer-const': 2, - - 'prettier/prettier': 'error', - 'eslint-plugin/report-message-format': ['error', "^[A-Z`'{].*\\.$"], - 'eslint-plugin/prefer-placeholders': 'error', - 'eslint-plugin/consistent-output': 'error', - - 'no-debugger': 'error', - 'no-console': 'error', - 'no-alert': 'error', - 'no-void': 'error', - - 'no-warning-comments': 'warn', - 'no-var': 'error', - 'prefer-template': 'error', - 'object-shorthand': 'error', - 'prefer-rest-params': 'error', - 'prefer-arrow-callback': 'error', - 'prefer-spread': 'error', - - 'dot-notation': 'error' - }, - overrides: [ - { - files: ['./**/*.vue'], - parser: require.resolve('vue-eslint-parser'), - parserOptions: { - ecmaVersion: 2020, - sourceType: 'module' - } - }, - { - files: ['lib/rules/*.js'], - rules: { - 'eslint-plugin/no-deprecated-context-methods': 'error', - 'eslint-plugin/no-only-tests': 'error', - 'eslint-plugin/prefer-object-rule': 'error', - 'eslint-plugin/require-meta-docs-description': 'error', - 'eslint-plugin/require-meta-docs-url': [ - 'error', - { - pattern: `https://eslint.vuejs.org/rules/{{name}}.html` - } - ], - 'eslint-plugin/require-meta-has-suggestions': 'error', - 'eslint-plugin/require-meta-schema': 'error', - 'eslint-plugin/require-meta-type': 'error', - 'no-invalid-meta': 'error', - 'no-invalid-meta-docs-categories': 'error' - } - }, - { - files: ['*.json'], - rules: { - 'prettier/prettier': 'off' - } - } - ] -} diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..c4d031e9c --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +github: + - ota-meshi + - FloEdelmann diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index f1169f466..08d755127 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -26,6 +26,7 @@ about: Create a report to help us improve - **ESLint version:** - **eslint-plugin-vue version:** +- **Vue version:** - **Node version:** - **Operating System:** diff --git a/.github/ISSUE_TEMPLATE/change.md b/.github/ISSUE_TEMPLATE/change.md index a6a4a7dc0..02397f6cd 100644 --- a/.github/ISSUE_TEMPLATE/change.md +++ b/.github/ISSUE_TEMPLATE/change.md @@ -13,6 +13,7 @@ about: Request a change that is not a bug fix, rule change, or new rule - **ESLint version:** - **eslint-plugin-vue version:** +- **Vue version:** - **Node version:** **The problem you want to solve.** diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 15c7d4193..fede1a47a 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -1,42 +1,110 @@ name: CI on: push: - branches: [master] + branches: + - 'master' pull_request: - branches: [master] + types: + - 'opened' + - 'synchronize' + - 'reopened' + +permissions: + contents: read jobs: lint: name: Lint runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Install Node.js - uses: actions/setup-node@v3 - with: - node-version: 16 - - name: Install Packages - run: npm install --legacy-peer-deps - - name: Lint - run: npm run lint + - name: Checkout + uses: actions/checkout@v4 + - name: Install Node.js + uses: actions/setup-node@v4 + - name: Install Packages + run: npm install --legacy-peer-deps + - name: Lint + run: npm run lint test: name: Test strategy: matrix: - node: [16, 17] - os: [ubuntu-latest] + node: [18, 20, 21, 'lts/*'] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Install Node.js v${{ matrix.node }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + - name: Install Packages + run: npm install + - 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 - runs-on: ${{ matrix.os }} + test-without-eslint-stylistic: + name: Test without ESLint Stylistic + 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: Uninstall @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 + + test-with-typescript-eslint-v7: + name: Test with typescript-eslint v7 + runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Install Node.js v${{ matrix.node }} - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node }} - - name: Install Packages - run: npm install --legacy-peer-deps - - name: Test - run: npm test + - 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 v7 + run: npm install -D @typescript-eslint/parser@7 --force + - 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 new file mode 100644 index 000000000..31f881b1d --- /dev/null +++ b/.github/workflows/check-for-resources-update.yml @@ -0,0 +1,31 @@ +name: Check for utils resources update +on: + workflow_dispatch: null + schedule: + - cron: 0 0 * * 0 # At 00:00 on Sunday, see https://crontab.guru/#0_0_*_*_0 + +permissions: + 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 + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version: 18 + - name: Install Packages + run: npm install + - name: Update + run: npm run update-resources + - uses: peter-evans/create-pull-request@v7 + with: + commit-message: Updates resources + branch: update-resources + branch-suffix: timestamp + title: Updates resources diff --git a/.gitignore b/.gitignore index e1401b951..d6fadf92c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,10 @@ /test.* yarn.lock yarn-error.log -docs/.vuepress/dist +/docs/.vitepress/dist +/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/.markdownlint.yml b/.markdownlint.yml index cb76e21d5..6591a3543 100644 --- a/.markdownlint.yml +++ b/.markdownlint.yml @@ -1,10 +1,13 @@ line-length: false +link-fragments: false single-title: false no-inline-html: allowed_elements: - badge - eslint-code-block - sup + - rules-table + - span # enforce consistency code-block-style: @@ -12,7 +15,7 @@ code-block-style: code-fence-style: style: backtick emphasis-style: - style: asterisk + style: underscore heading-style: style: atx hr-style: diff --git a/.markdownlintignore b/.markdownlintignore index 3c3629e64..e7becf85b 100644 --- a/.markdownlintignore +++ b/.markdownlintignore @@ -1 +1,2 @@ node_modules +CHANGELOG.md diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..d341f1772 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +tests/fixtures/ +.github/ISSUE_TEMPLATE/*.md diff --git a/.vscode/launch.json b/.vscode/launch.json index 324a79864..171c80066 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,12 +5,17 @@ "type": "node", "request": "launch", "name": "Start testing", - "program": "${workspaceFolder}/node_modules/.bin/mocha", - "args": [ - "${file}", - "--watch" - ], + "program": "${workspaceFolder}/node_modules/.bin/vitest", + "args": ["run", "${file}", "--reporter=verbose"], + "console": "integratedTerminal" + }, + { + "type": "node", + "request": "launch", + "name": "Start testing (watch)", + "program": "${workspaceFolder}/node_modules/.bin/vitest", + "args": ["${file}", "--reporter=verbose"], "console": "integratedTerminal" } ] -} +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 80e1f88fd..f80681b66 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,19 +1,15 @@ { - "editor.tabSize": 2, - "eslint.options": { - "rulePaths": ["eslint-internal-rules"] - }, - "eslint.validate": [ - "javascript", - "javascriptreact", - "vue", - "json", - "jsonc" - ], - "typescript.tsdk": "./node_modules/typescript/lib", - "vetur.validation.script": false, - "[typescript]": { - "editor.formatOnSave": true, - "editor.defaultFormatter": "esbenp.prettier-vscode" - }, + "editor.tabSize": 2, + "eslint.experimental.useFlatConfig": true, + "eslint.validate": ["javascript", "javascriptreact", "vue", "json", "jsonc"], + "typescript.tsdk": "./node_modules/typescript/lib", + "vetur.validation.script": false, + "[typescript]": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[javascript]": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode" + } } diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..fa7a29427 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,45 @@ +# eslint-plugin-vue + +## 10.4.0 + +### Minor Changes + +- Added `ignoreParents` option to [`vue/no-deprecated-slot-attribute`](https://eslint.vuejs.org/rules/no-deprecated-slot-attribute.html) ([#2784](https://github.com/vuejs/eslint-plugin-vue/pull/2784)) + +- Added new [`vue/no-negated-v-if-condition`](https://eslint.vuejs.org/rules/no-negated-v-if-condition.html) rule ([#2794](https://github.com/vuejs/eslint-plugin-vue/pull/2794)) + +- Added new [`vue/no-negated-condition`](https://eslint.vuejs.org/rules/no-negated-condition.html) rule ([#2795](https://github.com/vuejs/eslint-plugin-vue/pull/2795)) + +### Patch Changes + +- Resolved TypeScript compatibility issues introduced by eslint-typegen ([#2790](https://github.com/vuejs/eslint-plugin-vue/pull/2790)) + +- Fixed inconsistent quotes in [`vue/block-lang`](https://eslint.vuejs.org/rules/block-lang.html) error messages ([#2805](https://github.com/vuejs/eslint-plugin-vue/pull/2805)) + +## 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 cacd80209..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 @@ -13,7 +13,14 @@ Please refer to the [official website](https://eslint.vuejs.org). ## :anchor: Versioning Policy -This plugin follows [Semantic Versioning](https://semver.org) and [ESLint's Semantic Versioning Policy](https://github.com/eslint/eslint#semantic-versioning-policy). +This plugin follows [Semantic Versioning]. +However, please note that we do not follow [ESLint's Semantic Versioning Policy]. +In minor version releases, this plugin may change the sharable configs provided by the plugin or the default behavior of the plugin's rules in order to add features to the plugin. Because we want to add many features to the plugin soon, so that users can easily take advantage of new features in Vue and Nuxt. + +According to our policy, any minor update may report more linting errors than the previous release. As such, we recommend using the [tilde (`~`)](https://semver.npmjs.com/#syntax-examples) in `package.json` to guarantee the results of your builds. + +[Semantic Versioning]: https://semver.org/ +[ESLint's Semantic Versioning Policy]: https://github.com/eslint/eslint#semantic-versioning-policy ## :newspaper: Releases diff --git a/docs/.vitepress/build-system/build.mts b/docs/.vitepress/build-system/build.mts new file mode 100644 index 000000000..edda69143 --- /dev/null +++ b/docs/.vitepress/build-system/build.mts @@ -0,0 +1,91 @@ +/** + * Pre-build cjs packages that cannot be bundled well. + */ +import esbuild from 'esbuild' +import path from 'pathe' +import fs from 'fs' +import { fileURLToPath } from 'url' + +const dirname = path.dirname(fileURLToPath(import.meta.url)) + +build( + 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/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[] = []) { + // eslint-disable-next-line no-console -- ignore + console.log(`build@ ${input}`) + let code = bundle(input, injects) + code = transform(code, injects) + fs.mkdirSync(path.dirname(out), { recursive: true }) + fs.writeFileSync(out, code, 'utf8') +} + +function bundle(entryPoint: string, externals: string[]) { + const result = esbuild.buildSync({ + entryPoints: [entryPoint], + format: 'esm', + bundle: true, + external: externals, + write: false, + inject: [path.join(dirname, './src/process-shim.mjs')] + }) + + return `${result.outputFiles[0].text}` +} + +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 ` +${normalizeInjects + .map( + (inject) => + `import $inject_${inject.replace(/[\-:]/gu, '_')}$ from '${inject}';` + ) + .join('\n')} +const $_injects_$ = {${injects + .map( + (inject) => + `"${inject}":$inject_${inject.replace(/^node:/u, '').replace(/[\-:]/gu, '_')}$` + ) + .join(',\n')}}; +function require(module, ...args) { + return $_injects_$[module] || {} +} +${newCode} +` +} diff --git a/docs/.vitepress/build-system/shim/empty.mjs b/docs/.vitepress/build-system/shim/empty.mjs new file mode 100644 index 000000000..57d1de9f1 --- /dev/null +++ b/docs/.vitepress/build-system/shim/empty.mjs @@ -0,0 +1,2 @@ +export {} +export default {} diff --git a/docs/.vitepress/build-system/src/process-shim.mjs b/docs/.vitepress/build-system/src/process-shim.mjs new file mode 100644 index 000000000..6b75bf56e --- /dev/null +++ b/docs/.vitepress/build-system/src/process-shim.mjs @@ -0,0 +1,10 @@ +/* globals window */ +// @ts-nocheck +export const process = { + env: {}, + cwd: () => '', + stdout: {} +} +if (typeof window !== 'undefined') { + window.process = process +} diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts new file mode 100644 index 000000000..7d198d588 --- /dev/null +++ b/docs/.vitepress/config.mts @@ -0,0 +1,235 @@ +import type { DefaultTheme } from 'vitepress' +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' + +const dirname = path.dirname(fileURLToPath(import.meta.url)) + +export default async () => { + const rulesPath = '../../tools/lib/rules.js' // Avoid bundle + const rules: typeof import('../../tools/lib/rules.js') = await import( + rulesPath + ).then((mod) => mod.default || mod) + const uncategorizedRules = rules.filter( + (rule) => + !rule.meta.docs.categories && + !rule.meta.docs.extensionSource && + !rule.meta.deprecated + ) + const uncategorizedExtensionRule = rules.filter( + (rule) => + !rule.meta.docs.categories && + rule.meta.docs.extensionSource && + !rule.meta.deprecated + ) + const deprecatedRules = rules.filter((rule) => rule.meta.deprecated) + + const sidebarCategories = [ + { title: 'Base Rules', categoryIds: ['base'] }, + { + title: 'Priority A: Essential', + categoryIds: ['vue3-essential', 'vue2-essential'] + }, + { + title: 'Priority A: Essential for Vue.js 3.x', + categoryIds: ['vue3-essential'] + }, + { + title: 'Priority A: Essential for Vue.js 2.x', + categoryIds: ['vue2-essential'] + }, + { + title: 'Priority B: Strongly Recommended', + categoryIds: ['vue3-strongly-recommended', 'vue2-strongly-recommended'] + }, + { + title: 'Priority B: Strongly Recommended for Vue.js 3.x', + categoryIds: ['vue3-strongly-recommended'] + }, + { + title: 'Priority B: Strongly Recommended for Vue.js 2.x', + categoryIds: ['vue2-strongly-recommended'] + }, + { + title: 'Priority C: Recommended', + categoryIds: ['vue3-recommended', 'vue2-recommended'] + }, + { + title: 'Priority C: Recommended for Vue.js 3.x', + categoryIds: ['vue3-recommended'] + }, + { + title: 'Priority C: Recommended for Vue.js 2.x', + categoryIds: ['vue2-recommended'] + } + ] + + const categorizedRules: DefaultTheme.SidebarItem[] = [] + for (const { title, categoryIds } of sidebarCategories) { + const categoryRules = rules + .filter((rule) => rule.meta.docs.categories && !rule.meta.deprecated) + .filter((rule) => + categoryIds.every((categoryId) => + rule.meta.docs.categories.includes(categoryId) + ) + ) + const children: DefaultTheme.SidebarItem[] = categoryRules + .filter(({ ruleId }) => { + const exists = categorizedRules.some( + ({ items }) => + items && + items.some(({ text: alreadyRuleId }) => alreadyRuleId === ruleId) + ) + return !exists + }) + .map(({ ruleId, name }) => { + return { + text: ruleId, + link: `/rules/${name}` + } + }) + + if (children.length === 0) { + continue + } + categorizedRules.push({ + text: title, + collapsed: false, + items: children + }) + } + + const extraCategories: DefaultTheme.SidebarItem[] = [] + if (uncategorizedRules.length > 0) { + extraCategories.push({ + text: 'Uncategorized', + collapsed: false, + items: uncategorizedRules.map(({ ruleId, name }) => ({ + text: ruleId, + link: `/rules/${name}` + })) + }) + } + if (uncategorizedExtensionRule.length > 0) { + extraCategories.push({ + text: 'Extension Rules', + collapsed: false, + items: uncategorizedExtensionRule.map(({ ruleId, name }) => ({ + text: ruleId, + link: `/rules/${name}` + })) + }) + } + if (deprecatedRules.length > 0) { + extraCategories.push({ + text: 'Deprecated', + collapsed: false, + items: deprecatedRules.map(({ ruleId, name }) => ({ + text: ruleId, + link: `/rules/${name}` + })) + }) + } + return defineConfig({ + base: '/', + title: 'eslint-plugin-vue', + description: 'Official ESLint plugin for Vue.js', + head: [['link', { rel: 'icon', href: '/favicon.png' }]], + + vite: { + publicDir: path.resolve(dirname, './public'), + plugins: [ + vitePluginRequireResolve(), + viteCommonjs(), + eslint4b() as any, + requireESLintUseAtYourOwnRisk4b() + ], + resolve: { + alias: { + 'vue-eslint-parser': path.join( + dirname, + './build-system/shim/vue-eslint-parser.mjs' + ), + '@typescript-eslint/parser': path.join( + dirname, + './build-system/shim/@typescript-eslint/parser.mjs' + ), + + tslib: path.join(dirname, '../../node_modules/tslib/tslib.es6.js'), + 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: { + 'require.cache': '{}' + } + }, + + lastUpdated: true, + themeConfig: { + editLink: { + pattern: + 'https://github.com/vuejs/eslint-plugin-vue/edit/master/docs/:path' + }, + socialLinks: [ + { + icon: 'github', + link: 'https://github.com/vuejs/eslint-plugin-vue' + } + ], + + nav: [ + { text: 'User Guide', link: '/user-guide/' }, + { text: 'Developer Guide', link: '/developer-guide/' }, + { text: 'Rules', link: '/rules/' }, + { + text: 'Demo', + link: 'https://ota-meshi.github.io/eslint-plugin-vue-demo/' + } + ], + + sidebar: { + '/rules/': [ + { + text: 'Rules', + items: [{ text: 'Available Rules', link: '/rules/' }] + }, + + // Rules in each category. + ...categorizedRules, + + // Rules in no category. + ...extraCategories + ], + + '/': [ + { + text: 'Guide', + items: [ + { text: 'Introduction', link: '/' }, + { text: 'User Guide', link: '/user-guide/' }, + { text: 'Developer Guide', link: '/developer-guide/' }, + { text: 'Rules', link: '/rules/' } + ] + } + ] + }, + + outline: { + level: 'deep' + }, + + algolia: { + appId: '2L4MGZSULB', + apiKey: 'fdf57932b27a6c230d01a890492ab76d', + indexName: 'eslint-plugin-vue' + } + } + }) +} diff --git a/docs/.vuepress/public/favicon.png b/docs/.vitepress/public/favicon.png similarity index 100% rename from docs/.vuepress/public/favicon.png rename to docs/.vitepress/public/favicon.png diff --git a/docs/.vitepress/public/service-worker.js b/docs/.vitepress/public/service-worker.js new file mode 100644 index 000000000..e80d3f2d7 --- /dev/null +++ b/docs/.vitepress/public/service-worker.js @@ -0,0 +1,14 @@ +// https://github.com/NekR/self-destroying-sw +/* globals self */ +self.addEventListener('install', (e) => { + self.skipWaiting() +}) + +self.addEventListener('activate', (e) => { + self.registration + .unregister() + .then(() => self.clients.matchAll()) + .then((clients) => { + for (const client of clients) client.navigate(client.url) + }) +}) diff --git a/docs/.vitepress/theme/Layout.vue b/docs/.vitepress/theme/Layout.vue new file mode 100644 index 000000000..3be00694b --- /dev/null +++ b/docs/.vitepress/theme/Layout.vue @@ -0,0 +1,21 @@ + + + + + diff --git a/docs/.vitepress/theme/components/eslint-code-block.vue b/docs/.vitepress/theme/components/eslint-code-block.vue new file mode 100644 index 000000000..12cd1ff8b --- /dev/null +++ b/docs/.vitepress/theme/components/eslint-code-block.vue @@ -0,0 +1,217 @@ + + + + + diff --git a/docs/.vitepress/theme/components/rules-table.vue b/docs/.vitepress/theme/components/rules-table.vue new file mode 100644 index 000000000..c517d4591 --- /dev/null +++ b/docs/.vitepress/theme/components/rules-table.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts new file mode 100644 index 000000000..757e63cab --- /dev/null +++ b/docs/.vitepress/theme/index.ts @@ -0,0 +1,32 @@ +// @ts-expect-error -- Browser +if (typeof window !== 'undefined') { + if (typeof require === 'undefined') { + // @ts-expect-error -- Browser + ;(window as any).require = () => { + const e = new Error('require is not defined') + ;(e as any).code = 'MODULE_NOT_FOUND' + throw e + } + } +} +// @ts-expect-error -- Cannot change `module` option +import type { Theme } from 'vitepress' +// @ts-expect-error -- Cannot change `module` option +import DefaultTheme from 'vitepress/theme' +// @ts-expect-error -- ignore +import Layout from './Layout.vue' +// @ts-expect-error -- ignore +import ESLintCodeBlock from './components/eslint-code-block.vue' +// @ts-expect-error -- ignore +import RulesTable from './components/rules-table.vue' + +const theme: Theme = { + ...DefaultTheme, + Layout, + enhanceApp(ctx) { + DefaultTheme.enhanceApp(ctx) + ctx.app.component('eslint-code-block', ESLintCodeBlock) + ctx.app.component('rules-table', RulesTable) + } +} +export default theme diff --git a/docs/.vitepress/vite-plugin.mts b/docs/.vitepress/vite-plugin.mts new file mode 100644 index 000000000..cd6811cb6 --- /dev/null +++ b/docs/.vitepress/vite-plugin.mts @@ -0,0 +1,83 @@ +import type { UserConfig } from 'vitepress' +import path from 'pathe' +import { fileURLToPath } from 'url' +import esbuild from 'esbuild' +type Plugin = Extract< + NonNullable['plugins']>[number], + { name: string } +> + +const libRoot = path.join(fileURLToPath(import.meta.url), '../../../lib') +export function vitePluginRequireResolve(): Plugin { + return { + name: 'vite-plugin-require.resolve', + transform(code, id, _options) { + if (id.startsWith(libRoot)) { + return code.replace(/require\.resolve/gu, '(function(){return 0})') + } + return undefined + } + } +} + +export function viteCommonjs(): Plugin { + return { + name: 'vite-plugin-cjs-to-esm', + apply: () => true, + async transform(code, id) { + if (!id.startsWith(libRoot)) { + return undefined + } + const base = transformRequire(code) + try { + const transformed = esbuild.transformSync(base, { + format: 'esm' + }) + return transformed.code + } catch (e) { + console.error('Transform error. base code:\n' + base, e) + } + return undefined + } + } +} + +/** + * Transform `require()` to `import` + */ +function transformRequire(code: string) { + if (!code.includes('require')) { + return code + } + const modules = new Map() + const replaced = code.replace( + /(\/\/[^\n\r]*|\/\*[\s\S]*?\*\/)|\brequire\s*\(\s*(["'].*?["'])\s*\)/gu, + (match, comment, moduleString) => { + if (comment) { + return match + } + + let id = + '__' + + moduleString.replace(/[^a-zA-Z0-9_$]+/gu, '_') + + Math.random().toString(32).substring(2) + while (code.includes(id) || modules.has(id)) { + id += Math.random().toString(32).substring(2) + } + modules.set(id, moduleString) + return id + '()' + } + ) + + return ( + [...modules] + .map(([id, moduleString]) => { + return `import * as __temp_${id} from ${moduleString}; +const ${id} = () => __temp_${id}.default || __temp_${id}; +` + }) + .join('') + + ';\n' + + replaced + ) +} diff --git a/docs/.vuepress/components/eslint-code-block.vue b/docs/.vuepress/components/eslint-code-block.vue deleted file mode 100644 index 2c6abd2cc..000000000 --- a/docs/.vuepress/components/eslint-code-block.vue +++ /dev/null @@ -1,156 +0,0 @@ - - - - - diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js deleted file mode 100644 index 68aec1af9..000000000 --- a/docs/.vuepress/config.js +++ /dev/null @@ -1,192 +0,0 @@ -/** - * @author Toru Nagashima - * See LICENSE file in root directory for full license. - */ -'use strict' - -const rules = require('../../tools/lib/rules') -const path = require('path') - -const uncategorizedRules = rules.filter( - (rule) => - !rule.meta.docs.categories && - !rule.meta.docs.extensionRule && - !rule.meta.deprecated -) -const uncategorizedExtensionRule = rules.filter( - (rule) => - !rule.meta.docs.categories && - rule.meta.docs.extensionRule && - !rule.meta.deprecated -) -const deprecatedRules = rules.filter((rule) => rule.meta.deprecated) - -const sidebarCategories = [ - { title: 'Base Rules', categoryIds: ['base'] }, - { - title: 'Priority A: Essential', - categoryIds: ['vue3-essential', 'essential'] - }, - { - title: 'Priority A: Essential for Vue.js 3.x', - categoryIds: ['vue3-essential'] - }, - { title: 'Priority A: Essential for Vue.js 2.x', categoryIds: ['essential'] }, - { - title: 'Priority B: Strongly Recommended', - categoryIds: ['vue3-strongly-recommended', 'strongly-recommended'] - }, - { - title: 'Priority B: Strongly Recommended for Vue.js 3.x', - categoryIds: ['vue3-strongly-recommended'] - }, - { - title: 'Priority B: Strongly Recommended for Vue.js 2.x', - categoryIds: ['strongly-recommended'] - }, - { - title: 'Priority C: Recommended', - categoryIds: ['vue3-recommended', 'recommended'] - }, - { - title: 'Priority C: Recommended for Vue.js 3.x', - categoryIds: ['vue3-recommended'] - }, - { - title: 'Priority C: Recommended for Vue.js 2.x', - categoryIds: ['recommended'] - } -] - -const categorizedRules = [] -for (const { title, categoryIds } of sidebarCategories) { - const categoryRules = rules - .filter((rule) => rule.meta.docs.categories && !rule.meta.deprecated) - .filter((rule) => - categoryIds.every((categoryId) => - rule.meta.docs.categories.includes(categoryId) - ) - ) - const children = categoryRules - .filter(({ ruleId }) => { - const exists = categorizedRules.some(({ children }) => - children.some(([, alreadyRuleId]) => alreadyRuleId === ruleId) - ) - return !exists - }) - .map(({ ruleId, name }) => [`/rules/${name}`, ruleId]) - - if (children.length === 0) { - continue - } - categorizedRules.push({ - title, - collapsable: false, - children - }) -} - -const extraCategories = [] -if (uncategorizedRules.length > 0) { - extraCategories.push({ - title: 'Uncategorized', - collapsable: false, - children: uncategorizedRules.map(({ ruleId, name }) => [ - `/rules/${name}`, - ruleId - ]) - }) -} -if (uncategorizedExtensionRule.length > 0) { - extraCategories.push({ - title: 'Extension Rules', - collapsable: false, - children: uncategorizedExtensionRule.map(({ ruleId, name }) => [ - `/rules/${name}`, - ruleId - ]) - }) -} -if (deprecatedRules.length > 0) { - extraCategories.push({ - title: 'Deprecated', - collapsable: false, - children: deprecatedRules.map(({ ruleId, name }) => [ - `/rules/${name}`, - ruleId - ]) - }) -} - -module.exports = { - configureWebpack(_config, _isServer) { - return { - resolve: { - alias: { - module: require.resolve('./shim/module'), - eslint$: require.resolve('./shim/eslint'), - esquery: path.resolve( - __dirname, - '../../node_modules/esquery/dist/esquery.min.js' - ), - '@eslint/eslintrc/universal': path.resolve( - __dirname, - '../../node_modules/@eslint/eslintrc/dist/eslintrc-universal.cjs' - ) - } - } - } - }, - - base: '/', - title: 'eslint-plugin-vue', - description: 'Official ESLint plugin for Vue.js', - evergreen: true, - head: [['link', { rel: 'icon', href: '/favicon.png' }]], - - plugins: { - '@vuepress/pwa': { - serviceWorker: true, - updatePopup: true - } - }, - - themeConfig: { - repo: 'vuejs/eslint-plugin-vue', - docsRepo: 'vuejs/eslint-plugin-vue', - docsDir: 'docs', - docsBranch: 'master', - editLinks: true, - lastUpdated: true, - - nav: [ - { text: 'User Guide', link: '/user-guide/' }, - { text: 'Developer Guide', link: '/developer-guide/' }, - { text: 'Rules', link: '/rules/' }, - { - text: 'Demo', - link: 'https://ota-meshi.github.io/eslint-plugin-vue-demo/' - } - ], - - sidebar: { - '/rules/': [ - '/rules/', - - // Rules in each category. - ...categorizedRules, - - // Rules in no category. - ...extraCategories - ], - - '/': ['/', '/user-guide/', '/developer-guide/', '/rules/'] - }, - - algolia: { - appId: '2L4MGZSULB', - apiKey: 'fdf57932b27a6c230d01a890492ab76d', - indexName: 'eslint-plugin-vue' - } - } -} diff --git a/docs/.vuepress/enhanceApp.js b/docs/.vuepress/enhanceApp.js deleted file mode 100644 index dc7e30771..000000000 --- a/docs/.vuepress/enhanceApp.js +++ /dev/null @@ -1,28 +0,0 @@ -/* globals window */ -export default ( - // eslint-disable-next-line no-empty-pattern - { - // Vue, // the version of Vue being used in the VuePress app - // options, // the options for the root Vue instance - // router, // the router instance for the app - // siteData, // site metadata - } -) => { - if (typeof window !== 'undefined') { - if (typeof window.process === 'undefined') { - window.process = new Proxy( - { - env: {}, - cwd: () => undefined - }, - { - get(target, name) { - // For debug - // console.log(name) - return target[name] - } - } - ) - } - } -} diff --git a/docs/.vuepress/shim/eslint.js b/docs/.vuepress/shim/eslint.js deleted file mode 100644 index 08af6dfcd..000000000 --- a/docs/.vuepress/shim/eslint.js +++ /dev/null @@ -1,4 +0,0 @@ -const { Linter } = require('eslint/lib/linter') -module.exports = { - Linter -} diff --git a/docs/.vuepress/shim/module.js b/docs/.vuepress/shim/module.js deleted file mode 100644 index 66ab9785e..000000000 --- a/docs/.vuepress/shim/module.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - createRequire: () => () => null -} diff --git a/docs/.vuepress/styles/index.styl b/docs/.vuepress/styles/index.styl deleted file mode 100644 index 48680bbf3..000000000 --- a/docs/.vuepress/styles/index.styl +++ /dev/null @@ -1,20 +0,0 @@ -.theme-container.rule-details .theme-default-content > h1 { - font-size: 1.8rem; - - + blockquote { - margin-top: -15px; - padding: 0; - border: 0; - font-weight: 500; - font-size: 1.4rem; - color: currentColor; - - ::first-letter { - text-transform: uppercase; - } - - p { - line-height: 1.2; - } - } -} diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 96f92a921..000000000 --- a/docs/README.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -sidebarDepth: 0 ---- - -# Introduction - -Official ESLint plugin for Vue.js. - -This plugin allows us to check the ``, output: null, - errors: ['`slot-scope` are deprecated.'] + errors: [ + { + message: '`slot-scope` are deprecated.', + line: 4, + column: 21, + endLine: 4, + endColumn: 31 + } + ] } ] }) diff --git a/tests/lib/rules/no-deprecated-v-bind-sync.js b/tests/lib/rules/no-deprecated-v-bind-sync.js index 6f9d6860d..355d1a86c 100644 --- a/tests/lib/rules/no-deprecated-v-bind-sync.js +++ b/tests/lib/rules/no-deprecated-v-bind-sync.js @@ -4,20 +4,11 @@ */ 'use strict' -// ------------------------------------------------------------------------------ -// Requirements -// ------------------------------------------------------------------------------ - const rule = require('../../../lib/rules/no-deprecated-v-bind-sync') -const RuleTester = require('eslint').RuleTester - -// ------------------------------------------------------------------------------ -// Tests -// ------------------------------------------------------------------------------ +const RuleTester = require('../../eslint-compat').RuleTester const ruleTester = new RuleTester({ - parser: require.resolve('vue-eslint-parser'), - parserOptions: { ecmaVersion: 2015 } + languageOptions: { parser: require('vue-eslint-parser'), ecmaVersion: 2015 } }) ruleTester.run('no-deprecated-v-bind-sync', rule, { @@ -46,7 +37,14 @@ ruleTester.run('no-deprecated-v-bind-sync', rule, { code: "", output: "", errors: [ - "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead." + { + message: + "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead.", + line: 1, + column: 24, + endLine: 1, + endColumn: 45 + } ] }, { @@ -54,7 +52,14 @@ ruleTester.run('no-deprecated-v-bind-sync', rule, { code: "", output: "", errors: [ - "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead." + { + message: + "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead.", + line: 1, + column: 24, + endLine: 1, + endColumn: 39 + } ] }, { @@ -62,7 +67,14 @@ ruleTester.run('no-deprecated-v-bind-sync', rule, { code: "", output: "", errors: [ - "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead." + { + message: + "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead.", + line: 1, + column: 24, + endLine: 1, + endColumn: 54 + } ] }, { @@ -70,32 +82,59 @@ ruleTester.run('no-deprecated-v-bind-sync', rule, { code: "", output: "", errors: [ - "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead." + { + message: + "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead.", + line: 1, + column: 24, + endLine: 1, + endColumn: 48 + } ] }, { filename: 'test.vue', code: "", - output: "", + output: null, errors: [ - "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead." + { + message: + "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead.", + line: 1, + column: 24, + endLine: 1, + endColumn: 41 + } ] }, { filename: 'test.vue', code: '', - output: '', + output: null, errors: [ - "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead." + { + message: + "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead.", + line: 1, + column: 24, + endLine: 1, + endColumn: 47 + } ] }, { filename: 'test.vue', code: '', - output: - '', + output: null, errors: [ - "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead." + { + message: + "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead.", + line: 1, + column: 24, + endLine: 1, + endColumn: 56 + } ] }, { @@ -104,7 +143,14 @@ ruleTester.run('no-deprecated-v-bind-sync', rule, { output: '', errors: [ - "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead." + { + message: + "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead.", + line: 1, + column: 52, + endLine: 1, + endColumn: 69 + } ] }, { @@ -113,7 +159,14 @@ ruleTester.run('no-deprecated-v-bind-sync', rule, { output: '', errors: [ - "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead." + { + message: + "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead.", + line: 1, + column: 52, + endLine: 1, + endColumn: 70 + } ] }, { @@ -122,7 +175,14 @@ ruleTester.run('no-deprecated-v-bind-sync', rule, { output: '', errors: [ - "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead." + { + message: + "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead.", + line: 1, + column: 52, + endLine: 1, + endColumn: 74 + } ] }, { @@ -131,7 +191,14 @@ ruleTester.run('no-deprecated-v-bind-sync', rule, { output: '', errors: [ - "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead." + { + message: + "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead.", + line: 1, + column: 52, + endLine: 1, + endColumn: 75 + } ] }, { @@ -140,7 +207,14 @@ ruleTester.run('no-deprecated-v-bind-sync', rule, { output: '', errors: [ - "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead." + { + message: + "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead.", + line: 1, + column: 52, + endLine: 1, + endColumn: 82 + } ] }, { @@ -149,7 +223,14 @@ ruleTester.run('no-deprecated-v-bind-sync', rule, { output: '', errors: [ - "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead." + { + message: + "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead.", + line: 1, + column: 52, + endLine: 1, + endColumn: 80 + } ] }, { @@ -158,7 +239,14 @@ ruleTester.run('no-deprecated-v-bind-sync', rule, { output: '', errors: [ - "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead." + { + message: + "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead.", + line: 1, + column: 52, + endLine: 1, + endColumn: 77 + } ] }, { @@ -167,7 +255,14 @@ ruleTester.run('no-deprecated-v-bind-sync', rule, { output: '', errors: [ - "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead." + { + message: + "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead.", + line: 1, + column: 52, + endLine: 1, + endColumn: 72 + } ] }, { @@ -176,7 +271,14 @@ ruleTester.run('no-deprecated-v-bind-sync', rule, { output: '', errors: [ - "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead." + { + message: + "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead.", + line: 1, + column: 52, + endLine: 1, + endColumn: 89 + } ] }, { @@ -185,7 +287,14 @@ ruleTester.run('no-deprecated-v-bind-sync', rule, { output: '', errors: [ - "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead." + { + message: + "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead.", + line: 1, + column: 52, + endLine: 1, + endColumn: 77 + } ] }, { @@ -194,7 +303,14 @@ ruleTester.run('no-deprecated-v-bind-sync', rule, { output: '', errors: [ - "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead." + { + message: + "'.sync' modifier on 'v-bind' directive is deprecated. Use 'v-model:propName' instead.", + line: 1, + column: 52, + endLine: 1, + endColumn: 78 + } ] } ] diff --git a/tests/lib/rules/no-deprecated-v-is.js b/tests/lib/rules/no-deprecated-v-is.js index cdc47b9aa..3935c9b39 100644 --- a/tests/lib/rules/no-deprecated-v-is.js +++ b/tests/lib/rules/no-deprecated-v-is.js @@ -1,13 +1,10 @@ 'use strict' -const RuleTester = require('eslint').RuleTester +const RuleTester = require('../../eslint-compat').RuleTester const rule = require('../../../lib/rules/no-deprecated-v-is') const tester = new RuleTester({ - parser: require.resolve('vue-eslint-parser'), - parserOptions: { - ecmaVersion: 2015 - } + languageOptions: { parser: require('vue-eslint-parser'), ecmaVersion: 2015 } }) tester.run('no-deprecated-v-is', rule, { @@ -28,7 +25,10 @@ tester.run('no-deprecated-v-is', rule, { errors: [ { message: '`v-is` directive is deprecated.', - line: 3 + line: 3, + column: 14, + endLine: 3, + endColumn: 18 } ] } diff --git a/tests/lib/rules/no-deprecated-v-on-native-modifier.js b/tests/lib/rules/no-deprecated-v-on-native-modifier.js index d201cd478..b9863d9ed 100644 --- a/tests/lib/rules/no-deprecated-v-on-native-modifier.js +++ b/tests/lib/rules/no-deprecated-v-on-native-modifier.js @@ -4,20 +4,11 @@ */ 'use strict' -// ------------------------------------------------------------------------------ -// Requirements -// ------------------------------------------------------------------------------ - const rule = require('../../../lib/rules/no-deprecated-v-on-native-modifier') -const RuleTester = require('eslint').RuleTester - -// ------------------------------------------------------------------------------ -// Tests -// ------------------------------------------------------------------------------ +const RuleTester = require('../../eslint-compat').RuleTester const ruleTester = new RuleTester({ - parser: require.resolve('vue-eslint-parser'), - parserOptions: { ecmaVersion: 2015 } + languageOptions: { parser: require('vue-eslint-parser'), ecmaVersion: 2015 } }) ruleTester.run('no-deprecated-v-on-native-modifier', rule, { diff --git a/tests/lib/rules/no-deprecated-v-on-number-modifiers.js b/tests/lib/rules/no-deprecated-v-on-number-modifiers.js index dc7ae6500..f039d1162 100644 --- a/tests/lib/rules/no-deprecated-v-on-number-modifiers.js +++ b/tests/lib/rules/no-deprecated-v-on-number-modifiers.js @@ -4,20 +4,11 @@ */ 'use strict' -// ------------------------------------------------------------------------------ -// Requirements -// ------------------------------------------------------------------------------ - const rule = require('../../../lib/rules/no-deprecated-v-on-number-modifiers') -const RuleTester = require('eslint').RuleTester - -// ------------------------------------------------------------------------------ -// Tests -// ------------------------------------------------------------------------------ +const RuleTester = require('../../eslint-compat').RuleTester const ruleTester = new RuleTester({ - parser: require.resolve('vue-eslint-parser'), - parserOptions: { ecmaVersion: 2015 } + languageOptions: { parser: require('vue-eslint-parser'), ecmaVersion: 2015 } }) ruleTester.run('no-deprecated-v-on-number-modifiers', rule, { @@ -78,7 +69,14 @@ ruleTester.run('no-deprecated-v-on-number-modifiers', rule, { code: "", output: "", errors: [ - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead." + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 1, + column: 29, + endLine: 1, + endColumn: 31 + } ] }, { @@ -87,7 +85,14 @@ ruleTester.run('no-deprecated-v-on-number-modifiers', rule, { output: "", errors: [ - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead." + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 1, + column: 29, + endLine: 1, + endColumn: 31 + } ] }, { @@ -96,7 +101,14 @@ ruleTester.run('no-deprecated-v-on-number-modifiers', rule, { output: "", errors: [ - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead." + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 1, + column: 37, + endLine: 1, + endColumn: 39 + } ] }, { @@ -105,7 +117,14 @@ ruleTester.run('no-deprecated-v-on-number-modifiers', rule, { output: "", errors: [ - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead." + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 1, + column: 36, + endLine: 1, + endColumn: 38 + } ] }, { @@ -114,7 +133,14 @@ ruleTester.run('no-deprecated-v-on-number-modifiers', rule, { output: "", errors: [ - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead." + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 1, + column: 44, + endLine: 1, + endColumn: 46 + } ] }, { @@ -123,7 +149,14 @@ ruleTester.run('no-deprecated-v-on-number-modifiers', rule, { output: "", errors: [ - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead." + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 1, + column: 36, + endLine: 1, + endColumn: 38 + } ] }, { @@ -131,7 +164,14 @@ ruleTester.run('no-deprecated-v-on-number-modifiers', rule, { code: "", output: "", errors: [ - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead." + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 1, + column: 25, + endLine: 1, + endColumn: 27 + } ] }, { @@ -140,7 +180,14 @@ ruleTester.run('no-deprecated-v-on-number-modifiers', rule, { output: "", errors: [ - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead." + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 1, + column: 25, + endLine: 1, + endColumn: 27 + } ] }, { @@ -149,7 +196,14 @@ ruleTester.run('no-deprecated-v-on-number-modifiers', rule, { output: "", errors: [ - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead." + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 1, + column: 33, + endLine: 1, + endColumn: 35 + } ] }, { @@ -158,7 +212,14 @@ ruleTester.run('no-deprecated-v-on-number-modifiers', rule, { output: "", errors: [ - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead." + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 1, + column: 32, + endLine: 1, + endColumn: 34 + } ] }, { @@ -167,7 +228,14 @@ ruleTester.run('no-deprecated-v-on-number-modifiers', rule, { output: "", errors: [ - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead." + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 1, + column: 40, + endLine: 1, + endColumn: 42 + } ] }, { @@ -176,7 +244,14 @@ ruleTester.run('no-deprecated-v-on-number-modifiers', rule, { output: "", errors: [ - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead." + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 1, + column: 32, + endLine: 1, + endColumn: 34 + } ] }, { @@ -184,7 +259,14 @@ ruleTester.run('no-deprecated-v-on-number-modifiers', rule, { code: "", output: null, errors: [ - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead." + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 1, + column: 25, + endLine: 1, + endColumn: 27 + } ] }, { @@ -192,7 +274,14 @@ ruleTester.run('no-deprecated-v-on-number-modifiers', rule, { code: "", output: null, errors: [ - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead." + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 1, + column: 25, + endLine: 1, + endColumn: 27 + } ] }, { @@ -200,7 +289,14 @@ ruleTester.run('no-deprecated-v-on-number-modifiers', rule, { code: "", output: null, errors: [ - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead." + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 1, + column: 33, + endLine: 1, + endColumn: 35 + } ] }, { @@ -208,7 +304,14 @@ ruleTester.run('no-deprecated-v-on-number-modifiers', rule, { code: "", output: null, errors: [ - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead." + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 1, + column: 40, + endLine: 1, + endColumn: 42 + } ] }, { @@ -225,13 +328,62 @@ ruleTester.run('no-deprecated-v-on-number-modifiers', rule, { `, output: null, errors: [ - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead." + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 3, + column: 25, + endLine: 3, + endColumn: 27 + }, + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 4, + column: 25, + endLine: 4, + endColumn: 27 + }, + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 5, + column: 25, + endLine: 5, + endColumn: 27 + }, + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 6, + column: 25, + endLine: 6, + endColumn: 27 + }, + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 7, + column: 25, + endLine: 7, + endColumn: 27 + }, + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 8, + column: 25, + endLine: 8, + endColumn: 27 + }, + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 9, + column: 25, + endLine: 9, + endColumn: 28 + } ] }, { @@ -253,11 +405,46 @@ ruleTester.run('no-deprecated-v-on-number-modifiers', rule, { `, errors: [ - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", - "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead." + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 3, + column: 25, + endLine: 3, + endColumn: 27 + }, + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 4, + column: 25, + endLine: 4, + endColumn: 27 + }, + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 5, + column: 25, + endLine: 5, + endColumn: 27 + }, + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 6, + column: 25, + endLine: 6, + endColumn: 27 + }, + { + message: + "'KeyboardEvent.keyCode' modifier on 'v-on' directive is deprecated. Using 'KeyboardEvent.key' instead.", + line: 7, + column: 25, + endLine: 7, + endColumn: 27 + } ] } ] diff --git a/tests/lib/rules/no-deprecated-vue-config-keycodes.js b/tests/lib/rules/no-deprecated-vue-config-keycodes.js index dae0ec800..1a00c1c86 100644 --- a/tests/lib/rules/no-deprecated-vue-config-keycodes.js +++ b/tests/lib/rules/no-deprecated-vue-config-keycodes.js @@ -4,20 +4,11 @@ */ 'use strict' -// ------------------------------------------------------------------------------ -// Requirements -// ------------------------------------------------------------------------------ - const rule = require('../../../lib/rules/no-deprecated-vue-config-keycodes') -const RuleTester = require('eslint').RuleTester - -// ------------------------------------------------------------------------------ -// Tests -// ------------------------------------------------------------------------------ +const RuleTester = require('../../eslint-compat').RuleTester const ruleTester = new RuleTester({ - parser: require.resolve('vue-eslint-parser'), - parserOptions: { ecmaVersion: 2020 } + languageOptions: { parser: require('vue-eslint-parser'), ecmaVersion: 2020 } }) ruleTester.run('no-deprecated-vue-config-keycodes', rule, { @@ -55,12 +46,28 @@ ruleTester.run('no-deprecated-vue-config-keycodes', rule, { { filename: 'test.js', code: 'Vue?.config?.keyCodes', - errors: ['`Vue.config.keyCodes` are deprecated.'] + errors: [ + { + message: '`Vue.config.keyCodes` are deprecated.', + line: 1, + column: 1, + endLine: 1, + endColumn: 22 + } + ] }, { filename: 'test.js', code: '(Vue?.config)?.keyCodes', - errors: ['`Vue.config.keyCodes` are deprecated.'] + errors: [ + { + message: '`Vue.config.keyCodes` are deprecated.', + line: 1, + column: 1, + endLine: 1, + endColumn: 24 + } + ] } ] }) diff --git a/tests/lib/rules/no-dupe-keys.js b/tests/lib/rules/no-dupe-keys.js index 2abae46d0..794dbd2ec 100644 --- a/tests/lib/rules/no-dupe-keys.js +++ b/tests/lib/rules/no-dupe-keys.js @@ -4,19 +4,11 @@ */ 'use strict' -// ------------------------------------------------------------------------------ -// Requirements -// ------------------------------------------------------------------------------ - const rule = require('../../../lib/rules/no-dupe-keys') -const RuleTester = require('eslint').RuleTester - -// ------------------------------------------------------------------------------ -// Tests -// ------------------------------------------------------------------------------ +const RuleTester = require('../../eslint-compat').RuleTester const ruleTester = new RuleTester({ - parserOptions: { + languageOptions: { ecmaVersion: 2018, sourceType: 'module' } @@ -398,6 +390,127 @@ ruleTester.run('no-dupe-keys', rule, { }, } ` + }, + { + filename: 'test.vue', + code: ` + + `, + languageOptions: { parser: require('vue-eslint-parser') } + }, + { + filename: 'test.vue', + code: ` + + `, + languageOptions: { + parser: require('vue-eslint-parser'), + parserOptions: { parser: require.resolve('@typescript-eslint/parser') } + } + }, + { + filename: 'test.vue', + code: ` + + `, + languageOptions: { parser: require('vue-eslint-parser') } + }, + { + filename: 'test.vue', + code: ` + + `, + languageOptions: { parser: require('vue-eslint-parser') } + }, + { + filename: 'test.vue', + code: ` + + `, + languageOptions: { parser: require('vue-eslint-parser') } + }, + { + filename: 'test.vue', + code: ` + + `, + languageOptions: { parser: require('vue-eslint-parser') } + }, + { + filename: 'test.vue', + code: ` + + `, + languageOptions: { parser: require('vue-eslint-parser') } + }, + { + filename: 'test.vue', + code: ` + + `, + languageOptions: { parser: require('vue-eslint-parser') } + }, + { + filename: 'test.vue', + code: ` + + `, + languageOptions: { + parser: require('vue-eslint-parser'), + parserOptions: { parser: require.resolve('@typescript-eslint/parser') } + } + }, + { + filename: 'test.vue', + code: ` + + `, + languageOptions: { parser: require('vue-eslint-parser') } } ], @@ -431,20 +544,36 @@ ruleTester.run('no-dupe-keys', rule, { `, errors: [ { - message: "Duplicated key 'foo'.", - line: 5 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 5, + column: 13, + endLine: 5, + endColumn: 16 }, { - message: "Duplicated key 'foo'.", - line: 10 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 10, + column: 15, + endLine: 10, + endColumn: 18 }, { - message: "Duplicated key 'foo'.", - line: 14 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 14, + column: 13, + endLine: 14, + endColumn: 16 }, { - message: "Duplicated key 'foo'.", - line: 21 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 21, + column: 15, + endLine: 21, + endColumn: 18 } ] }, @@ -477,20 +606,36 @@ ruleTester.run('no-dupe-keys', rule, { `, errors: [ { - message: "Duplicated key 'foo'.", - line: 5 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 5, + column: 13, + endLine: 5, + endColumn: 16 }, { - message: "Duplicated key 'foo'.", - line: 10 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 10, + column: 15, + endLine: 10, + endColumn: 18 }, { - message: "Duplicated key 'foo'.", - line: 14 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 14, + column: 13, + endLine: 14, + endColumn: 16 }, { - message: "Duplicated key 'foo'.", - line: 21 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 21, + column: 15, + endLine: 21, + endColumn: 18 } ] }, @@ -514,16 +659,28 @@ ruleTester.run('no-dupe-keys', rule, { `, errors: [ { - message: "Duplicated key 'foo'.", - line: 5 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 5, + column: 13, + endLine: 5, + endColumn: 16 }, { - message: "Duplicated key 'foo'.", - line: 9 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 9, + column: 13, + endLine: 9, + endColumn: 16 }, { - message: "Duplicated key 'foo'.", - line: 12 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 12, + column: 13, + endLine: 12, + endColumn: 16 } ] }, @@ -558,20 +715,36 @@ ruleTester.run('no-dupe-keys', rule, { `, errors: [ { - message: "Duplicated key 'foo'.", - line: 7 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 7, + column: 13, + endLine: 7, + endColumn: 16 }, { - message: "Duplicated key 'foo'.", - line: 13 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 13, + column: 13, + endLine: 13, + endColumn: 16 }, { - message: "Duplicated key 'foo'.", - line: 16 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 16, + column: 13, + endLine: 16, + endColumn: 16 }, { - message: "Duplicated key 'foo'.", - line: 23 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 23, + column: 15, + endLine: 23, + endColumn: 18 } ] }, @@ -590,8 +763,12 @@ ruleTester.run('no-dupe-keys', rule, { options: [{ groups: ['foo'] }], errors: [ { - message: "Duplicated key 'bar'.", - line: 7 + message: + "Duplicate key 'bar'. May cause name collision in script or template tag.", + line: 7, + column: 13, + endLine: 7, + endColumn: 16 } ] }, @@ -615,8 +792,12 @@ ruleTester.run('no-dupe-keys', rule, { `, errors: [ { - message: "Duplicated key 'foo'.", - line: 12 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 12, + column: 15, + endLine: 12, + endColumn: 18 } ] }, @@ -638,8 +819,12 @@ ruleTester.run('no-dupe-keys', rule, { `, errors: [ { - message: "Duplicated key 'foo'.", - line: 10 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 10, + column: 15, + endLine: 10, + endColumn: 18 } ] }, @@ -659,8 +844,12 @@ ruleTester.run('no-dupe-keys', rule, { `, errors: [ { - message: "Duplicated key 'foo'.", - line: 9 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 9, + column: 13, + endLine: 9, + endColumn: 16 } ] }, @@ -680,8 +869,12 @@ ruleTester.run('no-dupe-keys', rule, { `, errors: [ { - message: "Duplicated key 'foo'.", - line: 9 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 9, + column: 13, + endLine: 9, + endColumn: 16 } ] }, @@ -701,8 +894,12 @@ ruleTester.run('no-dupe-keys', rule, { `, errors: [ { - message: "Duplicated key 'foo'.", - line: 9 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 9, + column: 13, + endLine: 9, + endColumn: 16 } ] }, @@ -722,8 +919,12 @@ ruleTester.run('no-dupe-keys', rule, { `, errors: [ { - message: "Duplicated key 'foo'.", - line: 9 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 9, + column: 13, + endLine: 9, + endColumn: 16 } ] }, @@ -742,8 +943,12 @@ ruleTester.run('no-dupe-keys', rule, { options: [{ groups: ['foo'] }], errors: [ { - message: "Duplicated key 'bar'.", - line: 7 + message: + "Duplicate key 'bar'. May cause name collision in script or template tag.", + line: 7, + column: 13, + endLine: 7, + endColumn: 16 } ] }, @@ -762,8 +967,12 @@ ruleTester.run('no-dupe-keys', rule, { options: [{ groups: ['foo'] }], errors: [ { - message: "Duplicated key 'bar'.", - line: 7 + message: + "Duplicate key 'bar'. May cause name collision in script or template tag.", + line: 7, + column: 13, + endLine: 7, + endColumn: 16 } ] }, @@ -786,8 +995,12 @@ ruleTester.run('no-dupe-keys', rule, { `, errors: [ { - message: "Duplicated key 'foo'.", - line: 6 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 6, + column: 17, + endLine: 6, + endColumn: 20 } ] }, @@ -806,8 +1019,12 @@ ruleTester.run('no-dupe-keys', rule, { `, errors: [ { - message: "Duplicated key 'foo'.", - line: 7 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 7, + column: 17, + endLine: 7, + endColumn: 20 } ] }, @@ -825,8 +1042,12 @@ ruleTester.run('no-dupe-keys', rule, { `, errors: [ { - message: "Duplicated key 'foo'.", - line: 6 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 6, + column: 17, + endLine: 6, + endColumn: 20 } ] }, @@ -845,8 +1066,12 @@ ruleTester.run('no-dupe-keys', rule, { `, errors: [ { - message: "Duplicated key 'foo'.", - line: 7 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 7, + column: 17, + endLine: 7, + endColumn: 20 } ] }, @@ -865,8 +1090,159 @@ ruleTester.run('no-dupe-keys', rule, { `, errors: [ { - message: "Duplicated key 'foo'.", - line: 7 + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 7, + column: 17, + endLine: 7, + endColumn: 20 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + languageOptions: { parser: require('vue-eslint-parser') }, + errors: [ + { + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 6, + column: 15, + endLine: 6, + endColumn: 22 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + languageOptions: { parser: require('vue-eslint-parser') }, + errors: [ + { + message: + "Duplicate key 'baz'. May cause name collision in script or template tag.", + line: 4, + column: 16, + endLine: 4, + endColumn: 19 + }, + { + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 12, + column: 9, + endLine: 14, + endColumn: 10 + }, + { + message: + "Duplicate key 'bar'. May cause name collision in script or template tag.", + line: 15, + column: 15, + endLine: 15, + endColumn: 32 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + languageOptions: { + parser: require('vue-eslint-parser'), + parserOptions: { parser: require.resolve('@typescript-eslint/parser') } + }, + errors: [ + { + message: + "Duplicate key 'foo'. May cause name collision in script or template tag.", + line: 8, + column: 13, + endLine: 8, + endColumn: 24 + }, + { + message: + "Duplicate key 'bar'. May cause name collision in script or template tag.", + line: 9, + column: 13, + endLine: 9, + endColumn: 24 + } + ] + }, + { + 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, + column: 13, + endLine: 5, + endColumn: 21 + } + ] + }, + { + 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, + column: 13, + endLine: 5, + endColumn: 24 } ] } diff --git a/tests/lib/rules/no-dupe-v-else-if.js b/tests/lib/rules/no-dupe-v-else-if.js index 214657a9c..0d65ddf31 100644 --- a/tests/lib/rules/no-dupe-v-else-if.js +++ b/tests/lib/rules/no-dupe-v-else-if.js @@ -4,12 +4,12 @@ */ 'use strict' -const RuleTester = require('eslint').RuleTester +const RuleTester = require('../../eslint-compat').RuleTester const rule = require('../../../lib/rules/no-dupe-v-else-if') const tester = new RuleTester({ - parser: require.resolve('vue-eslint-parser'), - parserOptions: { + languageOptions: { + parser: require('vue-eslint-parser'), ecmaVersion: 2019, sourceType: 'module' } @@ -165,7 +165,10 @@ tester.run('no-dupe-v-else-if', rule, { errors: [ { messageId: 'unexpected', - line: 4 + line: 4, + column: 25, + endLine: 4, + endColumn: 39 } ] }, @@ -182,7 +185,10 @@ tester.run('no-dupe-v-else-if', rule, { errors: [ { messageId: 'unexpected', - line: 6 + line: 6, + column: 25, + endLine: 6, + endColumn: 31 } ] }, @@ -200,7 +206,10 @@ tester.run('no-dupe-v-else-if', rule, { errors: [ { messageId: 'unexpected', - line: 6 + line: 6, + column: 25, + endLine: 6, + endColumn: 32 } ] }, @@ -215,7 +224,10 @@ tester.run('no-dupe-v-else-if', rule, { errors: [ { messageId: 'unexpected', - line: 4 + line: 4, + column: 25, + endLine: 4, + endColumn: 26 } ] }, @@ -231,7 +243,10 @@ tester.run('no-dupe-v-else-if', rule, { errors: [ { messageId: 'unexpected', - line: 5 + line: 5, + column: 25, + endLine: 5, + endColumn: 31 } ] }, @@ -246,7 +261,10 @@ tester.run('no-dupe-v-else-if', rule, { errors: [ { messageId: 'unexpected', - line: 4 + line: 4, + column: 25, + endLine: 4, + endColumn: 26 } ] }, @@ -261,7 +279,10 @@ tester.run('no-dupe-v-else-if', rule, { errors: [ { messageId: 'unexpected', - line: 4 + line: 4, + column: 25, + endLine: 4, + endColumn: 36 } ] }, @@ -276,7 +297,10 @@ tester.run('no-dupe-v-else-if', rule, { errors: [ { messageId: 'unexpected', - line: 4 + line: 4, + column: 25, + endLine: 4, + endColumn: 26 } ] }, @@ -292,7 +316,10 @@ tester.run('no-dupe-v-else-if', rule, { errors: [ { messageId: 'unexpected', - line: 5 + line: 5, + column: 31, + endLine: 5, + endColumn: 47 } ] }, @@ -332,8 +359,20 @@ tester.run('no-dupe-v-else-if', rule, { `, errors: [ - { messageId: 'unexpected', line: 4 }, - { messageId: 'unexpected', line: 5 } + { + messageId: 'unexpected', + line: 4, + column: 25, + endLine: 4, + endColumn: 36 + }, + { + messageId: 'unexpected', + line: 5, + column: 25, + endLine: 5, + endColumn: 36 + } ] }, { @@ -346,8 +385,20 @@ tester.run('no-dupe-v-else-if', rule, { `, errors: [ - { messageId: 'unexpected', line: 4 }, - { messageId: 'unexpected', line: 5 } + { + messageId: 'unexpected', + line: 4, + column: 25, + endLine: 4, + endColumn: 26 + }, + { + messageId: 'unexpected', + line: 5, + column: 25, + endLine: 5, + endColumn: 26 + } ] }, { @@ -359,263 +410,702 @@ tester.run('no-dupe-v-else-if', rule, {
`, - errors: [{ messageId: 'unexpected' }, { messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 4, + column: 26, + endLine: 4, + endColumn: 60 + }, + { + messageId: 'unexpected', + line: 5, + column: 26, + endLine: 5, + endColumn: 60 + } + ] }, // Referred to the ESLint core rule. { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 43, + endLine: 1, + endColumn: 44 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 64, + endLine: 1, + endColumn: 65 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 64, + endLine: 1, + endColumn: 65 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 85, + endLine: 1, + endColumn: 86 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 64, + endLine: 1, + endColumn: 65 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 85, + endLine: 1, + endColumn: 86 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 85, + endLine: 1, + endColumn: 86 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 106, + endLine: 1, + endColumn: 107 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }, { messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 43, + endLine: 1, + endColumn: 44 + }, + { + messageId: 'unexpected', + line: 1, + column: 64, + endLine: 1, + endColumn: 65 + } + ] }, { filename: 'test.vue', code: '', errors: [ - { messageId: 'unexpected' }, - { messageId: 'unexpected' }, - { messageId: 'unexpected' } + { + messageId: 'unexpected', + line: 1, + column: 64, + endLine: 1, + endColumn: 65 + }, + { + messageId: 'unexpected', + line: 1, + column: 85, + endLine: 1, + endColumn: 86 + }, + { + messageId: 'unexpected', + line: 1, + column: 106, + endLine: 1, + endColumn: 107 + } ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 63, + endLine: 1, + endColumn: 64 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 49, + endLine: 1, + endColumn: 56 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 47, + endLine: 1, + endColumn: 52 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 46, + endLine: 1, + endColumn: 50 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 48, + endLine: 1, + endColumn: 54 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 53, + endLine: 1, + endColumn: 64 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 46, + endLine: 1, + endColumn: 50 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 49, + endLine: 1, + endColumn: 54 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 49, + endLine: 1, + endColumn: 70 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 48, + endLine: 1, + endColumn: 49 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }, { messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 48, + endLine: 1, + endColumn: 49 + }, + { + messageId: 'unexpected', + line: 1, + column: 69, + endLine: 1, + endColumn: 70 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 48, + endLine: 1, + endColumn: 54 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 64, + endLine: 1, + endColumn: 70 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 74, + endLine: 1, + endColumn: 80 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 65, + endLine: 1, + endColumn: 81 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 43, + endLine: 1, + endColumn: 44 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 48, + endLine: 1, + endColumn: 59 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 48, + endLine: 1, + endColumn: 59 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 64, + endLine: 1, + endColumn: 75 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 70, + endLine: 1, + endColumn: 76 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 75, + endLine: 1, + endColumn: 91 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 53, + endLine: 1, + endColumn: 64 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 48, + endLine: 1, + endColumn: 49 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 65, + endLine: 1, + endColumn: 71 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 62, + endLine: 1, + endColumn: 80 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 58, + endLine: 1, + endColumn: 69 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 75, + endLine: 1, + endColumn: 91 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 62, + endLine: 1, + endColumn: 75 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 49, + endLine: 1, + endColumn: 55 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 90, + endLine: 1, + endColumn: 91 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 53, + endLine: 1, + endColumn: 78 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 55, + endLine: 1, + endColumn: 68 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 91, + endLine: 1, + endColumn: 97 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 70, + endLine: 1, + endColumn: 81 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 43, + endLine: 1, + endColumn: 49 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 48, + endLine: 1, + endColumn: 54 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 48, + endLine: 1, + endColumn: 49 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 43, + endLine: 1, + endColumn: 44 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 48, + endLine: 1, + endColumn: 49 + } + ] }, { filename: 'test.vue', code: '', - errors: [{ messageId: 'unexpected' }] + errors: [ + { + messageId: 'unexpected', + line: 1, + column: 48, + endLine: 1, + endColumn: 49 + } + ] } ] }) diff --git a/tests/lib/rules/no-duplicate-attr-inheritance.js b/tests/lib/rules/no-duplicate-attr-inheritance.js index 8c4917071..8a007b491 100644 --- a/tests/lib/rules/no-duplicate-attr-inheritance.js +++ b/tests/lib/rules/no-duplicate-attr-inheritance.js @@ -4,21 +4,13 @@ */ 'use strict' -// ------------------------------------------------------------------------------ -// Requirements -// ------------------------------------------------------------------------------ - const rule = require('../../../lib/rules/no-duplicate-attr-inheritance') -const RuleTester = require('eslint').RuleTester - -// ------------------------------------------------------------------------------ -// Tests -// ------------------------------------------------------------------------------ +const RuleTester = require('../../eslint-compat').RuleTester const ruleTester = new RuleTester({ - parser: require.resolve('vue-eslint-parser'), - parserOptions: { + languageOptions: { + parser: require('vue-eslint-parser'), ecmaVersion: 2018, sourceType: 'module' } @@ -51,6 +43,57 @@ ruleTester.run('no-duplicate-attr-inheritance', rule, { ` }, + // ignore multi root by default + { + filename: 'test.vue', + code: ` + + + ` + }, + { + filename: 'test.vue', + code: ` + + ` + }, + { + filename: 'test.vue', + code: ` + + ` + }, + { + filename: 'test.vue', + code: ` + + ` + }, + { + filename: 'test.vue', + code: ` + + `, + options: [{ checkMultiRootNodes: false }] + }, { filename: 'test.vue', code: ` @@ -87,6 +130,26 @@ ruleTester.run('no-duplicate-attr-inheritance', rule, { export default { } ` + }, + { + filename: 'test.vue', + code: ` + + + + ` + }, + { + filename: 'test.vue', + code: ` + + + ` } ], @@ -94,7 +157,15 @@ ruleTester.run('no-duplicate-attr-inheritance', rule, { { filename: 'test.vue', code: '', - errors: ['Set "inheritAttrs" to false.'] + errors: [ + { + message: 'Set "inheritAttrs" to false.', + line: 1, + column: 29, + endLine: 1, + endColumn: 35 + } + ] }, { filename: 'test.vue', @@ -106,7 +177,162 @@ ruleTester.run('no-duplicate-attr-inheritance', rule, { } `, - errors: ['Set "inheritAttrs" to false.'] + errors: [ + { + message: 'Set "inheritAttrs" to false.', + line: 2, + column: 37, + endLine: 2, + endColumn: 43 + } + ] + }, + { + filename: 'test.vue', + code: ` + + + + `, + errors: [ + { + message: 'Set "inheritAttrs" to false.', + line: 7, + column: 30, + endLine: 7, + endColumn: 36 + } + ] + }, + { + filename: 'test.vue', + code: ` + + + `, + errors: [ + { + message: 'Set "inheritAttrs" to false.', + line: 5, + column: 30, + endLine: 5, + endColumn: 36 + } + ] + }, + { + filename: 'test.vue', + code: ``, + options: [{ checkMultiRootNodes: true }], + errors: [ + { + message: 'Set "inheritAttrs" to false.', + line: 1, + column: 24, + endLine: 1, + endColumn: 30 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + options: [{ checkMultiRootNodes: true }], + errors: [ + { + message: 'Set "inheritAttrs" to false.', + line: 3, + column: 40, + endLine: 3, + endColumn: 46 + } + ] + }, + // condition group as a single root node + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + message: 'Set "inheritAttrs" to false.', + line: 3, + column: 40, + endLine: 3, + endColumn: 46 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + message: 'Set "inheritAttrs" to false.', + line: 3, + column: 40, + endLine: 3, + endColumn: 46 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + message: 'Set "inheritAttrs" to false.', + line: 3, + column: 40, + endLine: 3, + endColumn: 46 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + errors: [ + { + message: 'Set "inheritAttrs" to false.', + line: 3, + column: 40, + endLine: 3, + endColumn: 46 + } + ] } ] }) diff --git a/tests/lib/rules/no-duplicate-attributes.js b/tests/lib/rules/no-duplicate-attributes.js index baa79dc98..48dedf509 100644 --- a/tests/lib/rules/no-duplicate-attributes.js +++ b/tests/lib/rules/no-duplicate-attributes.js @@ -5,20 +5,11 @@ */ 'use strict' -// ------------------------------------------------------------------------------ -// Requirements -// ------------------------------------------------------------------------------ - -const RuleTester = require('eslint').RuleTester +const RuleTester = require('../../eslint-compat').RuleTester const rule = require('../../../lib/rules/no-duplicate-attributes') -// ------------------------------------------------------------------------------ -// Tests -// ------------------------------------------------------------------------------ - const tester = new RuleTester({ - parser: require.resolve('vue-eslint-parser'), - parserOptions: { ecmaVersion: 2015 } + languageOptions: { parser: require('vue-eslint-parser'), ecmaVersion: 2015 } }) tester.run('no-duplicate-attributes', rule, { @@ -71,36 +62,84 @@ tester.run('no-duplicate-attributes', rule, { { filename: 'test.vue', code: '', - errors: ["Duplicate attribute 'foo'."] + errors: [ + { + message: "Duplicate attribute 'foo'.", + line: 1, + column: 25, + endLine: 1, + endColumn: 35 + } + ] }, { filename: 'test.vue', code: '', - errors: ["Duplicate attribute 'foo'."] + errors: [ + { + message: "Duplicate attribute 'foo'.", + line: 1, + column: 25, + endLine: 1, + endColumn: 29 + } + ] }, { filename: 'test.vue', code: '', - errors: ["Duplicate attribute 'style'."], - options: [{ allowCoexistStyle: false }] + options: [{ allowCoexistStyle: false }], + errors: [ + { + message: "Duplicate attribute 'style'.", + line: 1, + column: 27, + endLine: 1, + endColumn: 33 + } + ] }, { filename: 'test.vue', code: '', - errors: ["Duplicate attribute 'class'."], - options: [{ allowCoexistClass: false }] + options: [{ allowCoexistClass: false }], + errors: [ + { + message: "Duplicate attribute 'class'.", + line: 1, + column: 27, + endLine: 1, + endColumn: 33 + } + ] }, { filename: 'test.vue', code: '', - errors: ["Duplicate attribute 'style'."], - options: [{ allowCoexistStyle: false }] + options: [{ allowCoexistStyle: false }], + errors: [ + { + message: "Duplicate attribute 'style'.", + line: 1, + column: 28, + endLine: 1, + endColumn: 33 + } + ] }, { filename: 'test.vue', code: '', - errors: ["Duplicate attribute 'class'."], - options: [{ allowCoexistClass: false }] + options: [{ allowCoexistClass: false }], + errors: [ + { + message: "Duplicate attribute 'class'.", + line: 1, + column: 28, + endLine: 1, + endColumn: 33 + } + ] } ] }) diff --git a/tests/lib/rules/no-empty-component-block.js b/tests/lib/rules/no-empty-component-block.js index 8ba6a2f2c..87ad2dd66 100644 --- a/tests/lib/rules/no-empty-component-block.js +++ b/tests/lib/rules/no-empty-component-block.js @@ -3,12 +3,11 @@ */ 'use strict' -const RuleTester = require('eslint').RuleTester +const RuleTester = require('../../eslint-compat').RuleTester const rule = require('../../../lib/rules/no-empty-component-block') const tester = new RuleTester({ - parser: require.resolve('vue-eslint-parser'), - parserOptions: { ecmaVersion: 2018 } + languageOptions: { parser: require('vue-eslint-parser'), ecmaVersion: 2018 } }) tester.run('no-empty-component-block', rule, { @@ -28,117 +27,310 @@ tester.run('no-empty-component-block', rule, { invalid: [ { code: ``, + output: '', errors: [ { - message: '`