├── .editorconfig
├── .eslintrc.js
├── .github
└── workflows
│ └── ci.yaml
├── .gitignore
├── .husky
├── .gitignore
└── pre-commit
├── .yarn
└── releases
│ └── yarn-3.2.3.cjs
├── .yarnrc.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── docs
└── rules
│ ├── no-cjs-in-config.md
│ ├── no-env-in-context.md
│ ├── no-env-in-hooks.md
│ ├── no-globals-in-created.md
│ ├── no-this-in-fetch-data.md
│ ├── no-timing-in-fetch-data.md
│ └── require-func-head.md
├── lib
├── configs
│ ├── base.js
│ └── recommended.js
├── index.js
├── processors
│ ├── .gitkeep
│ └── index.js
├── rules
│ ├── .gitkeep
│ ├── __tests__
│ │ ├── no-cjs-in-config.test.js
│ │ ├── no-env-in-context.test.js
│ │ ├── no-env-in-hooks.test.js
│ │ ├── no-globals-in-created.test.js
│ │ ├── no-this-in-fetch-data.test.js
│ │ ├── no-timing-in-fetch-data.test.js
│ │ └── require-func-head.test.js
│ ├── no-cjs-in-config.js
│ ├── no-env-in-context.js
│ ├── no-env-in-hooks.js
│ ├── no-globals-in-created.js
│ ├── no-this-in-fetch-data.js
│ ├── no-timing-in-fetch-data.js
│ └── require-func-head.js
└── utils
│ ├── index.js
│ └── resolver.js
├── package.json
├── renovate.json
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 |
3 | root = true
4 |
5 | [*]
6 | charset = utf-8
7 | indent_style = space
8 | indent_size = 2
9 | end_of_line = lf
10 | insert_final_newline = true
11 | trim_trailing_whitespace = true
12 |
13 | [*.md]
14 | insert_final_newline = false
15 | trim_trailing_whitespace = false
16 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: 'standard',
3 | rules: {
4 | 'no-template-curly-in-string': 0
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yaml:
--------------------------------------------------------------------------------
1 | name: ci
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | branches:
9 | - master
10 |
11 | jobs:
12 | ci:
13 | runs-on: ${{ matrix.os }}
14 |
15 | strategy:
16 | matrix:
17 | os: [ubuntu-latest, macos-latest, windows-latest]
18 | node: [14, 16, 18]
19 |
20 | steps:
21 | - uses: actions/setup-node@v3
22 | with:
23 | node-version: ${{ matrix.node }}
24 |
25 | - name: checkout
26 | uses: actions/checkout@master
27 |
28 | - name: cache node_modules
29 | uses: actions/cache@v2
30 | with:
31 | path: node_modules
32 | key: ${{ matrix.os }}-node-v${{ matrix.node }}-deps-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }}
33 |
34 | - name: install
35 | run: yarn install
36 |
37 | - name: lint
38 | run: yarn lint
39 |
40 | - name: test
41 | run: yarn test
42 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # next.js build output
61 | .next
62 |
63 | # yarn
64 | .pnp.*
65 | .yarn/*
66 | !.yarn/patches
67 | !.yarn/plugins
68 | !.yarn/releases
69 | !.yarn/sdks
70 | !.yarn/versions
71 |
--------------------------------------------------------------------------------
/.husky/.gitignore:
--------------------------------------------------------------------------------
1 | _
2 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | yarn lint-staged
5 |
--------------------------------------------------------------------------------
/.yarnrc.yml:
--------------------------------------------------------------------------------
1 | nodeLinker: node-modules
2 |
3 | yarnPath: .yarn/releases/yarn-3.2.3.cjs
4 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4 |
5 | ## [4.0.0](https://github.com/nuxt/eslint-plugin-nuxt/compare/v3.2.0...v4.0.0) (2022-08-31)
6 |
7 | ## 3.2.0 (2022-03-13)
8 |
9 |
10 | ### Features
11 |
12 | * add base config ([fb94d7b](https://github.com/nuxt/eslint-plugin-nuxt/commit/fb94d7b20b6eded652b911cd82626c798192ea9e))
13 | * add no-env-in-context ([42ada82](https://github.com/nuxt/eslint-plugin-nuxt/commit/42ada82b306c3c259388392da565bd5fef260c76))
14 | * add no-env-in-hooks ([016f609](https://github.com/nuxt/eslint-plugin-nuxt/commit/016f6096cef49f5956d37c024faa64b7ac5ac96d))
15 | * add no-env-in-mounted ([4b32052](https://github.com/nuxt/eslint-plugin-nuxt/commit/4b3205269be683d258a45f06f9cddb3a4126f4ad))
16 | * add no-this-in-fetch ([94552c7](https://github.com/nuxt/eslint-plugin-nuxt/commit/94552c73299f2b60d58e895c1ab89917e2fca099))
17 | * add no-timing-in-fetch-data ([1436642](https://github.com/nuxt/eslint-plugin-nuxt/commit/1436642cdd6bf41f95f53c17020be80b25fed296))
18 | * add rule no-this-in-async-data ([96ce607](https://github.com/nuxt/eslint-plugin-nuxt/commit/96ce6077102c51bbabc51e606c0659c8b7ea1543))
19 | * init no-this-in-async-data ([cb03b4d](https://github.com/nuxt/eslint-plugin-nuxt/commit/cb03b4d9e05d10d4646b584a26ee227a7db2c72e))
20 | * init no-this-in-fetch ([581005a](https://github.com/nuxt/eslint-plugin-nuxt/commit/581005a1753e3394e021ee423d215e540f61c54c))
21 | * move ssr to base ([1da2f0c](https://github.com/nuxt/eslint-plugin-nuxt/commit/1da2f0cb61f4a2edce473784934eb5e93d66f70d))
22 | * **rule:** add no-globals-in-created ([09eaa50](https://github.com/nuxt/eslint-plugin-nuxt/commit/09eaa505a2a4691b94f7e1ae7e7ce2e19d5042c3))
23 | * **rule:** add require-func-head in recommended ([#62](https://github.com/nuxt/eslint-plugin-nuxt/issues/62)) ([f7e7b87](https://github.com/nuxt/eslint-plugin-nuxt/commit/f7e7b87670c510358811b4bc2847c176c77f6f03))
24 | * **rule:** no commonjs api in nuxt config ([eb02e0e](https://github.com/nuxt/eslint-plugin-nuxt/commit/eb02e0ebdb32608b67ad4de497313d5e10055b38))
25 | * upgrade eslint to v7 ([3e46242](https://github.com/nuxt/eslint-plugin-nuxt/commit/3e4624268fd2678539c34e0119554a8fadc81484))
26 | * upgrade eslint-plugin-vue to v6 ([b5b1bf4](https://github.com/nuxt/eslint-plugin-nuxt/commit/b5b1bf4c8abf5f2df66232130e83ef5412bce5a7))
27 |
28 |
29 | ### Bug Fixes
30 |
31 | * correct category for no-timing-in-fetch-data ([ae6b499](https://github.com/nuxt/eslint-plugin-nuxt/commit/ae6b499653252e126b9d524dbe9a700d8e48cd5b))
32 | * disallow `process.browser` in `no-env-in-hooks` ([#127](https://github.com/nuxt/eslint-plugin-nuxt/issues/127)) ([e421323](https://github.com/nuxt/eslint-plugin-nuxt/commit/e421323256ced99f8210105e3f2d215d7d4078a6))
33 | * enable no-this-in-fetch only for nuxt < 2.12 ([a0e3f73](https://github.com/nuxt/eslint-plugin-nuxt/commit/a0e3f736c94d3504cad7b09a718d86df8b54f0e4))
34 | * incompatible version of vue-eslint-parser ([a0e355f](https://github.com/nuxt/eslint-plugin-nuxt/commit/a0e355fb19613746810c4fa84b314a3724a78451))
35 | * not-null check for hooks ([ee73e8b](https://github.com/nuxt/eslint-plugin-nuxt/commit/ee73e8b68d541580a7017dbe8ed5c8e51bb257c7))
36 | * nuxt/require-func-head doesnt work with factories ([11492e2](https://github.com/nuxt/eslint-plugin-nuxt/commit/11492e20fb0a6ceaf9b7d379dada7e6b48da63ed)), closes [#94](https://github.com/nuxt/eslint-plugin-nuxt/issues/94)
37 | * remove require-func-head from recommend ([25d108c](https://github.com/nuxt/eslint-plugin-nuxt/commit/25d108cbb30005048d1972d285e70e8e67ceefe5)), closes [#93](https://github.com/nuxt/eslint-plugin-nuxt/issues/93)
38 | * rule not found ([976f28d](https://github.com/nuxt/eslint-plugin-nuxt/commit/976f28d5a3f6e7f75c082f4c941e2c36b86331b1))
39 | * undefined value in nuxt/no-env-in-context ([b9fed00](https://github.com/nuxt/eslint-plugin-nuxt/commit/b9fed007783217495c2c324f0d74576d3fb665a6))
40 | * use filename instead of full path ([d22e011](https://github.com/nuxt/eslint-plugin-nuxt/commit/d22e011c90700cc51279345740b2e6648c442c59))
41 | * wrong index file ([f95cf1d](https://github.com/nuxt/eslint-plugin-nuxt/commit/f95cf1d923ebb4a2fb7c0e8675c7ec54fb828671))
42 |
43 | ## [3.1.0](https://github.com/nuxt/eslint-plugin-nuxt/compare/v3.0.0...v3.1.0) (2021-11-28)
44 |
45 | ## [3.0.0](https://github.com/nuxt/eslint-plugin-nuxt/compare/v2.0.2...v3.0.0) (2021-10-24)
46 |
47 | ### [2.0.2](https://github.com/nuxt/eslint-plugin-nuxt/compare/v2.0.0...v2.0.2) (2021-10-24)
48 |
49 |
50 | ### Bug Fixes
51 |
52 | * disallow `process.browser` in `no-env-in-hooks` ([#127](https://github.com/nuxt/eslint-plugin-nuxt/issues/127)) ([07299c0](https://github.com/nuxt/eslint-plugin-nuxt/commit/07299c0ef16dc8efeef19bb2a29df9381aa99e77))
53 |
54 | ### [2.0.1](https://github.com/nuxt/eslint-plugin-nuxt/compare/v2.0.0...v2.0.1) (2021-10-24)
55 |
56 |
57 | ### Bug Fixes
58 |
59 | * disallow `process.browser` in `no-env-in-hooks` ([#127](https://github.com/nuxt/eslint-plugin-nuxt/issues/127)) ([07299c0](https://github.com/nuxt/eslint-plugin-nuxt/commit/07299c0ef16dc8efeef19bb2a29df9381aa99e77))
60 |
61 | ## [2.0.0](https://github.com/nuxt/eslint-plugin-nuxt/compare/v1.0.0...v2.0.0) (2020-11-14)
62 |
63 | ## [1.0.0](https://github.com/nuxt/eslint-plugin-nuxt/compare/v0.5.2...v1.0.0) (2020-05-12)
64 |
65 |
66 | ### Features
67 |
68 | * upgrade eslint to v7 ([c57a3de](https://github.com/nuxt/eslint-plugin-nuxt/commit/c57a3de0aaa71d33b09a1710d6b5c7ce478f71e3))
69 |
70 |
71 | ### Bug Fixes
72 |
73 | * nuxt/require-func-head doesnt work with factories ([5480fd0](https://github.com/nuxt/eslint-plugin-nuxt/commit/5480fd0d8eda0d6a5794548d60d3d84db8cbf86e)), closes [#94](https://github.com/nuxt/eslint-plugin-nuxt/issues/94)
74 | * remove require-func-head from recommend ([580ffa2](https://github.com/nuxt/eslint-plugin-nuxt/commit/580ffa26fa533c6e2cef2330965609ca879b118d)), closes [#93](https://github.com/nuxt/eslint-plugin-nuxt/issues/93)
75 |
76 | ### [0.5.2](https://github.com/nuxt/eslint-plugin-nuxt/compare/v0.5.1...v0.5.2) (2020-03-20)
77 |
78 |
79 | ### Bug Fixes
80 |
81 | * enable no-this-in-fetch only for nuxt < 2.12 ([66fc2e0](https://github.com/nuxt/eslint-plugin-nuxt/commit/66fc2e0f517865b3bf160eb096a5c81f788b33af))
82 |
83 | ### [0.5.1](https://github.com/nuxt/eslint-plugin-nuxt/compare/v0.5.0...v0.5.1) (2020-02-09)
84 |
85 |
86 | ### Features
87 |
88 | * **rule:** add require-func-head in recommended ([#62](https://github.com/nuxt/eslint-plugin-nuxt/issues/62)) ([7d0926f](https://github.com/nuxt/eslint-plugin-nuxt/commit/7d0926f4a73bbd3c91496f7ab8e0fc232f38d423))
89 |
90 |
91 | ### Bug Fixes
92 |
93 | * correct category for no-timing-in-fetch-data ([bbf6ce9](https://github.com/nuxt/eslint-plugin-nuxt/commit/bbf6ce985b0e40c1c9450fd3b3a7188d3a7a214a))
94 |
95 | ## [0.5.0](https://github.com/nuxt/eslint-plugin-nuxt/compare/v0.4.3...v0.5.0) (2019-11-09)
96 |
97 |
98 | ### Features
99 |
100 | * upgrade eslint-plugin-vue to v6 ([ecf42f2](https://github.com/nuxt/eslint-plugin-nuxt/commit/ecf42f2))
101 |
102 | ## [0.4.3](https://github.com/nuxt/eslint-plugin-nuxt/compare/v0.4.0...v0.4.3) (2019-03-12)
103 |
104 |
105 | ### Bug Fixes
106 |
107 | * incompatible version of vue-eslint-parser ([9bb12ae](https://github.com/nuxt/eslint-plugin-nuxt/commit/9bb12ae))
108 |
109 |
110 |
111 | ## [0.4.2](https://github.com/nuxt/eslint-plugin-nuxt/compare/v0.4.0...v0.4.2) (2019-02-21)
112 |
113 |
114 | ### Bug Fixes
115 |
116 | * use filename instead of full path ([4c62a37](https://github.com/nuxt/eslint-plugin-nuxt/commit/4c62a37))
117 |
118 |
119 |
120 |
121 | # [0.3.0](https://github.com/nuxt/eslint-plugin-nuxt/compare/v0.2.0...v0.3.0) (2018-12-19)
122 |
123 |
124 | ### Bug Fixes
125 |
126 | * not-null check for hooks ([daa93f3](https://github.com/nuxt/eslint-plugin-nuxt/commit/daa93f3))
127 |
128 |
129 | ### Features
130 |
131 | * add no-env-in-hooks ([bdcc9ec](https://github.com/nuxt/eslint-plugin-nuxt/commit/bdcc9ec))
132 |
133 |
134 |
135 |
136 | # [0.2.0](https://github.com/nuxt/eslint-plugin-nuxt/compare/v0.1.3...v0.2.0) (2018-12-10)
137 |
138 |
139 | ### Features
140 |
141 | * add no-env-in-mounted ([0037b34](https://github.com/nuxt/eslint-plugin-nuxt/commit/0037b34))
142 | * move ssr to base ([8f408dd](https://github.com/nuxt/eslint-plugin-nuxt/commit/8f408dd))
143 |
144 |
145 |
146 |
147 | ## [0.1.3](https://github.com/nuxt/eslint-plugin-nuxt/compare/v0.1.2...v0.1.3) (2018-12-10)
148 |
149 |
150 |
151 |
152 | ## [0.1.2](https://github.com/nuxt/eslint-plugin-nuxt/compare/v0.1.1...v0.1.2) (2018-12-10)
153 |
154 |
155 | ### Bug Fixes
156 |
157 | * rule not found ([c63f657](https://github.com/nuxt/eslint-plugin-nuxt/commit/c63f657))
158 | * undefined value in nuxt/no-env-in-context ([17cb2d9](https://github.com/nuxt/eslint-plugin-nuxt/commit/17cb2d9))
159 |
160 |
161 |
162 |
163 | ## [0.1.1](https://github.com/nuxt/eslint-plugin-nuxt/compare/v0.1.0...v0.1.1) (2018-12-10)
164 |
165 |
166 | ### Bug Fixes
167 |
168 | * wrong index file ([c50e96f](https://github.com/nuxt/eslint-plugin-nuxt/commit/c50e96f))
169 |
170 |
171 |
172 |
173 | # 0.1.0 (2018-12-10)
174 |
175 |
176 | ### Features
177 |
178 | * add base config ([bf0759a](https://github.com/nuxt/eslint-plugin-nuxt/commit/bf0759a))
179 | * **rule:** add no-globals-in-created ([d8736e9](https://github.com/nuxt/eslint-plugin-nuxt/commit/d8736e9))
180 | * add no-env-in-context ([71b09e9](https://github.com/nuxt/eslint-plugin-nuxt/commit/71b09e9))
181 | * add no-this-in-fetch ([fe4d381](https://github.com/nuxt/eslint-plugin-nuxt/commit/fe4d381))
182 | * add no-timing-in-fetch-data ([2945b70](https://github.com/nuxt/eslint-plugin-nuxt/commit/2945b70))
183 | * add rule no-this-in-async-data ([9a56aae](https://github.com/nuxt/eslint-plugin-nuxt/commit/9a56aae))
184 | * init no-this-in-async-data ([e23f4ed](https://github.com/nuxt/eslint-plugin-nuxt/commit/e23f4ed))
185 | * init no-this-in-fetch ([4bf0385](https://github.com/nuxt/eslint-plugin-nuxt/commit/4bf0385))
186 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Xin (Clark) Du
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | > [!NOTE]
2 | > `eslint-plugin-nuxt` was designed for Nuxt 2 and will not receive active development. Since many rules are no longer relevant in Nuxt 3, we created a new nuxt plugin [`@nuxt/eslint-plugin`](https://eslint.nuxt.com/packages/plugin) for Nuxt 3 under the [nuxt/eslint](https://github.com/nuxt/eslint) repository.
3 |
4 | ----
5 |
6 |
7 | # eslint-plugin-nuxt
8 |
9 | [![Standard JS][standard-js-src]][standard-js-href]
10 | [![Circle CI][circle-ci-src]][circle-ci-href]
11 | [![npm version][npm-version-src]][npm-version-href]
12 | [![npm downloads][npm-downloads-src]][npm-downloads-href]
13 |
14 | [standard-js-src]: https://flat.badgen.net/badge/code%20style/standard/green
15 | [standard-js-href]: https://standardjs.com
16 | [circle-ci-src]: https://flat.badgen.net/circleci/github/nuxt/eslint-plugin-nuxt
17 | [circle-ci-href]: https://circleci.com/gh/nuxt/eslint-plugin-nuxt
18 | [codecov-src]: https://flat.badgen.net/codecov/c/github/nuxt/eslint-plugin-nuxt
19 | [codecov-href]: https://codecov.io/gh/nuxt/eslint-plugin-nuxt
20 | [npm-version-src]: https://flat.badgen.net/npm/v/eslint-plugin-nuxt/latest
21 | [npm-version-href]: https://npmjs.com/package/eslint-plugin-nuxt
22 | [npm-downloads-src]: https://flat.badgen.net/npm/dt/eslint-plugin-nuxt
23 | [npm-downloads-href]: https://npmjs.com/package/eslint-plugin-nuxt
24 |
25 | :sparkles: ESLint plugin for Nuxt.js
26 |
27 | ## :cd: Installation
28 |
29 | You'll first need to install [ESLint](http://eslint.org):
30 |
31 | ```sh
32 | $ npm i eslint --save-dev
33 | success Saved 1 new dependencies
34 | ```
35 |
36 | Next, install `eslint-plugin-nuxt`:
37 |
38 | ```sh
39 | $ npm install eslint-plugin-nuxt --save-dev
40 | success Saved 1 new dependencies
41 | ```
42 |
43 | **Note:** If you installed ESLint globally (using the `-g` flag) then you must also install `eslint-plugin-nuxt` globally.
44 |
45 | ## :rocket: Usage
46 |
47 | Add `nuxt` to the plugins section of your `.eslintrc` configuration file. You can omit the `eslint-plugin-` prefix:
48 |
49 | 1. Use our preset to extend recommended defaults:
50 |
51 | ```json
52 | {
53 | "extends": [
54 | "plugin:nuxt/recommended"
55 | ]
56 | }
57 | ```
58 |
59 | 2. Or specify individual rules manually:
60 |
61 | ```json
62 | {
63 | "plugins": [
64 | "nuxt"
65 | ],
66 | "rules": {
67 | "nuxt/rule-name": 2
68 | }
69 | }
70 | ```
71 |
72 | ## :gear: Configs
73 |
74 | This plugin provides four predefined configs:
75 |
76 | - `plugin:nuxt/base` - Settings and rules to enable correct ESLint parsing
77 | - `plugin:nuxt/recommended` - Above, plus rules to enforce subjective community defaults to ensure consistency
78 |
79 | ## :bulb: Rules
80 |
81 |
82 |
83 | ### Base Rules
84 |
85 | ```json
86 | {
87 | "extends": "plugin:nuxt/base"
88 | }
89 | ```
90 |
91 | | | Rule ID | Description |
92 | |:---|:--------|:------------|
93 | | | [nuxt/no-env-in-context](./docs/rules/no-env-in-context.md) | Disallow `context.isServer/context.isClient` in `asyncData/fetch/nuxtServerInit` |
94 | | | [nuxt/no-env-in-hooks](./docs/rules/no-env-in-hooks.md) | Disallow `process.server/process.client` in client only Vue lifecycle hooks like: `mounted, beforeMount, updated...` |
95 | | | [nuxt/no-globals-in-created](./docs/rules/no-globals-in-created.md) | Disallow `window/document` in `created/beforeCreate` |
96 | | | [nuxt/no-this-in-fetch-data](./docs/rules/no-this-in-fetch-data.md) | Disallow `this` in `asyncData/fetch` |
97 | | | [nuxt/no-cjs-in-config](./docs/rules/no-cjs-in-config.md) | Disallow `require/modules.exports/exports` in `nuxt.config.js` |
98 |
99 | ### Recommended Rules
100 |
101 | Include all the below rules, as well as all priority rules in above categories, with:
102 |
103 | ```json
104 | {
105 | "extends": "plugin:nuxt/recommended"
106 | }
107 | ```
108 |
109 | | | Rule ID | Description |
110 | |:---|:--------|:------------|
111 | | | [nuxt/no-timing-in-fetch-data](./docs/rules/no-timing-in-fetch-data.md) | Disallow `setTimeout/setInterval` in `asyncData/fetch` |
112 |
113 | ### Other Rules
114 |
115 | | | Rule ID | Description |
116 | |:---|:--------|:------------|
117 | | | [nuxt/require-func-head](./docs/rules/require-func-head.md) | Enforce `head` property in component to be a function. |
118 |
--------------------------------------------------------------------------------
/docs/rules/no-cjs-in-config.md:
--------------------------------------------------------------------------------
1 | # nuxt/no-cjs-in-config
2 |
3 | > Disallow commonjs module api `require/modules.exports/exports` in `nuxt.config.js`
4 |
5 | - :gear: This rule is included in `"plugin:nuxt/base"`.
6 |
7 | ## Rule Details
8 |
9 | This rule is for preventing using `require/modules.exports/exports` in `nuxt.config.js`
10 |
11 | Examples of **incorrect** code for this rule:
12 |
13 | ```js
14 |
15 | const { name } = require('./package.json')
16 |
17 | module.exports = {
18 | mode: 'universal',
19 | name
20 | }
21 |
22 | ```
23 |
24 | Examples of **correct** code for this rule:
25 |
26 | ```js
27 |
28 | import { name } from './package.json'
29 |
30 | export default {
31 | mode: 'universal',
32 | name
33 | }
34 |
35 | ```
36 |
37 | ## :mag: Implementation
38 |
39 | - [Rule source](../../lib/rules/no-cjs-in-config.js)
40 | - [Test source](../../lib/rules/__tests__/no-cjs-in-config.test.js)
41 |
--------------------------------------------------------------------------------
/docs/rules/no-env-in-context.md:
--------------------------------------------------------------------------------
1 | # nuxt/no-env-in-context
2 |
3 | > disallow `context.isServer/context.isClient` in `asyncData/fetch/nuxtServerInit`
4 |
5 | - :gear: This rule is included in `"plugin:nuxt/base"`.
6 |
7 | ## Rule Details
8 |
9 | This rule is for preventing using `context.isServer/context.isClient` in `asyncData/fetch/nuxtServerInit`
10 |
11 | Examples of **incorrect** code for this rule:
12 |
13 | ```js
14 |
15 | export default {
16 | asyncData(context) {
17 | if (context.isServer) {
18 | const foo = 'bar'
19 | }
20 | },
21 | fetch({ isClient }) {
22 | if (isClient) {
23 | const foo = 'bar'
24 | }
25 | }
26 | }
27 |
28 | ```
29 |
30 | Examples of **correct** code for this rule:
31 |
32 | ```js
33 |
34 | export default {
35 | async asyncData() {
36 | if (process.server) {
37 | const foo = 'bar'
38 | }
39 | },
40 | fetch() {
41 | if (process.client) {
42 | const foo = 'bar'
43 | }
44 | }
45 | }
46 |
47 | ```
48 |
49 | ## :mag: Implementation
50 |
51 | - [Rule source](../../lib/rules/no-env-in-context.js)
52 | - [Test source](../../lib/rules/__tests__/no-env-in-context.test.js)
53 |
--------------------------------------------------------------------------------
/docs/rules/no-env-in-hooks.md:
--------------------------------------------------------------------------------
1 | # nuxt/no-env-in-hooks
2 |
3 | > Disallow `process.server`, `process.client` and `process.browser` in the following lifecycle hooks: `beforeMount`, `mounted`, `beforeUpdate`, `updated`, `activated`, `deactivated`, `beforeDestroy` and `destroyed`.
4 |
5 | - :gear: This rule is included in `"plugin:nuxt/base"`.
6 |
7 | ## Rule Details
8 |
9 | This rule is for preventing using `process.server`/`process.client`/`process.browser` in client only Vue lifecycle hooks since they're only executed in client side.
10 |
11 | Examples of **incorrect** code for this rule:
12 |
13 | ```js
14 |
15 | export default {
16 | mounted() {
17 | if (process.server) {
18 | const foo = 'bar'
19 | }
20 | },
21 | beforeMount() {
22 | if (process.client) {
23 | const foo = 'bar'
24 | }
25 | },
26 | beforeDestroy() {
27 | if (process.browser) {
28 | const foo = 'bar'
29 | }
30 | }
31 | }
32 |
33 | ```
34 |
35 | Examples of **correct** code for this rule:
36 |
37 |
38 | ```js
39 |
40 | export default {
41 | mounted() {
42 | const foo = 'bar'
43 | },
44 | beforeMount() {
45 | const foo = 'bar'
46 | },
47 | beforeDestroy() {
48 | const foo = 'bar'
49 | }
50 | }
51 |
52 | ```
53 |
54 | ## :mag: Implementation
55 |
56 | - [Rule source](../../lib/rules/no-env-in-hooks.js)
57 | - [Test source](../../lib/rules/__tests__/no-env-in-hooks.test.js)
58 |
--------------------------------------------------------------------------------
/docs/rules/no-globals-in-created.md:
--------------------------------------------------------------------------------
1 | # nuxt/no-globals-in-created
2 |
3 | > disallow `window/document` in `created/beforeCreate`
4 |
5 | - :gear: This rule is included in `"plugin:nuxt/base"`.
6 |
7 | ## Rule Details
8 |
9 | This rule is for preventing using `window/document` in `created/beforeCreate`, since `created/beforeCreate` may be executed in server side in SSR.
10 |
11 | Examples of **incorrect** code for this rule:
12 |
13 | ```js
14 |
15 | export default {
16 | created() {
17 | window.foo = 'bar'
18 | }
19 | }
20 |
21 | ```
22 |
23 | Examples of **correct** code for this rule:
24 |
25 | ```js
26 |
27 | export default {
28 | created() {
29 | const foo = 'bar'
30 | }
31 | }
32 |
33 | ```
34 |
35 | ## :mag: Implementation
36 |
37 | - [Rule source](../../lib/rules/no-globals-in-created.js)
38 | - [Test source](../../lib/rules/__tests__/no-globals-in-created.test.js)
39 |
--------------------------------------------------------------------------------
/docs/rules/no-this-in-fetch-data.md:
--------------------------------------------------------------------------------
1 | # nuxt/no-this-in-fetch-data
2 |
3 | > disallow `this` in `asyncData/fetch`
4 |
5 | - :gear: This rule is included in `"plugin:nuxt/base"`.
6 |
7 | ## Rule Details
8 |
9 | This rule is for preventing using `this` in `asyncData/fetch`
10 |
11 | > **NOTE**: `No this in fetch` is only for Nuxt.js < 2.12.0, Nuxt.js v2.12 has introduced new `fetch` API which supports `this`.
12 |
13 | Examples of **incorrect** code for this rule:
14 |
15 | ```js
16 |
17 | export default {
18 | ...foo,
19 | async asyncData() {
20 | if (this.$route.path === 'foo') {
21 |
22 | }
23 | }
24 | }
25 |
26 | ```
27 |
28 | Examples of **correct** code for this rule:
29 |
30 | ```js
31 |
32 | export default {
33 | ...foo,
34 | async asyncData() {
35 | // no this
36 | }
37 | }
38 |
39 | ```
40 |
41 | ## :mag: Implementation
42 |
43 | - [Rule source](../../lib/rules/no-this-in-fetch-data.js)
44 | - [Test source](../../lib/rules/__tests__/no-this-in-fetch-data.test.js)
45 |
--------------------------------------------------------------------------------
/docs/rules/no-timing-in-fetch-data.md:
--------------------------------------------------------------------------------
1 | # nuxt/no-timing-in-fetch-data
2 |
3 | > disallow `setTimeout/setInterval` in `asyncData/fetch`
4 |
5 | - :gear: This rule is included in `"plugin:nuxt/recommended"`.
6 |
7 | ## Rule Details
8 |
9 | This rule is for preventing using `setTimeout/setInterval` in `asyncData/fetch` since it may lead to memory leak
10 |
11 | Examples of **incorrect** code for this rule:
12 |
13 | ```js
14 |
15 | export default {
16 | asyncData() {
17 | let foo = 'bar'
18 | setTimeout(() => {
19 | foo = 'baz'
20 | }, 0)
21 | },
22 | fetch() {
23 | let foo = 'bar'
24 | setInterval(() => {
25 | foo = 'baz'
26 | }, 0)
27 | }
28 | }
29 |
30 | ```
31 |
32 | Examples of **correct** code for this rule:
33 |
34 |
35 | ```js
36 |
37 | export default {
38 | async asyncData() {
39 | let foo = 'baz'
40 | },
41 | fetch() {
42 | let foo = 'baz'
43 | }
44 | }
45 |
46 | ```
47 |
48 | ## :mag: Implementation
49 |
50 | - [Rule source](../../lib/rules/no-timing-in-fetch-data.js)
51 | - [Test source](../../lib/rules/__tests__/no-timing-in-fetch-data.test.js)
52 |
--------------------------------------------------------------------------------
/docs/rules/require-func-head.md:
--------------------------------------------------------------------------------
1 | # nuxt/require-func-head
2 |
3 | > enforce `head` property in component to be a function.
4 |
5 | ## Rule Details
6 |
7 | This rule is enforcing `head` property in component to be a function.
8 |
9 | Examples of **incorrect** code for this rule:
10 |
11 | ```js
12 |
13 | export default {
14 | head: {
15 | title: "My page"
16 | }
17 | }
18 |
19 | ```
20 |
21 | Examples of **correct** code for this rule:
22 |
23 | ```js
24 |
25 | export default {
26 | head() {
27 | return {
28 | title: "My page"
29 | }
30 | }
31 | }
32 |
33 | ```
34 |
35 | ## :mag: Implementation
36 |
37 | - [Rule source](../../lib/rules/require-func-head.js)
38 | - [Test source](../../lib/rules/__tests__/require-func-head.test.js)
39 |
--------------------------------------------------------------------------------
/lib/configs/base.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: require.resolve('vue-eslint-parser'),
3 | parserOptions: {
4 | ecmaVersion: 2018,
5 | sourceType: 'module',
6 | ecmaFeatures: {
7 | jsx: true
8 | }
9 | },
10 | env: {
11 | browser: true,
12 | es6: true
13 | },
14 | plugins: [
15 | 'nuxt'
16 | ],
17 | rules: {
18 | 'nuxt/no-env-in-context': 'error',
19 | 'nuxt/no-env-in-hooks': 'error',
20 | 'nuxt/no-globals-in-created': 'error',
21 | 'nuxt/no-this-in-fetch-data': 'error',
22 | 'nuxt/no-cjs-in-config': 'error'
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/lib/configs/recommended.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: require.resolve('./base.js'),
3 | rules: {
4 | 'nuxt/no-timing-in-fetch-data': 'error'
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | rules: {
3 | 'no-env-in-context': require('./rules/no-env-in-context'),
4 | 'no-env-in-hooks': require('./rules/no-env-in-hooks'),
5 | 'no-globals-in-created': require('./rules/no-globals-in-created'),
6 | 'no-this-in-fetch-data': require('./rules/no-this-in-fetch-data'),
7 | 'no-timing-in-fetch-data': require('./rules/no-timing-in-fetch-data'),
8 | 'no-cjs-in-config': require('./rules/no-cjs-in-config'),
9 | 'require-func-head': require('./rules/require-func-head')
10 | },
11 | configs: {
12 | base: require('./configs/base'),
13 | recommended: require('./configs/recommended')
14 | },
15 | processors: {
16 | '.vue': require('./processors')
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/lib/processors/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nuxt/eslint-plugin-nuxt/e9e88eba7d35d3fdccc0c04b5630fb4cf3a05113/lib/processors/.gitkeep
--------------------------------------------------------------------------------
/lib/processors/index.js:
--------------------------------------------------------------------------------
1 | module.exports = require('eslint-plugin-vue/lib/processor')
2 |
--------------------------------------------------------------------------------
/lib/rules/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nuxt/eslint-plugin-nuxt/e9e88eba7d35d3fdccc0c04b5630fb4cf3a05113/lib/rules/.gitkeep
--------------------------------------------------------------------------------
/lib/rules/__tests__/no-cjs-in-config.test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview Disallow `require/modules.exports/exports` in `nuxt.config.js`
3 | * @author Xin Du
4 | */
5 | 'use strict'
6 |
7 | // ------------------------------------------------------------------------------
8 | // Requirements
9 | // ------------------------------------------------------------------------------
10 |
11 | const rule = require('../no-cjs-in-config')
12 |
13 | const RuleTester = require('eslint').RuleTester
14 |
15 | const parserOptions = {
16 | ecmaVersion: 2018,
17 | sourceType: 'module'
18 | }
19 |
20 | // ------------------------------------------------------------------------------
21 | // Tests
22 | // ------------------------------------------------------------------------------
23 |
24 | const ruleTester = new RuleTester()
25 | ruleTester.run('no-cjs-in-config', rule, {
26 |
27 | valid: [
28 | {
29 | filename: 'nuxt.config.js',
30 | code: `
31 | import { name } from './package.json'
32 |
33 | export default {
34 | mode: 'universal',
35 | name
36 | }
37 | `,
38 | parserOptions
39 | }
40 | ],
41 |
42 | invalid: [
43 | {
44 | filename: 'nuxt.config.js',
45 | code: `
46 | const { name } = require('./package.json')
47 | `,
48 | errors: [{
49 | message: 'Unexpected require, please use import instead.',
50 | type: 'Identifier'
51 | }],
52 | parserOptions
53 | },
54 | {
55 | filename: 'nuxt.config.js',
56 | code: `
57 | module.exports = {
58 | mode: 'universal',
59 | name
60 | }
61 | `,
62 | errors: [{
63 | message: 'Unexpected module.exports, please use export default instead.',
64 | type: 'MemberExpression'
65 | }],
66 | parserOptions
67 | },
68 | {
69 | filename: 'nuxt.config.js',
70 | code: `
71 | exports.test = {
72 | mode: 'universal',
73 | name
74 | }
75 | `,
76 | errors: [{
77 | message: 'Unexpected exports, please use export default instead.',
78 | type: 'MemberExpression'
79 | }],
80 | parserOptions
81 | }
82 | ]
83 | })
84 |
--------------------------------------------------------------------------------
/lib/rules/__tests__/no-env-in-context.test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview disallow `context.isServer/context.isClient` in `asyncData/fetch/nuxtServerInit`
3 | * @author Xin Du
4 | */
5 | 'use strict'
6 |
7 | // ------------------------------------------------------------------------------
8 | // Requirements
9 | // ------------------------------------------------------------------------------
10 |
11 | const rule = require('../no-env-in-context')
12 |
13 | const RuleTester = require('eslint').RuleTester
14 |
15 | const parserOptions = {
16 | ecmaVersion: 2018,
17 | sourceType: 'module'
18 | }
19 |
20 | // ------------------------------------------------------------------------------
21 | // Tests
22 | // ------------------------------------------------------------------------------
23 |
24 | const ruleTester = new RuleTester()
25 | ruleTester.run('no-env-in-context', rule, {
26 |
27 | valid: [
28 | {
29 | filename: 'test.vue',
30 | code: `
31 | export default {
32 | async asyncData() {
33 | if(process.server) {
34 | const foo = 'bar'
35 | }
36 | },
37 | fetch() {
38 | if(process.client) {
39 | const foo = 'bar'
40 | }
41 | }
42 | }
43 | `,
44 | parserOptions
45 | }
46 | ],
47 |
48 | invalid: [
49 | {
50 | filename: 'test.vue',
51 | code: `
52 | export default {
53 | asyncData(context) {
54 | if(context.isServer) {
55 | const foo = 'bar'
56 | }
57 | },
58 | fetch(context) {
59 | if(context.isClient) {
60 | const foo = 'bar'
61 | }
62 | }
63 | }
64 | `,
65 | errors: [{
66 | message: 'Unexpected isServer in asyncData.',
67 | type: 'MemberExpression'
68 | }, {
69 | message: 'Unexpected isClient in fetch.',
70 | type: 'MemberExpression'
71 | }],
72 | parserOptions
73 | },
74 | {
75 | filename: 'test.vue',
76 | code: `
77 | export default {
78 | asyncData(context) {
79 | if(context['isClient']) {
80 | const foo = 'bar'
81 | }
82 | },
83 | fetch(context) {
84 | if(context['isServer']) {
85 | const foo = 'bar'
86 | }
87 | }
88 | }
89 | `,
90 | errors: [{
91 | message: 'Unexpected isClient in asyncData.',
92 | type: 'MemberExpression'
93 | }, {
94 | message: 'Unexpected isServer in fetch.',
95 | type: 'MemberExpression'
96 | }],
97 | parserOptions
98 | },
99 | {
100 | filename: 'test.vue',
101 | code: `
102 | export default {
103 | asyncData({ isClient }) {
104 | if(isClient) {
105 | const foo = 'bar'
106 | }
107 | },
108 | fetch({ isServer }) {
109 | if(isServer) {
110 | const foo = 'bar'
111 | }
112 | }
113 | }
114 | `,
115 | errors: [{
116 | message: 'Unexpected isClient in asyncData.',
117 | type: 'Property'
118 | }, {
119 | message: 'Unexpected isServer in fetch.',
120 | type: 'Property'
121 | }],
122 | parserOptions
123 | }
124 | ]
125 | })
126 |
--------------------------------------------------------------------------------
/lib/rules/__tests__/no-env-in-hooks.test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview disallow `process.server`/`process.client`/`process.browser` in `Vue Lifecycle Hooks`
3 | * @author Xin Du
4 | */
5 | 'use strict'
6 |
7 | // ------------------------------------------------------------------------------
8 | // Requirements
9 | // ------------------------------------------------------------------------------
10 |
11 | const rule = require('../no-env-in-hooks')
12 |
13 | const RuleTester = require('eslint').RuleTester
14 |
15 | const parserOptions = {
16 | ecmaVersion: 2018,
17 | sourceType: 'module'
18 | }
19 |
20 | // ------------------------------------------------------------------------------
21 | // Tests
22 | // ------------------------------------------------------------------------------
23 |
24 | const ruleTester = new RuleTester()
25 | ruleTester.run('no-env-in-hooks', rule, {
26 |
27 | valid: [
28 | {
29 | filename: 'test.vue',
30 | code: `
31 | export default {
32 | mounted() {
33 | const foo = 'bar'
34 | },
35 | beforeMount() {
36 | const foo = 'bar'
37 | },
38 | beforeDestroy() {
39 | const foo = 'bar'
40 | }
41 | }
42 | `,
43 | parserOptions
44 | }
45 | ],
46 |
47 | invalid: [
48 | {
49 | filename: 'test.vue',
50 | code: `
51 | export default {
52 | mounted() {
53 | if(process.server) {
54 | const foo = 'bar'
55 | }
56 | },
57 | beforeMount() {
58 | if(process.client) {
59 | const foo = 'bar'
60 | }
61 | },
62 | beforeDestroy() {
63 | if(process.browser) {
64 | const foo = 'bar'
65 | }
66 | }
67 | }
68 | `,
69 | errors: [{
70 | message: 'Unexpected process.server in mounted.',
71 | type: 'MemberExpression'
72 | }, {
73 | message: 'Unexpected process.client in beforeMount.',
74 | type: 'MemberExpression'
75 | }, {
76 | message: 'Unexpected process.browser in beforeDestroy.',
77 | type: 'MemberExpression'
78 | }],
79 | parserOptions
80 | },
81 | {
82 | filename: 'test.vue',
83 | code: `
84 | export default {
85 | mounted() {
86 | if(process['client']) {
87 | const foo = 'bar'
88 | }
89 | },
90 | beforeMount() {
91 | if(process['server']) {
92 | const foo = 'bar'
93 | }
94 | },
95 | beforeDestroy() {
96 | if(process['browser']) {
97 | const foo = 'bar'
98 | }
99 | }
100 | }
101 | `,
102 | errors: [{
103 | message: 'Unexpected process.client in mounted.',
104 | type: 'MemberExpression'
105 | }, {
106 | message: 'Unexpected process.server in beforeMount.',
107 | type: 'MemberExpression'
108 | }, {
109 | message: 'Unexpected process.browser in beforeDestroy.',
110 | type: 'MemberExpression'
111 | }],
112 | parserOptions
113 | }
114 | ]
115 | })
116 |
--------------------------------------------------------------------------------
/lib/rules/__tests__/no-globals-in-created.test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview disallow `window/document` in `created/beforeCreate`
3 | * @author Xin Du
4 | */
5 | 'use strict'
6 |
7 | // ------------------------------------------------------------------------------
8 | // Requirements
9 | // ------------------------------------------------------------------------------
10 |
11 | const rule = require('../no-globals-in-created')
12 |
13 | const RuleTester = require('eslint').RuleTester
14 |
15 | const parserOptions = {
16 | ecmaVersion: 2018,
17 | sourceType: 'module'
18 | }
19 |
20 | // ------------------------------------------------------------------------------
21 | // Tests
22 | // ------------------------------------------------------------------------------
23 |
24 | const ruleTester = new RuleTester()
25 | ruleTester.run('no-globals-in-created', rule, {
26 |
27 | valid: [
28 | {
29 | filename: 'test.vue',
30 | code: `
31 | export default {
32 | created() {
33 | const path = this.$route.path
34 | },
35 | beforeCreate() {
36 | const path = this.$route.params.foo
37 | }
38 | }
39 | `,
40 | parserOptions
41 | }
42 | ],
43 |
44 | invalid: [
45 | {
46 | filename: 'test.vue',
47 | code: `
48 | export default {
49 | created() {
50 | const path = window.location.pathname
51 | },
52 | beforeCreate() {
53 | const foo = document.foo
54 | }
55 | }
56 | `,
57 | errors: [{
58 | message: 'Unexpected window in created.',
59 | type: 'MemberExpression'
60 | }, {
61 | message: 'Unexpected document in beforeCreate.',
62 | type: 'MemberExpression'
63 | }],
64 | parserOptions
65 | },
66 | {
67 | filename: 'test.vue',
68 | code: `
69 | export default {
70 | created() {
71 | document.foo = 'bar'
72 | },
73 | beforeCreate() {
74 | window.foo = 'bar'
75 | }
76 | }
77 | `,
78 | errors: [{
79 | message: 'Unexpected document in created.',
80 | type: 'MemberExpression'
81 | }, {
82 | message: 'Unexpected window in beforeCreate.',
83 | type: 'MemberExpression'
84 | }],
85 | parserOptions
86 | },
87 | {
88 | filename: 'test.vue',
89 | code: `
90 | export default {
91 | created() {
92 | return window.foo
93 | },
94 | beforeCreate() {
95 | return document.foo
96 | }
97 | }
98 | `,
99 | errors: [{
100 | message: 'Unexpected window in created.',
101 | type: 'MemberExpression'
102 | }, {
103 | message: 'Unexpected document in beforeCreate.',
104 | type: 'MemberExpression'
105 | }],
106 | parserOptions
107 | }
108 | ]
109 | })
110 |
--------------------------------------------------------------------------------
/lib/rules/__tests__/no-this-in-fetch-data.test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview disallow `this` in `asyncData/fetch`
3 | * @author Xin Du
4 | */
5 | 'use strict'
6 |
7 | // ------------------------------------------------------------------------------
8 | // Requirements
9 | // ------------------------------------------------------------------------------
10 |
11 | const rule = require('../no-this-in-fetch-data')
12 |
13 | const RuleTester = require('eslint').RuleTester
14 |
15 | const parserOptions = {
16 | ecmaVersion: 2018,
17 | sourceType: 'module'
18 | }
19 |
20 | // ------------------------------------------------------------------------------
21 | // Tests
22 | // ------------------------------------------------------------------------------
23 |
24 | const ruleTester = new RuleTester()
25 | ruleTester.run('no-this-in-fetch-data', rule, {
26 |
27 | valid: [
28 | {
29 | filename: 'test.vue',
30 | code: `
31 | export default {
32 | ...foo,
33 | asyncData() {
34 | },
35 | fetch() {
36 | }
37 | }
38 | `,
39 | parserOptions
40 | }
41 | ],
42 |
43 | invalid: [
44 | {
45 | filename: 'test.vue',
46 | code: `
47 | export default {
48 | ...foo,
49 | asyncData() {
50 | if(this.$route.path === 'foo') {}
51 | }
52 | }
53 | `,
54 | errors: [{
55 | message: 'Unexpected this in asyncData.',
56 | type: 'ThisExpression'
57 | }],
58 | parserOptions
59 | },
60 | {
61 | filename: 'test.vue',
62 | code: `
63 | export default {
64 | ...foo,
65 | async asyncData() {
66 | if(this.$route.path === 'foo') {}
67 | }
68 | }
69 | `,
70 | errors: [{
71 | message: 'Unexpected this in asyncData.',
72 | type: 'ThisExpression'
73 | }],
74 | parserOptions
75 | },
76 | {
77 | filename: 'test.vue',
78 | code: `
79 | export default {
80 | ...foo,
81 | asyncData: () => {
82 | if(this.$route.path === 'foo') {}
83 | }
84 | }
85 | `,
86 | errors: [{
87 | message: 'Unexpected this in asyncData.',
88 | type: 'ThisExpression'
89 | }],
90 | parserOptions
91 | },
92 | {
93 | filename: 'test.vue',
94 | code: `
95 | export default {
96 | ...foo,
97 | asyncData: function test() {
98 | if(this.$route.path === 'foo') {}
99 | }
100 | }
101 | `,
102 | errors: [{
103 | message: 'Unexpected this in asyncData.',
104 | type: 'ThisExpression'
105 | }],
106 | parserOptions
107 | },
108 | {
109 | filename: 'test.vue',
110 | code: `
111 | export default {
112 | ...foo,
113 | fetch() {
114 | if(this.$route.path === 'foo') {}
115 | }
116 | }
117 | `,
118 | errors: [{
119 | message: 'Unexpected this in fetch.',
120 | type: 'ThisExpression'
121 | }],
122 | options: [{ methods: ['fetch'] }],
123 | parserOptions
124 | },
125 | {
126 | filename: 'test.vue',
127 | code: `
128 | export default {
129 | ...foo,
130 | async fetch() {
131 | if(this.$route.path === 'foo') {}
132 | }
133 | }
134 | `,
135 | errors: [{
136 | message: 'Unexpected this in fetch.',
137 | type: 'ThisExpression'
138 | }],
139 | options: [{ methods: ['fetch'] }],
140 | parserOptions
141 | },
142 | {
143 | filename: 'test.vue',
144 | code: `
145 | export default {
146 | ...foo,
147 | fetch: () => {
148 | if(this.$route.path === 'foo') {}
149 | }
150 | }
151 | `,
152 | errors: [{
153 | message: 'Unexpected this in fetch.',
154 | type: 'ThisExpression'
155 | }],
156 | options: [{ methods: ['fetch'] }],
157 | parserOptions
158 | },
159 | {
160 | filename: 'test.vue',
161 | code: `
162 | export default {
163 | ...foo,
164 | fetch: function test() {
165 | if(this.$route.path === 'foo') {}
166 | }
167 | }
168 | `,
169 | errors: [{
170 | message: 'Unexpected this in fetch.',
171 | type: 'ThisExpression'
172 | }],
173 | options: [{ methods: ['fetch'] }],
174 | parserOptions
175 | }
176 | ]
177 | })
178 |
--------------------------------------------------------------------------------
/lib/rules/__tests__/no-timing-in-fetch-data.test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview disallow `setTimeout/setInterval` in `asyncData/fetch`
3 | * @author Xin Du
4 | */
5 | 'use strict'
6 |
7 | // ------------------------------------------------------------------------------
8 | // Requirements
9 | // ------------------------------------------------------------------------------
10 |
11 | const rule = require('../no-timing-in-fetch-data')
12 |
13 | const RuleTester = require('eslint').RuleTester
14 |
15 | const parserOptions = {
16 | ecmaVersion: 2018,
17 | sourceType: 'module'
18 | }
19 |
20 | // ------------------------------------------------------------------------------
21 | // Tests
22 | // ------------------------------------------------------------------------------
23 |
24 | const ruleTester = new RuleTester()
25 | ruleTester.run('no-timing-in-fetch-data', rule, {
26 |
27 | valid: [
28 | {
29 | filename: 'test.vue',
30 | code: `
31 | export default {
32 | async asyncData() {
33 | let foo = 'baz'
34 | },
35 | fetch() {
36 | let foo = 'baz'
37 | }
38 | }
39 | `,
40 | parserOptions
41 | }
42 | ],
43 |
44 | invalid: [
45 | {
46 | filename: 'test.vue',
47 | code: `
48 | export default {
49 | asyncData() {
50 | let foo = 'bar'
51 | setTimeout(() => {
52 | foo = 'baz'
53 | }, 0)
54 | },
55 | fetch() {
56 | let foo = 'bar'
57 | setInterval(() => {
58 | foo = 'baz'
59 | }, 0)
60 | }
61 | }
62 | `,
63 | errors: [{
64 | message: 'Unexpected setTimeout in asyncData.',
65 | type: 'CallExpression'
66 | }, {
67 | message: 'Unexpected setInterval in fetch.',
68 | type: 'CallExpression'
69 | }],
70 | parserOptions
71 | },
72 | {
73 | filename: 'test.vue',
74 | code: `
75 | export default {
76 | asyncData() {
77 | let timer = setInterval
78 | },
79 | fetch() {
80 | let timer = setTimeout
81 | }
82 | }
83 | `,
84 | errors: [{
85 | message: 'Unexpected setInterval in asyncData.',
86 | type: 'VariableDeclarator'
87 | }, {
88 | message: 'Unexpected setTimeout in fetch.',
89 | type: 'VariableDeclarator'
90 | }],
91 | parserOptions
92 | }
93 | ]
94 | })
95 |
--------------------------------------------------------------------------------
/lib/rules/__tests__/require-func-head.test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview disallow `setTimeout/setInterval` in `asyncData/fetch`
3 | * @author Xin Du
4 | */
5 | 'use strict'
6 |
7 | // ------------------------------------------------------------------------------
8 | // Requirements
9 | // ------------------------------------------------------------------------------
10 |
11 | const rule = require('../require-func-head')
12 |
13 | const RuleTester = require('eslint').RuleTester
14 |
15 | const parserOptions = {
16 | ecmaVersion: 2018,
17 | sourceType: 'module'
18 | }
19 |
20 | // ------------------------------------------------------------------------------
21 | // Tests
22 | // ------------------------------------------------------------------------------
23 |
24 | const ruleTester = new RuleTester()
25 | ruleTester.run('require-func-head', rule, {
26 |
27 | valid: [
28 | {
29 | filename: 'test.vue',
30 | code: `
31 | export default {
32 | head() {
33 | return {
34 | title: "My page"
35 | }
36 | }
37 | }
38 | `,
39 | parserOptions
40 | }
41 | ],
42 |
43 | invalid: [
44 | {
45 | filename: 'test.vue',
46 | code: `
47 | export default {
48 | head: {
49 | title: "My page"
50 | }
51 | }
52 | `,
53 | errors: [{
54 | message: '`head` property in component must be a function.',
55 | type: 'Property'
56 | }],
57 | output: `
58 | export default {
59 | head: function() {
60 | return {
61 | title: "My page"
62 | };
63 | }
64 | }
65 | `,
66 | parserOptions
67 | }
68 | ]
69 | })
70 |
--------------------------------------------------------------------------------
/lib/rules/no-cjs-in-config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview Disallow `require/modules.exports/exports` in `nuxt.config.js`
3 | * @author Xin Du
4 | */
5 | 'use strict'
6 |
7 | const path = require('path')
8 |
9 | // ------------------------------------------------------------------------------
10 | // Rule Definition
11 | // ------------------------------------------------------------------------------
12 |
13 | module.exports = {
14 | meta: {
15 | docs: {
16 | description:
17 | 'disallow commonjs module api `require/modules.exports/exports` in `nuxt.config.js`',
18 | category: 'base'
19 | },
20 | messages: {
21 | noCjs: 'Unexpected {{cjs}}, please use {{esm}} instead.'
22 | }
23 | },
24 |
25 | create (context) {
26 | // variables should be defined here
27 | const options = context.options[0] || {}
28 | const configFile = options.file || 'nuxt.config.js'
29 | let isNuxtConfig = false
30 |
31 | // ----------------------------------------------------------------------
32 | // Public
33 | // ----------------------------------------------------------------------
34 |
35 | return {
36 | Program (node) {
37 | const filename = path.basename(context.getFilename())
38 | if (filename === configFile) {
39 | isNuxtConfig = true
40 | }
41 | },
42 | MemberExpression: function (node) {
43 | if (!isNuxtConfig) {
44 | return
45 | }
46 |
47 | // module.exports
48 | if (node.object.name === 'module' && node.property.name === 'exports') {
49 | context.report({
50 | node,
51 | messageId: 'noCjs',
52 | data: {
53 | cjs: 'module.exports',
54 | esm: 'export default'
55 | }
56 | })
57 | }
58 |
59 | // exports.
60 | if (node.object.name === 'exports') {
61 | const isInScope = context.getScope()
62 | .variables
63 | .some(variable => variable.name === 'exports')
64 | if (!isInScope) {
65 | context.report({
66 | node,
67 | messageId: 'noCjs',
68 | data: {
69 | cjs: 'exports',
70 | esm: 'export default'
71 | }
72 | })
73 | }
74 | }
75 | },
76 | CallExpression: function (call) {
77 | const module = call.arguments[0]
78 |
79 | if (
80 | !isNuxtConfig ||
81 | context.getScope().type !== 'module' ||
82 | !['ExpressionStatement', 'VariableDeclarator'].includes(call.parent.type) ||
83 | call.callee.type !== 'Identifier' ||
84 | call.callee.name !== 'require' ||
85 | call.arguments.length !== 1 ||
86 | module.type !== 'Literal' ||
87 | typeof module.value !== 'string'
88 | ) {
89 | return
90 | }
91 |
92 | context.report({
93 | node: call.callee,
94 | messageId: 'noCjs',
95 | data: {
96 | cjs: 'require',
97 | esm: 'import'
98 | }
99 | })
100 | }
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/lib/rules/no-env-in-context.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview disallow `context.isServer/context.isClient` in `asyncData/fetch/nuxtServerInit`
3 | * @author Xin Du
4 | */
5 | 'use strict'
6 |
7 | const utils = require('../utils')
8 |
9 | // ------------------------------------------------------------------------------
10 | // Rule Definition
11 | // ------------------------------------------------------------------------------
12 |
13 | module.exports = {
14 | meta: {
15 | docs: {
16 | description:
17 | 'disallow `context.isServer/context.isClient` in `asyncData/fetch/nuxtServerInit`',
18 | category: 'base'
19 | },
20 | messages: {
21 | noEnv: 'Unexpected {{env}} in {{funcName}}.'
22 | }
23 | },
24 |
25 | create (context) {
26 | // variables should be defined here
27 | const forbiddenNodes = []
28 | const options = context.options[0] || {}
29 |
30 | const ENV = ['isServer', 'isClient']
31 | const HOOKS = new Set(['asyncData', 'fetch'].concat(options.methods || []))
32 |
33 | // ----------------------------------------------------------------------
34 | // Public
35 | // ----------------------------------------------------------------------
36 |
37 | return {
38 | MemberExpression (node) {
39 | const propertyName = node.computed ? node.property.value : node.property.name
40 | if (propertyName && ENV.includes(propertyName)) {
41 | forbiddenNodes.push({ name: propertyName, node })
42 | }
43 | },
44 | ...utils.executeOnVue(context, obj => {
45 | for (const funcName of HOOKS) {
46 | const func = utils.getFunctionWithName(obj, funcName)
47 | const param = func && func.value ? func.value.params && func.value.params[0] : false
48 | if (param) {
49 | if (param.type === 'ObjectPattern') {
50 | for (const prop of param.properties) {
51 | if (prop.key && prop.key.name && ENV.includes(prop.key.name)) {
52 | context.report({
53 | node: prop,
54 | messageId: 'noEnv',
55 | data: {
56 | env: prop.key.name,
57 | funcName
58 | }
59 | })
60 | }
61 | }
62 | } else {
63 | for (const { name, node: child } of forbiddenNodes) {
64 | if (utils.isInFunction(func, child)) {
65 | if (param.name === child.object.name) {
66 | context.report({
67 | node: child,
68 | messageId: 'noEnv',
69 | data: {
70 | env: name,
71 | funcName
72 | }
73 | })
74 | }
75 | }
76 | }
77 | }
78 | }
79 | }
80 | })
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/lib/rules/no-env-in-hooks.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview disallow process.server, process.client and process.browser in the following lifecycle hooks: beforeMount, mounted, beforeUpdate, updated, activated, deactivated, beforeDestroy and destroyed
3 | * @author Xin Du
4 | */
5 | 'use strict'
6 |
7 | const utils = require('../utils')
8 |
9 | // ------------------------------------------------------------------------------
10 | // Rule Definition
11 | // ------------------------------------------------------------------------------
12 |
13 | module.exports = {
14 | meta: {
15 | docs: {
16 | description:
17 | 'disallow process.server and process.client in the following lifecycle hooks: beforeMount, mounted, beforeUpdate, updated, activated, deactivated, beforeDestroy and destroyed',
18 | category: 'base'
19 | },
20 | messages: {
21 | noEnv: 'Unexpected {{name}} in {{funcName}}.'
22 | }
23 | },
24 |
25 | create (context) {
26 | // variables should be defined here
27 | const forbiddenNodes = []
28 | const options = context.options[0] || {}
29 |
30 | const ENV = ['server', 'client', 'browser']
31 | const HOOKS = new Set(['beforeMount', 'mounted', 'beforeUpdate', 'updated', 'activated', 'deactivated', 'beforeDestroy', 'destroyed'].concat(options.methods || []))
32 |
33 | // ----------------------------------------------------------------------
34 | // Public
35 | // ----------------------------------------------------------------------
36 |
37 | return {
38 | MemberExpression (node) {
39 | const objectName = node.object.name
40 | if (objectName === 'process') {
41 | const propertyName = node.computed ? node.property.value : node.property.name
42 | if (propertyName && ENV.includes(propertyName)) {
43 | forbiddenNodes.push({ name: 'process.' + propertyName, node })
44 | }
45 | }
46 | },
47 | ...utils.executeOnVue(context, obj => {
48 | for (const funcName of HOOKS) {
49 | const func = utils.getFunctionWithName(obj, funcName)
50 | if (func) {
51 | for (const { name, node: child } of forbiddenNodes) {
52 | if (utils.isInFunction(func, child)) {
53 | context.report({
54 | node: child,
55 | messageId: 'noEnv',
56 | data: {
57 | name,
58 | funcName
59 | }
60 | })
61 | }
62 | }
63 | }
64 | }
65 | })
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/lib/rules/no-globals-in-created.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview disallow `window/document` in `created/beforeCreate`
3 | * @author Xin Du
4 | */
5 | 'use strict'
6 |
7 | const utils = require('../utils')
8 |
9 | // ------------------------------------------------------------------------------
10 | // Rule Definition
11 | // ------------------------------------------------------------------------------
12 |
13 | module.exports = {
14 | meta: {
15 | docs: {
16 | description: 'disallow `window/document` in `created/beforeCreate`',
17 | category: 'base'
18 | },
19 | messages: {
20 | noGlobals: 'Unexpected {{name}} in {{funcName}}.'
21 | }
22 | },
23 |
24 | create (context) {
25 | const forbiddenNodes = []
26 | const options = context.options[0] || {}
27 |
28 | const HOOKS = new Set(
29 | ['created', 'beforeCreate'].concat(options.methods || [])
30 | )
31 | const GLOBALS = ['window', 'document']
32 |
33 | function isGlobals (name) {
34 | return GLOBALS.includes(name)
35 | }
36 |
37 | return {
38 | MemberExpression (node) {
39 | if (!node.object) return
40 |
41 | const name = node.object.name
42 |
43 | if (isGlobals(name)) {
44 | forbiddenNodes.push({ name, node })
45 | }
46 | },
47 | VariableDeclarator (node) {
48 | if (!node.init) return
49 |
50 | const name = node.init.name
51 |
52 | if (isGlobals(name)) {
53 | forbiddenNodes.push({ name, node })
54 | }
55 | },
56 | ...utils.executeOnVue(context, obj => {
57 | for (const { funcName, name, node } of utils.getFunctionWithChild(obj, HOOKS, forbiddenNodes)) {
58 | context.report({
59 | node,
60 | messageId: 'noGlobals',
61 | data: {
62 | name,
63 | funcName
64 | }
65 | })
66 | }
67 | })
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/lib/rules/no-this-in-fetch-data.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview disallow `this` in `asyncData/fetch`
3 | * @author Xin Du
4 | */
5 | 'use strict'
6 |
7 | const satisfies = require('semver/ranges/intersects')
8 | const utils = require('../utils')
9 | const resolver = require('../utils/resolver')
10 |
11 | // ------------------------------------------------------------------------------
12 | // Rule Definition
13 | // ------------------------------------------------------------------------------
14 |
15 | module.exports = {
16 | meta: {
17 | docs: {
18 | description: 'disallow `this` in `asyncData/fetch`',
19 | category: 'base'
20 | },
21 | messages: {
22 | noThis: 'Unexpected this in {{funcName}}.'
23 | }
24 | },
25 |
26 | create (context) {
27 | // variables should be defined here
28 | const forbiddenNodes = new Map()
29 | const options = context.options[0] || {}
30 |
31 | const HOOKS = new Set(
32 | ['asyncData'].concat(options.methods || [])
33 | )
34 |
35 | const { version } = resolver
36 | // new fetch API can use `this` since 2.12.0
37 | if (version && satisfies(version, '<2.12.0')) {
38 | HOOKS.add('fetch')
39 | }
40 |
41 | let nodeUsingThis = []
42 |
43 | // ----------------------------------------------------------------------
44 | // Helpers
45 | // ----------------------------------------------------------------------
46 |
47 | function enterFunction () {
48 | nodeUsingThis = []
49 | }
50 |
51 | function exitFunction (node) {
52 | if (nodeUsingThis.length > 0) {
53 | forbiddenNodes.set(node, nodeUsingThis)
54 | }
55 | }
56 |
57 | function markThisUsed (node) {
58 | nodeUsingThis.push(node)
59 | }
60 |
61 | // ----------------------------------------------------------------------
62 | // Public
63 | // ----------------------------------------------------------------------
64 |
65 | return {
66 | FunctionExpression: enterFunction,
67 | 'FunctionExpression:exit': exitFunction,
68 | ArrowFunctionExpression: enterFunction,
69 | 'ArrowFunctionExpression:exit': exitFunction,
70 | ThisExpression: markThisUsed,
71 | Super: markThisUsed,
72 | ...utils.executeOnVue(context, obj => {
73 | for (const funcName of HOOKS) {
74 | const prop = utils.getFunctionWithName(obj, funcName)
75 | if (prop && forbiddenNodes.has(prop.value)) {
76 | for (const node of forbiddenNodes.get(prop.value)) {
77 | context.report({
78 | node,
79 | messageId: 'noThis',
80 | data: {
81 | funcName
82 | }
83 | })
84 | }
85 | }
86 | }
87 | })
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/lib/rules/no-timing-in-fetch-data.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview disallow `setTimeout/setInterval` in `asyncData/fetch`
3 | * @author Xin Du
4 | */
5 | 'use strict'
6 |
7 | const utils = require('../utils')
8 |
9 | // ------------------------------------------------------------------------------
10 | // Rule Definition
11 | // ------------------------------------------------------------------------------
12 |
13 | module.exports = {
14 | meta: {
15 | docs: {
16 | description: 'disallow `setTimeout/setInterval` in `asyncData/fetch`',
17 | category: 'recommended'
18 | },
19 | messages: {
20 | noTiming: 'Unexpected {{name}} in {{funcName}}.'
21 | }
22 | },
23 |
24 | create (context) {
25 | const forbiddenNodes = []
26 | const options = context.options[0] || {}
27 |
28 | const HOOKS = new Set(
29 | ['fetch', 'asyncData'].concat(options.methods || [])
30 | )
31 | const TIMING = ['setTimeout', 'setInterval']
32 |
33 | function isTiming (name) {
34 | return TIMING.includes(name)
35 | }
36 |
37 | return {
38 | CallExpression (node) {
39 | if (!node.callee) return
40 |
41 | const name = node.callee.name
42 |
43 | if (isTiming(name)) {
44 | forbiddenNodes.push({ name, node })
45 | }
46 | },
47 | VariableDeclarator (node) {
48 | if (!node.init) return
49 |
50 | const name = node.init.name
51 |
52 | if (isTiming(name)) {
53 | forbiddenNodes.push({ name, node })
54 | }
55 | },
56 | ...utils.executeOnVue(context, obj => {
57 | for (const { funcName, name, node } of utils.getFunctionWithChild(obj, HOOKS, forbiddenNodes)) {
58 | context.report({
59 | node,
60 | messageId: 'noTiming',
61 | data: {
62 | name,
63 | funcName
64 | }
65 | })
66 | }
67 | })
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/lib/rules/require-func-head.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview enforce component's head property to be a function.
3 | * @author Xin Du
4 | */
5 | 'use strict'
6 |
7 | const utils = require('../utils')
8 |
9 | // ------------------------------------------------------------------------------
10 | // Rule Definition
11 | // ------------------------------------------------------------------------------
12 |
13 | module.exports = {
14 | meta: {
15 | docs: {
16 | description: "enforce component's head property to be a function",
17 | category: 'recommended'
18 | },
19 | fixable: 'code',
20 | messages: {
21 | head: '`head` property in component must be a function.'
22 | }
23 | },
24 |
25 | create (context) {
26 | const sourceCode = context.getSourceCode()
27 |
28 | return utils.executeOnVueComponent(context, (obj) => {
29 | obj.properties
30 | .filter(p =>
31 | p.type === 'Property' &&
32 | p.key.type === 'Identifier' &&
33 | p.key.name === 'head' &&
34 | p.value.type !== 'FunctionExpression' &&
35 | p.value.type !== 'ArrowFunctionExpression' &&
36 | p.value.type !== 'Identifier' &&
37 | p.value.type !== 'CallExpression'
38 | )
39 | .forEach(p => {
40 | context.report({
41 | node: p,
42 | messageId: 'head',
43 | fix (fixer) {
44 | const tokens = utils.getFirstAndLastTokens(p.value, sourceCode)
45 |
46 | return [
47 | fixer.insertTextBefore(tokens.first, 'function() {\nreturn '),
48 | fixer.insertTextAfter(tokens.last, ';\n}')
49 | ]
50 | }
51 | })
52 | })
53 | })
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/lib/utils/index.js:
--------------------------------------------------------------------------------
1 | const utils = require('eslint-plugin-vue/lib/utils')
2 |
3 | module.exports = Object.assign(
4 | {
5 | getProperty (node, name, condition) {
6 | return node.properties.find(
7 | p => p.type === 'Property' && name === utils.getStaticPropertyName(p) && condition(p)
8 | )
9 | },
10 | getProperties (node, names) {
11 | return node.properties.filter(
12 | p => p.type === 'Property' && (!names.size || names.has(utils.getStaticPropertyName(p)))
13 | )
14 | },
15 | getFunctionWithName (rootNode, name) {
16 | return this.getProperty(
17 | rootNode,
18 | name,
19 | item => item.value.type === 'ArrowFunctionExpression' || item.value.type === 'FunctionExpression'
20 | )
21 | },
22 | isInFunction (func, child) {
23 | if (func.value.type === 'FunctionExpression') {
24 | if (
25 | child &&
26 | child.loc.start.line >= func.value.loc.start.line &&
27 | child.loc.end.line <= func.value.loc.end.line
28 | ) {
29 | return true
30 | }
31 | }
32 | },
33 | * getFunctionWithChild (rootNode, funcNames, childNodes) {
34 | const funcNodes = this.getProperties(rootNode, funcNames)
35 |
36 | for (const func of funcNodes) {
37 | for (const { name, node: child } of childNodes) {
38 | const funcName = utils.getStaticPropertyName(func)
39 | if (!funcName) continue
40 |
41 | if (this.isInFunction(func, child)) {
42 | yield { name, node: child, func, funcName }
43 | }
44 | }
45 | }
46 | },
47 | isOpenParen (token) {
48 | return token.type === 'Punctuator' && token.value === '('
49 | },
50 | isCloseParen (token) {
51 | return token.type === 'Punctuator' && token.value === ')'
52 | },
53 | getFirstAndLastTokens (node, sourceCode) {
54 | let first = sourceCode.getFirstToken(node)
55 | let last = sourceCode.getLastToken(node)
56 |
57 | // If the value enclosed by parentheses, update the 'first' and 'last' by the parentheses.
58 | while (true) {
59 | const prev = sourceCode.getTokenBefore(first)
60 | const next = sourceCode.getTokenAfter(last)
61 | if (this.isOpenParen(prev) && this.isCloseParen(next)) {
62 | first = prev
63 | last = next
64 | } else {
65 | return { first, last }
66 | }
67 | }
68 | }
69 | },
70 | utils
71 | )
72 |
--------------------------------------------------------------------------------
/lib/utils/resolver.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | __version: undefined,
3 | get version () {
4 | if (this.__version === undefined) {
5 | return this.loadNuxtPkg()
6 | }
7 | return this.__version
8 | },
9 | loadPkg (pkgName) {
10 | try {
11 | return require(`${pkgName}/package.json`)
12 | } catch (e) {
13 | return {}
14 | }
15 | },
16 | loadNuxtPkg () {
17 | const { version } = this.loadPkg('nuxt') || this.loadPkg('nuxt-edge')
18 | this.__version = version || false
19 | return this.__version
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "eslint-plugin-nuxt",
3 | "version": "4.0.0",
4 | "description": "ESLint plugin for Nuxt.js",
5 | "author": "Clark Du ",
6 | "license": "MIT",
7 | "main": "lib/index.js",
8 | "homepage": "https://github.com/nuxt/eslint-plugin-nuxt#readme",
9 | "bugs": {
10 | "url": "https://github.com/nuxt/eslint-plugin-nuxt/issues"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git+https://github.com/nuxt/eslint-plugin-nuxt.git"
15 | },
16 | "keywords": [
17 | "nuxt",
18 | "eslint",
19 | "eslintplugin"
20 | ],
21 | "files": [
22 | "lib",
23 | "!__tests__"
24 | ],
25 | "scripts": {
26 | "test": "jest --silent",
27 | "lint": "eslint ./",
28 | "release": "standard-version",
29 | "postinstall": "husky install",
30 | "prepublishOnly": "pinst --disable",
31 | "postpublish": "pinst --enable",
32 | "prepare": "husky install"
33 | },
34 | "lint-staged": {
35 | "*.js": [
36 | "eslint"
37 | ]
38 | },
39 | "devDependencies": {
40 | "eslint": "^8.23.0",
41 | "eslint-config-standard": "^17.0.0",
42 | "eslint-plugin-import": "^2.26.0",
43 | "eslint-plugin-n": "^15.2.5",
44 | "eslint-plugin-promise": "^6.0.1",
45 | "eslint-plugin-standard": "^5.0.0",
46 | "husky": "^8.0.1",
47 | "jest": "^29.0.1",
48 | "lint-staged": "^13.0.3",
49 | "pinst": "^3.0.0",
50 | "standard-version": "^9.3.2"
51 | },
52 | "dependencies": {
53 | "eslint-plugin-vue": "^9.4.0",
54 | "semver": "^7.3.7",
55 | "vue-eslint-parser": "^9.0.3"
56 | },
57 | "packageManager": "yarn@3.2.3"
58 | }
59 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "@nuxtjs"
4 | ],
5 | "lockFileMaintenance": {
6 | "enabled": true
7 | }
8 | }
9 |
--------------------------------------------------------------------------------