eslint-plugin-lube 0.5.1 → 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 +260 -0
- package/LICENSE +21 -0
- package/README.md +120 -9
- package/docs/ascii-order.md +81 -0
- package/docs/pretty-imports.md +70 -59
- package/docs/pretty-jsdoc-casting.md +31 -23
- package/docs/pretty-sequence.md +129 -117
- package/docs/pretty-ternary.md +55 -0
- package/docs/svelte-naming-convention.md +59 -46
- package/package.json +60 -38
- package/src/index.js +299 -0
- package/src/rules/ascii-order.js +940 -0
- package/src/rules/pretty-imports.js +176 -0
- package/src/rules/pretty-jsdoc-casting.js +278 -0
- package/src/rules/pretty-sequence.js +489 -0
- package/src/rules/pretty-ternary.js +227 -0
- package/src/rules/svelte-naming-convention.js +903 -0
- package/src/utils/fix_recorder.js +50 -0
- package/src/utils/keep_comments.js +99 -0
- package/src/utils/keep_line_breaks.js +56 -0
- package/src/utils/skip_hole_commas.js +32 -0
- package/src/utils/skip_optional_patterns.js +27 -0
- package/src/utils/skip_unchanged_fixes.js +35 -0
- package/src/utils/source_text.js +442 -0
- package/src/utils/split_declarations.js +75 -0
- package/src/utils/text_width.js +9 -0
- package/types/index.d.ts +27 -13
- package/types/index.d.ts.map +1 -1
- package/index.js +0 -126
- package/private.d.ts +0 -168
- package/rules/pretty-imports.js +0 -147
- package/rules/pretty-jsdoc-casting.js +0 -236
- package/rules/pretty-sequence.js +0 -441
- package/rules/svelte-naming-convention.js +0 -361
- package/test/pretty-imports/ExportNamedDeclaration.js +0 -123
- package/test/pretty-imports/ImportDeclaration.js +0 -125
- package/test/pretty-imports.js +0 -20
- package/test/pretty-jsdoc-casting/case_by_expression.js +0 -289
- package/test/pretty-jsdoc-casting/various_situations.js +0 -111
- package/test/pretty-jsdoc-casting.js +0 -22
- package/test/pretty-sequence/case_by_node_type.js +0 -360
- package/test/pretty-sequence/case_by_option.js +0 -142
- package/test/pretty-sequence/various_situations.js +0 -204
- package/test/pretty-sequence.js +0 -23
- package/test/svelte-naming-convention/basic_snake_case.js +0 -67
- package/test/svelte-naming-convention/case_by_identifier.js +0 -1394
- package/test/svelte-naming-convention/snake_case_with_symbols.js +0 -67
- package/test/svelte-naming-convention.js +0 -25
- package/tsconfig.json +0 -21
- package/types/rules/pretty-imports.d.ts +0 -3
- package/types/rules/pretty-imports.d.ts.map +0 -1
- package/types/rules/pretty-jsdoc-casting.d.ts +0 -3
- package/types/rules/pretty-jsdoc-casting.d.ts.map +0 -1
- package/types/rules/pretty-sequence.d.ts +0 -3
- package/types/rules/pretty-sequence.d.ts.map +0 -1
- package/types/rules/svelte-naming-convention.d.ts +0 -3
- package/types/rules/svelte-naming-convention.d.ts.map +0 -1
- package/types/test/pretty-imports/ExportNamedDeclaration.d.ts +0 -2
- package/types/test/pretty-imports/ExportNamedDeclaration.d.ts.map +0 -1
- package/types/test/pretty-imports/ImportDeclaration.d.ts +0 -2
- package/types/test/pretty-imports/ImportDeclaration.d.ts.map +0 -1
- package/types/test/pretty-imports.d.ts +0 -2
- package/types/test/pretty-imports.d.ts.map +0 -1
- package/types/test/pretty-jsdoc-casting/case_by_expression.d.ts +0 -2
- package/types/test/pretty-jsdoc-casting/case_by_expression.d.ts.map +0 -1
- package/types/test/pretty-jsdoc-casting/various_situations.d.ts +0 -2
- package/types/test/pretty-jsdoc-casting/various_situations.d.ts.map +0 -1
- package/types/test/pretty-jsdoc-casting.d.ts +0 -2
- package/types/test/pretty-jsdoc-casting.d.ts.map +0 -1
- package/types/test/pretty-sequence/case_by_node_type.d.ts +0 -2
- package/types/test/pretty-sequence/case_by_node_type.d.ts.map +0 -1
- package/types/test/pretty-sequence/case_by_option.d.ts +0 -2
- package/types/test/pretty-sequence/case_by_option.d.ts.map +0 -1
- package/types/test/pretty-sequence/various_situations.d.ts +0 -2
- package/types/test/pretty-sequence/various_situations.d.ts.map +0 -1
- package/types/test/pretty-sequence.d.ts +0 -2
- package/types/test/pretty-sequence.d.ts.map +0 -1
- package/types/test/svelte-naming-convention/basic_snake_case.d.ts +0 -2
- package/types/test/svelte-naming-convention/basic_snake_case.d.ts.map +0 -1
- package/types/test/svelte-naming-convention/case_by_identifier.d.ts +0 -2
- package/types/test/svelte-naming-convention/case_by_identifier.d.ts.map +0 -1
- package/types/test/svelte-naming-convention/snake_case_with_symbols.d.ts +0 -2
- package/types/test/svelte-naming-convention/snake_case_with_symbols.d.ts.map +0 -1
- package/types/test/svelte-naming-convention.d.ts +0 -2
- package/types/test/svelte-naming-convention.d.ts.map +0 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.6.0
|
|
4
|
+
|
|
5
|
+
### Breaking
|
|
6
|
+
|
|
7
|
+
- **Two configs replace `configs.plugins` and `configs.rules`.** `configs.strict` holds the rules
|
|
8
|
+
`configs.rules` held, the house style with renaming, sorting and core rules, and
|
|
9
|
+
`configs.recommended` is a lighter set that only formats and orders, with rules that all have a
|
|
10
|
+
fix. Each is a flat config object with `plugins` and `rules`: replace
|
|
11
|
+
`plugins: lube.configs.plugins, rules: { ...lube.configs.rules }` with
|
|
12
|
+
`plugins: lube.configs.strict.plugins, rules: { ...lube.configs.strict.rules }`, or spread
|
|
13
|
+
`...lube.configs.strict` into the config.
|
|
14
|
+
- **Every rule rejects options it does not know.** A misspelled option such as `maxLenght` is a
|
|
15
|
+
configuration error instead of being ignored, and `pretty-jsdoc-casting` takes no options.
|
|
16
|
+
- **`svelte-naming-convention` is a `suggestion` rule, no longer `layout`,** since its fix renames
|
|
17
|
+
identifiers: `eslint --fix --fix-type layout` leaves names alone now.
|
|
18
|
+
- **The package is an ES module only.** `import lube from "eslint-plugin-lube"` works as before on
|
|
19
|
+
Node.js 18.18+, 20.9+ and 21.1+, the versions `@stylistic/eslint-plugin` supports. A CommonJS
|
|
20
|
+
`eslint.config.cjs` still gets the plugin itself from `require("eslint-plugin-lube")` on Node.js
|
|
21
|
+
20.19+ and 22.12+, which ESLint 10 requires anyway. Deep paths such as `eslint-plugin-lube/rules/ascii-order` are gone; the rules are
|
|
22
|
+
`lube.rules`.
|
|
23
|
+
- **Both configs use `@stylistic/eslint-plugin` instead of the deprecated core formatting
|
|
24
|
+
rules,** which ESLint 11 removes. Rename overrides of those rules:
|
|
25
|
+
```js
|
|
26
|
+
// before
|
|
27
|
+
rules: { ...lube.configs.rules, "indent": ["error", 4] }
|
|
28
|
+
// after
|
|
29
|
+
rules: { ...lube.configs.strict.rules, "@stylistic/indent": ["error", 4] }
|
|
30
|
+
```
|
|
31
|
+
`func-call-spacing` is `@stylistic/function-call-spacing`. `@stylistic/indent` also checks
|
|
32
|
+
TypeScript syntax, and `@stylistic/operator-linebreak` checks `=` of type aliases, which stays at the
|
|
33
|
+
end of the line: `type Name =` followed by `| "a"`.
|
|
34
|
+
- **The strict config reports blank lines** with `@stylistic/no-multiple-empty-lines` (`max: 0`)
|
|
35
|
+
and fixes `arrow-body-style`, `new-parens`, `no-extra-boolean-cast`, `no-extra-semi`,
|
|
36
|
+
`no-unneeded-ternary`, `no-useless-computed-key`, `no-useless-rename`, `no-useless-return`,
|
|
37
|
+
`prefer-exponentiation-operator`, `prefer-object-spread` and `yoda`. Run `eslint --fix` once.
|
|
38
|
+
- **The strict config reports functions assigned to variables** with `func-style`
|
|
39
|
+
(`declaration`): write `function name() {}` instead of `const name = () => {}`. Callbacks and
|
|
40
|
+
arrow functions that use `this` are not reported. It cannot be fixed.
|
|
41
|
+
- **The strict config sorts import statements, import and export names, object keys, function
|
|
42
|
+
declarations and test cases** with the new `ascii-order`, all of its options on. Run
|
|
43
|
+
`eslint --fix` once, then reorder by hand what it reports without a fix, or disable it where the
|
|
44
|
+
order matters: `// eslint-disable-next-line lube/ascii-order`. A report without a fix says why,
|
|
45
|
+
``Move key "a" before "b" to keep keys in ASCII order; it is not fixed automatically because moving
|
|
46
|
+
`f()` could change the order of side effects, so reorder it by hand``, or that a comment or statement
|
|
47
|
+
next to the item would end up in the wrong place. Keys whose values construct a
|
|
48
|
+
built-in from literals, such as `{ updatedAt: new Date(), createdAt: new Date() }` and
|
|
49
|
+
`{ s: new Set([ 1 ]), m: new Map() }`, are fixed, and so are keys whose values are a `const`, a
|
|
50
|
+
namespace import or a function or class declaration that is never assigned, which no call can
|
|
51
|
+
change: `{ shadow: shadowed(), helper }`. A `const` or class counts only where the value comes
|
|
52
|
+
after its declaration and outside a function declaration, which could run before it, so a read
|
|
53
|
+
that throws in the temporal dead zone still throws after the calls written before it. A
|
|
54
|
+
construction that always throws, such as `new RegExp("(")`, `new Array(-1)` or `new Map([ 1 ])`,
|
|
55
|
+
is not moved, nor one that another runtime may reject or that allocates a lot while linting:
|
|
56
|
+
`new RegExp` with a flag other than `gimsuy` or with syntax newer than ES2018, such as
|
|
57
|
+
`new RegExp("a", "v")` or `(?i:a)`, and `new Array`, a buffer, a typed array or a `DataView` with a
|
|
58
|
+
number over 65536 in its arguments, such as `new Set(new Array(1e8))`. Its fix assumes modules can run
|
|
59
|
+
in any order and nothing reads key order: sorted keys change `Object.keys`, `JSON.stringify` and
|
|
60
|
+
`for...in`, and an import without names, such as `import "./setup.js"`, is never moved and no
|
|
61
|
+
import moves across it. Under `exports` and `imports` of a
|
|
62
|
+
`package.json` it puts `types` first and `default` last, as TypeScript and Node.js read them.
|
|
63
|
+
- **Both configs break nested and long ternaries** with the new `pretty-ternary`: a
|
|
64
|
+
ternary with a ternary branch, or longer than 80 characters, puts `?` and `:` at the start of their
|
|
65
|
+
lines, one indent deeper per level. Run `eslint --fix` once.
|
|
66
|
+
- **`pretty-imports` checks imports with a default import** such as `import def, {a,b} from "m"`,
|
|
67
|
+
which it skipped before.
|
|
68
|
+
- **`pretty-sequence` and `pretty-imports` leave the indentation of code that is already written over
|
|
69
|
+
several lines to `@stylistic/indent`,** and write it only for the line breaks they insert themselves.
|
|
70
|
+
The two rules owned the same lines before, so wherever the indent rule measures a line differently,
|
|
71
|
+
`eslint --fix` never finished. Turn `fixIndent` on in a config without an indent rule.
|
|
72
|
+
- **Both configs wrap the `@stylistic` rules whose fixes break code or never settle:**
|
|
73
|
+
`comma-style` leaves the comma of an array hole on its own line, `operator-linebreak` leaves an
|
|
74
|
+
operator a comment follows, `object-curly-newline` and `object-curly-spacing` skip optional
|
|
75
|
+
destructured parameters, `key-spacing`, `semi-spacing`, `space-unary-ops`, `generator-star-spacing`,
|
|
76
|
+
`rest-spread-spacing` and `yield-star-spacing` keep the comments in the space they remove, every fix
|
|
77
|
+
writes the line break of the file, and a fix that would change nothing is dropped.
|
|
78
|
+
- **`max-len` is in neither config,** since it cannot be fixed.
|
|
79
|
+
- **`svelte-naming-convention` reports more declarations.** Function expression names and
|
|
80
|
+
parameters, `catch` parameters, parameters of exported camelCase functions, non-shorthand
|
|
81
|
+
destructuring such as `const { key: camelCase } = value` and `import { "name" as camelCase }`
|
|
82
|
+
are reported now. Expect new errors on existing code.
|
|
83
|
+
- **`svelte-naming-convention` treats `for...in` and `for...of` targets as usages.** They are fixed
|
|
84
|
+
together with their declaration, like assignments, instead of being renamed on their own.
|
|
85
|
+
- **`pretty-jsdoc-casting` puts one empty comment after nested castings that end together,** after
|
|
86
|
+
the outermost one: `/** @type {A} */(/** @type {unknown} */(a))/**/` instead of
|
|
87
|
+
`/** @type {A} */(/** @type {unknown} */(a)/**/)/**/`. Run `eslint --fix` once.
|
|
88
|
+
- **Every rule message says what to change and why:** `Rename 'isV' to 'is_v'`,
|
|
89
|
+
``Write these items on one line as `[ a, b ]`, since they fit in 30 characters``,
|
|
90
|
+
`Put each item and the closing bracket on a line of its own, since the items are longer than 30
|
|
91
|
+
characters together`, ``Break this ternary before `?` and `:`, since a branch is another ternary``,
|
|
92
|
+
`Move key "a" before "b" to keep keys in ASCII order`. The message IDs are new:
|
|
93
|
+
`pretty-sequence` reports `multiline`, `single_line` and `indent`; `pretty-imports` `multiline`,
|
|
94
|
+
`single_line`, `indent`, `semicolon` and `no_semicolon` for imports and exports alike;
|
|
95
|
+
`pretty-ternary` `multiline` and `spacing`; `pretty-jsdoc-casting` `marker` and `format`; and
|
|
96
|
+
`svelte-naming-convention` `rename` and `case`.
|
|
97
|
+
|
|
98
|
+
### Fixed
|
|
99
|
+
|
|
100
|
+
- The `maxLength` of `pretty-sequence` and `pretty-imports` counts a character that takes two
|
|
101
|
+
columns, such as a Korean, Chinese or Japanese one, as two. A line of Korean strings and a line of
|
|
102
|
+
Latin ones that take the same width on screen are now broken or joined alike, where the Korean one
|
|
103
|
+
used to stay on one line at twice the width.
|
|
104
|
+
- The message that asks for one line said the items "fit in" the `maxLength`, although it measures
|
|
105
|
+
the items alone, without the code around them, so the line it wrote could be much longer. It now
|
|
106
|
+
names the width it measured: "since the items are 75 characters together, within the 80 allowed".
|
|
107
|
+
- `pretty-jsdoc-casting` added `/**/` after casts in TypeScript files, where a JSDoc cast means
|
|
108
|
+
nothing. `.ts`, `.tsx`, `.mts` and `.cts` files are not checked now.
|
|
109
|
+
- The `one-var` fix of the strict config left `const a = 1; const b = 2` on one line, which
|
|
110
|
+
`@stylistic/max-statements-per-line` reported without a fix. `eslint --fix` puts each of the
|
|
111
|
+
declarations on a line of its own now.
|
|
112
|
+
- `no-duplicate-imports` of the strict config reported `import type { A } from "m"` next to
|
|
113
|
+
`import { b } from "m"`. A separate type import is allowed now.
|
|
114
|
+
- The `@stylistic/space-unary-ops`, `rest-spread-spacing`, `generator-star-spacing`,
|
|
115
|
+
`yield-star-spacing`, `semi-spacing` and `key-spacing` fixes of both configs deleted a
|
|
116
|
+
comment in the space they remove, or moved a colon into one: `!/** @type {A} */(a)/**/` lost its
|
|
117
|
+
type cast, `.../* @__PURE__ */ f()` its comment, and `a // note` followed by `: 1` became
|
|
118
|
+
`a // note: 1`. Such a space is left unreported now.
|
|
119
|
+
- In a file whose line breaks are CRLF, CR, U+2028 or U+2029, `pretty-sequence`, `pretty-imports`
|
|
120
|
+
and `pretty-ternary` counted only LF as a line break, so they indented from the wrong line, wrote
|
|
121
|
+
LF line breaks into the file and never stopped fixing it; `pretty-sequence` also indented the lines
|
|
122
|
+
inside a string or a template that spans such lines, changing its value, `` f(`a `` + U+2028 +
|
|
123
|
+
`` b`, c) `` grew a tab in front of `b`, and `pretty-ternary` and `pretty-jsdoc-casting` read those
|
|
124
|
+
line breaks as none. Every rule and the `@stylistic` fixes of both configs follow the
|
|
125
|
+
line break of the file now.
|
|
126
|
+
- `ascii-order` sorted only the outermost of nested objects, patterns or import braces per
|
|
127
|
+
`eslint --fix` pass, one pass per nesting level, so deeply nested files needed more than the 10
|
|
128
|
+
passes ESLint runs. Nested ones are sorted in the same pass now.
|
|
129
|
+
- `ascii-order` swapped destructuring targets whose order matters: `var { b: x, a: x } = o` changed
|
|
130
|
+
the value of `x`, and `({ b: this.b, a: this.a } = o)` the order of the setter calls. They are
|
|
131
|
+
reported without a fix now.
|
|
132
|
+
- `pretty-imports` removed `type` from `import type` and `export type`, import attributes such as
|
|
133
|
+
`with { type: "json" }`, and comments between the braces.
|
|
134
|
+
- `pretty-imports` removed a semicolon another statement needs: the one before a statement on the
|
|
135
|
+
same line, `import { a } from "m";var b = 1` became `import { a } from "m"var b = 1`, and the one
|
|
136
|
+
that starts the next line, `;[a].map(f)`. It also added a semicolon before the `}` that closes a
|
|
137
|
+
namespace, which `@stylistic/semi` of both configs removed again on every fix.
|
|
138
|
+
- `pretty-jsdoc-casting` changed what a cast means: it moved the cast of an inner expression out of
|
|
139
|
+
the parentheses, `/** @type {X} */(/** @type {A} */(a).b)` became
|
|
140
|
+
`/** @type {A} *//** @type {X} */((a).b)`, deleted the text after the type of a type comment,
|
|
141
|
+
`/** @type {A} @deprecated */ (a)` lost `@deprecated`, turned the plain comment
|
|
142
|
+
`/* @type {A} */ (a)` into a type cast, and removed the empty comment after a type comment that
|
|
143
|
+
spans lines. A type comment is kept as written now unless it holds only the type. It also mangled
|
|
144
|
+
`/** @type {A} */(a)/**//**/`, left a double space for `/** @type {A} */ (a)` and moved a cast onto
|
|
145
|
+
the next line when a line break followed the type comment.
|
|
146
|
+
- `pretty-jsdoc-casting` moved what stood between the cast parenthesis and the expression in front
|
|
147
|
+
of the type comment: a line break, so `return /** @type {A} */(` followed by `b)/**/` returned
|
|
148
|
+
`undefined`; the JSDoc of a function inside the cast, which landed between `export default` and
|
|
149
|
+
the cast with broken indentation; and the white space of a cast written over several lines, which
|
|
150
|
+
put the cast on a new line and left the old one empty, so with either config every
|
|
151
|
+
`eslint --fix` added one more line and one more indent level. That white space is dropped now,
|
|
152
|
+
unless a line comment ends there, and a cast is left unfixed when another comment stands there or
|
|
153
|
+
when a line break after `return`, `throw` or `yield` would stay.
|
|
154
|
+
- `pretty-jsdoc-casting` read the argument parentheses of a call as cast parentheses when a type
|
|
155
|
+
comment stood before them, so `var x = 1` followed by `/** @type {T} */(f(a))` (a call, because no
|
|
156
|
+
semicolon ends the first line) got a `/**/` marker and never stopped fighting `pretty-sequence`.
|
|
157
|
+
The parentheses of a call, `new` or `import()` are left alone now.
|
|
158
|
+
- `pretty-sequence` and `pretty-jsdoc-casting` took time quadratic in the file size, and
|
|
159
|
+
`pretty-sequence` in the line length: a 258 KB file took about 40 seconds per rule and takes about
|
|
160
|
+
0.1 seconds, and a 1.4 MB single-line file took 33 seconds and takes about 2 seconds, most of it
|
|
161
|
+
parsing.
|
|
162
|
+
- `pretty-sequence` broke TypeScript: `({ a, b }: Props) => a` became `({ a, b s) => a`, the
|
|
163
|
+
annotation of an array pattern was deleted, and `f<(x: number) => void>( a )` became `f<(a)`.
|
|
164
|
+
- `pretty-sequence` lost or moved comments and holes: a line comment after the last item commented
|
|
165
|
+
out the closing bracket, `[ b, c // note` followed by `]` became `[ b, c // note ]`; comments after
|
|
166
|
+
a trailing comma or inside empty brackets and the trailing hole of `[a, ,]` were deleted; and a
|
|
167
|
+
line comment after an item's comma moved onto the next item's line. It stays with its item now.
|
|
168
|
+
- `pretty-sequence` changed the value of a multiline template literal, a string with a line
|
|
169
|
+
continuation or a multiline JSX attribute string, `f(a, <div title="one` followed by ` two">)`,
|
|
170
|
+
by re-indenting its lines. Such sequences are left unfixed.
|
|
171
|
+
- `pretty-sequence`: with `funcCallSpacing`, `a => b` gained more spaces on every fix.
|
|
172
|
+
- `pretty-sequence` wrote indentation onto the empty lines of a function it moved to a new line.
|
|
173
|
+
- `pretty-sequence` and `@stylistic/indent` fixed each other endlessly ("Circular fixes detected")
|
|
174
|
+
for a sequence opening on the first line of a declaration whose last declarator starts on a later
|
|
175
|
+
line, `let i = [` … `], a = 1`, for a line starting with `;` as `@stylistic/semi-style: first`
|
|
176
|
+
writes it, for the arguments of a call that follows a multiline parenthesized expression on the
|
|
177
|
+
same line, `(a` `|| b).catch(c, d)` or `(a ? b : "") + f(c, d)`, and for a sequence on a line that
|
|
178
|
+
starts inside a block comment, `*/ const a = [b, c]`. `pretty-sequence` indents them like
|
|
179
|
+
`@stylistic/indent` now.
|
|
180
|
+
- In `.svelte` files, `pretty-sequence` and `pretty-ternary` indented a template expression such as
|
|
181
|
+
`{await f(` from the column where the markup before it started, and `@stylistic/indent` undid it
|
|
182
|
+
on every fix.
|
|
183
|
+
- The `pretty-sequence` rule description was copied from `pretty-jsdoc-casting`.
|
|
184
|
+
- `svelte-naming-convention` renamed usages as if they were declarations, arrow function bodies and
|
|
185
|
+
`extends` clauses among them, so references to imported or global names broke, and it left other
|
|
186
|
+
usages with the old name: `do...while` conditions, computed keys, class field values, `import()`,
|
|
187
|
+
JSX, decorators, TypeScript expressions such as `camelCase as T`, `camelCase!` and
|
|
188
|
+
`typeof camelCase`, `export = camelCase`, enum member values, type predicates, the overloads of a
|
|
189
|
+
function (only the implementation was renamed), the object of a JSX member tag such as
|
|
190
|
+
`<routeModule.Layout>`, and the markup of a `.svelte` file, where every node was read as a name
|
|
191
|
+
the rule must not touch, so `{camelCase}` in a mustache tag, an attribute, a directive or a block
|
|
192
|
+
expression stopped the rename. Every usage that scope analysis reaches is renamed with its
|
|
193
|
+
declaration now, a shorthand attribute becomes `camelCase={camel_case}`, what the markup declares,
|
|
194
|
+
such as the context of `{#each}` or a `let:` property, is left alone, and a name is reported
|
|
195
|
+
without a fix where the rule cannot tell a reference from a type or a property, such as
|
|
196
|
+
`let a: camelCase`, or where it is a component tag, `<My_Comp />`, which a lowercase name would
|
|
197
|
+
turn into an HTML tag.
|
|
198
|
+
- `svelte-naming-convention` broke destructuring and exports: `{ camelCase: camelCase }` was read as
|
|
199
|
+
a shorthand property and became `{ camelCase: camelCase: camel_case }`, a shorthand with a default,
|
|
200
|
+
`{ camelCase = 1 }` in a pattern, was never renamed while every other use of the name was, and
|
|
201
|
+
`export { camelCase }` lost its binding. They become `{ camelCase: camel_case }`,
|
|
202
|
+
`{ camelCase: camel_case = 1 }` and `export { camel_case as camelCase }` now, the declaration and
|
|
203
|
+
its export specifier in one fix, since separate fixes in one pass could leave `export` pointing at
|
|
204
|
+
a name that no longer exists, a syntax error.
|
|
205
|
+
- `svelte-naming-convention` matched usages to declarations by name only, so its fixes broke code
|
|
206
|
+
that the Svelte code base holds: a global or an exported camelCase function used where a parameter
|
|
207
|
+
of the same name was renamed elsewhere was renamed too, e.g. `requestAnimationFrame()` or
|
|
208
|
+
`flushSync()` became undefined; the usages of an import, `import { fetchModule }`, were renamed
|
|
209
|
+
with a same-named declaration elsewhere but not the import; a name whose snake_case form is already
|
|
210
|
+
a variable was renamed into it, e.g. `itemCount` next to `item_count`; the type annotation and `?`
|
|
211
|
+
of a TypeScript name were deleted, `itemCount?: number` became `item_count`; a parameter mentioned
|
|
212
|
+
in the prose of a JSDoc comment was renamed while `@param {T} callbackFn`, `[superClass]`,
|
|
213
|
+
`{callbackFn is F}` and `typeof callbackFn` kept the old name and failed type checking; and a store
|
|
214
|
+
read as `$userStore` lost its declaration. Usages follow scope analysis now, an import becomes
|
|
215
|
+
`import { fetchModule as fetch_module }` and `import { foo_bar as fooBar }` becomes
|
|
216
|
+
`import { foo_bar }`, a colliding rename is reported without a fix, only `typeof`, `asserts` and
|
|
217
|
+
`is` inside `{ }` of a JSDoc comment are renamed with the parameter, and in a `.svelte` file the
|
|
218
|
+
`$camelCase` subscriptions are renamed with the store in one fix, while outside one `$camelCase`
|
|
219
|
+
stays a name of its own and nothing is renamed.
|
|
220
|
+
- `svelte-naming-convention` renamed only part of a name and broke the code when another rule's fix
|
|
221
|
+
overlapped a usage in the same `eslint --fix` pass, such as one inside an argument list
|
|
222
|
+
`pretty-sequence` reformats, or when a declaration of the name is one the rule does not rename: a
|
|
223
|
+
function merged with a TypeScript namespace of the same name, as in `.d.ts` files,
|
|
224
|
+
`declare namespace pLimit` and `declare function pLimit(): pLimit.Limit`, a declaration exported
|
|
225
|
+
with `export var` next to a `var` of the same name, a parameter that shadows a function of the same
|
|
226
|
+
name, and a declaration turned off with `// eslint-disable-next-line`, `// eslint-disable-line` or
|
|
227
|
+
`/* eslint-disable */`, whose usages were renamed anyway. With `fixSameNames`, usages are renamed
|
|
228
|
+
first and the declaration in a later pass, once no usage of the old name is left, together with the
|
|
229
|
+
assignments to it and an `export default` of it, so `prefer-const` of the strict config never
|
|
230
|
+
turns `let lastBid = 1` into a `const` whose `lastBid += 1` was renamed in an earlier pass, and
|
|
231
|
+
`ascii-order` never moves a default-exported function while the export names it differently; a
|
|
232
|
+
name whose snake_case form is declared elsewhere is renamed in one fix with its usages; with
|
|
233
|
+
`fixSameNames: false` a declaration is renamed with its usages instead of without them; and the
|
|
234
|
+
other names are reported without a fix.
|
|
235
|
+
|
|
236
|
+
### Added
|
|
237
|
+
|
|
238
|
+
- `pretty-sequence` and `pretty-imports` take `fixIndent`. With it on, the rule reports a sequence or a
|
|
239
|
+
list of specifiers whose lines differ from it only in their indentation, as it always did.
|
|
240
|
+
- `ascii-order`, in the strict config: sorts import statements by module path, names in import
|
|
241
|
+
and export braces, object keys, function declarations next to each other and `describe`, `it` and
|
|
242
|
+
`test` calls in ASCII order, each turned off with `checkImports`, `checkNames`, `checkKeys`,
|
|
243
|
+
`checkDeclarations` or `checkTests`. Side-effect imports and a function exported with
|
|
244
|
+
`export default name` keep their place. When moving an item could change what the code does, such
|
|
245
|
+
as swapping two object values that call functions, it reports without a fix.
|
|
246
|
+
- `pretty-ternary`, in both configs: breaks a ternary or TypeScript conditional type
|
|
247
|
+
before `?` and `:` when a branch is another ternary, when it is longer than `maxLength` (80) or
|
|
248
|
+
when it already spans lines, indenting each nested level once more. Only the spaces around `?`
|
|
249
|
+
and `:` change.
|
|
250
|
+
- `configs.recommended`, for format on save: the `@stylistic` formatting rules, `pretty-imports`,
|
|
251
|
+
`pretty-jsdoc-casting`, `pretty-sequence` and `pretty-ternary` with items on one line up to 80
|
|
252
|
+
characters, and `ascii-order` for the names inside import and export braces only. It ends a file
|
|
253
|
+
with a line break, allows one blank line, never renames or moves statements or keys, and every
|
|
254
|
+
rule in it has a fix: `{ ...lube.configs.recommended, files: ["**/*.js"] }`, or
|
|
255
|
+
`extends: ["lube/recommended"]` with `defineConfig`.
|
|
256
|
+
- `configs.strict`, the house style: everything above plus `svelte-naming-convention`, every
|
|
257
|
+
`ascii-order` check, `pretty-sequence` and `pretty-imports` at 30 characters, no blank lines, no
|
|
258
|
+
line break at the end of a file, one statement per line and core rules such as `func-style`,
|
|
259
|
+
`no-shadow` and `prefer-const`.
|
|
260
|
+
- `meta.version`, so ESLint can cache results per plugin version.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 artxe
|
|
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.
|
package/README.md
CHANGED
|
@@ -1,9 +1,120 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
# ESLint Plugin Lube
|
|
2
|
+
Fixable formatting and ordering rules, so `eslint --fix` formats a project without Prettier.
|
|
3
|
+
|
|
4
|
+
Instead of Prettier next to ESLint, with a second config and a plugin to keep the two from fighting, formatting is a set of ESLint rules: one `eslint --fix` formats and lints, and each rule can be tuned or turned off like any other.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
```bash
|
|
8
|
+
npm i -D eslint eslint-plugin-lube
|
|
9
|
+
```
|
|
10
|
+
Requires ESLint 9 or later and Node.js 18.18+, 20.9+ or 21.1+; a CommonJS `eslint.config.cjs` needs Node.js 20.19+ or 22.12+ to `require` it. `@stylistic/eslint-plugin` is installed with the plugin.
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
```js
|
|
14
|
+
// eslint.config.js
|
|
15
|
+
import lube from "eslint-plugin-lube"
|
|
16
|
+
|
|
17
|
+
export default [
|
|
18
|
+
{
|
|
19
|
+
...lube.configs.recommended,
|
|
20
|
+
files: ["**/*.js", "**/*.ts"]
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
```
|
|
24
|
+
`eslint --fix` with `recommended` turns this:
|
|
25
|
+
```js
|
|
26
|
+
import {writeFile,readFile} from 'node:fs/promises';
|
|
27
|
+
|
|
28
|
+
export async function copy(from,to){
|
|
29
|
+
const text=await readFile(from,'utf8');
|
|
30
|
+
await writeFile(to,text.replace(/\r\n/g,'\n'),{encoding:'utf8',flag:'wx',mode:0o644,flush:true});
|
|
31
|
+
return text.length>1000?text.length>100000?'large':'medium':'small';
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
into this:
|
|
35
|
+
```js
|
|
36
|
+
import { readFile, writeFile } from "node:fs/promises"
|
|
37
|
+
|
|
38
|
+
export async function copy(from, to) {
|
|
39
|
+
const text = await readFile(from, "utf8")
|
|
40
|
+
await writeFile(
|
|
41
|
+
to,
|
|
42
|
+
text.replace(/\r\n/g, "\n"),
|
|
43
|
+
{ encoding: "utf8", flag: "wx", mode: 0o644, flush: true }
|
|
44
|
+
)
|
|
45
|
+
return text.length > 1000
|
|
46
|
+
? text.length > 100000
|
|
47
|
+
? "large"
|
|
48
|
+
: "medium"
|
|
49
|
+
: "small"
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
For TypeScript files, add the parser from `@typescript-eslint/parser`:
|
|
54
|
+
```js
|
|
55
|
+
// eslint.config.js
|
|
56
|
+
import tsParser from "@typescript-eslint/parser"
|
|
57
|
+
import lube from "eslint-plugin-lube"
|
|
58
|
+
|
|
59
|
+
export default [
|
|
60
|
+
{
|
|
61
|
+
...lube.configs.recommended,
|
|
62
|
+
files: ["**/*.js", "**/*.ts"],
|
|
63
|
+
languageOptions: { parser: tsParser }
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
```
|
|
67
|
+
With `defineConfig`, extend the config by name:
|
|
68
|
+
```js
|
|
69
|
+
// eslint.config.js
|
|
70
|
+
import { defineConfig } from "eslint/config"
|
|
71
|
+
import lube from "eslint-plugin-lube"
|
|
72
|
+
|
|
73
|
+
export default defineConfig({
|
|
74
|
+
extends: ["lube/recommended"],
|
|
75
|
+
files: ["**/*.js"],
|
|
76
|
+
plugins: { lube }
|
|
77
|
+
})
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Choosing a config
|
|
81
|
+
Both configs are flat config objects with `plugins` and `rules`, and differ in how much they decide for you. Start with `recommended`; take `strict` for a code base that follows the Svelte code conventions or wants every choice made for it.
|
|
82
|
+
|
|
83
|
+
**`configs.recommended`** only formats and orders, and every rule in it has a fix, so it suits format on save.
|
|
84
|
+
- The `@stylistic` formatting rules: tab indentation, double quotes, no semicolons, spacing and line breaks.
|
|
85
|
+
- `pretty-imports`, `pretty-jsdoc-casting`, `pretty-sequence` and `pretty-ternary`, with items on one line up to 80 characters.
|
|
86
|
+
- `ascii-order` for the names inside import and export braces only.
|
|
87
|
+
- A line break at the end of a file and at most one blank line, as editors write them.
|
|
88
|
+
- It never renames an identifier, never moves an import, key, function or test, and reports nothing about what the code does.
|
|
89
|
+
|
|
90
|
+
**`configs.strict`** is the house style of this repository, and several of its rules cannot be fixed. It is everything in `recommended` plus:
|
|
91
|
+
- `svelte-naming-convention`, which renames declarations to snake_case.
|
|
92
|
+
- `ascii-order` for import statements, object keys, function declarations and test cases too (see below).
|
|
93
|
+
- `pretty-sequence` and `pretty-imports` at 30 characters.
|
|
94
|
+
- No blank lines, no line break at the end of a file and one statement per line.
|
|
95
|
+
- Core rules such as `func-style` (declarations), `no-shadow`, `prefer-const`, `one-var` (never), `no-console` and `no-await-in-loop`.
|
|
96
|
+
|
|
97
|
+
In `strict`, `ascii-order` fixes import order assuming modules can run in any order, and key order assuming nothing reads it: sorted keys change `Object.keys`, `JSON.stringify` and `for...in`.
|
|
98
|
+
- Import a module that has to run first without names, `import "./setup.js"`, which is never moved.
|
|
99
|
+
- Disable the rule where key or import order matters; [ascii-order](https://github.com/artxe/lube-series/blob/master/packages/eslint-plugin-lube/docs/ascii-order.md) lists what it does not fix.
|
|
100
|
+
|
|
101
|
+
### Changing a rule
|
|
102
|
+
Override a rule after the spread: `rules: { ...lube.configs.recommended.rules, "@stylistic/indent": ["error", 4] }`.
|
|
103
|
+
- Formatting rules go by their `@stylistic/` name.
|
|
104
|
+
- An indentation of your own also goes to the `indent` option of `pretty-imports`, `pretty-sequence` and `pretty-ternary`, or those rules and `@stylistic/indent` keep rewriting each other's fixes.
|
|
105
|
+
- `pretty-sequence` writes the items of an array, object or call one per line once they are longer than its `maxLength` together, 80 in `recommended` and 30 in `strict`: `"lube/pretty-sequence": ["error", { maxLength: 100 }]`.
|
|
106
|
+
- Every option of a rule is checked, so a misspelled option is a configuration error.
|
|
107
|
+
|
|
108
|
+
## Rules
|
|
109
|
+
| Rule | Enforces | `recommended` |
|
|
110
|
+
| --- | --- | --- |
|
|
111
|
+
| [ascii-order](https://github.com/artxe/lube-series/blob/master/packages/eslint-plugin-lube/docs/ascii-order.md) | ASCII order of import statements, import and export names, object keys, function declarations and test cases | names only |
|
|
112
|
+
| [pretty-imports](https://github.com/artxe/lube-series/blob/master/packages/eslint-plugin-lube/docs/pretty-imports.md) | Import and export names on one line when they fit, or one per line | yes |
|
|
113
|
+
| [pretty-jsdoc-casting](https://github.com/artxe/lube-series/blob/master/packages/eslint-plugin-lube/docs/pretty-jsdoc-casting.md) | JSDoc type casts written as `/** @type {T} */(value)/**/` | yes |
|
|
114
|
+
| [pretty-sequence](https://github.com/artxe/lube-series/blob/master/packages/eslint-plugin-lube/docs/pretty-sequence.md) | Items of arrays, objects, calls and parameters on one line when they fit, or one per line | yes |
|
|
115
|
+
| [pretty-ternary](https://github.com/artxe/lube-series/blob/master/packages/eslint-plugin-lube/docs/pretty-ternary.md) | Nested and long ternaries broken before `?` and `:`, one indent deeper per level | yes |
|
|
116
|
+
| [svelte-naming-convention](https://github.com/artxe/lube-series/blob/master/packages/eslint-plugin-lube/docs/svelte-naming-convention.md) | snake_case declarations, following the Svelte code conventions | no |
|
|
117
|
+
|
|
118
|
+
## What it is not
|
|
119
|
+
- **Not a formatter you run on its own.** There is no CLI and no config file: the rules run inside `eslint --fix`, and a file ESLint does not lint is not formatted.
|
|
120
|
+
- **Not a whole style guide.** `recommended` only formats and orders, and every rule it turns on has a fix. The opinions, such as renaming and the core rules, are in `strict`, which is the house style of this repository rather than a recommendation.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# ascii-order
|
|
2
|
+
Sorts import statements, import and export names, object keys, function declarations and test cases in ASCII order, so uppercase before lowercase. The strict config turns all five on; the recommended config only sorts names inside import and export braces, which never changes what the code does.
|
|
3
|
+
|
|
4
|
+
- **Import statements** next to each other, by module path: `"../a.js"`, `"./b.js"`, `"c"`, `"node:d"`. Side-effect imports such as `import "polyfill"` keep their place and split the imports into groups.
|
|
5
|
+
- **Names** in import and export braces, by the name written first: `import def, { B, a as c }`, `export { a as z, b }`.
|
|
6
|
+
- **Keys** of object literals, destructuring patterns, TypeScript type literals and interfaces. Spread, rest, computed keys and index signatures split the keys into groups sorted on their own. Under `exports` and `imports` of a `package.json`, where conditions match in order, `types` goes first and `default` last, and the conditions between them are in ASCII order.
|
|
7
|
+
- **Function declarations** next to each other in the same block, TypeScript overloads included. A function exported with `export default name` keeps its place.
|
|
8
|
+
- **Test cases**: `describe`, `it` and `test` calls next to each other with a string title, `it.skip` and `test.only` included.
|
|
9
|
+
|
|
10
|
+
Comments on their own lines above an item and comments after it on the same line move with it.
|
|
11
|
+
Nested objects, patterns and braces are sorted in the same pass.
|
|
12
|
+
|
|
13
|
+
The fix assumes three things it cannot see, and changes behavior where they do not hold:
|
|
14
|
+
- **Modules evaluate in any order.** Moving an import statement changes the order in which its module and the modules it imports run their top-level code. A module whose top-level code has to run first, such as a polyfill or a setup file, is imported without names, `import "./setup.js"`, which the rule never moves and never moves another import across. Disable the rule for the other imports whose order matters.
|
|
15
|
+
- **Key order is not observed.** Sorting keys changes the order of `Object.keys`, `Object.entries`, `JSON.stringify` and `for...in`, so an object literal serialized or iterated in a written order changes its output, and a destructuring pattern reads the properties, running their getters, in the new order. Integer-like keys such as `2` and `10` are listed in numeric order by JavaScript anyway. A key written twice keeps its last value.
|
|
16
|
+
- **Tests do not depend on each other.**
|
|
17
|
+
|
|
18
|
+
Where the order matters, disable the rule for that statement, `// eslint-disable-next-line lube/ascii-order`, or turn off one kind with the options below.
|
|
19
|
+
|
|
20
|
+
Beyond that, only the error is reported, without a fix, when moving would change what the code evaluates or where comments end up. The message then says why and names the value that keeps it in place, as in ``Move key "a" before "b" to keep keys in ASCII order; it is not fixed automatically because moving `f()` could change the order of side effects, so reorder it by hand``:
|
|
21
|
+
- An object value that calls a function, constructs an object, assigns, updates, deletes, awaits or yields would change places with another value that is not a constant or a function. A variable is a constant when it is a `const`, a namespace import (`import * as x`), or a function or class declaration that is never assigned, and the value is the variable itself, also inside an array, `!x`, `typeof x`, `x === y`, `a ? x : y` or `x ?? y`; `x.y`, `` `${x}` ``, `-x`, `x + 1` and `...x` can run code of `x`. A `let`, `var`, parameter, global or named import, which the exporting module can reassign, still counts as a variable a call may change, so `{ b: f(), a: x }` is fixed only for such a constant `x`. A `const` or class counts only where the value comes after its declaration and not inside a function declaration, which can run before it: reading it earlier throws in its temporal dead zone, and moving the read before `f()` would throw before `f()` runs. Constructing a built-in counts as reading a variable: it reads the global of the constructor, which a call may replace, so it never moves across a call, while `{ updatedAt: new Date(), createdAt: new Date() }` and `{ s: new Set([ 1 ]), m: new Map() }` are fixed: `new` of `Array`, `ArrayBuffer`, `Date`, `Map`, `RegExp`, `Set`, `WeakMap`, `WeakSet`, the typed arrays such as `Uint8Array`, and `Error` and its subclasses except `AggregateError`, when the name is not declared in the file and every argument is built only from literals, `undefined`, `NaN`, `Infinity`, templates without expressions, negative numbers, array and object literals and such constructions, and when the construction does not throw with those arguments, which the rule tries while linting: `new RegExp("(")`, `new Array(-1)`, `new Set(1)`, `new Map([ 1 ])`, `new WeakSet([ 1 ])` and `new URL("/a")` would throw before the values moved in front of them run, and are not fixed. The runtime that lints is not the one that runs the code, so `new RegExp` is fixed only with the flags `g`, `i`, `m`, `s`, `u` and `y` and the syntax of ES2018: `new RegExp("a", "v")`, the `d` flag, modifiers such as `(?i:a)` and a group name used twice may throw in an older runtime, and are not fixed. The same goes for `DataView` and `URL`, as in `new DataView(new ArrayBuffer(8))` and `new URL("a", "https://example.com")`. An `Array`, `ArrayBuffer`, typed array or `DataView` with a number, a numeric string or an object property over 65536 in its arguments, as in `new Array(1e8)`, `new ArrayBuffer(8, { maxByteLength: 1e9 })` or `new Uint8Array({ length: 1e9 })`, is not tried and not fixed, since trying it would allocate that much while linting. Two `new Date()` values may then read the clock in the other order. `new Date(x)` and `new Set(items)` can run code of `x` and `items`, and are not fixed.
|
|
22
|
+
- A destructuring default that is not a constant would change places with another key.
|
|
23
|
+
- A destructuring target is assigned by two keys, or a member such as `this.a` would change places with another key.
|
|
24
|
+
- A comment shares a line with two items, or a line comment would end up before a closing bracket.
|
|
25
|
+
- The first statement of a file has comments before it and would move.
|
|
26
|
+
- A statement without a semicolon would end up on a line with the next one, as in `import b from "b"; import a from "a"`.
|
|
27
|
+
|
|
28
|
+
## options
|
|
29
|
+
```js
|
|
30
|
+
schema: [
|
|
31
|
+
{
|
|
32
|
+
additionalProperties: false,
|
|
33
|
+
properties: {
|
|
34
|
+
checkDeclarations: { default: true, type: "boolean" },
|
|
35
|
+
checkImports: { default: true, type: "boolean" },
|
|
36
|
+
checkKeys: { default: true, type: "boolean" },
|
|
37
|
+
checkNames: { default: true, type: "boolean" },
|
|
38
|
+
checkTests: { default: true, type: "boolean" }
|
|
39
|
+
},
|
|
40
|
+
type: "object"
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
```
|
|
44
|
+
### checkDeclarations
|
|
45
|
+
If it is `true`, it sorts function declarations.
|
|
46
|
+
### checkImports
|
|
47
|
+
If it is `true`, it sorts import statements.
|
|
48
|
+
### checkKeys
|
|
49
|
+
If it is `true`, it sorts object keys.
|
|
50
|
+
### checkNames
|
|
51
|
+
If it is `true`, it sorts the names in import and export braces.
|
|
52
|
+
### checkTests
|
|
53
|
+
If it is `true`, it sorts test cases.
|
|
54
|
+
|
|
55
|
+
## Valid
|
|
56
|
+
```js
|
|
57
|
+
import { A, B, a } from "a-module"
|
|
58
|
+
import value from "b-module"
|
|
59
|
+
const object = { a: 1, b: 2, ...rest, a_b: 3 }
|
|
60
|
+
function main() {}
|
|
61
|
+
function b() {}
|
|
62
|
+
function c() {}
|
|
63
|
+
export default main
|
|
64
|
+
it("a", () => {})
|
|
65
|
+
it("b", () => {})
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Invalid
|
|
69
|
+
```js
|
|
70
|
+
import other from "b-module"
|
|
71
|
+
import { y, x } from "a-module"
|
|
72
|
+
const value = { b: 1, a: 2 }
|
|
73
|
+
function b() {}
|
|
74
|
+
function a() {}
|
|
75
|
+
it("b", () => {})
|
|
76
|
+
it("a", () => {})
|
|
77
|
+
// reported without a fix: g() would run before f()
|
|
78
|
+
const later = { b: f(), a: g() }
|
|
79
|
+
// fixed: constructing a built-in from literals runs no code of the file
|
|
80
|
+
const empty = { s: new Set([ 1 ]), m: new Map() }
|
|
81
|
+
```
|
package/docs/pretty-imports.md
CHANGED
|
@@ -1,60 +1,71 @@
|
|
|
1
|
-
# pretty-imports
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
export {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
1
|
+
# pretty-imports
|
|
2
|
+
Formats import and export statements: the names on one line when they fit, or one per line. The order of imports is checked by [ascii-order](ascii-order.md).
|
|
3
|
+
|
|
4
|
+
- `import type`, `export type` and import attributes are kept, and a statement containing comments is not checked.
|
|
5
|
+
- A statement already written over several lines is left to `@stylistic/indent`, which owns the indentation of lines this rule did not write; `fixIndent` gives that back to this rule.
|
|
6
|
+
|
|
7
|
+
## options
|
|
8
|
+
```js
|
|
9
|
+
schema: [
|
|
10
|
+
{
|
|
11
|
+
additionalProperties: false,
|
|
12
|
+
properties: {
|
|
13
|
+
checkExports: { default: true, type: "boolean" },
|
|
14
|
+
checkImports: { default: true, type: "boolean" },
|
|
15
|
+
fixIndent: { default: false, type: "boolean" },
|
|
16
|
+
indent: { default: "\t", type: "string" },
|
|
17
|
+
maxLength: { default: 30, type: "number" },
|
|
18
|
+
semicolon: { default: false, type: "boolean" }
|
|
19
|
+
},
|
|
20
|
+
type: "object"
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
```
|
|
24
|
+
### checkExports
|
|
25
|
+
If it is `true`, it checks export statements.
|
|
26
|
+
### checkImports
|
|
27
|
+
If it is `true`, it checks import statements.
|
|
28
|
+
### fixIndent
|
|
29
|
+
If it is `true`, it also reports a statement whose lines differ from this rule only in their indentation. Leave it off while `@stylistic/indent` is on, or the two rules keep rewriting each other's fixes.
|
|
30
|
+
### indent
|
|
31
|
+
The string of one indentation level. Match it to `@stylistic/indent`, or the two rules keep rewriting each other's fixes.
|
|
32
|
+
### maxLength
|
|
33
|
+
The names are written one per line when they are longer than this together, commas and spaces not counted, a character that takes two columns counting as two.
|
|
34
|
+
```js
|
|
35
|
+
// If maxLength is less than or equal to 20, an error occurs.
|
|
36
|
+
export { fff, ggg, hhh, iii, jjj, kkk, lll } from 'module/2'
|
|
37
|
+
```
|
|
38
|
+
### semicolon
|
|
39
|
+
If it is `true`, insert a semicolon explicitly.
|
|
40
|
+
A semicolon that separates the statement from the next one on the same line is kept either way, and so is one that starts the next line, as `@stylistic/semi-style` writes it.
|
|
41
|
+
|
|
42
|
+
## Valid
|
|
43
|
+
```js
|
|
44
|
+
export { a, b as c, d } from 'module'
|
|
45
|
+
export { fff, ggg, hhh, iii, jjj, kkk, lll } from 'module/2'
|
|
46
|
+
import {
|
|
47
|
+
aaaaa_bbbbb,
|
|
48
|
+
aaaaa_ccccc,
|
|
49
|
+
aaaaa_ddddd
|
|
50
|
+
} from "module"
|
|
51
|
+
import def, { a, b } from "module/2"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Invalid
|
|
55
|
+
```js
|
|
56
|
+
export { a, b as c, d } from 'module';
|
|
57
|
+
export {e, f as g, h} from 'module'
|
|
58
|
+
export {
|
|
59
|
+
i,
|
|
60
|
+
j as k,
|
|
61
|
+
l
|
|
62
|
+
} from 'module'
|
|
63
|
+
import { aaaaa_bbbbb, aaaaa_ccccc, aaaaa_ddddd } from "module"
|
|
64
|
+
import def, {m, n} from "module/2"
|
|
65
|
+
// only with fixIndent: true
|
|
66
|
+
import {
|
|
67
|
+
aaaaa_eeeee,
|
|
68
|
+
aaaaa_fffff,
|
|
69
|
+
aaaaa_ggggg
|
|
70
|
+
} from "module"
|
|
60
71
|
```
|