@st1ggy/linter-config 7.4.0 → 8.0.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.
@@ -34,6 +34,7 @@
34
34
  "engines": {
35
35
  "oxlint": "1.86.0",
36
36
  "oxlint-tsgolint": "7.0.2003",
37
+ "oxfmt": "0.71.0",
37
38
  "@typescript/native": "7.0.2"
38
39
  },
39
40
  "decisions": {
@@ -5476,22 +5477,23 @@
5476
5477
  "implementation": "js-plugin",
5477
5478
  "evidence": "module:preserve-caught-error:f29315f7e300"
5478
5479
  },
5479
- "module:prettier/prettier:038966de9f6b": {
5480
+ "module:prettier/prettier:038966de9f6b:oxfmt": {
5480
5481
  "sourceId": "prettier/prettier",
5481
5482
  "sourceValue": [
5482
5483
  2
5483
5484
  ],
5484
5485
  "domain": "module",
5485
5486
  "documentation": "https://github.com/prettier/eslint-plugin-prettier#options",
5486
- "status": "js-plugin",
5487
- "targetId": "prettier/prettier",
5487
+ "status": "formatter",
5488
+ "implementation": "formatter",
5489
+ "formatter": "oxfmt",
5490
+ "skipConfiguration": true,
5491
+ "targetId": "oxfmt/check",
5488
5492
  "targetValue": [
5489
5493
  2
5490
5494
  ],
5491
- "typeAware": false,
5492
- "reason": "No native equivalent is registered; use the original JS rule.",
5493
- "implementation": "js-plugin",
5494
- "evidence": "module:prettier/prettier:038966de9f6b"
5495
+ "evidence": "capability:oxfmt-check",
5496
+ "reason": "Formatting is checked separately by Oxfmt using the migrated common formatter options. No Prettier rule is executed inside Oxlint for this stack."
5495
5497
  },
5496
5498
  "module:quote-props:d0bca111f862": {
5497
5499
  "sourceId": "quote-props",
@@ -22430,23 +22432,23 @@
22430
22432
  "evidence": "module:preserve-caught-error:f29315f7e300",
22431
22433
  "limitation": "script-extraction"
22432
22434
  },
22433
- "vue:prettier/prettier:038966de9f6b": {
22435
+ "vue:prettier/prettier:038966de9f6b:oxfmt": {
22434
22436
  "sourceId": "prettier/prettier",
22435
22437
  "sourceValue": [
22436
22438
  2
22437
22439
  ],
22438
22440
  "domain": "vue",
22439
22441
  "documentation": "https://github.com/prettier/eslint-plugin-prettier#options",
22440
- "status": "partial",
22441
- "targetId": "prettier/prettier",
22442
+ "status": "formatter",
22443
+ "implementation": "formatter",
22444
+ "formatter": "oxfmt",
22445
+ "skipConfiguration": true,
22446
+ "targetId": "oxfmt/check",
22442
22447
  "targetValue": [
22443
22448
  2
22444
22449
  ],
22445
- "typeAware": false,
22446
- "reason": "The implementation is exercised on JS/TS fixtures and runs on extracted scripts here; template AST, bindings and whole-component equivalence are not provided by Oxlint.",
22447
- "implementation": "js-plugin",
22448
- "evidence": "module:prettier/prettier:038966de9f6b",
22449
- "limitation": "script-extraction"
22450
+ "evidence": "capability:oxfmt-check",
22451
+ "reason": "Formatting is checked separately by Oxfmt using the migrated common formatter options. No Prettier rule is executed inside Oxlint for this stack."
22450
22452
  },
22451
22453
  "vue:quote-props:d0bca111f862": {
22452
22454
  "sourceId": "quote-props",
@@ -56265,6 +56267,23 @@
56265
56267
  "limitation": "script-extraction",
56266
56268
  "reason": "The implementation is exercised on JS/TS fixtures and runs on extracted scripts here; template AST, bindings and whole-component equivalence are not provided by Oxlint."
56267
56269
  },
56270
+ "module:prettier/prettier:038966de9f6b": {
56271
+ "sourceId": "prettier/prettier",
56272
+ "sourceValue": [
56273
+ 2
56274
+ ],
56275
+ "domain": "module",
56276
+ "documentation": "https://github.com/prettier/eslint-plugin-prettier#options",
56277
+ "status": "js-plugin",
56278
+ "targetId": "prettier/prettier",
56279
+ "targetValue": [
56280
+ 2
56281
+ ],
56282
+ "typeAware": false,
56283
+ "reason": "No native equivalent is registered; use the original JS rule.",
56284
+ "implementation": "js-plugin",
56285
+ "evidence": "module:prettier/prettier:038966de9f6b"
56286
+ },
56268
56287
  "module:svelte/comment-directive:038966de9f6b": {
56269
56288
  "sourceId": "svelte/comment-directive",
56270
56289
  "sourceValue": [
@@ -56760,6 +56779,24 @@
56760
56779
  "limitation": "framework-template",
56761
56780
  "evidence": "capability:framework-template"
56762
56781
  },
56782
+ "vue:prettier/prettier:038966de9f6b": {
56783
+ "sourceId": "prettier/prettier",
56784
+ "sourceValue": [
56785
+ 2
56786
+ ],
56787
+ "domain": "vue",
56788
+ "documentation": "https://github.com/prettier/eslint-plugin-prettier#options",
56789
+ "status": "partial",
56790
+ "targetId": "prettier/prettier",
56791
+ "targetValue": [
56792
+ 2
56793
+ ],
56794
+ "typeAware": false,
56795
+ "reason": "The implementation is exercised on JS/TS fixtures and runs on extracted scripts here; template AST, bindings and whole-component equivalence are not provided by Oxlint.",
56796
+ "implementation": "js-plugin",
56797
+ "evidence": "module:prettier/prettier:038966de9f6b",
56798
+ "limitation": "script-extraction"
56799
+ },
56763
56800
  "vue:svelte/comment-directive:038966de9f6b": {
56764
56801
  "sourceId": "svelte/comment-directive",
56765
56802
  "sourceValue": [
@@ -2,20 +2,24 @@
2
2
 
3
3
  Generated by `npm run inventory:ox`. Runtime configuration is generated from the checked source inventory and migration policy.
4
4
 
5
- Only Oxlint executes the new presets. Native typed rules use tsgolint/TypeScript 7. JS plugins do not receive a TS6 Program.
5
+ Code checks run through Oxlint and tsgolint/TypeScript 7. Formatting uses a separate Oxfmt check for common/react/solid/next-ox and Prettier for svelte/astro-ox. JS plugins do not receive a TS6 Program.
6
6
 
7
7
  The committed corpus contains 708 records: 702 positive/negative pairs and 6 explicitly conditional default-configuration controls. SFC entries are partial script-only coverage, not template parity.
8
8
 
9
9
  ## Representative scopes
10
10
 
11
- | Preset | Sample | Native | JS | Partial | Unsupported | Disabled | Source parser |
12
- | --------- | ---------------- | ------ | --- | ------- | ----------- | -------- | ------------- |
13
- | common-ox | src/probe.ts | 205 | 363 | 8 | 57 | 479 | lintable |
14
- | react-ox | src/probe.tsx | 246 | 378 | 12 | 57 | 473 | lintable |
15
- | solid-ox | src/probe.tsx | 206 | 387 | 8 | 57 | 475 | lintable |
16
- | next-ox | src/probe.tsx | 267 | 379 | 12 | 57 | 473 | lintable |
17
- | svelte-ox | src/probe.svelte | 0 | 0 | 586 | 92 | 464 | lintable |
18
- | astro-ox | src/probe.astro | 0 | 0 | 572 | 67 | 455 | lintable |
11
+ | Preset | Sample | Native | JS | Formatter | Partial | Unsupported | Disabled | Source parser |
12
+ | --------- | ---------------- | ------ | --- | --------- | ------- | ----------- | -------- | ------------- |
13
+ | common-ox | src/probe.ts | 205 | 362 | 1 | 8 | 57 | 479 | lintable |
14
+ | react-ox | src/probe.tsx | 246 | 377 | 1 | 12 | 57 | 473 | lintable |
15
+ | solid-ox | src/probe.tsx | 206 | 386 | 1 | 8 | 57 | 475 | lintable |
16
+ | next-ox | src/probe.tsx | 267 | 378 | 1 | 12 | 57 | 473 | lintable |
17
+ | svelte-ox | src/probe.svelte | 0 | 0 | 0 | 586 | 92 | 464 | lintable |
18
+ | astro-ox | src/probe.astro | 0 | 0 | 0 | 572 | 67 | 455 | lintable |
19
+
20
+ ## External formatter checks
21
+
22
+ The source rule `prettier/prettier` is checked by `oxfmt --check` using `@st1ggy/linter-config/oxfmt-common` for the four Oxfmt stacks. These entries use status `formatter`, not `disabled`; the configured lint presets do not load or run the Prettier plugin. The `capability:oxfmt-check` tests verify rejected unformatted input, formatting fixes, the shared config, and comparison with the source Prettier options.
19
23
 
20
24
  ## Limitations and partial mappings
21
25
 
@@ -203,7 +207,6 @@ Each row includes the source options, target, scope and evidence reference. `cap
203
207
  | prefer-const | [2,{"destructuring":"any","ignoreReadBeforeAssign":false}] | vue | partial | eslint/prefer-const | The implementation is exercised on JS/TS fixtures and runs on extracted scripts here; template AST, bindings and whole-component equivalence are not provided by Oxlint. | module:prefer-const:7e9b5d5032e7 |
204
208
  | prefer-template | [2] | vue | partial | eslint/prefer-template | The implementation is exercised on JS/TS fixtures and runs on extracted scripts here; template AST, bindings and whole-component equivalence are not provided by Oxlint. | module:prefer-template:038966de9f6b |
205
209
  | preserve-caught-error | [2,{"requireCatchParameter":false,"errorClassNames":[]}] | vue | partial | eslint-js/preserve-caught-error | The implementation is exercised on JS/TS fixtures and runs on extracted scripts here; template AST, bindings and whole-component equivalence are not provided by Oxlint. | module:preserve-caught-error:f29315f7e300 |
206
- | prettier/prettier | [2] | vue | partial | prettier/prettier | The implementation is exercised on JS/TS fixtures and runs on extracted scripts here; template AST, bindings and whole-component equivalence are not provided by Oxlint. | module:prettier/prettier:038966de9f6b |
207
210
  | require-yield | [2] | vue | partial | eslint/require-yield | The implementation is exercised on JS/TS fixtures and runs on extracted scripts here; template AST, bindings and whole-component equivalence are not provided by Oxlint. | module:require-yield:038966de9f6b |
208
211
  | sonarjs/anchor-precedence | [2] | vue | unsupported | — | The JS rule requires TypeScript parser services, which the Oxlint JS plugin API does not provide; no native equivalent is registered. | capability:js-type-services |
209
212
  | sonarjs/argument-type | [2] | vue | unsupported | — | The JS rule requires TypeScript parser services, which the Oxlint JS plugin API does not provide; no native equivalent is registered. | capability:js-type-services |
@@ -1577,6 +1580,7 @@ Each row includes the source options, target, scope and evidence reference. `cap
1577
1580
  | svelte/system | [2] | module | unsupported | — | Requires framework parser/processor AST; Oxlint exposes extracted scripts, not template nodes. | capability:framework-template |
1578
1581
  | svelte/valid-each-key | [2] | module | unsupported | — | Requires framework parser/processor AST; Oxlint exposes extracted scripts, not template nodes. | capability:framework-template |
1579
1582
  | svelte/valid-prop-names-in-kit-pages | [2] | module | unsupported | — | Requires framework parser/processor AST; Oxlint exposes extracted scripts, not template nodes. | capability:framework-template |
1583
+ | prettier/prettier | [2] | vue | partial | prettier/prettier | The implementation is exercised on JS/TS fixtures and runs on extracted scripts here; template AST, bindings and whole-component equivalence are not provided by Oxlint. | module:prettier/prettier:038966de9f6b |
1580
1584
  | svelte/comment-directive | [2] | vue | unsupported | — | Requires framework parser/processor AST; Oxlint exposes extracted scripts, not template nodes. | capability:framework-template |
1581
1585
  | svelte/infinite-reactive-loop | [2] | vue | unsupported | — | Requires framework parser/processor AST; Oxlint exposes extracted scripts, not template nodes. | capability:framework-template |
1582
1586
  | svelte/no-at-debug-tags | [1] | vue | unsupported | — | Requires framework parser/processor AST; Oxlint exposes extracted scripts, not template nodes. | capability:framework-template |
@@ -37,7 +37,7 @@ Inventory rule counts (sample files in this repository):
37
37
 
38
38
  The package also exports `common-ox`, `react-ox`, `solid-ox`, `next-ox`, `svelte-ox` and `astro-ox`. Each is one `OxlintConfig` object, used through `oxlint.config.ts`, with `options.typeAware: true` and the native TS7 tsgolint engine. The original ESLint presets remain available.
39
39
 
40
- The new variants use explicit migrated rules plus compatible JS adapters, and keep each stack's existing Prettier and Stylelint selections. See [OXLINT_RULE_MAPPING.md](OXLINT_RULE_MAPPING.md) for source/target correspondence, per-scope counts, partial mappings and unsupported rules. Native script extraction does not provide Svelte/Astro template linting.
40
+ The new variants use explicit migrated rules plus compatible JS adapters. Common/React/Solid/Next pair with `oxfmt-common` and a separate `oxfmt --check`; their source `prettier/prettier` check is recorded as `formatter` in the audit instead of running a Prettier JS plugin. Svelte/Astro keep their existing Prettier selections. Every stack retains Stylelint. See [OXLINT_RULE_MAPPING.md](OXLINT_RULE_MAPPING.md) for source/target correspondence, per-scope counts, partial mappings and unsupported rules. Native script extraction does not provide Svelte/Astro template linting.
41
41
 
42
42
  Regenerate and verify the Oxlint inventory with:
43
43
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@st1ggy/linter-config",
3
- "version": "7.4.0",
4
- "description": "ESLint, Prettier, and Stylelint shareable configs (sources under src/).",
3
+ "version": "8.0.0",
4
+ "description": "Shareable ESLint, Oxlint, Oxfmt, Prettier, and Stylelint configs.",
5
5
  "private": false,
6
6
  "repository": {
7
7
  "type": "git",
@@ -128,6 +128,11 @@
128
128
  "import": "./src/prettier/prettier.config.common.js",
129
129
  "default": "./src/prettier/prettier.config.common.js"
130
130
  },
131
+ "./oxfmt-common": {
132
+ "types": "./src/oxfmt/index.d.ts",
133
+ "import": "./src/oxfmt/oxfmt.config.common.js",
134
+ "default": "./src/oxfmt/oxfmt.config.common.js"
135
+ },
131
136
  "./prettier-svelte": {
132
137
  "types": "./index.d.ts",
133
138
  "import": "./src/prettier/prettier-svelte.config.js",
@@ -153,6 +158,7 @@
153
158
  "!scripts/fixtures",
154
159
  "!scripts/*.test.mjs",
155
160
  "!scripts/oxlint-*.mjs",
161
+ "!scripts/oxfmt-*.mjs",
156
162
  "!scripts/package-smoke.mjs"
157
163
  ],
158
164
  "scripts": {
@@ -172,6 +178,8 @@
172
178
  "inventory:ox": "node scripts/oxlint-inventory.mjs --write",
173
179
  "inventory:ox:check": "node scripts/oxlint-inventory.mjs --source-only --check && node scripts/oxlint-inventory.mjs --check",
174
180
  "test:ox": "node --test --test-concurrency=2 scripts/oxlint-*.test.mjs",
181
+ "format:ox:compare": "node scripts/oxfmt-compare.mjs",
182
+ "format:ox:check": "oxfmt --config ./src/oxfmt/oxfmt.config.common.js --check .",
175
183
  "config:init": "node ./scripts/linter-init.mjs init --common --dir ./examples/init-smoke",
176
184
  "config:migrate": "node ./scripts/linter-init.mjs migrate --common --dir ./examples/init-smoke",
177
185
  "config:reinit": "node ./scripts/linter-init.mjs reinit --common --dir ./examples/init-smoke",
@@ -189,6 +197,7 @@
189
197
  "eslint-plugin-svelte": "^3.22.0",
190
198
  "next": "^16.3.0",
191
199
  "oxlint": "1.86.0",
200
+ "oxfmt": "0.71.0",
192
201
  "oxlint-tsgolint": "7.0.2003",
193
202
  "prettier": "^3.9.6",
194
203
  "prettier-plugin-astro": "^0.14.1",
@@ -225,6 +234,9 @@
225
234
  "oxlint": {
226
235
  "optional": true
227
236
  },
237
+ "oxfmt": {
238
+ "optional": true
239
+ },
228
240
  "oxlint-tsgolint": {
229
241
  "optional": true
230
242
  },
@@ -264,6 +276,7 @@
264
276
  "eslint-plugin-solid": "^0.18.0",
265
277
  "eslint-plugin-svelte": "^3.22.0",
266
278
  "oxlint": "1.86.0",
279
+ "oxfmt": "0.71.0",
267
280
  "oxlint-tsgolint": "7.0.2003",
268
281
  "prettier-plugin-astro": "^0.14.1",
269
282
  "prettier-plugin-svelte": "^4.1.1",
package/scripts/README.md CHANGED
@@ -53,7 +53,7 @@ For SolidJS, `init-solid.sh` selects `eslint-solid`, `prettier-common`, and `sty
53
53
 
54
54
  ## Oxlint wrappers
55
55
 
56
- The six `init-*-ox.sh` shortcuts select the corresponding `*-ox` stack. They write `oxlint.config.ts`, `prettier.config.js` and `stylelint.config.js`. The wizard pins `oxlint@1.86.0` and `oxlint-tsgolint@7.0.2003` and installs only the framework integrations used by that preset. Svelte projects provide their Svelte runtime; their formatter and ESLint-compatible script rules use it.
56
+ The six `init-*-ox.sh` shortcuts select the corresponding `*-ox` stack. All write `oxlint.config.ts` and `stylelint.config.js`. Common/React/Solid/Next write `oxfmt.config.ts`; Svelte/Astro write `prettier.config.js`. The wizard pins `oxlint@1.86.0` and `oxlint-tsgolint@7.0.2003`, adds `oxfmt@0.71.0` to the four Oxfmt stacks, and installs only the selected framework integrations. Svelte projects provide their Svelte runtime; their formatter and ESLint-compatible script rules use it.
57
57
 
58
58
  ```bash
59
59
  npx @st1ggy/linter-config init --react-ox
@@ -61,7 +61,9 @@ npx @st1ggy/linter-config migrate --astro-ox
61
61
  node ./scripts/linter-init.mjs init --solid-ox --dir ./my-app --skip-install
62
62
  ```
63
63
 
64
- `init` preserves existing wrappers, including the other engine's config. `migrate` offers the opposite engine config and old `.oxlintrc.*` files for removal before generating the selected wrappers. It never deletes them without confirmation.
64
+ `init` preserves existing wrappers, including the other linter/formatter config. `migrate` offers the opposite configs and old `.oxlintrc.*`/`.oxfmtrc.*` files for removal before generating the selected wrappers. It never deletes them without confirmation.
65
+
66
+ For the four Oxfmt stacks, run `oxlint .` and `oxfmt --check .` separately. Their lint presets do not run Prettier's JS rule. `oxfmt --write .` formats after lint fixes; import and package.json sorting are disabled. The shared formatter options are available through `@st1ggy/linter-config/oxfmt-common`.
65
67
 
66
68
  Oxlint uses native TS7 for typed linting. The consumer tsconfig must be TS7-compatible; the generator does not modify it. Read the [usage guide](../README.md#oxlint-variants) and [coverage report](../docs/OXLINT_RULE_MAPPING.md) before switching a project with Svelte/Astro templates or TS parser-service-dependent JS rules.
67
69
 
@@ -74,6 +76,8 @@ npm run inventory:ox
74
76
  npm run generate:ox:check
75
77
  npm run inventory:ox:check
76
78
  npm run test:ox
79
+ npm run format:ox:check
80
+ npm run format:ox:compare
77
81
  npm run typecheck:ox
78
82
  node scripts/package-smoke.mjs
79
83
  node scripts/package-smoke.mjs --pm pnpm
@@ -4,7 +4,7 @@ import { spawnSync } from 'node:child_process'
4
4
  import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs'
5
5
  import path from 'node:path'
6
6
 
7
- import { OX_FRAMEWORK_PACKAGES, OX_VERSIONS } from '../src/oxlint/stacks.js'
7
+ import { OXFMT_STACKS, OX_FRAMEWORK_PACKAGES, oxStackToolVersions } from '../src/oxlint/stacks.js'
8
8
 
9
9
  export const PACKAGE = '@st1ggy/linter-config'
10
10
 
@@ -83,14 +83,23 @@ for (const key of BASE_STACK_KEYS) {
83
83
 
84
84
  base.linterFile = 'eslint.config.js'
85
85
  base.linterPreset = base.eslint
86
+ base.formatterFile = 'prettier.config.js'
87
+ base.formatterPreset = base.prettier
88
+ const hasOxfmt = OXFMT_STACKS.includes(key)
89
+
86
90
  STACKS[`${key}-ox`] = {
87
91
  linterFile: 'oxlint.config.ts',
88
92
  linterPreset: `${key}-ox`,
89
93
  prettier: base.prettier,
94
+ formatterFile: hasOxfmt ? 'oxfmt.config.ts' : 'prettier.config.js',
95
+ formatterPreset: hasOxfmt ? 'oxfmt-common' : base.prettier,
90
96
  stylelint: base.stylelint,
91
- packages: [...Object.keys(OX_VERSIONS), ...OX_FRAMEWORK_PACKAGES[key]],
97
+ packages: [...Object.keys(oxStackToolVersions(key)), ...OX_FRAMEWORK_PACKAGES[key]],
92
98
  }
93
- STACK_CHOICES.push({ value: `${key}-ox`, name: `${key}-ox — Oxlint + native TypeScript 7` })
99
+ STACK_CHOICES.push({
100
+ value: `${key}-ox`,
101
+ name: `${key}-ox — Oxlint + native TypeScript 7 + ${hasOxfmt ? 'Oxfmt' : 'Prettier'}`,
102
+ })
94
103
  }
95
104
 
96
105
  export function readPackageJson(directory) {
@@ -298,9 +307,13 @@ export function stackPackages(stackKey) {
298
307
  export function stackPackageSpecs(stackKey) {
299
308
  stackPackages(stackKey)
300
309
 
301
- return stackKey.endsWith('-ox')
302
- ? Object.fromEntries(Object.entries(OX_VERSIONS).map(([name, version]) => [name, `${name}@${version}`]))
303
- : {}
310
+ if (!stackKey.endsWith('-ox')) {
311
+ return {}
312
+ }
313
+
314
+ const versions = oxStackToolVersions(stackKey.slice(0, -3))
315
+
316
+ return Object.fromEntries(Object.entries(versions).map(([name, version]) => [name, `${name}@${version}`]))
304
317
  }
305
318
 
306
319
  export function printHelp() {
@@ -317,7 +330,8 @@ Commands:
317
330
 
318
331
  Writes (each command):
319
332
  ESLint stacks: eslint.config.js, prettier.config.js, stylelint.config.js.
320
- Oxlint stacks: oxlint.config.ts, prettier.config.js, stylelint.config.js.
333
+ common/react/solid/next-ox: oxlint.config.ts, oxfmt.config.ts, stylelint.config.js.
334
+ svelte/astro-ox: oxlint.config.ts, prettier.config.js, stylelint.config.js.
321
335
 
322
336
  Unless --skip-install: if package.json exists, runs the detected package manager to add or sync
323
337
  ${PACKAGE} and the selected stack's integration plugins.
@@ -349,8 +363,8 @@ Repo (paths from root):
349
363
  `)
350
364
  }
351
365
 
352
- export function jsReExport(subpath) {
353
- return `export { default } from '${PACKAGE}/${subpath}';\n`
366
+ export function jsReExport(subpath, hasSemicolon = true) {
367
+ return `export { default } from '${PACKAGE}/${subpath}'${hasSemicolon ? ';' : ''}\n`
354
368
  }
355
369
 
356
370
  export function resolveTargetDirectory(raw) {
@@ -382,7 +396,7 @@ export function writeFile(targetDirectory, name, content, overwrite, options = {
382
396
  export function wrapperFileNames(stackKey = 'common') {
383
397
  stackPackages(stackKey)
384
398
 
385
- return [STACKS[stackKey].linterFile, 'prettier.config.js', 'stylelint.config.js']
399
+ return [STACKS[stackKey].linterFile, STACKS[stackKey].formatterFile, 'stylelint.config.js']
386
400
  }
387
401
 
388
402
  export function existingWrapperFiles(targetDirectory, stackKey = 'common') {
@@ -399,7 +413,7 @@ export function legacyConfigFiles(targetDirectory, stackKey = 'common') {
399
413
  return readdirSync(targetDirectory, { withFileTypes: true })
400
414
  .filter(
401
415
  (entry) =>
402
- entry.isFile() && /(?:eslint|oxlint|prettier|stylelint)/i.test(entry.name) && !wrappers.has(entry.name),
416
+ entry.isFile() && /(?:eslint|oxlint|oxfmt|prettier|stylelint)/i.test(entry.name) && !wrappers.has(entry.name),
403
417
  )
404
418
  .map((entry) => entry.name)
405
419
  .toSorted((left, right) => left.localeCompare(right))
@@ -443,7 +457,13 @@ export function run(mode, targetDirectory, stackKey, options = {}) {
443
457
 
444
458
  const shouldOverwrite = mode === 'migrate' || mode === 'reinit'
445
459
 
446
- writeFile(targetDirectory, stack.linterFile, jsReExport(stack.linterPreset), shouldOverwrite, { quiet })
447
- writeFile(targetDirectory, 'prettier.config.js', jsReExport(stack.prettier), shouldOverwrite, { quiet })
448
- writeFile(targetDirectory, 'stylelint.config.js', jsReExport(stack.stylelint), shouldOverwrite, { quiet })
460
+ const hasSemicolon = stack.formatterPreset !== 'oxfmt-common'
461
+
462
+ writeFile(targetDirectory, stack.linterFile, jsReExport(stack.linterPreset, hasSemicolon), shouldOverwrite, { quiet })
463
+ writeFile(targetDirectory, stack.formatterFile, jsReExport(stack.formatterPreset, hasSemicolon), shouldOverwrite, {
464
+ quiet,
465
+ })
466
+ writeFile(targetDirectory, 'stylelint.config.js', jsReExport(stack.stylelint, hasSemicolon), shouldOverwrite, {
467
+ quiet,
468
+ })
449
469
  }
@@ -60,7 +60,7 @@ async function selectCommand(command) {
60
60
  choices: [
61
61
  {
62
62
  value: 'init',
63
- name: 'init — create missing linter, Prettier and Stylelint wrappers',
63
+ name: 'init — create missing linter, formatter and Stylelint wrappers',
64
64
  },
65
65
  {
66
66
  value: 'migrate',
@@ -0,0 +1,8 @@
1
+ // Kept separate from the legacy declarations to make the formatter an optional peer.
2
+ declare module '@st1ggy/linter-config/oxfmt-common' {
3
+ import type { OxfmtConfig } from 'oxfmt'
4
+
5
+ const config: OxfmtConfig
6
+
7
+ export default config
8
+ }
@@ -0,0 +1,16 @@
1
+ export default {
2
+ useTabs: false,
3
+ printWidth: 120,
4
+ tabWidth: 2,
5
+ semi: false,
6
+ singleQuote: true,
7
+ trailingComma: 'all',
8
+ bracketSpacing: true,
9
+ arrowParens: 'always',
10
+ proseWrap: 'never',
11
+ endOfLine: 'lf',
12
+ insertFinalNewline: true,
13
+ sortImports: false,
14
+ sortPackageJson: false,
15
+ ignorePatterns: ['**/node_modules/**', '**/.git/**'],
16
+ }
@@ -1,6 +1,7 @@
1
1
  // Generated by scripts/oxlint-generate.mjs.
2
2
  /* eslint-disable unicorn/prefer-string-raw, unicorn/numeric-separators-style -- Serialized rule options. */
3
3
  export default {
4
+ formatter: 'prettier',
4
5
  plugins: ['eslint', 'import', 'typescript', 'unicorn'],
5
6
  jsPlugins: [
6
7
  'astro',
@@ -1,8 +1,9 @@
1
1
  // Generated by scripts/oxlint-generate.mjs.
2
2
  /* eslint-disable unicorn/prefer-string-raw, unicorn/numeric-separators-style -- Serialized rule options. */
3
3
  export default {
4
+ formatter: 'oxfmt',
4
5
  plugins: ['eslint', 'import', 'typescript', 'unicorn'],
5
- jsPlugins: ['eslint-js', 'import-x-js', 'prettier', 'sonarjs', 'stylistic-js', 'typescript-js', 'unicorn-js'],
6
+ jsPlugins: ['eslint-js', 'import-x-js', 'sonarjs', 'stylistic-js', 'typescript-js', 'unicorn-js'],
6
7
  settings: {
7
8
  'import-x/extensions': ['.ts', '.tsx', '.cts', '.mts', '.js', '.jsx', '.cjs', '.mjs'],
8
9
  'import-x/external-module-folders': ['node_modules', 'node_modules/@types'],
@@ -11,7 +12,7 @@ export default {
11
12
  react: { version: '999.999.999' },
12
13
  },
13
14
  profiles: {
14
- '2dc3f9032ff33b34': {
15
+ a1e9c43871ddb707: {
15
16
  rules: {
16
17
  'stylistic-js/lines-between-class-members': [
17
18
  2,
@@ -179,7 +180,6 @@ export default {
179
180
  'eslint/prefer-const': [2, { destructuring: 'any', ignoreReadBeforeAssign: false }],
180
181
  'eslint/prefer-template': [2],
181
182
  'eslint-js/preserve-caught-error': [2, { requireCatchParameter: false, errorClassNames: [] }],
182
- 'prettier/prettier': [2],
183
183
  'eslint/require-yield': [2],
184
184
  'sonarjs/assertions-in-test-cases': [2],
185
185
  'sonarjs/async-test-assertions': [2],
@@ -807,7 +807,7 @@ export default {
807
807
  WeakSet: 'readonly',
808
808
  },
809
809
  },
810
- '4f5c7a9e6f7d7cca': {
810
+ dbd3839dc2ff074c: {
811
811
  rules: {
812
812
  'stylistic-js/lines-between-class-members': [
813
813
  2,
@@ -975,7 +975,6 @@ export default {
975
975
  'eslint/prefer-const': [2, { destructuring: 'any', ignoreReadBeforeAssign: false }],
976
976
  'eslint/prefer-template': [2],
977
977
  'eslint-js/preserve-caught-error': [2, { requireCatchParameter: false, errorClassNames: [] }],
978
- 'prettier/prettier': [2],
979
978
  'eslint/require-yield': [2],
980
979
  'sonarjs/assertions-in-test-cases': [2],
981
980
  'sonarjs/async-test-assertions': [2],
@@ -1603,7 +1602,7 @@ export default {
1603
1602
  WeakSet: 'readonly',
1604
1603
  },
1605
1604
  },
1606
- '2d19a2206178c65c': {
1605
+ '227d3b2aac8f52e5': {
1607
1606
  rules: {
1608
1607
  'stylistic-js/lines-between-class-members': [
1609
1608
  2,
@@ -1771,7 +1770,6 @@ export default {
1771
1770
  'eslint/prefer-const': [2, { destructuring: 'any', ignoreReadBeforeAssign: false }],
1772
1771
  'eslint/prefer-template': [2],
1773
1772
  'eslint-js/preserve-caught-error': [2, { requireCatchParameter: false, errorClassNames: [] }],
1774
- 'prettier/prettier': [2],
1775
1773
  'eslint/require-yield': [2],
1776
1774
  'sonarjs/assertions-in-test-cases': [2],
1777
1775
  'sonarjs/async-test-assertions': [2],
@@ -2399,7 +2397,7 @@ export default {
2399
2397
  WeakSet: 'readonly',
2400
2398
  },
2401
2399
  },
2402
- '496d5045088c2ca1': {
2400
+ '6a32e0a7d1f6f3bf': {
2403
2401
  rules: {
2404
2402
  'stylistic-js/lines-between-class-members': [
2405
2403
  2,
@@ -2564,7 +2562,6 @@ export default {
2564
2562
  'eslint/prefer-const': [2, { destructuring: 'any', ignoreReadBeforeAssign: false }],
2565
2563
  'eslint/prefer-template': [2],
2566
2564
  'eslint-js/preserve-caught-error': [2, { requireCatchParameter: false, errorClassNames: [] }],
2567
- 'prettier/prettier': 'off',
2568
2565
  'eslint/require-yield': [2],
2569
2566
  'sonarjs/assertions-in-test-cases': [2],
2570
2567
  'sonarjs/async-test-assertions': [2],
@@ -3194,16 +3191,16 @@ export default {
3194
3191
  },
3195
3192
  },
3196
3193
  overrides: [
3197
- { files: ['**/*.js'], profile: '2dc3f9032ff33b34' },
3198
- { files: ['**/*.ts'], profile: '4f5c7a9e6f7d7cca' },
3199
- { files: ['**/*.cjs'], profile: '2dc3f9032ff33b34' },
3200
- { files: ['**/*.cts'], profile: '4f5c7a9e6f7d7cca' },
3201
- { files: ['**/*.jsx', '**/*.mjs'], profile: '2dc3f9032ff33b34' },
3202
- { files: ['**/*.mts', '**/*.tsx'], profile: '4f5c7a9e6f7d7cca' },
3203
- { files: ['**/*.vue'], profile: '2d19a2206178c65c' },
3204
- { files: ['**/*.d.ts'], profile: '4f5c7a9e6f7d7cca' },
3205
- { files: ['**/*.svelte'], profile: '496d5045088c2ca1' },
3206
- { files: ['**/*.svelte.js'], profile: '2dc3f9032ff33b34' },
3207
- { files: ['**/*.svelte.ts'], profile: '4f5c7a9e6f7d7cca' },
3194
+ { files: ['**/*.js'], profile: 'a1e9c43871ddb707' },
3195
+ { files: ['**/*.ts'], profile: 'dbd3839dc2ff074c' },
3196
+ { files: ['**/*.cjs'], profile: 'a1e9c43871ddb707' },
3197
+ { files: ['**/*.cts'], profile: 'dbd3839dc2ff074c' },
3198
+ { files: ['**/*.jsx', '**/*.mjs'], profile: 'a1e9c43871ddb707' },
3199
+ { files: ['**/*.mts', '**/*.tsx'], profile: 'dbd3839dc2ff074c' },
3200
+ { files: ['**/*.vue'], profile: '227d3b2aac8f52e5' },
3201
+ { files: ['**/*.d.ts'], profile: 'dbd3839dc2ff074c' },
3202
+ { files: ['**/*.svelte'], profile: '6a32e0a7d1f6f3bf' },
3203
+ { files: ['**/*.svelte.js'], profile: 'a1e9c43871ddb707' },
3204
+ { files: ['**/*.svelte.ts'], profile: 'dbd3839dc2ff074c' },
3208
3205
  ],
3209
3206
  }
@@ -1,12 +1,12 @@
1
1
  // Generated by scripts/oxlint-generate.mjs.
2
2
  /* eslint-disable unicorn/prefer-string-raw, unicorn/numeric-separators-style -- Serialized rule options. */
3
3
  export default {
4
+ formatter: 'oxfmt',
4
5
  plugins: ['eslint', 'import', 'nextjs', 'react', 'typescript', 'unicorn'],
5
6
  jsPlugins: [
6
7
  'eslint-js',
7
8
  'import-x-js',
8
9
  'next-js',
9
- 'prettier',
10
10
  'react-hooks-js',
11
11
  'react-js',
12
12
  'sonarjs',
@@ -22,7 +22,7 @@ export default {
22
22
  react: { version: '999.999.999' },
23
23
  },
24
24
  profiles: {
25
- e1b8d9afc309039e: {
25
+ '030f64f9c04fbae1': {
26
26
  rules: {
27
27
  'nextjs/google-font-display': [1],
28
28
  'nextjs/google-font-preconnect': [1],
@@ -231,7 +231,6 @@ export default {
231
231
  'eslint/prefer-const': [2, { destructuring: 'any', ignoreReadBeforeAssign: false }],
232
232
  'eslint/prefer-template': [2],
233
233
  'eslint-js/preserve-caught-error': [2, { requireCatchParameter: false, errorClassNames: [] }],
234
- 'prettier/prettier': [2],
235
234
  'react-hooks-js/config': [2],
236
235
  'react/error-boundaries': [2],
237
236
  'react/exhaustive-deps': [1],
@@ -911,7 +910,7 @@ export default {
911
910
  WeakSet: 'readonly',
912
911
  },
913
912
  },
914
- '65407869e0e99988': {
913
+ '6154ace1ea00ed42': {
915
914
  rules: {
916
915
  'nextjs/google-font-display': [1],
917
916
  'nextjs/google-font-preconnect': [1],
@@ -1120,7 +1119,6 @@ export default {
1120
1119
  'eslint/prefer-const': [2, { destructuring: 'any', ignoreReadBeforeAssign: false }],
1121
1120
  'eslint/prefer-template': [2],
1122
1121
  'eslint-js/preserve-caught-error': [2, { requireCatchParameter: false, errorClassNames: [] }],
1123
- 'prettier/prettier': [2],
1124
1122
  'react-hooks-js/config': [2],
1125
1123
  'react/error-boundaries': [2],
1126
1124
  'react/exhaustive-deps': [1],
@@ -1800,7 +1798,7 @@ export default {
1800
1798
  WeakSet: 'readonly',
1801
1799
  },
1802
1800
  },
1803
- a7f4f19712df37e4: {
1801
+ '1d68a15be7e2c62a': {
1804
1802
  rules: {
1805
1803
  'nextjs/google-font-display': [1],
1806
1804
  'nextjs/google-font-preconnect': [1],
@@ -2009,7 +2007,6 @@ export default {
2009
2007
  'eslint/prefer-const': [2, { destructuring: 'any', ignoreReadBeforeAssign: false }],
2010
2008
  'eslint/prefer-template': [2],
2011
2009
  'eslint-js/preserve-caught-error': [2, { requireCatchParameter: false, errorClassNames: [] }],
2012
- 'prettier/prettier': [2],
2013
2010
  'react-hooks-js/config': [2],
2014
2011
  'react/error-boundaries': [2],
2015
2012
  'react/exhaustive-deps': [1],
@@ -2689,7 +2686,7 @@ export default {
2689
2686
  WeakSet: 'readonly',
2690
2687
  },
2691
2688
  },
2692
- '8534dfea4a52c0dd': {
2689
+ f41aec2e0587cd54: {
2693
2690
  rules: {
2694
2691
  'nextjs/google-font-display': [1],
2695
2692
  'nextjs/google-font-preconnect': [1],
@@ -2895,7 +2892,6 @@ export default {
2895
2892
  'eslint/prefer-const': [2, { destructuring: 'any', ignoreReadBeforeAssign: false }],
2896
2893
  'eslint/prefer-template': [2],
2897
2894
  'eslint-js/preserve-caught-error': [2, { requireCatchParameter: false, errorClassNames: [] }],
2898
- 'prettier/prettier': 'off',
2899
2895
  'react-hooks-js/config': [2],
2900
2896
  'react/error-boundaries': [2],
2901
2897
  'react/exhaustive-deps': [1],
@@ -3577,16 +3573,16 @@ export default {
3577
3573
  },
3578
3574
  },
3579
3575
  overrides: [
3580
- { files: ['**/*.js'], profile: 'e1b8d9afc309039e' },
3581
- { files: ['**/*.ts'], profile: '65407869e0e99988' },
3582
- { files: ['**/*.cjs'], profile: 'e1b8d9afc309039e' },
3583
- { files: ['**/*.cts'], profile: '65407869e0e99988' },
3584
- { files: ['**/*.jsx', '**/*.mjs'], profile: 'e1b8d9afc309039e' },
3585
- { files: ['**/*.mts', '**/*.tsx'], profile: '65407869e0e99988' },
3586
- { files: ['**/*.vue'], profile: 'a7f4f19712df37e4' },
3587
- { files: ['**/*.d.ts'], profile: '65407869e0e99988' },
3588
- { files: ['**/*.svelte'], profile: '8534dfea4a52c0dd' },
3589
- { files: ['**/*.svelte.js'], profile: 'e1b8d9afc309039e' },
3590
- { files: ['**/*.svelte.ts'], profile: '65407869e0e99988' },
3576
+ { files: ['**/*.js'], profile: '030f64f9c04fbae1' },
3577
+ { files: ['**/*.ts'], profile: '6154ace1ea00ed42' },
3578
+ { files: ['**/*.cjs'], profile: '030f64f9c04fbae1' },
3579
+ { files: ['**/*.cts'], profile: '6154ace1ea00ed42' },
3580
+ { files: ['**/*.jsx', '**/*.mjs'], profile: '030f64f9c04fbae1' },
3581
+ { files: ['**/*.mts', '**/*.tsx'], profile: '6154ace1ea00ed42' },
3582
+ { files: ['**/*.vue'], profile: '1d68a15be7e2c62a' },
3583
+ { files: ['**/*.d.ts'], profile: '6154ace1ea00ed42' },
3584
+ { files: ['**/*.svelte'], profile: 'f41aec2e0587cd54' },
3585
+ { files: ['**/*.svelte.js'], profile: '030f64f9c04fbae1' },
3586
+ { files: ['**/*.svelte.ts'], profile: '6154ace1ea00ed42' },
3591
3587
  ],
3592
3588
  }