@antelopejs/tooling-configs 0.0.1
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 +225 -0
- package/dist/eslint.d.mts +34 -0
- package/dist/eslint.mjs +46 -0
- package/dist/knip.d.mts +25 -0
- package/dist/knip.mjs +30 -0
- package/dist/oxc/anti-slop/index.d.mts +5 -0
- package/dist/oxc/anti-slop/index.mjs +1524 -0
- package/dist/oxc/fmt.d.mts +108 -0
- package/dist/oxc/fmt.mjs +52 -0
- package/dist/oxc/lint.d.mts +175 -0
- package/dist/oxc/lint.mjs +179 -0
- package/dist/shared-DYvliWWW.mjs +28 -0
- package/package.json +86 -0
package/README.md
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# @antelopejs/tooling-configs
|
|
2
|
+
|
|
3
|
+
Shared tooling presets for AntelopeJS repositories: [oxlint](https://oxc.rs) (including
|
|
4
|
+
the vendored [anti-slop](https://github.com/dmmulroy/anti-slop) rules), [oxfmt](https://oxc.rs)
|
|
5
|
+
and [Knip](https://knip.dev).
|
|
6
|
+
|
|
7
|
+
Together they replace Biome outright — lint, format and import order — and Prettier in the
|
|
8
|
+
Nuxt layers, since oxfmt formats `.vue` and sorts Tailwind classes natively. The front end
|
|
9
|
+
keeps ESLint for linting, from a shared config here.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
Node **24** (or at least 22.18). oxlint reads `oxlint.config.ts` and loads JS plugins by
|
|
14
|
+
executing TypeScript, which earlier runtimes cannot do.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
The package is not on npm yet. Until it is, consume it straight from this repository:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm add -D oxlint@1.81.0 oxfmt "github:AntelopeJS/tooling-configs"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Add `eslint-plugin-perfectionist` too unless you turn import sorting off — it is an
|
|
25
|
+
optional peer dependency because it pulls ESLint and typescript-eslint along with it:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pnpm add -D eslint-plugin-perfectionist
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`dist/` is committed for exactly as long as that install path lasts: pnpm 11 refuses to
|
|
32
|
+
run a git dependency's build unless every consumer allowlists it by commit hash, which
|
|
33
|
+
would break on every push here. CI fails if the committed build is stale. When the
|
|
34
|
+
package reaches npm, delete `dist/` from git, restore the `prepare` script, and change
|
|
35
|
+
consumers from `github:AntelopeJS/tooling-configs` to a version range — the import
|
|
36
|
+
specifiers never change.
|
|
37
|
+
|
|
38
|
+
Pin `oxlint` to the exact version this package depends on for `@oxlint/plugins`
|
|
39
|
+
(currently **1.81.0**). The JS plugin API is still alpha and the two packages must move
|
|
40
|
+
together. Once the package is published, this becomes a normal version range.
|
|
41
|
+
|
|
42
|
+
## oxlint
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
// oxlint.config.ts
|
|
46
|
+
import { defineConfig } from "oxlint";
|
|
47
|
+
import { antelopePreset } from "@antelopejs/tooling-configs/oxc/lint";
|
|
48
|
+
|
|
49
|
+
export default defineConfig({
|
|
50
|
+
extends: [antelopePreset()],
|
|
51
|
+
// Only read from the root config, never from a preset.
|
|
52
|
+
options: { typeAware: true },
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```jsonc
|
|
57
|
+
// package.json
|
|
58
|
+
{
|
|
59
|
+
"scripts": {
|
|
60
|
+
"lint": "oxlint",
|
|
61
|
+
"lint:fix": "oxlint --fix",
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Type-aware rules (`typescript/no-floating-promises`) also need the tsgolint binary:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pnpm add -D oxlint-tsgolint
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### What the preset turns on
|
|
73
|
+
|
|
74
|
+
| Group | Contents |
|
|
75
|
+
| -------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
76
|
+
| oxc defaults | the `correctness` category, plus the `eslint`, `typescript`, `node`, `oxc`, `import` and `promise` plugins |
|
|
77
|
+
| imports | `import/no-cycle`, `import/no-self-import`, `import/no-duplicates` as errors |
|
|
78
|
+
| | (a repository with existing cycles starts with `importCycles: "warn"`) |
|
|
79
|
+
| import sorting | `perfectionist/sort-imports`, autofixed by `oxlint --fix` |
|
|
80
|
+
| complexity | `max-params` 5, `max-lines-per-function` 120, `max-lines` 500, `max-depth` 4, `complexity` 20 — as warnings |
|
|
81
|
+
| anti-slop | all 15 generic rules, as warnings |
|
|
82
|
+
| type-aware | `typescript/no-floating-promises` as an error |
|
|
83
|
+
|
|
84
|
+
### Options
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
antelopePreset({
|
|
88
|
+
antiSlop: "error", // "warn" (default) | "error" | false
|
|
89
|
+
importCycles: "warn", // "error" (default) | "warn" | false
|
|
90
|
+
complexity: { maxParams: 8 }, // override thresholds, or false
|
|
91
|
+
importSorting: false, // leave imports alone
|
|
92
|
+
typeAware: false, // no tsgolint in this repository
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`correctness` is raised to error deliberately. oxlint reports it as warnings, and warnings
|
|
97
|
+
do not fail the command — a preset that left it alone could never fail a pipeline, while
|
|
98
|
+
Biome was failing the build on the same rules.
|
|
99
|
+
|
|
100
|
+
`antiSlop` and `complexity` default to warnings on purpose: a repository adopting them
|
|
101
|
+
has findings to work through, and a red pipeline on day one teaches the team to ignore
|
|
102
|
+
the pipeline. Raise them to `"error"` once the backlog is clear.
|
|
103
|
+
|
|
104
|
+
### Adding your own ignore patterns
|
|
105
|
+
|
|
106
|
+
oxlint does not merge `ignorePatterns` across `extends`. A root config that declares its
|
|
107
|
+
own **replaces** the preset's, so spread them:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
import {
|
|
111
|
+
ANTELOPE_IGNORE_PATTERNS,
|
|
112
|
+
antelopePreset,
|
|
113
|
+
} from "@antelopejs/tooling-configs/oxc/lint";
|
|
114
|
+
|
|
115
|
+
export default defineConfig({
|
|
116
|
+
extends: [antelopePreset()],
|
|
117
|
+
ignorePatterns: [...ANTELOPE_IGNORE_PATTERNS, "playground/**"],
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## oxfmt
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
// oxfmt.config.ts
|
|
125
|
+
import { antelopeFmtPreset } from "@antelopejs/tooling-configs/oxc/fmt";
|
|
126
|
+
|
|
127
|
+
export default antelopeFmtPreset();
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
```jsonc
|
|
131
|
+
// package.json
|
|
132
|
+
{
|
|
133
|
+
"scripts": {
|
|
134
|
+
"format": "oxfmt .",
|
|
135
|
+
"format:check": "oxfmt --check .",
|
|
136
|
+
},
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### The house style
|
|
141
|
+
|
|
142
|
+
| Option | Value |
|
|
143
|
+
| ---------------------- | ---------- |
|
|
144
|
+
| `printWidth` | 80 |
|
|
145
|
+
| `tabWidth` / `useTabs` | 2 / spaces |
|
|
146
|
+
| `semi` | true |
|
|
147
|
+
| `singleQuote` | false |
|
|
148
|
+
| `trailingComma` | `"all"` |
|
|
149
|
+
|
|
150
|
+
Every field is set explicitly, including those that already match oxfmt's defaults.
|
|
151
|
+
Repositories carry `.editorconfig` files that contradict each other — five declare tabs,
|
|
152
|
+
two declare spaces, which is why the codebases drifted apart in the first place — and
|
|
153
|
+
oxfmt falls back to `.editorconfig` for any field a config leaves unset. Stating all of
|
|
154
|
+
them is what makes the style identical everywhere. Fix the repository's `.editorconfig`
|
|
155
|
+
to match anyway, so editors agree with the formatter.
|
|
156
|
+
|
|
157
|
+
Import order is not part of it: `perfectionist/sort-imports` owns that on the lint side.
|
|
158
|
+
Enabling oxfmt's `sortImports` as well would have two tools sorting the same imports
|
|
159
|
+
differently, each undoing the other on every save.
|
|
160
|
+
|
|
161
|
+
Extra ignores are **added** to the shared ones rather than replacing them, so a repository
|
|
162
|
+
adopting oxfmt in stages can park a directory without losing the rest:
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
export default antelopeFmtPreset({ ignorePatterns: ["nuxt-layer/**"] });
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
In a Nuxt layer, pass the theme stylesheet to replace `prettier-plugin-tailwindcss`:
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
export default antelopeFmtPreset({
|
|
172
|
+
tailwindStylesheet: "./assets/css/main.css",
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Replacing Biome
|
|
177
|
+
|
|
178
|
+
Per repository: delete `biome.json` and the `@biomejs/biome` dependency, point `lint`,
|
|
179
|
+
`lint:fix` and `format` at oxlint and oxfmt, and port anything the Biome config carried
|
|
180
|
+
that the preset does not (`noRestrictedImports` guards become `import/no-cycle`). Reformat
|
|
181
|
+
in its own commit and record it in `.git-blame-ignore-revs`, which GitHub honours, so the
|
|
182
|
+
pass does not bury the history.
|
|
183
|
+
|
|
184
|
+
## ESLint (Nuxt layers)
|
|
185
|
+
|
|
186
|
+
oxlint does not lint `.vue` files yet, so the front end stays on ESLint:
|
|
187
|
+
|
|
188
|
+
```js
|
|
189
|
+
// nuxt-layer/eslint.config.mjs
|
|
190
|
+
import { antelopeNuxtConfig } from "@antelopejs/tooling-configs/eslint";
|
|
191
|
+
|
|
192
|
+
export default antelopeNuxtConfig({ dirs: ["./playground"] });
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
`@nuxt/eslint` supplies the Vue and TypeScript rules; the preset only records where
|
|
196
|
+
AntelopeJS layers differ from it — single-word page components, `any` and `{}` as
|
|
197
|
+
load-bearing types in the interface layer, `_`-prefixed unused bindings, and import order
|
|
198
|
+
left to the formatter.
|
|
199
|
+
|
|
200
|
+
Formatting rules are deliberately absent, `vue/max-attributes-per-line` included: oxfmt
|
|
201
|
+
formats `.vue`, and a lint rule that also reflows markup would fight it on every save.
|
|
202
|
+
Declare `@nuxt/eslint-config` explicitly — nine layers use it today through
|
|
203
|
+
`@nuxt/eslint` without declaring it.
|
|
204
|
+
|
|
205
|
+
## Knip
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
// knip.config.ts
|
|
209
|
+
import { antelopeKnipConfig } from "@antelopejs/tooling-configs/knip";
|
|
210
|
+
|
|
211
|
+
export default antelopeKnipConfig();
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
The defaults declare what Knip cannot infer for an AntelopeJS module: `src/index.ts` and
|
|
215
|
+
the interface subpaths as public API, and `src/test/**/*.test.ts` as entry points, since
|
|
216
|
+
`ajs module test` is not a runner Knip has a plugin for. Without them, Knip reports the
|
|
217
|
+
whole test suite as dead code.
|
|
218
|
+
|
|
219
|
+
## Vendored anti-slop
|
|
220
|
+
|
|
221
|
+
`src/oxc/anti-slop/` is a copy of upstream, kept byte-identical so it can be diffed
|
|
222
|
+
against new releases. See `src/oxc/anti-slop/VENDORED.md` for the commit it came from and
|
|
223
|
+
any local edits. It is excluded from this repository's own formatting and linting.
|
|
224
|
+
|
|
225
|
+
Upstream is MIT (`src/oxc/anti-slop/LICENSE`); the rest of this repository is Apache-2.0.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createConfigForNuxt } from "@nuxt/eslint-config/flat";
|
|
2
|
+
//#region src/eslint.d.ts
|
|
3
|
+
/** The rule map `overrideRules` accepts, derived so no transitive type is named. */
|
|
4
|
+
type NuxtRules = Parameters<ReturnType<typeof createConfigForNuxt>["overrideRules"]>[0];
|
|
5
|
+
interface AntelopeNuxtConfigOptions {
|
|
6
|
+
/** Extra source directories for the Nuxt config, e.g. `["./playground"]`. */
|
|
7
|
+
dirs?: string[];
|
|
8
|
+
/** Rules layered on top of the shared set. */
|
|
9
|
+
rules?: NuxtRules;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The shared rules for a Nuxt layer. oxlint does not lint `.vue` files yet, so
|
|
13
|
+
* the front end stays on ESLint, and `@nuxt/eslint` supplies the Vue and
|
|
14
|
+
* TypeScript rules; this only records where AntelopeJS layers differ from it.
|
|
15
|
+
*
|
|
16
|
+
* Formatting rules are deliberately absent. oxfmt formats `.vue`, and a lint
|
|
17
|
+
* rule that also reflows markup (`vue/max-attributes-per-line`, which eight
|
|
18
|
+
* layers carry today) would fight it on every save.
|
|
19
|
+
*/
|
|
20
|
+
declare const ANTELOPE_NUXT_RULES: NuxtRules;
|
|
21
|
+
/**
|
|
22
|
+
* ESLint config for an AntelopeJS Nuxt layer.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```js
|
|
26
|
+
* // eslint.config.mjs
|
|
27
|
+
* import { antelopeNuxtConfig } from "@antelopejs/tooling-configs/eslint";
|
|
28
|
+
*
|
|
29
|
+
* export default antelopeNuxtConfig({ dirs: ["./playground"] });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
declare function antelopeNuxtConfig(options?: AntelopeNuxtConfigOptions): ReturnType<typeof createConfigForNuxt>;
|
|
33
|
+
//#endregion
|
|
34
|
+
export { ANTELOPE_NUXT_RULES, AntelopeNuxtConfigOptions, antelopeNuxtConfig };
|
package/dist/eslint.mjs
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { createConfigForNuxt } from "@nuxt/eslint-config/flat";
|
|
2
|
+
//#region src/eslint.ts
|
|
3
|
+
/**
|
|
4
|
+
* The shared rules for a Nuxt layer. oxlint does not lint `.vue` files yet, so
|
|
5
|
+
* the front end stays on ESLint, and `@nuxt/eslint` supplies the Vue and
|
|
6
|
+
* TypeScript rules; this only records where AntelopeJS layers differ from it.
|
|
7
|
+
*
|
|
8
|
+
* Formatting rules are deliberately absent. oxfmt formats `.vue`, and a lint
|
|
9
|
+
* rule that also reflows markup (`vue/max-attributes-per-line`, which eight
|
|
10
|
+
* layers carry today) would fight it on every save.
|
|
11
|
+
*/
|
|
12
|
+
const ANTELOPE_NUXT_RULES = {
|
|
13
|
+
"import/first": "off",
|
|
14
|
+
"import/order": "off",
|
|
15
|
+
"vue/multi-word-component-names": "off",
|
|
16
|
+
"vue/require-default-prop": "off",
|
|
17
|
+
"@typescript-eslint/no-explicit-any": "off",
|
|
18
|
+
"@typescript-eslint/no-empty-object-type": "off",
|
|
19
|
+
"@typescript-eslint/no-unused-vars": ["error", {
|
|
20
|
+
argsIgnorePattern: "^_",
|
|
21
|
+
varsIgnorePattern: "^_",
|
|
22
|
+
caughtErrorsIgnorePattern: "^_"
|
|
23
|
+
}]
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* ESLint config for an AntelopeJS Nuxt layer.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```js
|
|
30
|
+
* // eslint.config.mjs
|
|
31
|
+
* import { antelopeNuxtConfig } from "@antelopejs/tooling-configs/eslint";
|
|
32
|
+
*
|
|
33
|
+
* export default antelopeNuxtConfig({ dirs: ["./playground"] });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
function antelopeNuxtConfig(options = {}) {
|
|
37
|
+
return createConfigForNuxt({
|
|
38
|
+
features: { tooling: true },
|
|
39
|
+
dirs: { src: options.dirs ?? [] }
|
|
40
|
+
}).overrideRules({
|
|
41
|
+
...ANTELOPE_NUXT_RULES,
|
|
42
|
+
...options.rules
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
export { ANTELOPE_NUXT_RULES, antelopeNuxtConfig };
|
package/dist/knip.d.mts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { KnipConfig } from "knip";
|
|
2
|
+
//#region src/knip.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Knip finds files, exports and dependencies nothing reaches any more. Its
|
|
5
|
+
* defaults assume a conventional entry point, which an AntelopeJS module does
|
|
6
|
+
* not have: the runtime loads `src/index.ts` and every interface subpath, and
|
|
7
|
+
* `ajs module test` runs the compiled test tree rather than a test runner Knip
|
|
8
|
+
* knows about. Without those declared, Knip reports the whole test suite as
|
|
9
|
+
* dead code.
|
|
10
|
+
*/
|
|
11
|
+
interface AntelopeKnipOptions {
|
|
12
|
+
/** Extra entry points, appended to the AntelopeJS defaults. */
|
|
13
|
+
entry?: string[];
|
|
14
|
+
/** Extra project files to analyse, appended to the AntelopeJS defaults. */
|
|
15
|
+
project?: string[];
|
|
16
|
+
/** Dependencies Knip cannot see (loaded by the runtime, a CLI, or a config). */
|
|
17
|
+
ignoreDependencies?: string[];
|
|
18
|
+
/** Paths to leave out entirely. */
|
|
19
|
+
ignore?: string[];
|
|
20
|
+
/** Binaries Knip cannot resolve, appended to the AntelopeJS defaults. */
|
|
21
|
+
ignoreBinaries?: string[];
|
|
22
|
+
}
|
|
23
|
+
declare function antelopeKnipConfig(options?: AntelopeKnipOptions): KnipConfig;
|
|
24
|
+
//#endregion
|
|
25
|
+
export { AntelopeKnipOptions, antelopeKnipConfig };
|
package/dist/knip.mjs
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region src/knip.ts
|
|
2
|
+
const DEFAULT_ENTRY = [
|
|
3
|
+
"src/interfaces/**/*.ts",
|
|
4
|
+
"src/test/**/*.test.ts",
|
|
5
|
+
"scripts/**/*.{ts,mjs}"
|
|
6
|
+
];
|
|
7
|
+
const DEFAULT_PROJECT = ["src/**/*.ts", "scripts/**/*.{ts,mjs}"];
|
|
8
|
+
const DEFAULT_IGNORE = [
|
|
9
|
+
"dist/**",
|
|
10
|
+
"nuxt-layer/**",
|
|
11
|
+
"playground/**",
|
|
12
|
+
".antelope/**"
|
|
13
|
+
];
|
|
14
|
+
/**
|
|
15
|
+
* Every layer's CI runs `cd nuxt-layer && pnpm typecheck`. Knip parses the
|
|
16
|
+
* workflow, sees a binary it cannot resolve, and reports it: the script lives in
|
|
17
|
+
* the layer's own package.json, outside the analysed project.
|
|
18
|
+
*/
|
|
19
|
+
const DEFAULT_IGNORE_BINARIES = ["typecheck"];
|
|
20
|
+
function antelopeKnipConfig(options = {}) {
|
|
21
|
+
return {
|
|
22
|
+
entry: [...DEFAULT_ENTRY, ...options.entry ?? []],
|
|
23
|
+
project: [...DEFAULT_PROJECT, ...options.project ?? []],
|
|
24
|
+
ignore: [...DEFAULT_IGNORE, ...options.ignore ?? []],
|
|
25
|
+
ignoreDependencies: options.ignoreDependencies ?? [],
|
|
26
|
+
ignoreBinaries: [...DEFAULT_IGNORE_BINARIES, ...options.ignoreBinaries ?? []]
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { antelopeKnipConfig };
|