@lewishowles/lint-config 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +38 -6
- package/base.json +23 -4
- package/comments/plugin.js +2 -12
- package/comments/rules/class-documentation.js +8 -5
- package/comments/rules/configured-api-calls.js +3 -3
- package/comments/rules/formatting.js +868 -0
- package/comments/rules/variable-declarations.js +41 -4
- package/comments/rules/vue-component-documentation.js +10 -8
- package/comments/rules/vue-emit-documentation.js +2 -1
- package/comments/utils/documentation.js +0 -1
- package/comments/utils/jsdoc.js +84 -63
- package/comments/utils/source.js +15 -2
- package/comments/utils/wrap.js +123 -2
- package/comments.json +10 -7
- package/package.json +3 -2
- package/comments/rules/block-comments.js +0 -70
- package/comments/rules/jsdoc-tag-formatting.js +0 -70
- package/comments/rules/line-comments.js +0 -86
- package/comments/rules/max-line-length.js +0 -159
- package/comments/rules/placement.js +0 -290
- package/comments/rules/sentence-punctuation.js +0 -275
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.0: 2026-09-21
|
|
4
|
+
|
|
5
|
+
### Changes
|
|
6
|
+
|
|
7
|
+
- Breaking: replace `comments/line-comments`, `comments/max-line-length`, `comments/sentence-punctuation`, `comments/block-comments`, `comments/jsdoc-tag-formatting`, and `comments/placement` with a single `comments/formatting` rule. Remove the old rule IDs from your configuration; `comments.json` already enables `comments/formatting`.
|
|
8
|
+
- Breaking: `base` now reports an error when statements of different kinds, such as a declaration followed by a function call, have no blank line between them, and when consecutive `const` or `let` declarations are separated by a blank line. Run `--fix` once to update existing code.
|
|
9
|
+
- `comments/formatting` moves trailing line comments onto their own line above the code.
|
|
10
|
+
|
|
11
|
+
### Fixes
|
|
12
|
+
|
|
13
|
+
- `comments/formatting`: refill comment lines that were wrapped before the 80-column limit.
|
|
14
|
+
- `comments/variable-declarations`: skip the line-comment requirement for `const` declarations assigned to arrow functions or function expressions.
|
|
15
|
+
|
|
16
|
+
## 0.5.0: 2026-09-11
|
|
17
|
+
|
|
18
|
+
### Changes
|
|
19
|
+
|
|
20
|
+
- `comments/variable-declarations`: add a `rootOnly` option; `comments.json` enables it for test files so only root-level variables need comments there. If you override `comments.json` rules, concatenate the test-file override (see README).
|
|
21
|
+
|
|
22
|
+
### Fixes
|
|
23
|
+
|
|
24
|
+
- Measure comment width in display columns, with tabs counted as four, so indented comments wrap and validate against the visible 80-column limit.
|
|
25
|
+
|
|
3
26
|
## 0.4.0: 2026-08-28
|
|
4
27
|
|
|
5
28
|
### New rules
|
package/README.md
CHANGED
|
@@ -49,7 +49,7 @@ The Vue layer extends `base.json` internally, so you only need to extend `vue.js
|
|
|
49
49
|
|
|
50
50
|
### Comment formatting (optional)
|
|
51
51
|
|
|
52
|
-
Add the comments layer alongside the base or Vue layer to enforce the comment-formatting rules, variable-declaration documentation, JSDoc on named functions and first-level object methods, documentation directly after each Vue `<script setup>` opening tag, and block comments for runtime `defineProps` properties:
|
|
52
|
+
Add the comments layer alongside the base or Vue layer to enforce the comment-formatting rules, including moving trailing line comments onto their own line, variable-declaration documentation, JSDoc on named functions and first-level object methods, documentation directly after each Vue `<script setup>` opening tag, and block comments for runtime `defineProps` properties:
|
|
53
53
|
|
|
54
54
|
```json
|
|
55
55
|
{
|
|
@@ -73,7 +73,7 @@ The Vue component rule reads the raw `.vue` file because Oxlint's JS Plugin API
|
|
|
73
73
|
}
|
|
74
74
|
],
|
|
75
75
|
"rules": {
|
|
76
|
-
"comments/
|
|
76
|
+
"comments/formatting": "error"
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
```
|
|
@@ -92,13 +92,45 @@ The `comments/configured-api-calls` rule requires an immediately preceding line
|
|
|
92
92
|
}
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
+
The `comments/variable-declarations` rule accepts a `rootOnly` option to require comments only before root-level `const`, `let`, and `using` declarations. The comments layer already enables `rootOnly` for test files matched by `**/*.test.*`, `**/*.spec.*`, and `**/test/**`; other files keep the default of `false`. Override it for another scope or to change the behaviour:
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"rules": {
|
|
100
|
+
"comments/variable-declarations": ["error", { "rootOnly": true }]
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
95
105
|
The `comments/class-documentation` rule requires an immediately preceding block comment before class declarations and const-assigned class expressions. Constructors, methods, getters, and setters require full JSDoc; constructors never need an `@returns` tag, and getters and setters need one only when they return a value. Instance and static fields require an immediately preceding line comment.
|
|
96
106
|
|
|
97
107
|
### `vp check` configuration
|
|
98
108
|
|
|
99
109
|
The `vp check` and `vp lint` commands read Oxlint settings only from a `lint` block in `vite.config.js`; they do not read `.oxlintrc.json` directly. If `vite.config.js` is missing, they silently use an unrelated default configuration. You may still see plausible warnings and exit codes, but none of your rules are applied.
|
|
100
110
|
|
|
101
|
-
Each consuming repo needs a `vite.config.js` with a `lint` block built from the config layer(s) and the repo's `.oxlintrc.json`, imported as JSON. Verify the setup with `vp lint --print-config <file>` and check that your real values, not defaults, are active.
|
|
111
|
+
Each consuming repo needs a `vite.config.js` with a `lint` block built from the config layer(s) and the repo's `.oxlintrc.json`, imported as JSON. Concatenate the `overrides` arrays from every imported layer before the local overrides so shared file-specific rules still apply. Verify the setup with `vp lint --print-config <file>` and check that your real values, not defaults, are active.
|
|
112
|
+
|
|
113
|
+
```js
|
|
114
|
+
import { defineConfig } from "vite-plus";
|
|
115
|
+
import lintConfigBase from "@lewishowles/lint-config/base.json" with { type: "json" };
|
|
116
|
+
import lintConfigComments from "@lewishowles/lint-config/comments.json" with { type: "json" };
|
|
117
|
+
import oxlintrc from "./.oxlintrc.json" with { type: "json" };
|
|
118
|
+
|
|
119
|
+
const lint = {
|
|
120
|
+
...lintConfigBase,
|
|
121
|
+
env: oxlintrc.env,
|
|
122
|
+
ignorePatterns: oxlintrc.ignorePatterns,
|
|
123
|
+
jsPlugins: [...lintConfigBase.jsPlugins, ...lintConfigComments.jsPlugins],
|
|
124
|
+
overrides: [
|
|
125
|
+
...(lintConfigBase.overrides ?? []),
|
|
126
|
+
...(lintConfigComments.overrides ?? []),
|
|
127
|
+
...(oxlintrc.overrides ?? []),
|
|
128
|
+
],
|
|
129
|
+
rules: { ...lintConfigBase.rules, ...lintConfigComments.rules },
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export default defineConfig({ lint });
|
|
133
|
+
```
|
|
102
134
|
|
|
103
135
|
## Customising
|
|
104
136
|
|
|
@@ -130,7 +162,7 @@ Ignore patterns are project-specific, so they always live in your project config
|
|
|
130
162
|
|
|
131
163
|
### Adding overrides
|
|
132
164
|
|
|
133
|
-
Overrides are additive: shared overrides
|
|
165
|
+
Overrides are additive in the `vite.config.js` lint block: shared overrides still apply, and your local ones are appended.
|
|
134
166
|
|
|
135
167
|
```json
|
|
136
168
|
{
|
|
@@ -167,7 +199,7 @@ The base layer sorts named members within each import statement, but leaves decl
|
|
|
167
199
|
## What stays repo-local
|
|
168
200
|
|
|
169
201
|
- `ignorePatterns`, since every project has different build output and tool directories
|
|
170
|
-
- `overrides` for project-specific directories (e.g. `bin/**/*.js`, `src/cli/**/*.js`, `src/playwright/**/*.js`), since the file paths differ per project and can't be generalised
|
|
202
|
+
- `overrides` for project-specific directories (e.g. `bin/**/*.js`, `src/cli/**/*.js`, `src/playwright/**/*.js`), since the file paths differ per project and can't be generalised. The `vite.config.js` lint block appends these local entries after the shared layer overrides.
|
|
171
203
|
- Rule relaxations for specific file patterns (e.g. turning off `vite-plus/prefer-vite-plus-imports` in generated `.d.ts` files)
|
|
172
204
|
- Additional plugins, only for projects that need them
|
|
173
205
|
|
|
@@ -176,6 +208,6 @@ The base layer sorts named members within each import statement, but leaves decl
|
|
|
176
208
|
When a project's `.oxlintrc.json` extends a shared layer:
|
|
177
209
|
|
|
178
210
|
- **Rules** shallow-merge by key: your value wins for any rule defined in both
|
|
179
|
-
- **Overrides** are additive:
|
|
211
|
+
- **Overrides** are additive in the `vite.config.js` lint block: it concatenates shared layer and local `overrides` entries, including any `env` declared inside an override block
|
|
180
212
|
- **Plugins** are additive: both shared and local `plugins`/`jsPlugins` load, deduplicated
|
|
181
213
|
- **`env`, `globals`, and `ignorePatterns` don't merge through `extends` at all** (an open Oxlint bug), which is why the usage examples above redeclare `env`/`globals` directly. See [known limitations](docs/limitations.md) for the full detail, including the separate `vite-plus` caveat around resolving `extends` paths.
|
package/base.json
CHANGED
|
@@ -35,13 +35,32 @@
|
|
|
35
35
|
"@stylistic/no-confusing-arrow": "error",
|
|
36
36
|
"@stylistic/padding-line-between-statements": [
|
|
37
37
|
"error",
|
|
38
|
-
{ "blankLine": "always", "prev": "const", "next": "let" },
|
|
39
|
-
{ "blankLine": "always", "prev": "let", "next": "const" },
|
|
40
38
|
{ "blankLine": "always", "prev": "*", "next": "break" },
|
|
41
39
|
{ "blankLine": "always", "prev": ["const", "let"], "next": "*" },
|
|
40
|
+
{ "blankLine": "always", "prev": "*", "next": ["const", "let"] },
|
|
42
41
|
{ "blankLine": "always", "prev": "*", "next": "return" },
|
|
43
|
-
{
|
|
44
|
-
|
|
42
|
+
{
|
|
43
|
+
"blankLine": "always",
|
|
44
|
+
"prev": ["block-like", "class", "do", "for", "function", "if", "switch", "try", "while"],
|
|
45
|
+
"next": "*"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"blankLine": "always",
|
|
49
|
+
"prev": "*",
|
|
50
|
+
"next": ["block-like", "class", "do", "for", "function", "if", "switch", "try", "while"]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"blankLine": "always",
|
|
54
|
+
"prev": { "selector": "ExpressionStatement[expression.type=\"AssignmentExpression\"]" },
|
|
55
|
+
"next": { "selector": "ExpressionStatement[expression.type=\"CallExpression\"]" }
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"blankLine": "always",
|
|
59
|
+
"prev": { "selector": "ExpressionStatement[expression.type=\"CallExpression\"]" },
|
|
60
|
+
"next": { "selector": "ExpressionStatement[expression.type=\"AssignmentExpression\"]" }
|
|
61
|
+
},
|
|
62
|
+
{ "blankLine": "never", "prev": "const", "next": "const" },
|
|
63
|
+
{ "blankLine": "never", "prev": "let", "next": "let" },
|
|
45
64
|
{ "blankLine": "always", "prev": "multiline-const", "next": "*" },
|
|
46
65
|
{ "blankLine": "always", "prev": "*", "next": "multiline-const" }
|
|
47
66
|
],
|
package/comments/plugin.js
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
import blockComments from "./rules/block-comments.js";
|
|
2
1
|
import classDocumentation from "./rules/class-documentation.js";
|
|
3
2
|
import configuredApiCalls from "./rules/configured-api-calls.js";
|
|
3
|
+
import formatting from "./rules/formatting.js";
|
|
4
4
|
import functionDocumentation from "./rules/function-documentation.js";
|
|
5
|
-
import jsdocTagFormatting from "./rules/jsdoc-tag-formatting.js";
|
|
6
|
-
import lineComments from "./rules/line-comments.js";
|
|
7
|
-
import maxLineLength from "./rules/max-line-length.js";
|
|
8
|
-
import placement from "./rules/placement.js";
|
|
9
|
-
import sentencePunctuation from "./rules/sentence-punctuation.js";
|
|
10
5
|
import variableDeclarations from "./rules/variable-declarations.js";
|
|
11
6
|
import vueComponentDocumentation from "./rules/vue-component-documentation.js";
|
|
12
7
|
import vueEmitDocumentation from "./rules/vue-emit-documentation.js";
|
|
@@ -15,15 +10,10 @@ import vuePropDocumentation from "./rules/vue-prop-documentation.js";
|
|
|
15
10
|
export default {
|
|
16
11
|
meta: { name: "comments" },
|
|
17
12
|
rules: {
|
|
18
|
-
"block-comments": blockComments,
|
|
19
13
|
"class-documentation": classDocumentation,
|
|
20
14
|
"configured-api-calls": configuredApiCalls,
|
|
15
|
+
formatting,
|
|
21
16
|
"function-documentation": functionDocumentation,
|
|
22
|
-
"jsdoc-tag-formatting": jsdocTagFormatting,
|
|
23
|
-
"line-comments": lineComments,
|
|
24
|
-
"max-line-length": maxLineLength,
|
|
25
|
-
placement,
|
|
26
|
-
"sentence-punctuation": sentencePunctuation,
|
|
27
17
|
"variable-declarations": variableDeclarations,
|
|
28
18
|
"vue-component-documentation": vueComponentDocumentation,
|
|
29
19
|
"vue-emit-documentation": vueEmitDocumentation,
|
|
@@ -33,7 +33,8 @@ export default {
|
|
|
33
33
|
* The class declaration node.
|
|
34
34
|
*/
|
|
35
35
|
ClassDeclaration(node) {
|
|
36
|
-
// Resolves any export wrapper before checking for
|
|
36
|
+
// Resolves any export wrapper before checking for
|
|
37
|
+
// documentation.
|
|
37
38
|
const documentationNode = getDocumentationNode(node);
|
|
38
39
|
|
|
39
40
|
if (!hasImmediateBlockComment(context.sourceCode, documentationNode)) {
|
|
@@ -44,8 +45,8 @@ export default {
|
|
|
44
45
|
}
|
|
45
46
|
},
|
|
46
47
|
/**
|
|
47
|
-
* Check class methods for required JSDoc blocks and tags.
|
|
48
|
-
* exempt from the @returns requirement.
|
|
48
|
+
* Check class methods for required JSDoc blocks and tags.
|
|
49
|
+
* Constructors are exempt from the @returns requirement.
|
|
49
50
|
*
|
|
50
51
|
* @param {object} node
|
|
51
52
|
* The method-definition node.
|
|
@@ -93,7 +94,8 @@ export default {
|
|
|
93
94
|
return;
|
|
94
95
|
}
|
|
95
96
|
|
|
96
|
-
// Static and instance fields share the requirement; only the
|
|
97
|
+
// Static and instance fields share the requirement; only the
|
|
98
|
+
// wording differs.
|
|
97
99
|
const message = node.static
|
|
98
100
|
? "Static fields require an immediately preceding line comment."
|
|
99
101
|
: "Instance fields require an immediately preceding line comment.";
|
|
@@ -116,7 +118,8 @@ export default {
|
|
|
116
118
|
return;
|
|
117
119
|
}
|
|
118
120
|
|
|
119
|
-
// Resolves any export wrapper before checking for
|
|
121
|
+
// Resolves any export wrapper before checking for
|
|
122
|
+
// documentation.
|
|
120
123
|
const documentationNode = getDocumentationNode(node.parent);
|
|
121
124
|
|
|
122
125
|
if (!hasImmediateBlockComment(context.sourceCode, documentationNode)) {
|
|
@@ -117,9 +117,9 @@ export default {
|
|
|
117
117
|
* The call expression node.
|
|
118
118
|
*/
|
|
119
119
|
CallExpression(node) {
|
|
120
|
-
// Read fresh for every call: createOnce's visitor is shared
|
|
121
|
-
// in the run, so caching this at
|
|
122
|
-
// file's options.
|
|
120
|
+
// Read fresh for every call: createOnce's visitor is shared
|
|
121
|
+
// across every file in the run, so caching this at
|
|
122
|
+
// closure-creation time would freeze the first file's options.
|
|
123
123
|
const configuredApis = getConfiguredApis(context);
|
|
124
124
|
|
|
125
125
|
if (node.callee.type !== "Identifier" || !configuredApis.has(node.callee.name)) {
|