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/.editorconfig b/.editorconfig new file mode 100644 index 000000000..4bd3bd8be --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.env-cmdrc b/.env-cmdrc new file mode 100644 index 000000000..59d3db357 --- /dev/null +++ b/.env-cmdrc @@ -0,0 +1,5 @@ +{ + "version": { + "IN_VERSION_SCRIPT": "true" + } +} diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 872909c93..000000000 --- a/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules -lib/recommended-rules.js diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 906fd952a..000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,23 +0,0 @@ -module.exports = { - root: true, - parserOptions: { - ecmaVersion: 6 - }, - env: { - node: true, - mocha: true - }, - extends: [ - 'plugin:eslint-plugin/recommended', - 'plugin:vue-libs/recommended' - ], - plugins: [ - 'eslint-plugin' - ], - rules: { - 'complexity': 'off', - 'eslint-plugin/report-message-format': ['error', '^[A-Z].*\\.$'], - 'eslint-plugin/prefer-placeholders': 'error', - 'eslint-plugin/consistent-output': 'error' - } -} 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 new file mode 100644 index 000000000..08d755127 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,60 @@ +--- +name: Bug report +about: Create a report to help us improve +--- + + + + + +**Checklist** + +- [ ] I have tried restarting my IDE and the issue persists. +- [ ] I have read the [FAQ](https://eslint.vuejs.org/user-guide/#faq) and my problem is not listed. + + +**Tell us about your environment** + +- **ESLint version:** +- **eslint-plugin-vue version:** +- **Vue version:** +- **Node version:** +- **Operating System:** + +**Please show your full configuration:** + +```json5 + +``` + +**What did you do?** + +```vue + +``` + +**What did you expect to happen?** + + +**What actually happened?** + + +**Repository to reproduce this issue** + + diff --git a/.github/ISSUE_TEMPLATE/change.md b/.github/ISSUE_TEMPLATE/change.md new file mode 100644 index 000000000..02397f6cd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/change.md @@ -0,0 +1,27 @@ +--- +name: "Non-rule change request" +about: Request a change that is not a bug fix, rule change, or new rule +--- + + + +**Tell us about your environment** + +- **ESLint version:** +- **eslint-plugin-vue version:** +- **Vue version:** +- **Node version:** + +**The problem you want to solve.** + + +**Your take on the correct solution to problem.** + + +**Additional context** + + diff --git a/.github/ISSUE_TEMPLATE/rule-change.md b/.github/ISSUE_TEMPLATE/rule-change.md new file mode 100644 index 000000000..78a3a2dd1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/rule-change.md @@ -0,0 +1,31 @@ +--- +name: "Rule change request" +about: Request a change to an existing rule +--- + + + +**What rule do you want to change?** + +**Does this change cause the rule to produce more or fewer warnings?** + +**How will the change be implemented? (New option, new default behavior, etc.)?** + +**Please provide some example code that this change will affect:** + + +```vue + +``` + +**What does the rule currently do for this code?** + +**What will the rule do after it's changed?** + +**Additional context** + + diff --git a/.github/ISSUE_TEMPLATE/rule-proposal.md b/.github/ISSUE_TEMPLATE/rule-proposal.md new file mode 100644 index 000000000..6c571721c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/rule-proposal.md @@ -0,0 +1,30 @@ +--- +name: Rule Proposal +about: Suggest an idea for a new rule +--- + + + +**Please describe what the rule should do:** + + +**What category should the rule belong to?** + +[ ] Enforces code style (layout) +[ ] Warns about a potential error (problem) +[ ] Suggests an alternate way of doing something (suggestion) +[ ] Other (please specify:) + +**Provide 2-3 code examples that this rule should warn about:** + +```vue + +``` + +**Additional context** + + diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml new file mode 100644 index 000000000..fede1a47a --- /dev/null +++ b/.github/workflows/CI.yml @@ -0,0 +1,110 @@ +name: CI +on: + push: + branches: + - 'master' + pull_request: + types: + - 'opened' + - 'synchronize' + - 'reopened' + +permissions: + contents: read + +jobs: + lint: + name: Lint + 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 --legacy-peer-deps + - name: Lint + run: npm run lint + + test: + name: Test + strategy: + matrix: + 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 + + 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@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 0f23426ce..d6fadf92c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,16 @@ +.idea +*.iml /.nyc_output /coverage +/tests/integrations/*/node_modules /node_modules /test.* +yarn.lock +yarn-error.log +/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 new file mode 100644 index 000000000..6591a3543 --- /dev/null +++ b/.markdownlint.yml @@ -0,0 +1,26 @@ +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: + style: fenced +code-fence-style: + style: backtick +emphasis-style: + style: underscore +heading-style: + style: atx +hr-style: + style: --- +strong-style: + style: asterisk +ul-style: + style: dash diff --git a/.markdownlintignore b/.markdownlintignore new file mode 100644 index 000000000..e7becf85b --- /dev/null +++ b/.markdownlintignore @@ -0,0 +1,2 @@ +node_modules +CHANGELOG.md diff --git a/.npmrc b/.npmrc new file mode 100644 index 000000000..43c97e719 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +package-lock=false 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/.prettierrc b/.prettierrc new file mode 100644 index 000000000..38d9aa9aa --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +semi: false +singleQuote: true +printWidth: 80 +trailingComma: none diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..171c80066 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,21 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Start testing", + "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 new file mode 100644 index 000000000..f80681b66 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,15 @@ +{ + "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 aa7a9bfee..bdeb5e167 100644 --- a/README.md +++ b/README.md @@ -2,128 +2,54 @@ [![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://circleci.com/gh/vuejs/eslint-plugin-vue.svg?style=svg)](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 -## :exclamation: Requirements +## :book: Documentation -- [ESLint](http://eslint.org/) `>=3.18.0`. -- Node.js `>=4.0.0` +Please refer to the [official website](https://eslint.vuejs.org). -## :cd: Installation +## :anchor: Versioning Policy -``` -npm install --save-dev eslint eslint-plugin-vue -``` +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. -## :rocket: Usage +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. -Create `.eslintrc.*` file to configure rules. See also: [http://eslint.org/docs/user-guide/configuring](http://eslint.org/docs/user-guide/configuring). +[Semantic Versioning]: https://semver.org/ +[ESLint's Semantic Versioning Policy]: https://github.com/eslint/eslint#semantic-versioning-policy -Example **.eslintrc.js**: +## :newspaper: Releases -```javascript -module.exports = { - extends: [ - 'eslint:recommended', - 'plugin:vue/recommended' // or 'plugin:vue/base' - ], - rules: { - // override/add rules' settings here - 'vue/no-invalid-v-if': 'error' - } -} -``` +This project uses [GitHub Releases](https://github.com/vuejs/eslint-plugin-vue/releases). -## ⚙ Configs +## :beers: Contribution Guide -This plugin provides two predefined configs: -- `plugin:vue/base` - contains necessary settings for this plugin to work properly -- `plugin:vue/recommended` - extends base config with recommended rules (the ones with check mark :white_check_mark: in the table below) +Contributing is welcome! See the [ESLint Vue Plugin Developer Guide](https://eslint.vuejs.org/developer-guide). -## :bulb: Rules +### Working With Rules -Rules are grouped by category to help you understand their purpose. +Be sure to read the [official ESLint guide](https://eslint.org/docs/developer-guide/working-with-rules) before you start writing a new rule. -No rules are enabled by `plugin:vue/base` config. The `plugin:vue/recommended` config enables rules that report common problems, which have a check mark :white_check_mark: below. +To see what an abstract syntax tree (AST) of your code looks like, you may use [AST Explorer](https://astexplorer.net). After opening [AST Explorer](https://astexplorer.net), select `Vue` as the syntax and `vue-eslint-parser` as the parser. -The `--fix` option on the command line automatically fixes problems reported by rules which have a wrench :wrench: below. +The default JavaScript parser must be replaced because [Vue.js single file components](https://vuejs.org/guide/scaling-up/sfc.html) are not plain JavaScript, but a custom file format. [`vue-eslint-parser`](https://github.com/vuejs/vue-eslint-parser) is a replacement parser that generates an enhanced AST with nodes that represent specific parts of the template syntax, as well as the contents of the ` + + + + 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/developer-guide/index.md b/docs/developer-guide/index.md new file mode 100644 index 000000000..9bfc68007 --- /dev/null +++ b/docs/developer-guide/index.md @@ -0,0 +1,69 @@ +# Developer Guide + +Contributing is welcome. + +## :bug: Bug reporting + +If you think you’ve found a bug in ESLint, please [create a new issue](https://github.com/vuejs/eslint-plugin-vue/issues/new?labels=&template=bug_report.md) or a pull request on GitHub. + +Please include as much detail as possible to help us properly address your issue. If we need to triage issues and constantly ask people for more detail, that’s time taken away from actually fixing issues. Help us be as efficient as possible by including a lot of detail in your issues. + +## :seedling: Project Setup + +To develop locally, fork the eslint-plugin-vue repository and clone it in your local machine. Use the [npm](https://www.npmjs.com/) package manager to install and link dependencies and the LTS version of [Node.js](https://nodejs.org/). + +To develop and test the `eslint-plugin-vue` package: + +1. Run `npm install` in the project's root folder. +2. Run `npm test` to make sure everything is set up correctly. + +## :sparkles: Proposing a new rule or a rule change + +In order to add a new rule or a rule change, you should: + +- Create issue on GitHub with description of proposed rule +- Generate a new rule using the `npm run new ` command +- Write test scenarios & implement logic +- Describe the rule in the generated `docs` file +- Make sure all tests are passing +- Run `npm run lint` and fix any errors +- Run `npm run update` in order to update readme and recommended configuration +- Create PR and link created issue in description + +We're more than happy to see potential contributions, so don't hesitate. If you have any suggestions, ideas or problems feel free to add new [issue](https://github.com/vuejs/eslint-plugin-vue/issues), but first please make sure your question does not repeat previous ones. + +## :fire: Working with rules + +Before you start writing new rule, please read the [official ESLint guide](https://eslint.org/docs/developer-guide/working-with-rules). + +Next, in order to get an idea how does the AST of the code that you want to check looks like, use the [astexplorer.net]. +The [astexplorer.net] is a great tool to inspect ASTs, also Vue templates are supported. + +After opening [astexplorer.net], select `Vue` as the syntax and `vue-eslint-parser` as the parser. + +[astexplorer.net]: https://astexplorer.net/ + +Since single file components in Vue are not plain JavaScript, we can't use the default parser, and we had to introduce additional one: `vue-eslint-parser`, that generates enhanced AST with nodes that represent specific parts of the template syntax, as well as what's inside the ` +``` + + + + + +```vue + + +``` + + + +Specify the block name for the key of the option object. +You can use the object as a value and use the following properties: + +- `lang` ... Specifies the available value for the `lang` attribute of the block. If multiple languages are available, specify them as an array. If you do not specify it, will disallow any language. +- `allowNoLang` ... If `true`, allows the `lang` attribute not to be specified (allows the use of the default language of block). + +::: warning Note +If the default language is specified for `lang` option of `