load-oxfmt-config 0.27.0 → 0.29.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 +23 -4
- package/dist/index.d.mts +7 -2
- package/dist/index.mjs +24 -21
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -33,9 +33,24 @@ yarn add oxfmt load-oxfmt-config
|
|
|
33
33
|
pnpm add oxfmt load-oxfmt-config
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
> `oxfmt >=0.
|
|
36
|
+
> `oxfmt >=0.74.0` is a peer dependency and is installed alongside this package.
|
|
37
37
|
> Node.js `^22.13.0 || >=24` is supported.
|
|
38
38
|
|
|
39
|
+
Oxfmt 0.74.0 accepts BOM-prefixed JSON/JSONC configs and uses EditorConfig
|
|
40
|
+
`indent_size` as a fallback when `tab_width` is absent, including for tab or
|
|
41
|
+
unspecified indentation styles. The loader follows these changes and preserves
|
|
42
|
+
out-of-range widths so oxfmt reports configuration errors instead of silently
|
|
43
|
+
wrapping them. Config merge precedence is unchanged, and no options were added,
|
|
44
|
+
renamed, or removed. See the upstream
|
|
45
|
+
[0.74.0 release notes](https://github.com/oxc-project/oxc/releases/tag/oxfmt_v0.74.0).
|
|
46
|
+
|
|
47
|
+
Oxfmt 0.73.0 adds `associations` and `astro` options. The loader preserves
|
|
48
|
+
association entries and Astro options in `OxfmtOptions`; it does not select a
|
|
49
|
+
formatter. Association globs are relative to the returned config `dirname`, and
|
|
50
|
+
later matching entries win. Consumers must resolve these before calling oxfmt's
|
|
51
|
+
`format()` API, which does not evaluate `associations`. Symlinked configs are
|
|
52
|
+
already discovered, with relative patterns based on the link's directory.
|
|
53
|
+
|
|
39
54
|
## Usage
|
|
40
55
|
|
|
41
56
|
### Basic Usage
|
|
@@ -462,7 +477,7 @@ The loader reads the nearest `.editorconfig` file and maps the subset of fields
|
|
|
462
477
|
|
|
463
478
|
- `end_of_line` → `endOfLine`
|
|
464
479
|
- `indent_style` → `useTabs`
|
|
465
|
-
- `indent_size` → `tabWidth` when `indent_style = space`
|
|
480
|
+
- `indent_size` → `tabWidth` when `indent_style = space`, or as a fallback when `tab_width` is absent
|
|
466
481
|
- `tab_width` → `tabWidth`
|
|
467
482
|
- `max_line_length` → `printWidth`
|
|
468
483
|
- `insert_final_newline` → `insertFinalNewline`
|
|
@@ -473,7 +488,10 @@ sections also generates an override to preserve source order. Other sections
|
|
|
473
488
|
such as `[**]` and `[*.ts]` are converted into returned `overrides` entries;
|
|
474
489
|
basename patterns such as `*.ts` are normalized to `**/*.ts` to match descendants.
|
|
475
490
|
The per-file API evaluates matching sections directly, without rebasing them to
|
|
476
|
-
the oxfmt config directory.
|
|
491
|
+
the oxfmt config directory. It combines their raw properties before selecting
|
|
492
|
+
`tabWidth`, so a scoped `indent_size` preserves an inherited `tab_width` unless
|
|
493
|
+
the effective `indent_style` is `space`. Static overrides inherit global
|
|
494
|
+
indentation properties when selecting their widths.
|
|
477
495
|
|
|
478
496
|
## Ignore Strategy
|
|
479
497
|
|
|
@@ -525,7 +543,8 @@ Section-specific `.editorconfig` entries are represented as generated `overrides
|
|
|
525
543
|
|
|
526
544
|
`loadOxfmtConfig()` returns a static merged `OxfmtOptions` shape. Its generated
|
|
527
545
|
EditorConfig globs cannot represent every relationship between config directories,
|
|
528
|
-
particularly an ancestor EditorConfig with a nested oxfmt config
|
|
546
|
+
particularly an ancestor EditorConfig with a nested oxfmt config, or width
|
|
547
|
+
interactions between overlapping scoped sections. Use
|
|
529
548
|
`loadOxfmtConfigForFile()` to resolve EditorConfig against its original directory
|
|
530
549
|
for a specific target file. Both APIs retain the nearest-file discovery strategy;
|
|
531
550
|
they do not merge multiple EditorConfig files.
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FormatConfig } from "oxfmt";
|
|
1
|
+
import { FormatConfig, OxfmtAssociationConfig } from "oxfmt";
|
|
2
2
|
//#region src/types.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* Object-form `.editorconfig` option for fine-grained lookup control.
|
|
@@ -177,9 +177,14 @@ export interface OxfmtConfigOverride {
|
|
|
177
177
|
options?: FormatConfig;
|
|
178
178
|
}
|
|
179
179
|
/**
|
|
180
|
-
* Final oxfmt options, including config
|
|
180
|
+
* Final oxfmt options, including config associations, ignore patterns, and overrides.
|
|
181
181
|
*/
|
|
182
182
|
export interface OxfmtOptions extends FormatConfig {
|
|
183
|
+
/**
|
|
184
|
+
* File language associations, relative to the config directory.
|
|
185
|
+
* Later matching entries take precedence. The loader preserves these for consumers.
|
|
186
|
+
*/
|
|
187
|
+
associations?: OxfmtAssociationConfig[];
|
|
183
188
|
/**
|
|
184
189
|
* Ignore files matching these glob patterns.
|
|
185
190
|
*
|
package/dist/index.mjs
CHANGED
|
@@ -234,7 +234,7 @@ async function readConfigFromFile(resolvedPath, options = {}) {
|
|
|
234
234
|
if (!useCache && extension === ".js") return readConfigDefaultExport(await importFreshJavaScriptConfigModule(resolvedPath));
|
|
235
235
|
return readConfigDefaultExport(await importJitiConfigModule(resolvedPath, useCache));
|
|
236
236
|
}
|
|
237
|
-
const content = await readFile(resolvedPath, "utf8");
|
|
237
|
+
const content = (await readFile(resolvedPath, "utf8")).replace(/^\u{FEFF}/u, "");
|
|
238
238
|
if (extension === ".jsonc") {
|
|
239
239
|
const parseErrors = [];
|
|
240
240
|
const parsed = parse(content, parseErrors, {
|
|
@@ -550,7 +550,8 @@ async function readEditorconfigFromFile(editorconfigPath, anchorDir, options = {
|
|
|
550
550
|
const readSections = async () => parseBuffer(await readFile(editorconfigPath));
|
|
551
551
|
const parsedSections = useCache ? await cachePromise(sectionCache, editorconfigPath, readSections) : await readSections();
|
|
552
552
|
const editorconfigDir = dirname(editorconfigPath);
|
|
553
|
-
|
|
553
|
+
let rootOptions = {};
|
|
554
|
+
const resolvedSection = {};
|
|
554
555
|
const overrides = [];
|
|
555
556
|
const relativeFile = options.filepath ? toPosixPath(relative(editorconfigDir, options.filepath)) : void 0;
|
|
556
557
|
if (relativeFile !== void 0 && isPathOutsideBase(relativeFile)) return {
|
|
@@ -559,16 +560,17 @@ async function readEditorconfigFromFile(editorconfigPath, anchorDir, options = {
|
|
|
559
560
|
};
|
|
560
561
|
for (const [sectionName, sectionBody] of parsedSections) {
|
|
561
562
|
if (!sectionName) continue;
|
|
562
|
-
const mappedOptions = mapEditorconfigSectionToOptions(sectionBody);
|
|
563
|
-
if (Object.keys(mappedOptions).length === 0) continue;
|
|
564
563
|
if (relativeFile !== void 0) {
|
|
565
|
-
if (matchesEditorconfigSection(sectionName, relativeFile, useCache)) Object.assign(
|
|
564
|
+
if (matchesEditorconfigSection(sectionName, relativeFile, useCache)) Object.assign(resolvedSection, sectionBody);
|
|
566
565
|
continue;
|
|
567
566
|
}
|
|
567
|
+
const mappedOptions = mapEditorconfigSectionToOptions(sectionBody, resolvedSection);
|
|
568
568
|
if (isEditorconfigGlobalSection(sectionName)) {
|
|
569
|
-
Object.assign(
|
|
569
|
+
Object.assign(resolvedSection, sectionBody);
|
|
570
|
+
rootOptions = mapEditorconfigSectionToOptions(resolvedSection);
|
|
570
571
|
if (overrides.length === 0) continue;
|
|
571
572
|
}
|
|
573
|
+
if (Object.keys(mappedOptions).length === 0) continue;
|
|
572
574
|
overrides.push({
|
|
573
575
|
options: mappedOptions,
|
|
574
576
|
files: [rebaseEditorconfigPattern(sectionName, editorconfigDir, anchorDir)]
|
|
@@ -576,7 +578,7 @@ async function readEditorconfigFromFile(editorconfigPath, anchorDir, options = {
|
|
|
576
578
|
}
|
|
577
579
|
return {
|
|
578
580
|
overrides,
|
|
579
|
-
rootOptions
|
|
581
|
+
rootOptions: relativeFile === void 0 ? rootOptions : mapEditorconfigSectionToOptions(resolvedSection)
|
|
580
582
|
};
|
|
581
583
|
}
|
|
582
584
|
/**
|
|
@@ -615,9 +617,10 @@ function isEditorconfigGlobalSection(sectionName) {
|
|
|
615
617
|
* Maps a parsed EditorConfig section to the subset of oxfmt formatter options it supports.
|
|
616
618
|
*
|
|
617
619
|
* @param section - The parsed EditorConfig section body.
|
|
620
|
+
* @param inheritedSection - Global properties inherited by a static override.
|
|
618
621
|
* @returns Formatter options derived from the section.
|
|
619
622
|
*/
|
|
620
|
-
function mapEditorconfigSectionToOptions(section) {
|
|
623
|
+
function mapEditorconfigSectionToOptions(section, inheritedSection = {}) {
|
|
621
624
|
const options = {};
|
|
622
625
|
const endOfLine = parseEditorconfigEndOfLine(section.end_of_line);
|
|
623
626
|
if (endOfLine) options.endOfLine = endOfLine;
|
|
@@ -625,8 +628,13 @@ function mapEditorconfigSectionToOptions(section) {
|
|
|
625
628
|
else if (section.indent_style === "space") options.useTabs = false;
|
|
626
629
|
const singleQuote = parseEditorconfigQuoteType(section.quote_type);
|
|
627
630
|
if (isBoolean(singleQuote)) options.singleQuote = singleQuote;
|
|
628
|
-
|
|
629
|
-
|
|
631
|
+
if (section.indent_style !== void 0 || section.indent_size !== void 0 || section.tab_width !== void 0) {
|
|
632
|
+
const tabWidth = parseEditorconfigTabWidth({
|
|
633
|
+
...inheritedSection,
|
|
634
|
+
...section
|
|
635
|
+
});
|
|
636
|
+
if (isNumber(tabWidth)) options.tabWidth = tabWidth;
|
|
637
|
+
}
|
|
630
638
|
if (section.max_line_length && section.max_line_length !== "unset") {
|
|
631
639
|
const parsedPrintWidth = Number(section.max_line_length);
|
|
632
640
|
if (Number.isFinite(parsedPrintWidth)) options.printWidth = parsedPrintWidth;
|
|
@@ -703,19 +711,14 @@ function parseEditorconfigQuoteType(value) {
|
|
|
703
711
|
* Resolves the effective tab width from an EditorConfig section.
|
|
704
712
|
*
|
|
705
713
|
* @param section - The parsed EditorConfig section body.
|
|
706
|
-
* @param useTabs - The resolved indent style from the same section, when available.
|
|
707
714
|
* @returns The resolved tab width, or undefined when no numeric value is available.
|
|
708
715
|
*/
|
|
709
|
-
function parseEditorconfigTabWidth(section
|
|
710
|
-
const
|
|
711
|
-
const
|
|
712
|
-
|
|
713
|
-
const
|
|
714
|
-
if (Number.isFinite(
|
|
715
|
-
}
|
|
716
|
-
if (tabWidth && tabWidth !== "unset") {
|
|
717
|
-
const parsedTabWidth = Number(tabWidth);
|
|
718
|
-
if (Number.isFinite(parsedTabWidth)) return parsedTabWidth;
|
|
716
|
+
function parseEditorconfigTabWidth(section) {
|
|
717
|
+
const values = section.indent_style === "space" ? [section.indent_size, section.tab_width] : [section.tab_width, section.indent_size];
|
|
718
|
+
for (const value of values) {
|
|
719
|
+
if (!value || value === "unset" || value === "tab") continue;
|
|
720
|
+
const parsedWidth = Number(value);
|
|
721
|
+
if (Number.isFinite(parsedWidth)) return parsedWidth;
|
|
719
722
|
}
|
|
720
723
|
}
|
|
721
724
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "load-oxfmt-config",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.29.0",
|
|
5
5
|
"description": "Load and resolve oxfmt configuration files, including explicit JS/TS config paths, and merge supported `.editorconfig` settings for Oxfmt.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"editorconfig",
|
|
@@ -43,12 +43,12 @@
|
|
|
43
43
|
},
|
|
44
44
|
"sideEffects": false,
|
|
45
45
|
"peerDependencies": {
|
|
46
|
-
"oxfmt": ">=0.
|
|
46
|
+
"oxfmt": ">=0.74.0"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@ntnyq/utils": "^0.23.0",
|
|
50
50
|
"editorconfig": "^3.0.2",
|
|
51
|
-
"ignore": "^7.0.
|
|
51
|
+
"ignore": "^7.0.13",
|
|
52
52
|
"jiti": "^2.7.0",
|
|
53
53
|
"jsonc-parser": "^3.3.1",
|
|
54
54
|
"minimatch": "~10.2.6"
|