@sinemacula/coding-standards 1.18.0 → 1.19.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/README.md +47 -38
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -88,8 +88,8 @@ parameters:
|
|
|
88
88
|
|
|
89
89
|
For Laravel projects, also install
|
|
90
90
|
[`sinemacula/coding-standards-laravel`](https://github.com/sinemacula/coding-standards-laravel) and reference its
|
|
91
|
-
`SineMaculaLaravel` PHPCS standard (which includes this one) in place of `SineMacula`. It adds the
|
|
92
|
-
|
|
91
|
+
`SineMaculaLaravel` PHPCS standard (which includes this one) in place of `SineMacula`. It adds the Laravel-specific
|
|
92
|
+
sniffs and PHPStan rules; see that package's README for setup.
|
|
93
93
|
|
|
94
94
|
### Biome (JavaScript / TypeScript)
|
|
95
95
|
|
|
@@ -114,9 +114,8 @@ After installing the npm package, extend the shared Biome config from your proje
|
|
|
114
114
|
}
|
|
115
115
|
```
|
|
116
116
|
|
|
117
|
-
`extends` paths are resolved through normal Node module lookup, so the package only needs to be installed (no path
|
|
118
|
-
|
|
119
|
-
config.
|
|
117
|
+
`extends` paths are resolved through normal Node module lookup, so the package only needs to be installed (no path math
|
|
118
|
+
against `node_modules/` required). Project-specific `files.includes` and `files.excludes` stay in the consumer config.
|
|
120
119
|
|
|
121
120
|
### ESLint (JavaScript / TypeScript)
|
|
122
121
|
|
|
@@ -136,9 +135,9 @@ The package exposes three flat-config entry points:
|
|
|
136
135
|
- `@sinemacula/coding-standards/js/eslint/type-checked` - the opt-in type-aware layer. It includes the base layer and
|
|
137
136
|
adds the cross-file / type-driven rules, so it needs a consumer `tsconfig`; use it in place of the base layer where
|
|
138
137
|
one exists.
|
|
139
|
-
- `@sinemacula/coding-standards/js/eslint/vue` - the opt-in Vue layer for single-file components. Unlike the
|
|
140
|
-
|
|
141
|
-
|
|
138
|
+
- `@sinemacula/coding-standards/js/eslint/vue` - the opt-in Vue layer for single-file components. Unlike the type-aware
|
|
139
|
+
layer it carries no base rules of its own, so spread it *alongside* whichever layer the repository already uses rather
|
|
140
|
+
than in place of one.
|
|
142
141
|
|
|
143
142
|
Create an `eslint.config.js` (or `.qlty/configs/eslint.config.js` when wired through Qlty) that spreads the layer you
|
|
144
143
|
want. Without a `tsconfig`, use the base layer:
|
|
@@ -171,23 +170,23 @@ export default [...typeChecked, ...vue];
|
|
|
171
170
|
```
|
|
172
171
|
|
|
173
172
|
The Vue layer registers the single-file-component parser (without it `.vue` files are not linted at all), resolves
|
|
174
|
-
`<script lang="ts">` blocks through the TypeScript parser, and holds component filenames to kebab-case. It also
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
173
|
+
`<script lang="ts">` blocks through the TypeScript parser, and holds component filenames to kebab-case. It also carries
|
|
174
|
+
the template layout rules, which is the one place ESLint takes on formatting: Biome does not understand single-file
|
|
175
|
+
components, so `.vue` markup would otherwise go unformatted entirely. Those rules are aligned to the shared four-space
|
|
176
|
+
indent.
|
|
178
177
|
|
|
179
178
|
When wiring ESLint through Qlty, the shared eslint plugin sandbox installs only `eslint`, `jest`, and `prettier` by
|
|
180
|
-
default, so the flat config's imports of this package and `typescript-eslint` fail to resolve. Widen the install
|
|
181
|
-
|
|
182
|
-
|
|
179
|
+
default, so the flat config's imports of this package and `typescript-eslint` fail to resolve. Widen the install filter
|
|
180
|
+
in your `.qlty/qlty.toml` so the sandbox carries them (this repository's `source.toml` exports the same override, but
|
|
181
|
+
source-exported plugin definitions do not reliably propagate, so mirror it consumer-side):
|
|
183
182
|
|
|
184
183
|
```toml
|
|
185
184
|
[plugins.definitions.eslint]
|
|
186
185
|
package_filters = ["@sinemacula/coding-standards", "typescript-eslint", "@typescript-eslint", "eslint-plugin-jsdoc"]
|
|
187
186
|
```
|
|
188
187
|
|
|
189
|
-
Repositories enabling the Vue layer widen the same filter further, since its plugins have to resolve inside that
|
|
190
|
-
|
|
188
|
+
Repositories enabling the Vue layer widen the same filter further, since its plugins have to resolve inside that sandbox
|
|
189
|
+
too:
|
|
191
190
|
|
|
192
191
|
```toml
|
|
193
192
|
[plugins.definitions.eslint]
|
|
@@ -206,17 +205,25 @@ package (as above) and extend the base from your `tsconfig.json`:
|
|
|
206
205
|
{
|
|
207
206
|
"extends": "@sinemacula/coding-standards/js/tsconfig.base.json",
|
|
208
207
|
"compilerOptions": {
|
|
209
|
-
"lib": [
|
|
210
|
-
|
|
208
|
+
"lib": [
|
|
209
|
+
"ES2023",
|
|
210
|
+
"DOM",
|
|
211
|
+
"DOM.Iterable"
|
|
212
|
+
],
|
|
213
|
+
"types": [
|
|
214
|
+
"node"
|
|
215
|
+
]
|
|
211
216
|
},
|
|
212
|
-
"include": [
|
|
217
|
+
"include": [
|
|
218
|
+
"src"
|
|
219
|
+
]
|
|
213
220
|
}
|
|
214
221
|
```
|
|
215
222
|
|
|
216
|
-
The base carries only the environment-independent options: the full strictness set and the module/resolution
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
223
|
+
The base carries only the environment-independent options: the full strictness set and the module/resolution discipline.
|
|
224
|
+
Everything environment-specific stays in the consuming repo and layers on top - `lib` (DOM for the browser, none for a
|
|
225
|
+
Node service), `types`, Vue's `jsx`/`jsxImportSource`, `paths`, `noEmit`, and the `include`/`exclude` globs. The`target`
|
|
226
|
+
and `module` defaults suit bundler-built apps and libraries; a non-bundler project overrides them.
|
|
220
227
|
|
|
221
228
|
The base sets `noPropertyAccessFromIndexSignature`, so a property that comes from an index signature is accessed with
|
|
222
229
|
brackets (`config['key']`), not a dot. Biome cannot see types and so cannot tell that access apart from a normal one,
|
|
@@ -275,6 +282,7 @@ native directive - `// phpcs:ignore <code>` for a sniff, `@phpstan-ignore <ident
|
|
|
275
282
|
|------------------------------------------------------------|-----------------------------------------------------------------------------|
|
|
276
283
|
| `SineMacula.Attributes.DisallowToolingAttribute` | No IDE/tooling attributes (e.g. `JetBrains\PhpStorm`). |
|
|
277
284
|
| `SineMacula.Classes.RequireFinalClass` | Concrete classes must be `final` or `abstract` (`@inheritable` opts out). |
|
|
285
|
+
| `SineMacula.Classes.RequireReadonlyClass` | A class with only `readonly` properties (no statics) must be `readonly`. |
|
|
278
286
|
| `SineMacula.Classes.RequireReadonlyPublicProperty` | Public properties (declared or promoted) must be `readonly`. |
|
|
279
287
|
| `SineMacula.Commenting.CommentLineLength` | Standalone comment prose wrapped to 80 chars; premature wraps also fixed. |
|
|
280
288
|
| `SineMacula.Commenting.ConsistentEnumCaseComments` | Enum case docs are all-or-nothing within an enum. |
|
|
@@ -296,6 +304,7 @@ native directive - `// phpcs:ignore <code>` for a sniff, `@phpstan-ignore <ident
|
|
|
296
304
|
| `SineMacula.NamingConventions.DisallowInterfacePrefix` | Interface names must not use the Hungarian `I` prefix. |
|
|
297
305
|
| `SineMacula.NamingConventions.ValidEnumCaseName` | Enum cases must be `SCREAMING_SNAKE_CASE`. |
|
|
298
306
|
| `SineMacula.NamingConventions.ValidGlobalFunctionName` | Global functions must be declared in `snake_case`. |
|
|
307
|
+
| `SineMacula.TypeHints.DisallowFullyQualifiedConstantType` | Constant types must be imported, not inline fully-qualified names. |
|
|
299
308
|
| `SineMacula.TypeHints.RequireConstantType` | Class/interface/enum/trait constants must declare a native type. |
|
|
300
309
|
| `SineMacula.WhiteSpace.PromotedConstructorSpacing` | Blank line above each promoted-constructor parameter. |
|
|
301
310
|
|
|
@@ -327,28 +336,28 @@ type-checked layer.
|
|
|
327
336
|
|
|
328
337
|
`boolean-method-name` takes `additionalPrefixes`, `additionalPredicates` and `additionalCommandVerbs` (string arrays)
|
|
329
338
|
to widen the accepted vocabulary from a consumer config. `max-methods-per-class` takes `max`, `no-base-error` takes
|
|
330
|
-
`allow`, and `require-copyright` takes `tags` to adjust their defaults. `align-doc-tags` takes `tags` and `column`,
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
339
|
+
`allow`, and `require-copyright` takes `tags` to adjust their defaults. `align-doc-tags` takes `tags` and `column`, the
|
|
340
|
+
column counting from the `@`, so the default of 14 gives `@author` six spaces and `@copyright` three. Together
|
|
341
|
+
`single-line-property-doc` and `multiline-function-doc` set a member's comment shape by its kind: data members
|
|
342
|
+
(interface property signatures, enum members and data class fields) take one line, while methods, interface method
|
|
343
|
+
signatures and class fields holding a function take several. A data comment is never required, only held to one line
|
|
344
|
+
where present; a free function keeps the freedom of either shape.
|
|
336
345
|
|
|
337
346
|
`comment-line-wrap` takes `maxLength` (default 80) and is the syntax-only counterpart of the PHP
|
|
338
347
|
`SineMacula.Commenting.CommentLineLength` sniff. It fills standalone `//` runs and multi-line docblock prose greedily,
|
|
339
348
|
reporting an overflowing line and a prematurely wrapped line on their own footings and autofixing both. Markdown
|
|
340
349
|
headings, docblock tag lines, machine-parsed tool directives (`eslint`, `biome-ignore`, `@ts-`, `Stryker`, `c8`/`v8`/
|
|
341
|
-
`istanbul ignore`, `@vite-ignore` and the like), fenced code, an indented code or command block, a doc-tag whose
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
350
|
+
`istanbul ignore`, `@vite-ignore` and the like), fenced code, an indented code or command block, a doc-tag whose value
|
|
351
|
+
opens a multi-line bracketed type (an `array{...}` shape, a `<...>` generic or a `\Closure(...)` signature), tables,
|
|
352
|
+
separators, a line whose overflow is a single unbreakable token such as a long name or URL, trailing comments after code
|
|
353
|
+
and compact single-line docblocks are left untouched.
|
|
345
354
|
|
|
346
355
|
The base layer also switches on a set of built-in rules: `@typescript-eslint/no-explicit-any`, `curly` (a brace on every
|
|
347
356
|
control statement, as PSR-12 already requires on the PHP side), `max-lines-per-function` (50 lines, test code exempt)
|
|
348
|
-
and `max-depth` (4), plus `eslint-plugin-jsdoc` rules that require a documentation comment
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
357
|
+
and `max-depth` (4), plus `eslint-plugin-jsdoc` rules that require a documentation comment on every declared function,
|
|
358
|
+
method, class, interface member and class field, forbid types in `@param`/`@returns` (the tags themselves are welcome,
|
|
359
|
+
types belong in the signature) and keep a blank line above every documentation block, single-line blocks included. The
|
|
360
|
+
type-checked layer adds `@typescript-eslint/explicit-module-boundary-types` and
|
|
352
361
|
`@typescript-eslint/only-throw-error`.
|
|
353
362
|
|
|
354
363
|
## Requirements
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sinemacula/coding-standards",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.0",
|
|
4
4
|
"description": "Centralized coding standards, static analysis configurations, and code quality tooling for all Sine Macula repositories.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Ben Carey <bdmc@sinemacula.co.uk>",
|