biome-to-oxc 2.0.0 → 3.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.
- package/README.md +6 -0
- package/dist/bin/biome-to-oxc.mjs +4 -2
- package/dist/src/index.d.mts +11 -0
- package/dist/src/index.mjs +1 -1
- package/dist/{src-CYMpPpfK.mjs → src-CUWW9YZ_.mjs} +204 -7
- package/package.json +29 -25
package/README.md
CHANGED
|
@@ -135,6 +135,12 @@ ignore configuration before removing Biome.
|
|
|
135
135
|
- `docs/oxfmt-rules.tsv`: Oxfmt configuration surface inventory
|
|
136
136
|
- `docs/tsgolint-rules.tsv`: typed linting implementation matrix
|
|
137
137
|
- `docs/oxlint-vs-tsgolint.tsv`: typed rule availability cross-reference
|
|
138
|
+
- `docs/biome-rules.tsv`: Biome rule inventory, so a mapping cannot key off a rule Biome dropped
|
|
139
|
+
- `docs/biome-formatter-options.tsv`: Biome formatter surface inventory
|
|
140
|
+
|
|
141
|
+
All six are generated from the schemas of the installed `oxlint`, `oxfmt`,
|
|
142
|
+
`oxlint-tsgolint`, and `@biomejs/biome` packages by `pnpm docs:sync`; `pnpm docs:check`
|
|
143
|
+
fails when they drift, and it runs as part of `pnpm check`.
|
|
138
144
|
|
|
139
145
|
✅ **Script Rewrite Strategy Controls**
|
|
140
146
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { i as readJsonFile, n as DefaultReporter, r as findClosestPackageJson, t as migrate } from "../src-
|
|
2
|
+
import { i as readJsonFile, n as DefaultReporter, r as findClosestPackageJson, t as migrate } from "../src-CUWW9YZ_.mjs";
|
|
3
3
|
import { realpath } from "node:fs/promises";
|
|
4
4
|
import { dirname } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
@@ -19,6 +19,7 @@ const MigrationOptionsSchema = z.object({
|
|
|
19
19
|
delete: z.boolean().default(false),
|
|
20
20
|
noBackup: z.boolean().default(false),
|
|
21
21
|
updateScripts: z.boolean().default(false),
|
|
22
|
+
dom: z.boolean().default(false),
|
|
22
23
|
verbose: z.boolean().default(false),
|
|
23
24
|
typeAware: z.boolean().default(false),
|
|
24
25
|
typeCheck: z.boolean().default(false),
|
|
@@ -106,7 +107,7 @@ function createCommand(packageMetadata, streams) {
|
|
|
106
107
|
writeOut: (chunk) => {
|
|
107
108
|
streams.stdout.write(chunk);
|
|
108
109
|
}
|
|
109
|
-
}).option("-c, --config <path>", "Path to biome.json or biome.jsonc").option("-o, --output-dir <path>", "Output directory for generated configs").option("--dry-run", "Show what would be done without making changes").option("--delete", "Delete legacy Biome files after migration (biome.json/biome.jsonc and .biomeignore)").option("--no-backup", "Skip backup of existing config files").option("--update-scripts", "Update package.json scripts to use oxlint/oxfmt").option("--type-aware", "Include type-aware linting guidance and dependencies").option("--type-check", "Enable strict typed linting mode (implies --type-aware)").addOption(new Option("--type-aware-profile <profile>", "Type-aware profile: standard (--type-aware) or strict (--type-aware --type-check)").choices(["standard", "strict"]).default("standard")).addOption(new Option("--fix-strategy <strategy>", "Fix mode for rewritten scripts: safe | suggestions | dangerous").choices([
|
|
110
|
+
}).option("-c, --config <path>", "Path to biome.json or biome.jsonc").option("-o, --output-dir <path>", "Output directory for generated configs").option("--dry-run", "Show what would be done without making changes").option("--delete", "Delete legacy Biome files after migration (biome.json/biome.jsonc and .biomeignore)").option("--no-backup", "Skip backup of existing config files").option("--update-scripts", "Update package.json scripts to use oxlint/oxfmt").addOption(new Option("--dom").hideHelp()).option("--type-aware", "Include type-aware linting guidance and dependencies").option("--type-check", "Enable strict typed linting mode (implies --type-aware)").addOption(new Option("--type-aware-profile <profile>", "Type-aware profile: standard (--type-aware) or strict (--type-aware --type-check)").choices(["standard", "strict"]).default("standard")).addOption(new Option("--fix-strategy <strategy>", "Fix mode for rewritten scripts: safe | suggestions | dangerous").choices([
|
|
110
111
|
"safe",
|
|
111
112
|
"suggestions",
|
|
112
113
|
"dangerous"
|
|
@@ -130,6 +131,7 @@ function normalizeMigrationOptions(options) {
|
|
|
130
131
|
delete: options.delete,
|
|
131
132
|
noBackup: options.backup === false,
|
|
132
133
|
updateScripts: options.updateScripts,
|
|
134
|
+
dom: options.dom,
|
|
133
135
|
verbose: options.verbose,
|
|
134
136
|
typeAware,
|
|
135
137
|
typeCheck,
|
package/dist/src/index.d.mts
CHANGED
|
@@ -69,6 +69,9 @@ interface BiomeFormatterConfig {
|
|
|
69
69
|
lineWidth?: number;
|
|
70
70
|
attributePosition?: 'auto' | 'multiline';
|
|
71
71
|
bracketSpacing?: boolean;
|
|
72
|
+
bracketSameLine?: boolean;
|
|
73
|
+
expand?: 'auto' | 'always' | 'never';
|
|
74
|
+
trailingNewline?: boolean;
|
|
72
75
|
[key: string]: unknown;
|
|
73
76
|
}
|
|
74
77
|
interface BiomeJavaScriptConfig {
|
|
@@ -86,10 +89,13 @@ interface BiomeJavaScriptConfig {
|
|
|
86
89
|
arrowParentheses?: 'always' | 'asNeeded';
|
|
87
90
|
bracketSameLine?: boolean;
|
|
88
91
|
bracketSpacing?: boolean;
|
|
92
|
+
expand?: 'auto' | 'always' | 'never';
|
|
89
93
|
indentStyle?: 'tab' | 'space';
|
|
90
94
|
indentWidth?: number;
|
|
91
95
|
lineEnding?: 'lf' | 'crlf' | 'cr' | 'auto';
|
|
92
96
|
lineWidth?: number;
|
|
97
|
+
operatorLinebreak?: 'after' | 'before';
|
|
98
|
+
trailingNewline?: boolean;
|
|
93
99
|
[key: string]: unknown;
|
|
94
100
|
};
|
|
95
101
|
linter?: {
|
|
@@ -105,11 +111,13 @@ interface BiomeJsonConfig {
|
|
|
105
111
|
};
|
|
106
112
|
formatter?: {
|
|
107
113
|
enabled?: boolean;
|
|
114
|
+
expand?: 'auto' | 'always' | 'never';
|
|
108
115
|
indentStyle?: 'tab' | 'space';
|
|
109
116
|
indentWidth?: number;
|
|
110
117
|
lineEnding?: 'lf' | 'crlf' | 'cr' | 'auto';
|
|
111
118
|
lineWidth?: number;
|
|
112
119
|
trailingCommas?: 'none' | 'all';
|
|
120
|
+
trailingNewline?: boolean;
|
|
113
121
|
};
|
|
114
122
|
linter?: {
|
|
115
123
|
enabled?: boolean;
|
|
@@ -126,6 +134,7 @@ interface BiomeCssConfig {
|
|
|
126
134
|
lineEnding?: 'lf' | 'crlf' | 'cr' | 'auto';
|
|
127
135
|
lineWidth?: number;
|
|
128
136
|
quoteStyle?: 'single' | 'double';
|
|
137
|
+
trailingNewline?: boolean;
|
|
129
138
|
};
|
|
130
139
|
linter?: {
|
|
131
140
|
enabled?: boolean;
|
|
@@ -233,6 +242,7 @@ interface OxfmtConfig {
|
|
|
233
242
|
endOfLine?: 'lf' | 'crlf' | 'cr';
|
|
234
243
|
singleAttributePerLine?: boolean;
|
|
235
244
|
objectWrap?: 'preserve' | 'collapse';
|
|
245
|
+
experimentalOperatorPosition?: 'start' | 'end';
|
|
236
246
|
insertFinalNewline?: boolean;
|
|
237
247
|
embeddedLanguageFormatting?: 'auto' | 'off';
|
|
238
248
|
htmlWhitespaceSensitivity?: 'css' | 'strict' | 'ignore';
|
|
@@ -306,6 +316,7 @@ interface MigrationOptions {
|
|
|
306
316
|
delete?: boolean;
|
|
307
317
|
noBackup?: boolean;
|
|
308
318
|
updateScripts?: boolean;
|
|
319
|
+
dom?: boolean;
|
|
309
320
|
verbose?: boolean;
|
|
310
321
|
typeAware?: boolean;
|
|
311
322
|
typeCheck?: boolean;
|
package/dist/src/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as migrate } from "../src-
|
|
1
|
+
import { t as migrate } from "../src-CUWW9YZ_.mjs";
|
|
2
2
|
export { migrate };
|
|
@@ -373,7 +373,14 @@ const BiomeFormatterConfigSchema = IncludeFieldsSchema.extend({
|
|
|
373
373
|
]).optional(),
|
|
374
374
|
lineWidth: z.number().int().optional(),
|
|
375
375
|
attributePosition: z.enum(["auto", "multiline"]).optional(),
|
|
376
|
-
bracketSpacing: z.boolean().optional()
|
|
376
|
+
bracketSpacing: z.boolean().optional(),
|
|
377
|
+
bracketSameLine: z.boolean().optional(),
|
|
378
|
+
expand: z.enum([
|
|
379
|
+
"auto",
|
|
380
|
+
"always",
|
|
381
|
+
"never"
|
|
382
|
+
]).optional(),
|
|
383
|
+
trailingNewline: z.boolean().optional()
|
|
377
384
|
}).passthrough();
|
|
378
385
|
const BiomeJavaScriptFormatterSchema = z.object({
|
|
379
386
|
enabled: z.boolean().optional(),
|
|
@@ -389,6 +396,11 @@ const BiomeJavaScriptFormatterSchema = z.object({
|
|
|
389
396
|
arrowParentheses: z.enum(["always", "asNeeded"]).optional(),
|
|
390
397
|
bracketSameLine: z.boolean().optional(),
|
|
391
398
|
bracketSpacing: z.boolean().optional(),
|
|
399
|
+
expand: z.enum([
|
|
400
|
+
"auto",
|
|
401
|
+
"always",
|
|
402
|
+
"never"
|
|
403
|
+
]).optional(),
|
|
392
404
|
indentStyle: z.enum(["tab", "space"]).optional(),
|
|
393
405
|
indentWidth: z.number().int().optional(),
|
|
394
406
|
lineEnding: z.enum([
|
|
@@ -397,7 +409,9 @@ const BiomeJavaScriptFormatterSchema = z.object({
|
|
|
397
409
|
"cr",
|
|
398
410
|
"auto"
|
|
399
411
|
]).optional(),
|
|
400
|
-
lineWidth: z.number().int().optional()
|
|
412
|
+
lineWidth: z.number().int().optional(),
|
|
413
|
+
operatorLinebreak: z.enum(["after", "before"]).optional(),
|
|
414
|
+
trailingNewline: z.boolean().optional()
|
|
401
415
|
}).passthrough();
|
|
402
416
|
const BiomeJavaScriptConfigSchema = z.object({
|
|
403
417
|
parser: z.object({
|
|
@@ -415,6 +429,11 @@ const BiomeJsonConfigSchema = z.object({
|
|
|
415
429
|
}).passthrough().optional(),
|
|
416
430
|
formatter: z.object({
|
|
417
431
|
enabled: z.boolean().optional(),
|
|
432
|
+
expand: z.enum([
|
|
433
|
+
"auto",
|
|
434
|
+
"always",
|
|
435
|
+
"never"
|
|
436
|
+
]).optional(),
|
|
418
437
|
indentStyle: z.enum(["tab", "space"]).optional(),
|
|
419
438
|
indentWidth: z.number().int().optional(),
|
|
420
439
|
lineEnding: z.enum([
|
|
@@ -424,7 +443,8 @@ const BiomeJsonConfigSchema = z.object({
|
|
|
424
443
|
"auto"
|
|
425
444
|
]).optional(),
|
|
426
445
|
lineWidth: z.number().int().optional(),
|
|
427
|
-
trailingCommas: z.enum(["none", "all"]).optional()
|
|
446
|
+
trailingCommas: z.enum(["none", "all"]).optional(),
|
|
447
|
+
trailingNewline: z.boolean().optional()
|
|
428
448
|
}).passthrough().optional(),
|
|
429
449
|
linter: z.object({ enabled: z.boolean().optional() }).passthrough().optional()
|
|
430
450
|
}).passthrough();
|
|
@@ -441,7 +461,8 @@ const BiomeCssConfigSchema = z.object({
|
|
|
441
461
|
"auto"
|
|
442
462
|
]).optional(),
|
|
443
463
|
lineWidth: z.number().int().optional(),
|
|
444
|
-
quoteStyle: z.enum(["single", "double"]).optional()
|
|
464
|
+
quoteStyle: z.enum(["single", "double"]).optional(),
|
|
465
|
+
trailingNewline: z.boolean().optional()
|
|
445
466
|
}).passthrough().optional(),
|
|
446
467
|
linter: z.object({ enabled: z.boolean().optional() }).passthrough().optional()
|
|
447
468
|
}).passthrough();
|
|
@@ -692,6 +713,7 @@ function generateESLintFormatterBridgeSuggestions() {
|
|
|
692
713
|
//#region src/oxfmt-overrides.ts
|
|
693
714
|
const EXPLICIT_OXFMT_OPTION_KEYS$1 = [
|
|
694
715
|
"objectWrap",
|
|
716
|
+
"experimentalOperatorPosition",
|
|
695
717
|
"insertFinalNewline",
|
|
696
718
|
"embeddedLanguageFormatting",
|
|
697
719
|
"htmlWhitespaceSensitivity",
|
|
@@ -731,11 +753,13 @@ const CSS_EXTENSIONS = [
|
|
|
731
753
|
];
|
|
732
754
|
const JSON_FORMATTER_KEYS = /* @__PURE__ */ new Set([
|
|
733
755
|
"enabled",
|
|
756
|
+
"expand",
|
|
734
757
|
"indentStyle",
|
|
735
758
|
"indentWidth",
|
|
736
759
|
"lineEnding",
|
|
737
760
|
"lineWidth",
|
|
738
761
|
"trailingCommas",
|
|
762
|
+
"trailingNewline",
|
|
739
763
|
...EXPLICIT_OXFMT_OPTION_KEYS$1,
|
|
740
764
|
...Object.keys(LEGACY_EXPLICIT_OXFMT_OPTION_ALIASES$1)
|
|
741
765
|
]);
|
|
@@ -746,9 +770,25 @@ const CSS_FORMATTER_KEYS = /* @__PURE__ */ new Set([
|
|
|
746
770
|
"lineEnding",
|
|
747
771
|
"lineWidth",
|
|
748
772
|
"quoteStyle",
|
|
773
|
+
"trailingNewline",
|
|
749
774
|
...EXPLICIT_OXFMT_OPTION_KEYS$1,
|
|
750
775
|
...Object.keys(LEGACY_EXPLICIT_OXFMT_OPTION_ALIASES$1)
|
|
751
776
|
]);
|
|
777
|
+
/**
|
|
778
|
+
* Biome's `expand` and Oxfmt's `objectWrap` agree on two of three modes: Biome's `auto`
|
|
779
|
+
* (expand when the literal already has a newline after `{`) is Oxfmt's `preserve`, and
|
|
780
|
+
* Biome's `never` is Oxfmt's `collapse`. Biome's `always` has no Oxfmt counterpart.
|
|
781
|
+
*/
|
|
782
|
+
function mapBiomeExpandToObjectWrap(expand, label, reporter) {
|
|
783
|
+
if (expand === "auto") return "preserve";
|
|
784
|
+
if (expand === "never") return "collapse";
|
|
785
|
+
if (expand === "always") reporter.loss(`Biome ${label}.expand "always" has no Oxfmt equivalent; Oxfmt's objectWrap only offers "preserve" and "collapse", so objects and arrays that fit on one line will not be forced to expand.`);
|
|
786
|
+
}
|
|
787
|
+
/** Biome places the operator after or before the break; Oxfmt names the same two positions. */
|
|
788
|
+
function mapBiomeOperatorLinebreakToOxfmt(operatorLinebreak) {
|
|
789
|
+
if (operatorLinebreak === "after") return "end";
|
|
790
|
+
if (operatorLinebreak === "before") return "start";
|
|
791
|
+
}
|
|
752
792
|
function generateOxfmtOverrides(biomeOverrides, reporter) {
|
|
753
793
|
if (!biomeOverrides || biomeOverrides.length === 0) return [];
|
|
754
794
|
const oxfmtOverrides = [];
|
|
@@ -792,7 +832,11 @@ function mapBaseFormatterOptions(formatter, reporter) {
|
|
|
792
832
|
if (formatter.indentWidth !== void 0) options.tabWidth = formatter.indentWidth;
|
|
793
833
|
if (formatter.lineEnding !== void 0) options.endOfLine = formatter.lineEnding;
|
|
794
834
|
if (formatter.bracketSpacing !== void 0) options.bracketSpacing = formatter.bracketSpacing;
|
|
835
|
+
if (formatter.bracketSameLine !== void 0) options.bracketSameLine = formatter.bracketSameLine;
|
|
795
836
|
if (formatter.attributePosition !== void 0) options.singleAttributePerLine = formatter.attributePosition === "multiline";
|
|
837
|
+
const objectWrap = mapBiomeExpandToObjectWrap(formatter.expand, "formatter", reporter);
|
|
838
|
+
if (objectWrap) options.objectWrap = objectWrap;
|
|
839
|
+
if (formatter.trailingNewline !== void 0) options.insertFinalNewline = formatter.trailingNewline;
|
|
796
840
|
if (formatter.formatWithErrors) reporter.warn("Biome's formatWithErrors option is not supported in Oxfmt overrides");
|
|
797
841
|
applyExplicitFormatterOptionPassThrough$1([formatter], options, reporter);
|
|
798
842
|
return options;
|
|
@@ -812,6 +856,12 @@ function mapJavaScriptFormatterOptions(jsFormatter, reporter) {
|
|
|
812
856
|
if (jsFormatter.arrowParentheses !== void 0) options.arrowParens = jsFormatter.arrowParentheses === "always" ? "always" : "avoid";
|
|
813
857
|
if (jsFormatter.bracketSpacing !== void 0) options.bracketSpacing = jsFormatter.bracketSpacing;
|
|
814
858
|
if (jsFormatter.bracketSameLine !== void 0) options.bracketSameLine = jsFormatter.bracketSameLine;
|
|
859
|
+
if (jsFormatter.attributePosition !== void 0) options.singleAttributePerLine = jsFormatter.attributePosition === "multiline";
|
|
860
|
+
const objectWrap = mapBiomeExpandToObjectWrap(jsFormatter.expand, "javascript.formatter", reporter);
|
|
861
|
+
if (objectWrap) options.objectWrap = objectWrap;
|
|
862
|
+
const operatorPosition = mapBiomeOperatorLinebreakToOxfmt(jsFormatter.operatorLinebreak);
|
|
863
|
+
if (operatorPosition) options.experimentalOperatorPosition = operatorPosition;
|
|
864
|
+
if (jsFormatter.trailingNewline !== void 0) options.insertFinalNewline = jsFormatter.trailingNewline;
|
|
815
865
|
applyExplicitFormatterOptionPassThrough$1([jsFormatter], options, reporter);
|
|
816
866
|
return options;
|
|
817
867
|
}
|
|
@@ -824,6 +874,9 @@ function mapJsonFormatterOptions(jsonFormatter, reporter) {
|
|
|
824
874
|
if (jsonFormatter.indentWidth !== void 0) options.tabWidth = jsonFormatter.indentWidth;
|
|
825
875
|
if (jsonFormatter.lineEnding !== void 0) options.endOfLine = jsonFormatter.lineEnding;
|
|
826
876
|
if (jsonFormatter.trailingCommas !== void 0) options.trailingComma = jsonFormatter.trailingCommas === "none" ? "none" : "all";
|
|
877
|
+
const objectWrap = mapBiomeExpandToObjectWrap(jsonFormatter.expand, "json.formatter", reporter);
|
|
878
|
+
if (objectWrap) options.objectWrap = objectWrap;
|
|
879
|
+
if (jsonFormatter.trailingNewline !== void 0) options.insertFinalNewline = jsonFormatter.trailingNewline;
|
|
827
880
|
applyExplicitFormatterOptionPassThrough$1([jsonFormatter], options, reporter);
|
|
828
881
|
return options;
|
|
829
882
|
}
|
|
@@ -836,6 +889,7 @@ function mapCssFormatterOptions(cssFormatter, reporter) {
|
|
|
836
889
|
if (cssFormatter.indentWidth !== void 0) options.tabWidth = cssFormatter.indentWidth;
|
|
837
890
|
if (cssFormatter.lineEnding !== void 0) options.endOfLine = cssFormatter.lineEnding;
|
|
838
891
|
if (cssFormatter.quoteStyle !== void 0) options.singleQuote = cssFormatter.quoteStyle === "single";
|
|
892
|
+
if (cssFormatter.trailingNewline !== void 0) options.insertFinalNewline = cssFormatter.trailingNewline;
|
|
839
893
|
applyExplicitFormatterOptionPassThrough$1([cssFormatter], options, reporter);
|
|
840
894
|
return options;
|
|
841
895
|
}
|
|
@@ -878,6 +932,7 @@ function patternTargetsExtension(pattern, extensions) {
|
|
|
878
932
|
//#region src/formatter-mapper.ts
|
|
879
933
|
const EXPLICIT_OXFMT_OPTION_KEYS = [
|
|
880
934
|
"objectWrap",
|
|
935
|
+
"experimentalOperatorPosition",
|
|
881
936
|
"insertFinalNewline",
|
|
882
937
|
"embeddedLanguageFormatting",
|
|
883
938
|
"htmlWhitespaceSensitivity",
|
|
@@ -906,6 +961,9 @@ const GLOBAL_FORMATTER_KEYS = /* @__PURE__ */ new Set([
|
|
|
906
961
|
"lineWidth",
|
|
907
962
|
"attributePosition",
|
|
908
963
|
"bracketSpacing",
|
|
964
|
+
"bracketSameLine",
|
|
965
|
+
"expand",
|
|
966
|
+
"trailingNewline",
|
|
909
967
|
...EXPLICIT_OXFMT_OPTION_KEYS,
|
|
910
968
|
...Object.keys(LEGACY_EXPLICIT_OXFMT_OPTION_ALIASES)
|
|
911
969
|
]);
|
|
@@ -919,10 +977,13 @@ const JAVASCRIPT_FORMATTER_KEYS = /* @__PURE__ */ new Set([
|
|
|
919
977
|
"arrowParentheses",
|
|
920
978
|
"bracketSameLine",
|
|
921
979
|
"bracketSpacing",
|
|
980
|
+
"expand",
|
|
922
981
|
"indentStyle",
|
|
923
982
|
"indentWidth",
|
|
924
983
|
"lineEnding",
|
|
925
984
|
"lineWidth",
|
|
985
|
+
"operatorLinebreak",
|
|
986
|
+
"trailingNewline",
|
|
926
987
|
...EXPLICIT_OXFMT_OPTION_KEYS,
|
|
927
988
|
...Object.keys(LEGACY_EXPLICIT_OXFMT_OPTION_ALIASES)
|
|
928
989
|
]);
|
|
@@ -1010,9 +1071,13 @@ function mapFormatterOptions(formatter, oxfmtConfig, reporter) {
|
|
|
1010
1071
|
oxfmtConfig.arrowParens = "always";
|
|
1011
1072
|
const bracketSpacing = formatter?.bracketSpacing;
|
|
1012
1073
|
if (bracketSpacing !== void 0) oxfmtConfig.bracketSpacing = bracketSpacing;
|
|
1074
|
+
if (formatter?.bracketSameLine !== void 0) oxfmtConfig.bracketSameLine = formatter.bracketSameLine;
|
|
1013
1075
|
const attributePosition = formatter?.attributePosition;
|
|
1014
1076
|
if (attributePosition === "multiline") oxfmtConfig.singleAttributePerLine = true;
|
|
1015
1077
|
else if (attributePosition === "auto") oxfmtConfig.singleAttributePerLine = false;
|
|
1078
|
+
const objectWrap = mapBiomeExpandToObjectWrap(formatter?.expand, "formatter", reporter);
|
|
1079
|
+
if (objectWrap) oxfmtConfig.objectWrap = objectWrap;
|
|
1080
|
+
if (formatter?.trailingNewline !== void 0) oxfmtConfig.insertFinalNewline = formatter.trailingNewline;
|
|
1016
1081
|
if (formatter?.formatWithErrors) reporter.warn("Biome's formatWithErrors option is not supported in Oxfmt");
|
|
1017
1082
|
}
|
|
1018
1083
|
function mapIgnorePatterns$1(biomeConfig, oxfmtConfig, additionalIgnorePatterns) {
|
|
@@ -1290,6 +1355,40 @@ const OXLINT_CATEGORIES = [
|
|
|
1290
1355
|
"style",
|
|
1291
1356
|
"suspicious"
|
|
1292
1357
|
];
|
|
1358
|
+
/**
|
|
1359
|
+
* The React Compiler rules Oxlint activates for ESLint's `react-hooks/recommended` preset.
|
|
1360
|
+
*
|
|
1361
|
+
* Oxlint 1.79 replaced the single `react/react-compiler` rule with 22 per-diagnostic rules;
|
|
1362
|
+
* Biome's `useReactCompiler` runs the compiler and reports every bailout it finds, so the
|
|
1363
|
+
* `recommended` slice is the closest equivalent. The remaining rules default to off upstream
|
|
1364
|
+
* and would fire on code Biome never flagged.
|
|
1365
|
+
*
|
|
1366
|
+
* @see https://oxc.rs/blog/2026-08-18-react-compiler-support
|
|
1367
|
+
*/
|
|
1368
|
+
const REACT_COMPILER_RECOMMENDED_RULES = [
|
|
1369
|
+
"react/error-boundaries",
|
|
1370
|
+
"react/globals",
|
|
1371
|
+
"react/immutability",
|
|
1372
|
+
"react/incompatible-library",
|
|
1373
|
+
"react/preserve-manual-memoization",
|
|
1374
|
+
"react/purity",
|
|
1375
|
+
"react/refs",
|
|
1376
|
+
"react/set-state-in-effect",
|
|
1377
|
+
"react/set-state-in-render",
|
|
1378
|
+
"react/static-components",
|
|
1379
|
+
"react/unsupported-syntax",
|
|
1380
|
+
"react/use-memo"
|
|
1381
|
+
];
|
|
1382
|
+
/**
|
|
1383
|
+
* Mappings where the Oxlint rule covers only part of what the Biome rule checked. The note
|
|
1384
|
+
* is reported once per migration so the narrowing is visible rather than silent.
|
|
1385
|
+
*/
|
|
1386
|
+
const PARTIAL_RULE_MAPPING_NOTES = {
|
|
1387
|
+
noComponentHookFactories: "Biome rule noComponentHookFactories was mapped to react/no-unstable-nested-components, which reports nested component definitions but not nested custom hook definitions.",
|
|
1388
|
+
noReactPropAssignments: "Biome rule noReactPropAssignments was mapped to the React Compiler rule react/immutability, which reports prop mutation alongside other mutations of values React treats as immutable.",
|
|
1389
|
+
useExplicitType: "Biome rule useExplicitType was mapped to typescript/explicit-function-return-type, which requires return types on functions and methods but not types on variables or parameters.",
|
|
1390
|
+
useReactCompiler: `Biome rule useReactCompiler was mapped to Oxlint's React Compiler rules for ESLint's recommended preset (${REACT_COMPILER_RECOMMENDED_RULES.join(", ")}); the compiler rules that are off by default upstream were not enabled. See https://oxc.rs/blog/2026-08-18-react-compiler-support`
|
|
1391
|
+
};
|
|
1293
1392
|
const BIOME_TO_OXLINT_RULE_MAP = {
|
|
1294
1393
|
noAccessKey: "jsx-a11y/no-access-key",
|
|
1295
1394
|
noAdjacentSpacesInRegex: "no-regex-spaces",
|
|
@@ -1311,6 +1410,7 @@ const BIOME_TO_OXLINT_RULE_MAP = {
|
|
|
1311
1410
|
noBaseToString: "typescript/no-base-to-string",
|
|
1312
1411
|
noBeforeInteractiveScriptOutsideDocument: "nextjs/no-before-interactive-script-outside-document",
|
|
1313
1412
|
noBitwiseOperators: "no-bitwise",
|
|
1413
|
+
noBlankTarget: "react/jsx-no-target-blank",
|
|
1314
1414
|
noCatchAssign: "no-ex-assign",
|
|
1315
1415
|
noChildrenProp: "react/no-children-prop",
|
|
1316
1416
|
noClassAssign: "no-class-assign",
|
|
@@ -1321,6 +1421,7 @@ const BIOME_TO_OXLINT_RULE_MAP = {
|
|
|
1321
1421
|
"typescript/no-require-imports",
|
|
1322
1422
|
"typescript/no-var-requires"
|
|
1323
1423
|
],
|
|
1424
|
+
noComponentHookFactories: "react/no-unstable-nested-components",
|
|
1324
1425
|
noCompareNegZero: "no-compare-neg-zero",
|
|
1325
1426
|
noConfusingLabels: "no-labels",
|
|
1326
1427
|
noConfusingVoidType: "typescript/no-invalid-void-type",
|
|
@@ -1358,6 +1459,8 @@ const BIOME_TO_OXLINT_RULE_MAP = {
|
|
|
1358
1459
|
noEqualsToNull: "no-eq-null",
|
|
1359
1460
|
noExcessiveClassesPerFile: "max-classes-per-file",
|
|
1360
1461
|
noExcessiveCognitiveComplexity: "complexity",
|
|
1462
|
+
noExcessiveLinesPerFile: "max-lines",
|
|
1463
|
+
noExcessiveLinesPerFunction: "max-lines-per-function",
|
|
1361
1464
|
noExcessiveNestedCallbacks: "max-nested-callbacks",
|
|
1362
1465
|
noExplicitAny: "typescript/no-explicit-any",
|
|
1363
1466
|
noExtendNative: "no-extend-native",
|
|
@@ -1369,7 +1472,10 @@ const BIOME_TO_OXLINT_RULE_MAP = {
|
|
|
1369
1472
|
noForEach: "unicorn/no-array-for-each",
|
|
1370
1473
|
noFunctionAssign: "no-func-assign",
|
|
1371
1474
|
noGlobalAssign: "no-global-assign",
|
|
1475
|
+
noGlobalDirnameFilename: "unicorn/prefer-module",
|
|
1372
1476
|
noGlobalEval: "no-eval",
|
|
1477
|
+
noGlobalIsFinite: "unicorn/prefer-number-properties",
|
|
1478
|
+
noGlobalIsNan: "unicorn/prefer-number-properties",
|
|
1373
1479
|
noGlobalObjectCalls: "no-obj-calls",
|
|
1374
1480
|
noHeaderScope: "jsx-a11y/scope",
|
|
1375
1481
|
noHeadElement: "nextjs/no-head-element",
|
|
@@ -1389,6 +1495,7 @@ const BIOME_TO_OXLINT_RULE_MAP = {
|
|
|
1389
1495
|
noIrregularWhitespace: "no-irregular-whitespace",
|
|
1390
1496
|
noInteractiveElementToNoninteractiveRole: "jsx-a11y/no-interactive-element-to-noninteractive-role",
|
|
1391
1497
|
noInvalidNewBuiltin: "no-new-native-nonconstructor",
|
|
1498
|
+
noJsRestrictedProperties: "no-restricted-properties",
|
|
1392
1499
|
noJsxLiterals: "react/jsx-no-literals",
|
|
1393
1500
|
noJsxNamespace: "react/no-namespace",
|
|
1394
1501
|
noLabelWithoutControl: "jsx-a11y/label-has-associated-control",
|
|
@@ -1403,6 +1510,7 @@ const BIOME_TO_OXLINT_RULE_MAP = {
|
|
|
1403
1510
|
noMultilineString: "no-multi-str",
|
|
1404
1511
|
noMultiStr: "no-multi-str",
|
|
1405
1512
|
noNegationElse: "no-negated-condition",
|
|
1513
|
+
noNegationInEqualityCheck: "unicorn/no-negation-in-equality-check",
|
|
1406
1514
|
noNewSymbol: "no-new-native-nonconstructor",
|
|
1407
1515
|
noNodejsModules: "import/no-nodejs-modules",
|
|
1408
1516
|
noNamespace: "typescript/no-namespace",
|
|
@@ -1426,12 +1534,14 @@ const BIOME_TO_OXLINT_RULE_MAP = {
|
|
|
1426
1534
|
noProto: "no-proto",
|
|
1427
1535
|
noPrototypeBuiltins: "no-prototype-builtins",
|
|
1428
1536
|
noRedeclare: "no-redeclare",
|
|
1537
|
+
noReactPropAssignments: "react/immutability",
|
|
1429
1538
|
noRedundantAlt: "jsx-a11y/img-redundant-alt",
|
|
1430
1539
|
noRedundantRoles: "jsx-a11y/no-redundant-roles",
|
|
1431
1540
|
noReactStringRefs: "react/no-string-refs",
|
|
1432
1541
|
noDuplicateTestHooks: ["jest/no-duplicate-hooks", "vitest/no-duplicate-hooks"],
|
|
1433
1542
|
noConditionalExpect: ["jest/no-conditional-expect", "vitest/no-conditional-expect"],
|
|
1434
1543
|
noExcessiveNestedTestSuites: ["jest/max-nested-describe", "vitest/max-nested-describe"],
|
|
1544
|
+
noExportsInTest: "jest/no-export",
|
|
1435
1545
|
noIdenticalTestTitle: ["jest/no-identical-title", "vitest/no-identical-title"],
|
|
1436
1546
|
noMisplacedAssertion: ["jest/no-standalone-expect", "vitest/no-standalone-expect"],
|
|
1437
1547
|
noRenderReturnValue: "react/no-render-return-value",
|
|
@@ -1469,6 +1579,7 @@ const BIOME_TO_OXLINT_RULE_MAP = {
|
|
|
1469
1579
|
noUnreachable: "no-unreachable",
|
|
1470
1580
|
noUnreachableSuper: "constructor-super",
|
|
1471
1581
|
noUnsafeDeclarationMerging: "typescript/no-unsafe-declaration-merging",
|
|
1582
|
+
noUnsafeTypeAssertion: "typescript/no-unsafe-type-assertion",
|
|
1472
1583
|
noUnsafeFinally: "no-unsafe-finally",
|
|
1473
1584
|
noUnsafeNegation: "no-unsafe-negation",
|
|
1474
1585
|
noUnsafeOptionalChaining: "no-unsafe-optional-chaining",
|
|
@@ -1479,8 +1590,10 @@ const BIOME_TO_OXLINT_RULE_MAP = {
|
|
|
1479
1590
|
noUnusedVariables: "no-unused-vars",
|
|
1480
1591
|
noUnwantedPolyfillio: "nextjs/no-unwanted-polyfillio",
|
|
1481
1592
|
noUselessCatch: "no-useless-catch",
|
|
1593
|
+
noUselessContinue: "no-continue",
|
|
1482
1594
|
noUselessCatchBinding: "unicorn/prefer-optional-catch-binding",
|
|
1483
1595
|
noUselessConstructor: "no-useless-constructor",
|
|
1596
|
+
noUselessElse: "no-else-return",
|
|
1484
1597
|
noUselessEmptyExport: "typescript/no-useless-empty-export",
|
|
1485
1598
|
noUselessEscapeInRegex: "no-useless-escape",
|
|
1486
1599
|
noUselessEscapeInString: "no-useless-escape",
|
|
@@ -1497,6 +1610,7 @@ const BIOME_TO_OXLINT_RULE_MAP = {
|
|
|
1497
1610
|
noUselessTypeConstraint: "typescript/no-unnecessary-type-constraint",
|
|
1498
1611
|
noUselessTypeConversion: "typescript/no-unnecessary-type-conversion",
|
|
1499
1612
|
noUselessUndefined: "unicorn/no-useless-undefined",
|
|
1613
|
+
noUselessUndefinedInitialization: "unicorn/no-useless-undefined",
|
|
1500
1614
|
noVoid: "no-void",
|
|
1501
1615
|
noVar: "no-var",
|
|
1502
1616
|
noVoidElementsWithChildren: "react/void-dom-elements-no-children",
|
|
@@ -1537,6 +1651,7 @@ const BIOME_TO_OXLINT_RULE_MAP = {
|
|
|
1537
1651
|
useConsistentMethodSignatures: "typescript/method-signature-style",
|
|
1538
1652
|
useConsistentTypeDefinitions: "typescript/consistent-type-definitions",
|
|
1539
1653
|
useConsistentMemberAccessibility: "typescript/explicit-member-accessibility",
|
|
1654
|
+
useConsistentObjectDefinitions: "object-shorthand",
|
|
1540
1655
|
useConsistentTestIt: ["jest/consistent-test-it", "vitest/consistent-test-it"],
|
|
1541
1656
|
useConst: "prefer-const",
|
|
1542
1657
|
useDateNow: "unicorn/prefer-date-now",
|
|
@@ -1551,6 +1666,8 @@ const BIOME_TO_OXLINT_RULE_MAP = {
|
|
|
1551
1666
|
useErrorMessage: "unicorn/error-message",
|
|
1552
1667
|
useExpect: ["jest/expect-expect", "vitest/expect-expect"],
|
|
1553
1668
|
useExplicitLengthCheck: "unicorn/explicit-length-check",
|
|
1669
|
+
useExplicitReturnType: "typescript/explicit-function-return-type",
|
|
1670
|
+
useExplicitType: "typescript/explicit-function-return-type",
|
|
1554
1671
|
useExponentiationOperator: "prefer-exponentiation-operator",
|
|
1555
1672
|
useExportsLast: "import/exports-last",
|
|
1556
1673
|
useExportType: "typescript/consistent-type-exports",
|
|
@@ -1573,6 +1690,7 @@ const BIOME_TO_OXLINT_RULE_MAP = {
|
|
|
1573
1690
|
useHookAtTopLevel: "react/rules-of-hooks",
|
|
1574
1691
|
useIframeSandbox: "react/iframe-missing-sandbox",
|
|
1575
1692
|
useIframeTitle: "jsx-a11y/iframe-has-title",
|
|
1693
|
+
useImportExtensions: "import/extensions",
|
|
1576
1694
|
useImportsFirst: "import/first",
|
|
1577
1695
|
useImportType: "typescript/consistent-type-imports",
|
|
1578
1696
|
useIncludes: "typescript/prefer-includes",
|
|
@@ -1602,6 +1720,7 @@ const BIOME_TO_OXLINT_RULE_MAP = {
|
|
|
1602
1720
|
useParseIntRadix: "radix",
|
|
1603
1721
|
useReadonlyClassProperties: "typescript/prefer-readonly",
|
|
1604
1722
|
useReactFunctionComponentDefinition: "react/function-component-definition",
|
|
1723
|
+
useReactCompiler: REACT_COMPILER_RECOMMENDED_RULES,
|
|
1605
1724
|
useReactFunctionComponents: "react/prefer-function-component",
|
|
1606
1725
|
useReduceTypeParameter: "typescript/prefer-reduce-type-parameter",
|
|
1607
1726
|
useRegexLiterals: "prefer-regex-literals",
|
|
@@ -1611,6 +1730,7 @@ const BIOME_TO_OXLINT_RULE_MAP = {
|
|
|
1611
1730
|
useSelfClosingElements: "react/self-closing-comp",
|
|
1612
1731
|
useShorthandAssign: "operator-assignment",
|
|
1613
1732
|
useShorthandFunctionType: "typescript/prefer-function-type",
|
|
1733
|
+
useSingleVarDeclarator: "one-var",
|
|
1614
1734
|
useSimplifiedLogicExpression: "unicorn/prefer-logical-operator-over-ternary",
|
|
1615
1735
|
useSpread: "prefer-spread",
|
|
1616
1736
|
useSpreadOverApply: "prefer-spread",
|
|
@@ -1639,6 +1759,7 @@ const BIOME_TO_OXLINT_RULE_MAP = {
|
|
|
1639
1759
|
useYield: "require-yield"
|
|
1640
1760
|
};
|
|
1641
1761
|
const WARNED_UNMAPPED_RULES_BY_REPORTER = /* @__PURE__ */ new WeakMap();
|
|
1762
|
+
const WARNED_PARTIAL_MAPPINGS_BY_REPORTER = /* @__PURE__ */ new WeakMap();
|
|
1642
1763
|
const WARNED_UNSUPPORTED_SEVERITIES_BY_REPORTER = /* @__PURE__ */ new WeakMap();
|
|
1643
1764
|
const OXLINT_SEVERITY_NORMALIZATION = {
|
|
1644
1765
|
allow: "off",
|
|
@@ -1663,6 +1784,20 @@ function mapBiomeRuleOptionsToOxlintSeverity(biomeName, severity, biomeSeverity,
|
|
|
1663
1784
|
if (biomeName === "noExcessiveNestedCallbacks") return [severity, { max: options && isNonNegativeInteger(options.max) ? options.max : 5 }];
|
|
1664
1785
|
if (biomeName === "useErrorCause") return [severity, { requireCatchParameter: options && typeof options.requireCatchParameter === "boolean" ? options.requireCatchParameter : true }];
|
|
1665
1786
|
if (biomeName === "useMaxParams") return [severity, { max: options && isNonNegativeInteger(options.max) ? options.max : 4 }];
|
|
1787
|
+
if (biomeName === "noExcessiveLinesPerFile") return [severity, {
|
|
1788
|
+
max: options && isNonNegativeInteger(options.maxLines) ? options.maxLines : 300,
|
|
1789
|
+
skipBlankLines: options?.skipBlankLines === true
|
|
1790
|
+
}];
|
|
1791
|
+
if (biomeName === "noExcessiveLinesPerFunction") return [severity, {
|
|
1792
|
+
max: options && isNonNegativeInteger(options.maxLines) ? options.maxLines : 50,
|
|
1793
|
+
skipBlankLines: options?.skipBlankLines === true,
|
|
1794
|
+
IIFEs: options?.skipIifes !== true
|
|
1795
|
+
}];
|
|
1796
|
+
if (biomeName === "useSingleVarDeclarator") return [severity, "never"];
|
|
1797
|
+
if (biomeName === "useImportExtensions") {
|
|
1798
|
+
if (options?.extensionMappings !== void 0 || options?.forceJsExtensions !== void 0) reporter.loss("Biome rule useImportExtensions options \"extensionMappings\" and \"forceJsExtensions\" are not supported by Oxlint import/extensions; the rule requires an extension without rewriting it.");
|
|
1799
|
+
return [severity, "ignorePackages"];
|
|
1800
|
+
}
|
|
1666
1801
|
if (biomeName === "noTsIgnore") return [severity, {
|
|
1667
1802
|
"ts-ignore": true,
|
|
1668
1803
|
"ts-expect-error": false,
|
|
@@ -1714,6 +1849,22 @@ function mapBiomeRuleOptionsToOxlintSeverity(biomeName, severity, biomeSeverity,
|
|
|
1714
1849
|
{ requireReturnForObjectLiteral: options.requireForObjectLiteral }
|
|
1715
1850
|
] : [severity, mode];
|
|
1716
1851
|
}
|
|
1852
|
+
if (biomeName === "noJsRestrictedProperties") {
|
|
1853
|
+
const { entries } = options;
|
|
1854
|
+
if (!Array.isArray(entries) || !entries.every(isRecord)) return severity;
|
|
1855
|
+
return [severity, ...entries];
|
|
1856
|
+
}
|
|
1857
|
+
if (biomeName === "useConsistentObjectDefinitions") {
|
|
1858
|
+
const { syntax } = options;
|
|
1859
|
+
return syntax === "shorthand" ? [severity, "always"] : syntax === "explicit" ? [severity, "never"] : severity;
|
|
1860
|
+
}
|
|
1861
|
+
if (biomeName === "useExplicitReturnType") {
|
|
1862
|
+
const oxlintOptions = {};
|
|
1863
|
+
if (typeof options.allowExpressions === "boolean") oxlintOptions.allowExpressions = options.allowExpressions;
|
|
1864
|
+
if (typeof options.allowIifes === "boolean") oxlintOptions.allowIIFEs = options.allowIifes;
|
|
1865
|
+
if (Array.isArray(options.allowedNames) && options.allowedNames.every((value) => typeof value === "string")) oxlintOptions.allowedNames = options.allowedNames;
|
|
1866
|
+
return Object.keys(oxlintOptions).length > 0 ? [severity, oxlintOptions] : severity;
|
|
1867
|
+
}
|
|
1717
1868
|
if (biomeName === "useConsistentMethodSignatures") {
|
|
1718
1869
|
const { style } = options;
|
|
1719
1870
|
return style === "method" || style === "property" ? [severity, style] : severity;
|
|
@@ -1780,10 +1931,24 @@ function mapBiomeRuleSeverity(severity, reporter, biomeRuleName) {
|
|
|
1780
1931
|
}
|
|
1781
1932
|
function mapBiomeRuleToOxlintRules(biomeName, reporter) {
|
|
1782
1933
|
const mapped = BIOME_TO_OXLINT_RULE_MAP[biomeName];
|
|
1783
|
-
if (mapped)
|
|
1934
|
+
if (mapped) {
|
|
1935
|
+
const partialMappingNote = PARTIAL_RULE_MAPPING_NOTES[biomeName];
|
|
1936
|
+
if (partialMappingNote) warnPartialMappingOnce(biomeName, partialMappingNote, reporter);
|
|
1937
|
+
return [...new Set((Array.isArray(mapped) ? mapped : [mapped]).map((ruleName) => normalizeOxlintRuleName(ruleName)))];
|
|
1938
|
+
}
|
|
1784
1939
|
warnUnmappedRuleOnce(biomeName, reporter);
|
|
1785
1940
|
return [];
|
|
1786
1941
|
}
|
|
1942
|
+
function warnPartialMappingOnce(biomeName, note, reporter) {
|
|
1943
|
+
let warnedRules = WARNED_PARTIAL_MAPPINGS_BY_REPORTER.get(reporter);
|
|
1944
|
+
if (!warnedRules) {
|
|
1945
|
+
warnedRules = /* @__PURE__ */ new Set();
|
|
1946
|
+
WARNED_PARTIAL_MAPPINGS_BY_REPORTER.set(reporter, warnedRules);
|
|
1947
|
+
}
|
|
1948
|
+
if (warnedRules.has(biomeName)) return;
|
|
1949
|
+
warnedRules.add(biomeName);
|
|
1950
|
+
reporter.loss(note);
|
|
1951
|
+
}
|
|
1787
1952
|
function warnUnmappedRuleOnce(biomeName, reporter) {
|
|
1788
1953
|
let warnedRules = WARNED_UNMAPPED_RULES_BY_REPORTER.get(reporter);
|
|
1789
1954
|
if (!warnedRules) {
|
|
@@ -2121,15 +2286,19 @@ async function updatePackageJson(projectDir, reporter, dryRun, options = {}) {
|
|
|
2121
2286
|
summary.found = true;
|
|
2122
2287
|
let modified = false;
|
|
2123
2288
|
const updateScriptsEnabled = options.updateScripts ?? false;
|
|
2289
|
+
const domModeEnabled = options.dom ?? false;
|
|
2124
2290
|
const removeBiomeAllowed = options.removeBiome ?? false;
|
|
2125
2291
|
const typeAwareProfile = options.typeAwareProfile ?? "standard";
|
|
2126
2292
|
const typeCheckEnabled = options.typeCheck ?? typeAwareProfile === "strict";
|
|
2127
2293
|
const typeAwareEnabled = options.typeAware ?? (typeCheckEnabled || typeAwareProfile === "strict");
|
|
2128
|
-
const needsTypeAwareDependency = typeAwareEnabled || typeCheckEnabled;
|
|
2294
|
+
const needsTypeAwareDependency = typeAwareEnabled || typeCheckEnabled || domModeEnabled;
|
|
2129
2295
|
const fixStrategy = options.fixStrategy ?? "safe";
|
|
2130
2296
|
const oxlintCommand = buildConfiguredCommand("oxlint", packageJsonPath, options.oxlintConfigPath);
|
|
2131
2297
|
const oxfmtCommand = buildConfiguredCommand("oxfmt", packageJsonPath, options.oxfmtConfigPath);
|
|
2132
|
-
if (
|
|
2298
|
+
if (domModeEnabled) {
|
|
2299
|
+
packageJson.scripts ??= {};
|
|
2300
|
+
modified = applyDomScriptPreset(packageJson.scripts, summary.scriptsUpdated, oxlintCommand, oxfmtCommand) || modified;
|
|
2301
|
+
} else if (updateScriptsEnabled && packageJson.scripts) modified = updateScripts(packageJson.scripts, reporter, summary.scriptsUpdated, {
|
|
2133
2302
|
typeAwareEnabled,
|
|
2134
2303
|
typeCheckEnabled,
|
|
2135
2304
|
fixStrategy,
|
|
@@ -2204,6 +2373,32 @@ async function detectLockfile(packageRoot, dependenciesChanged) {
|
|
|
2204
2373
|
};
|
|
2205
2374
|
}
|
|
2206
2375
|
}
|
|
2376
|
+
function applyDomScriptPreset(scripts, updates, oxlintCommand, oxfmtCommand) {
|
|
2377
|
+
let modified = false;
|
|
2378
|
+
const preset = {
|
|
2379
|
+
check: `${oxlintCommand} . && ${oxfmtCommand} --check .`,
|
|
2380
|
+
"check:fix": `${oxlintCommand} --fix . && ${oxfmtCommand} --write .`,
|
|
2381
|
+
format: `${oxfmtCommand} --write .`,
|
|
2382
|
+
"format:check": `${oxfmtCommand} --check .`,
|
|
2383
|
+
lint: `${oxlintCommand} -f github . > lint.md 2>&1`,
|
|
2384
|
+
"lint:fix": `${oxlintCommand} -f stylish --fix .`,
|
|
2385
|
+
"lint:fix-unsafe": `${oxlintCommand} -f stylish --react-plugin --import-plugin --react-perf-plugin --nextjs-plugin --type-aware --type-check --vitest-plugin --fix --fix-suggestions --fix-dangerously .`,
|
|
2386
|
+
"check:fix-suggestions": `${oxlintCommand} -f stylish --react-plugin --import-plugin --react-perf-plugin --nextjs-plugin --type-aware --type-check --vitest-plugin --fix --fix-suggestions . && ${oxfmtCommand} --write .`,
|
|
2387
|
+
"type-check": "tsc --noEmit"
|
|
2388
|
+
};
|
|
2389
|
+
for (const [scriptName, scriptValue] of Object.entries(preset)) {
|
|
2390
|
+
const before = scripts[scriptName];
|
|
2391
|
+
if (before === scriptValue) continue;
|
|
2392
|
+
scripts[scriptName] = scriptValue;
|
|
2393
|
+
updates.push({
|
|
2394
|
+
name: scriptName,
|
|
2395
|
+
before: before ?? "<missing>",
|
|
2396
|
+
after: scriptValue
|
|
2397
|
+
});
|
|
2398
|
+
modified = true;
|
|
2399
|
+
}
|
|
2400
|
+
return modified;
|
|
2401
|
+
}
|
|
2207
2402
|
function updateScripts(scripts, reporter, updates, options) {
|
|
2208
2403
|
let modified = false;
|
|
2209
2404
|
const lintBase = buildLintBaseCommand(options.oxlintCommand, options.typeAwareEnabled, options.typeCheckEnabled);
|
|
@@ -2810,6 +3005,7 @@ async function runMigration(options, reporter, biomeConfigPath) {
|
|
|
2810
3005
|
const packageJsonErrorCount = reporter.getErrors().length;
|
|
2811
3006
|
packageJsonSummary = await updatePackageJson(projectDir, reporter, false, {
|
|
2812
3007
|
updateScripts: options.updateScripts,
|
|
3008
|
+
dom: options.dom,
|
|
2813
3009
|
removeBiome: cleanupAllowed,
|
|
2814
3010
|
typeAware: typeAwareEnabled,
|
|
2815
3011
|
typeCheck: typeCheckEnabled,
|
|
@@ -2838,6 +3034,7 @@ async function runMigration(options, reporter, biomeConfigPath) {
|
|
|
2838
3034
|
const packageJsonErrorCount = reporter.getErrors().length;
|
|
2839
3035
|
packageJsonSummary = await updatePackageJson(projectDir, reporter, true, {
|
|
2840
3036
|
updateScripts: options.updateScripts,
|
|
3037
|
+
dom: options.dom,
|
|
2841
3038
|
removeBiome: cleanupAllowed,
|
|
2842
3039
|
typeAware: typeAwareEnabled,
|
|
2843
3040
|
typeCheck: typeCheckEnabled,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "biome-to-oxc",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Migrate from Biome to Oxc ecosystem (oxlint + oxfmt + oxlint-tsgolint)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"biome",
|
|
@@ -32,6 +32,24 @@
|
|
|
32
32
|
"types": "./dist/src/index.d.mts",
|
|
33
33
|
"import": "./dist/src/index.mjs"
|
|
34
34
|
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"test": "vitest",
|
|
37
|
+
"test:run": "vitest --run",
|
|
38
|
+
"test:coverage": "vitest --run --coverage",
|
|
39
|
+
"format": "oxfmt --write .",
|
|
40
|
+
"format:check": "oxfmt --check .",
|
|
41
|
+
"lint": "oxlint .",
|
|
42
|
+
"lint:fix": "oxlint --fix .",
|
|
43
|
+
"lint:fix-unsafe": "oxlint --import-plugin --node-plugin --type-aware --type-check --vitest-plugin --fix --fix-suggestions --fix-dangerously .",
|
|
44
|
+
"check:fix-suggestions": "oxlint --import-plugin --node-plugin --type-aware --type-check --vitest-plugin --fix --fix-suggestions . && oxfmt --write .",
|
|
45
|
+
"typecheck": "tsc --noEmit",
|
|
46
|
+
"docs:sync": "node scripts/sync-rule-inventories.ts",
|
|
47
|
+
"docs:check": "node scripts/sync-rule-inventories.ts --check",
|
|
48
|
+
"check": "pnpm format:check && pnpm lint && pnpm typecheck && pnpm docs:check && pnpm test:run",
|
|
49
|
+
"build": "tsdown",
|
|
50
|
+
"dev": "tsdown --watch",
|
|
51
|
+
"prepublishOnly": "pnpm check && pnpm build"
|
|
52
|
+
},
|
|
35
53
|
"dependencies": {
|
|
36
54
|
"commander": "15.0.0",
|
|
37
55
|
"jsonc-parser": "next",
|
|
@@ -40,34 +58,20 @@
|
|
|
40
58
|
},
|
|
41
59
|
"devDependencies": {
|
|
42
60
|
"@arethetypeswrong/core": "^0.18.5",
|
|
43
|
-
"@biomejs/biome": "^2.5.
|
|
61
|
+
"@biomejs/biome": "^2.5.9",
|
|
44
62
|
"@types/node": "^26.2.0",
|
|
45
|
-
"@vitest/coverage-v8": "^4.1.
|
|
46
|
-
"oxfmt": "^0.
|
|
47
|
-
"oxlint": "^1.
|
|
63
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
64
|
+
"oxfmt": "^0.64.0",
|
|
65
|
+
"oxlint": "^1.79.0",
|
|
48
66
|
"oxlint-tsgolint": "^7.0.2001",
|
|
49
|
-
"publint": "^0.3.
|
|
67
|
+
"publint": "^0.3.24",
|
|
50
68
|
"tsdown": "^0.22.14",
|
|
51
|
-
"typescript": "
|
|
52
|
-
"vitest": "^4.1.
|
|
69
|
+
"typescript": "next",
|
|
70
|
+
"vitest": "^4.1.11"
|
|
53
71
|
},
|
|
54
72
|
"engines": {
|
|
55
73
|
"node": ">=24.19.0",
|
|
56
|
-
"pnpm": ">=11.
|
|
74
|
+
"pnpm": ">=11.22.0"
|
|
57
75
|
},
|
|
58
|
-
"
|
|
59
|
-
|
|
60
|
-
"test:run": "vitest --run",
|
|
61
|
-
"test:coverage": "vitest --run --coverage",
|
|
62
|
-
"format": "oxfmt --write .",
|
|
63
|
-
"format:check": "oxfmt --check .",
|
|
64
|
-
"lint": "oxlint .",
|
|
65
|
-
"lint:fix": "oxlint --fix .",
|
|
66
|
-
"lint:fix-unsafe": "oxlint --import-plugin --node-plugin --type-aware --type-check --vitest-plugin --fix --fix-suggestions --fix-dangerously .",
|
|
67
|
-
"check:fix-suggestions": "oxlint --import-plugin --node-plugin --type-aware --type-check --vitest-plugin --fix --fix-suggestions . && oxfmt --write .",
|
|
68
|
-
"typecheck": "tsc --noEmit",
|
|
69
|
-
"check": "pnpm format:check && pnpm lint && pnpm typecheck && pnpm test:run",
|
|
70
|
-
"build": "tsdown",
|
|
71
|
-
"dev": "tsdown --watch"
|
|
72
|
-
}
|
|
73
|
-
}
|
|
76
|
+
"packageManager": "pnpm@11.22.0"
|
|
77
|
+
}
|