load-oxfmt-config 0.7.2 → 0.9.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 +55 -102
- package/dist/index.d.mts +20 -36
- package/dist/index.mjs +89 -42
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/load-oxfmt-config)
|
|
6
6
|
[](https://github.com/ntnyq/load-oxfmt-config/blob/main/LICENSE)
|
|
7
7
|
|
|
8
|
-
> Load and resolve oxfmt configuration files and merge supported `.editorconfig` settings for [oxfmt](https://oxc.rs/docs/guide/usage/formatter.html).
|
|
8
|
+
> Load and resolve oxfmt configuration files, including explicit JS/TS config paths, and merge supported `.editorconfig` settings for [oxfmt](https://oxc.rs/docs/guide/usage/formatter.html).
|
|
9
9
|
|
|
10
10
|
## Features
|
|
11
11
|
|
|
12
12
|
- 🔍 **Auto-discovery** - Automatically searches for config files in current and parent directories
|
|
13
|
-
- 📦 **Multiple formats** -
|
|
13
|
+
- 📦 **Multiple formats** - Auto-discovers `.oxfmtrc.json`, `.oxfmtrc.jsonc`, and `oxfmt.config.ts`, and also supports explicit `.js` / `.mjs` / `.cjs` / `.mts` / `.cts` config paths
|
|
14
14
|
- 🧩 **EditorConfig fallback** - Merges supported `.editorconfig` fields into the returned oxfmt config result
|
|
15
15
|
- 🚫 **Ignore resolution** - Resolves ignore status with oxfmt CLI-like global + config-scoped semantics
|
|
16
16
|
- ⚡ **Built-in caching** - Caches both file resolution and parsed configs for optimal performance
|
|
@@ -31,6 +31,8 @@ yarn add load-oxfmt-config
|
|
|
31
31
|
pnpm add load-oxfmt-config
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
> `oxfmt` is a peer dependency and should be installed alongside this package.
|
|
35
|
+
|
|
34
36
|
## Usage
|
|
35
37
|
|
|
36
38
|
### Basic Usage
|
|
@@ -38,19 +40,19 @@ pnpm add load-oxfmt-config
|
|
|
38
40
|
Load config from current directory or parent directories:
|
|
39
41
|
|
|
40
42
|
```ts
|
|
41
|
-
import {
|
|
43
|
+
import { loadOxfmtConfig } from 'load-oxfmt-config'
|
|
42
44
|
|
|
43
45
|
// Automatically searches for oxfmt config files and the nearest .editorconfig
|
|
44
|
-
const result = await
|
|
46
|
+
const result = await loadOxfmtConfig()
|
|
45
47
|
console.log(result.config) // { printWidth: 80, ... }
|
|
46
48
|
```
|
|
47
49
|
|
|
48
50
|
### Merge With `.editorconfig`
|
|
49
51
|
|
|
50
52
|
```ts
|
|
51
|
-
import {
|
|
53
|
+
import { loadOxfmtConfig } from 'load-oxfmt-config'
|
|
52
54
|
|
|
53
|
-
const result = await
|
|
55
|
+
const result = await loadOxfmtConfig({ cwd: '/path/to/project' })
|
|
54
56
|
|
|
55
57
|
// Returns one merged static config object
|
|
56
58
|
console.log(result.config)
|
|
@@ -66,9 +68,9 @@ console.log(result.config)
|
|
|
66
68
|
### Specify Working Directory
|
|
67
69
|
|
|
68
70
|
```ts
|
|
69
|
-
import {
|
|
71
|
+
import { loadOxfmtConfig } from 'load-oxfmt-config'
|
|
70
72
|
|
|
71
|
-
const result = await
|
|
73
|
+
const result = await loadOxfmtConfig({
|
|
72
74
|
cwd: '/path/to/project',
|
|
73
75
|
})
|
|
74
76
|
```
|
|
@@ -76,9 +78,9 @@ const result = await loadOxfmtConfigResult({
|
|
|
76
78
|
### Get Config Metadata
|
|
77
79
|
|
|
78
80
|
```ts
|
|
79
|
-
import {
|
|
81
|
+
import { loadOxfmtConfig } from 'load-oxfmt-config'
|
|
80
82
|
|
|
81
|
-
const result = await
|
|
83
|
+
const result = await loadOxfmtConfig({ cwd: '/path/to/project' })
|
|
82
84
|
|
|
83
85
|
console.log(result.config) // merged oxfmt options
|
|
84
86
|
console.log(result.filepath) // /path/to/project/.oxfmtrc.json (or undefined)
|
|
@@ -102,16 +104,16 @@ console.log(result)
|
|
|
102
104
|
### Explicit Config Path
|
|
103
105
|
|
|
104
106
|
```ts
|
|
105
|
-
import {
|
|
107
|
+
import { loadOxfmtConfig } from 'load-oxfmt-config'
|
|
106
108
|
|
|
107
109
|
// Relative path (resolved relative to cwd)
|
|
108
|
-
const result = await
|
|
110
|
+
const result = await loadOxfmtConfig({
|
|
109
111
|
configPath: 'configs/.oxfmtrc.json',
|
|
110
112
|
cwd: '/path/to/project',
|
|
111
113
|
})
|
|
112
114
|
|
|
113
115
|
// Absolute path
|
|
114
|
-
const absoluteResult = await
|
|
116
|
+
const absoluteResult = await loadOxfmtConfig({
|
|
115
117
|
configPath: '/absolute/path/to/.oxfmtrc.json',
|
|
116
118
|
})
|
|
117
119
|
```
|
|
@@ -119,10 +121,10 @@ const absoluteResult = await loadOxfmtConfigResult({
|
|
|
119
121
|
### Disable `.editorconfig`
|
|
120
122
|
|
|
121
123
|
```ts
|
|
122
|
-
import {
|
|
124
|
+
import { loadOxfmtConfig } from 'load-oxfmt-config'
|
|
123
125
|
|
|
124
126
|
// Skip .editorconfig reading entirely
|
|
125
|
-
const result = await
|
|
127
|
+
const result = await loadOxfmtConfig({
|
|
126
128
|
editorconfig: false,
|
|
127
129
|
})
|
|
128
130
|
```
|
|
@@ -130,10 +132,10 @@ const result = await loadOxfmtConfigResult({
|
|
|
130
132
|
### Limit `.editorconfig` to `cwd`
|
|
131
133
|
|
|
132
134
|
```ts
|
|
133
|
-
import {
|
|
135
|
+
import { loadOxfmtConfig } from 'load-oxfmt-config'
|
|
134
136
|
|
|
135
137
|
// Only look in the cwd directory itself, no upward traversal
|
|
136
|
-
const result = await
|
|
138
|
+
const result = await loadOxfmtConfig({
|
|
137
139
|
editorconfig: { onlyCwd: true },
|
|
138
140
|
})
|
|
139
141
|
```
|
|
@@ -141,10 +143,10 @@ const result = await loadOxfmtConfigResult({
|
|
|
141
143
|
### Override `.editorconfig` Search Directory
|
|
142
144
|
|
|
143
145
|
```ts
|
|
144
|
-
import {
|
|
146
|
+
import { loadOxfmtConfig } from 'load-oxfmt-config'
|
|
145
147
|
|
|
146
148
|
// Search .editorconfig from a custom directory instead of the config file's directory
|
|
147
|
-
const result = await
|
|
149
|
+
const result = await loadOxfmtConfig({
|
|
148
150
|
editorconfig: {
|
|
149
151
|
cwd: '/path/to/editorconfig-dir',
|
|
150
152
|
},
|
|
@@ -154,23 +156,14 @@ const result = await loadOxfmtConfigResult({
|
|
|
154
156
|
### Disable Caching
|
|
155
157
|
|
|
156
158
|
```ts
|
|
157
|
-
import {
|
|
159
|
+
import { loadOxfmtConfig } from 'load-oxfmt-config'
|
|
158
160
|
|
|
159
161
|
// Force reload from disk, bypassing cache
|
|
160
|
-
const result = await
|
|
162
|
+
const result = await loadOxfmtConfig({
|
|
161
163
|
useCache: false,
|
|
162
164
|
})
|
|
163
165
|
```
|
|
164
166
|
|
|
165
|
-
### Legacy API (Deprecated)
|
|
166
|
-
|
|
167
|
-
```ts
|
|
168
|
-
import { loadOxfmtConfig } from 'load-oxfmt-config'
|
|
169
|
-
|
|
170
|
-
// Deprecated: prefer loadOxfmtConfigResult
|
|
171
|
-
const config = await loadOxfmtConfig({ cwd: '/path/to/project' })
|
|
172
|
-
```
|
|
173
|
-
|
|
174
167
|
### Path Resolution Only
|
|
175
168
|
|
|
176
169
|
```ts
|
|
@@ -185,9 +178,7 @@ console.log(configPath) // '/path/to/.oxfmtrc.json' or undefined
|
|
|
185
178
|
|
|
186
179
|
### `loadOxfmtConfig(options?)`
|
|
187
180
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
Load and parse oxfmt configuration files, then merge supported `.editorconfig` fields into the returned result.
|
|
181
|
+
Load and parse oxfmt configuration files, merge supported `.editorconfig` fields, and return metadata for the resolved config file.
|
|
191
182
|
|
|
192
183
|
**Parameters:**
|
|
193
184
|
|
|
@@ -200,66 +191,16 @@ Option fields:
|
|
|
200
191
|
- **Type:** `string`
|
|
201
192
|
- **Default:** `process.cwd()`
|
|
202
193
|
|
|
203
|
-
Current working directory
|
|
194
|
+
Current working directory for config resolution.
|
|
195
|
+
By default config discovery starts here, unless `filepath` is provided.
|
|
204
196
|
|
|
205
|
-
#### `
|
|
197
|
+
#### `filepath`
|
|
206
198
|
|
|
207
199
|
- **Type:** `string`
|
|
208
200
|
- **Default:** `undefined`
|
|
209
201
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
- **Relative path:** Resolved relative to `cwd`
|
|
213
|
-
- **Absolute path:** Used as-is
|
|
214
|
-
- **When provided:** Skips auto-discovery and uses this path directly
|
|
215
|
-
|
|
216
|
-
#### `useCache`
|
|
217
|
-
|
|
218
|
-
- **Type:** `boolean`
|
|
219
|
-
- **Default:** `true`
|
|
220
|
-
|
|
221
|
-
Enable in-memory caching for both path resolution and parsed config contents. When enabled:
|
|
222
|
-
|
|
223
|
-
- Config file paths are cached to avoid repeated filesystem lookups
|
|
224
|
-
- Parsed config objects are cached to avoid re-parsing
|
|
225
|
-
- Subsequent calls with the same parameters return cached results instantly
|
|
226
|
-
|
|
227
|
-
Set to `false` to force reload from disk on every call.
|
|
228
|
-
|
|
229
|
-
#### `editorconfig`
|
|
230
|
-
|
|
231
|
-
- **Type:** `boolean | EditorconfigOption`
|
|
232
|
-
- **Default:** `true`
|
|
233
|
-
|
|
234
|
-
Control how `.editorconfig` files are read and merged:
|
|
235
|
-
|
|
236
|
-
- **`true`** — Read and merge the nearest `.editorconfig`, walking up from the config file's directory (or `cwd` when no config path is given).
|
|
237
|
-
- **`false`** — Disable `.editorconfig` reading entirely.
|
|
238
|
-
- **`EditorconfigOption`** — Enable with additional settings:
|
|
239
|
-
|
|
240
|
-
| Property | Type | Default | Description |
|
|
241
|
-
| --------- | --------- | ----------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
242
|
-
| `onlyCwd` | `boolean` | `false` | When `true`, only look for `.editorconfig` in `cwd` itself — no upward traversal. |
|
|
243
|
-
| `cwd` | `string` | `undefined` | Override the directory from which `.editorconfig` resolution starts, instead of the config file's directory or `cwd`. |
|
|
244
|
-
|
|
245
|
-
**Returns:** `Promise<OxfmtOptions>` - Parsed and merged oxfmt configuration object. Returns empty object `{}` if no supported config file is found.
|
|
246
|
-
|
|
247
|
-
### `loadOxfmtConfigResult(options?)`
|
|
248
|
-
|
|
249
|
-
Load and parse oxfmt configuration files, merge supported `.editorconfig` fields, and return metadata for the resolved config file.
|
|
250
|
-
|
|
251
|
-
**Parameters:**
|
|
252
|
-
|
|
253
|
-
- `options` - Optional configuration object (`LoadOxfmtConfigOptions`)
|
|
254
|
-
|
|
255
|
-
Option fields:
|
|
256
|
-
|
|
257
|
-
#### `cwd`
|
|
258
|
-
|
|
259
|
-
- **Type:** `string`
|
|
260
|
-
- **Default:** `process.cwd()`
|
|
261
|
-
|
|
262
|
-
Current working directory to start searching for config files. The loader will walk up from this directory to find a config file.
|
|
202
|
+
Target file path for nested config resolution.
|
|
203
|
+
When provided (and `configPath` is not set), config discovery starts from `dirname(filepath)` and walks upward to match oxfmt per-file semantics.
|
|
263
204
|
|
|
264
205
|
#### `configPath`
|
|
265
206
|
|
|
@@ -272,6 +213,14 @@ Explicit path to the config file:
|
|
|
272
213
|
- **Absolute path:** Used as-is
|
|
273
214
|
- **When provided:** Skips auto-discovery and uses this path directly
|
|
274
215
|
|
|
216
|
+
#### `disableNestedConfig`
|
|
217
|
+
|
|
218
|
+
- **Type:** `boolean`
|
|
219
|
+
- **Default:** `false`
|
|
220
|
+
|
|
221
|
+
Disable nested config lookup.
|
|
222
|
+
When `true`, config discovery is anchored to `cwd` (or explicit `configPath`) instead of `filepath`.
|
|
223
|
+
|
|
275
224
|
#### `useCache`
|
|
276
225
|
|
|
277
226
|
- **Type:** `boolean`
|
|
@@ -292,7 +241,9 @@ Set to `false` to force reload from disk on every call.
|
|
|
292
241
|
|
|
293
242
|
Control how `.editorconfig` files are read and merged:
|
|
294
243
|
|
|
295
|
-
- **`true`** — Read and merge the nearest `.editorconfig`, walking up from the config
|
|
244
|
+
- **`true`** — Read and merge the nearest `.editorconfig`, walking up from the config-discovery start directory:
|
|
245
|
+
- `dirname(filepath)` when nested lookup is enabled and `filepath` is provided
|
|
246
|
+
- otherwise `cwd`
|
|
296
247
|
- **`false`** — Disable `.editorconfig` reading entirely.
|
|
297
248
|
- **`EditorconfigOption`** — Enable with additional settings:
|
|
298
249
|
|
|
@@ -336,7 +287,7 @@ Option fields:
|
|
|
336
287
|
- **Default:** `process.cwd()`
|
|
337
288
|
|
|
338
289
|
Current working directory.
|
|
339
|
-
Also the base directory for default `.
|
|
290
|
+
Also the base directory for default `.prettierignore` lookup.
|
|
340
291
|
|
|
341
292
|
#### `filepath`
|
|
342
293
|
|
|
@@ -358,7 +309,7 @@ When provided, nested config lookup is disabled (same as oxfmt CLI `-c`).
|
|
|
358
309
|
- **Type:** `string | string[]`
|
|
359
310
|
- **Default:** `undefined`
|
|
360
311
|
|
|
361
|
-
Ignore files to use instead of cwd `.
|
|
312
|
+
Ignore files to use instead of default `.gitignore` hierarchy + cwd `.prettierignore`.
|
|
362
313
|
Can be passed multiple times in CLI style.
|
|
363
314
|
|
|
364
315
|
#### `withNodeModules`
|
|
@@ -404,6 +355,7 @@ When `false`, `isOxfmtIgnored()` only applies global ignore and skips config loa
|
|
|
404
355
|
- `default-dir`
|
|
405
356
|
- `lockfile`
|
|
406
357
|
- `gitignore`
|
|
358
|
+
- `git-info-exclude`
|
|
407
359
|
- `prettierignore`
|
|
408
360
|
- `ignore-path`
|
|
409
361
|
- `config-ignore-patterns`
|
|
@@ -412,7 +364,7 @@ When `false`, `isOxfmtIgnored()` only applies global ignore and skips config loa
|
|
|
412
364
|
|
|
413
365
|
When `configPath` is not provided, the loader automatically searches for config files:
|
|
414
366
|
|
|
415
|
-
1. **Search order:** Starts from `
|
|
367
|
+
1. **Search order:** Starts from `dirname(filepath)` when `filepath` is provided **and nested lookup is enabled**; otherwise starts from `cwd`, then walks up to parent directories
|
|
416
368
|
2. **Supported filenames:**
|
|
417
369
|
- `.oxfmtrc.json`
|
|
418
370
|
- `.oxfmtrc.jsonc`
|
|
@@ -420,7 +372,7 @@ When `configPath` is not provided, the loader automatically searches for config
|
|
|
420
372
|
3. **Stops when:**
|
|
421
373
|
- A valid config file is found
|
|
422
374
|
- Reaches the filesystem root
|
|
423
|
-
4. **EditorConfig:** The nearest `.editorconfig` is
|
|
375
|
+
4. **EditorConfig:** The nearest `.editorconfig` is resolved from the same start directory and merged into the returned result
|
|
424
376
|
5. **Returns:** Empty object `{}` if no config file is found
|
|
425
377
|
|
|
426
378
|
## Supported Config Formats
|
|
@@ -495,16 +447,15 @@ Global ignore includes:
|
|
|
495
447
|
- Default lockfiles: `package-lock.json`, `npm-shrinkwrap.json`, `pnpm-lock.yaml`, `yarn.lock`, `bun.lock`, `bun.lockb`
|
|
496
448
|
- Ignore files:
|
|
497
449
|
- If `ignorePath` is provided: use those files only (multiple supported)
|
|
498
|
-
- If `ignorePath` is not provided:
|
|
450
|
+
- If `ignorePath` is not provided:
|
|
451
|
+
- Read `.gitignore` from the file's directory upward until the git repo boundary
|
|
452
|
+
- Read `<repo>/.git/info/exclude` when inside a git repo
|
|
453
|
+
- Read `.prettierignore` from `cwd`
|
|
499
454
|
|
|
500
455
|
Notes:
|
|
501
456
|
|
|
502
457
|
- `node_modules` can be included by passing `withNodeModules: true`.
|
|
503
458
|
|
|
504
|
-
Type compatibility note:
|
|
505
|
-
|
|
506
|
-
- `Options` is still exported as a deprecated alias of `LoadOxfmtConfigOptions`.
|
|
507
|
-
- This package does not read parent `.gitignore` files or global gitignore settings.
|
|
508
459
|
- The default lockfile list mirrors oxfmt documentation intent (`package-lock.json`, `pnpm-lock.yaml`, etc.) and common ecosystem lockfiles. It is not guaranteed to be a complete internal oxfmt list.
|
|
509
460
|
- `ignorePatterns` are always interpreted relative to the resolved oxfmt config directory.
|
|
510
461
|
- `includeConfigIgnorePatterns` defaults to `true` to preserve current behavior.
|
|
@@ -513,6 +464,7 @@ Type compatibility note:
|
|
|
513
464
|
- default: nearest config from target file directory upward
|
|
514
465
|
- `disableNestedConfig: true`: resolve from `cwd` only
|
|
515
466
|
- `configPath`: also disables nested lookup (same intent as CLI `-c`)
|
|
467
|
+
- invalid nested config only fails files that resolve to that config (no project-wide pre-scan)
|
|
516
468
|
|
|
517
469
|
## Precedence
|
|
518
470
|
|
|
@@ -527,18 +479,18 @@ This means explicit oxfmt config values always win over `.editorconfig` fallback
|
|
|
527
479
|
|
|
528
480
|
## Limitations
|
|
529
481
|
|
|
530
|
-
`
|
|
482
|
+
`loadOxfmtConfig()` returns a static merged `OxfmtOptions` shape. That means `.editorconfig` support is represented as merged root + overrides config data, not as per-file runtime evaluation. In practice this works well for common root settings and section-based overrides, but it is not a full replacement for oxfmt's own file-by-file config resolution.
|
|
531
483
|
|
|
532
484
|
## Error Handling
|
|
533
485
|
|
|
534
486
|
```ts
|
|
535
|
-
import {
|
|
487
|
+
import { loadOxfmtConfig } from 'load-oxfmt-config'
|
|
536
488
|
|
|
537
489
|
try {
|
|
538
|
-
const result = await
|
|
490
|
+
const result = await loadOxfmtConfig()
|
|
539
491
|
console.log(result.config)
|
|
540
492
|
} catch (error) {
|
|
541
|
-
// Thrown when config file
|
|
493
|
+
// Thrown when a resolved config file cannot be parsed or loaded
|
|
542
494
|
console.error('Failed to parse oxfmt config:', error.message)
|
|
543
495
|
}
|
|
544
496
|
```
|
|
@@ -553,6 +505,7 @@ The caching system maintains two separate caches:
|
|
|
553
505
|
**Cache keys are based on:**
|
|
554
506
|
|
|
555
507
|
- `cwd` + `configPath` for path resolution
|
|
508
|
+
- or `dirname(filepath)` + `configPath` when `filepath` is provided and nested lookup is enabled
|
|
556
509
|
- Resolved oxfmt path and resolved `.editorconfig` path for config content
|
|
557
510
|
|
|
558
511
|
**Cache invalidation:**
|
package/dist/index.d.mts
CHANGED
|
@@ -48,6 +48,19 @@ interface LoadOxfmtConfigOptions {
|
|
|
48
48
|
* Current working directory
|
|
49
49
|
*/
|
|
50
50
|
cwd?: string;
|
|
51
|
+
/**
|
|
52
|
+
* File path being formatted. When provided (and `configPath` is not set),
|
|
53
|
+
* config discovery starts from this file's directory to match oxfmt nested
|
|
54
|
+
* config behavior.
|
|
55
|
+
*/
|
|
56
|
+
filepath?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Disable nested config lookup.
|
|
59
|
+
* When true, config discovery is anchored to `cwd` (or explicit `configPath`).
|
|
60
|
+
*
|
|
61
|
+
* @default false
|
|
62
|
+
*/
|
|
63
|
+
disableNestedConfig?: boolean;
|
|
51
64
|
/**
|
|
52
65
|
* Whether to use cache
|
|
53
66
|
*/
|
|
@@ -100,7 +113,7 @@ interface LoadOxfmtConfigResult {
|
|
|
100
113
|
interface IsOxfmtIgnoredOptions {
|
|
101
114
|
/**
|
|
102
115
|
* Current working directory.
|
|
103
|
-
* Also the base directory for default
|
|
116
|
+
* Also the base directory for default `.prettierignore` lookup.
|
|
104
117
|
*/
|
|
105
118
|
cwd?: string;
|
|
106
119
|
/**
|
|
@@ -113,7 +126,7 @@ interface IsOxfmtIgnoredOptions {
|
|
|
113
126
|
*/
|
|
114
127
|
configPath?: string;
|
|
115
128
|
/**
|
|
116
|
-
* Ignore files to use instead of cwd
|
|
129
|
+
* Ignore files to use instead of default `.gitignore` hierarchy + cwd `.prettierignore`.
|
|
117
130
|
* Can be passed multiple times in CLI style.
|
|
118
131
|
*/
|
|
119
132
|
ignorePath?: string | string[];
|
|
@@ -155,16 +168,8 @@ interface IsOxfmtIgnoredResult {
|
|
|
155
168
|
/**
|
|
156
169
|
* Matched ignore source.
|
|
157
170
|
*/
|
|
158
|
-
reason?: 'default-dir' | 'lockfile' | 'gitignore' | 'prettierignore' | 'ignore-path' | 'config-ignore-patterns';
|
|
171
|
+
reason?: 'default-dir' | 'lockfile' | 'gitignore' | 'git-info-exclude' | 'prettierignore' | 'ignore-path' | 'config-ignore-patterns';
|
|
159
172
|
}
|
|
160
|
-
/**
|
|
161
|
-
* @deprecated Use `OxfmtConfigOverride` instead
|
|
162
|
-
*/
|
|
163
|
-
type FormatOptionOverride = OxfmtConfigOverride;
|
|
164
|
-
/**
|
|
165
|
-
* @deprecated Use `LoadOxfmtConfigOptions` instead.
|
|
166
|
-
*/
|
|
167
|
-
type Options = LoadOxfmtConfigOptions;
|
|
168
173
|
//#endregion
|
|
169
174
|
//#region src/config-file.d.ts
|
|
170
175
|
/**
|
|
@@ -196,13 +201,13 @@ declare function resolveOxfmtrcPath(cwd: string, configPath?: string): Promise<s
|
|
|
196
201
|
*
|
|
197
202
|
* @example
|
|
198
203
|
* ```ts
|
|
199
|
-
* import {
|
|
204
|
+
* import { loadOxfmtConfig } from 'load-oxfmt-config'
|
|
200
205
|
*
|
|
201
|
-
* const result = await
|
|
206
|
+
* const result = await loadOxfmtConfig({ cwd: process.cwd() })
|
|
202
207
|
* console.log(result.config)
|
|
203
208
|
* ```
|
|
204
209
|
*/
|
|
205
|
-
declare function
|
|
210
|
+
declare function loadOxfmtConfig(options?: LoadOxfmtConfigOptions): Promise<LoadOxfmtConfigResult>;
|
|
206
211
|
//#endregion
|
|
207
212
|
//#region src/ignore.d.ts
|
|
208
213
|
/**
|
|
@@ -223,25 +228,4 @@ declare function loadOxfmtConfigResult(options?: LoadOxfmtConfigOptions): Promis
|
|
|
223
228
|
*/
|
|
224
229
|
declare function isOxfmtIgnored(options: IsOxfmtIgnoredOptions): Promise<IsOxfmtIgnoredResult>;
|
|
225
230
|
//#endregion
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Legacy API that returns only the merged config object.
|
|
229
|
-
*
|
|
230
|
-
* Prefer using `loadOxfmtConfigResult` when you also need resolved config metadata.
|
|
231
|
-
*
|
|
232
|
-
* @deprecated Prefer `loadOxfmtConfigResult`.
|
|
233
|
-
*
|
|
234
|
-
* @param options - Loader options.
|
|
235
|
-
* @returns Parsed and merged oxfmt options.
|
|
236
|
-
*
|
|
237
|
-
* @example
|
|
238
|
-
* ```ts
|
|
239
|
-
* import { loadOxfmtConfig } from 'load-oxfmt-config'
|
|
240
|
-
*
|
|
241
|
-
* // Deprecated: prefer loadOxfmtConfigResult.
|
|
242
|
-
* const config = await loadOxfmtConfig({ cwd: process.cwd() })
|
|
243
|
-
* ```
|
|
244
|
-
*/
|
|
245
|
-
declare function loadOxfmtConfig(options?: LoadOxfmtConfigOptions): Promise<OxfmtOptions>;
|
|
246
|
-
//#endregion
|
|
247
|
-
export { EditorconfigOption, FormatOptionOverride, IsOxfmtIgnoredOptions, IsOxfmtIgnoredResult, LoadOxfmtConfigOptions, LoadOxfmtConfigResult, Options, OxfmtConfigOverride, OxfmtOptions, isOxfmtIgnored, loadOxfmtConfig, loadOxfmtConfigResult, resolveOxfmtrcPath };
|
|
231
|
+
export { EditorconfigOption, IsOxfmtIgnoredOptions, IsOxfmtIgnoredResult, LoadOxfmtConfigOptions, LoadOxfmtConfigResult, OxfmtConfigOverride, OxfmtOptions, isOxfmtIgnored, loadOxfmtConfig, resolveOxfmtrcPath };
|
package/dist/index.mjs
CHANGED
|
@@ -53,10 +53,6 @@ const DEFAULT_IGNORED_LOCKFILES = [
|
|
|
53
53
|
"bun.lockb"
|
|
54
54
|
];
|
|
55
55
|
/**
|
|
56
|
-
* Default ignore files loaded from cwd when --ignore-path is not provided.
|
|
57
|
-
*/
|
|
58
|
-
const DEFAULT_IGNORE_FILES = [".gitignore", ".prettierignore"];
|
|
59
|
-
/**
|
|
60
56
|
* Supported EditorConfig filename.
|
|
61
57
|
*/
|
|
62
58
|
const EDITORCONFIG_FILE = ".editorconfig";
|
|
@@ -394,24 +390,26 @@ const configCache = /* @__PURE__ */ new Map();
|
|
|
394
390
|
*
|
|
395
391
|
* @example
|
|
396
392
|
* ```ts
|
|
397
|
-
* import {
|
|
393
|
+
* import { loadOxfmtConfig } from 'load-oxfmt-config'
|
|
398
394
|
*
|
|
399
|
-
* const result = await
|
|
395
|
+
* const result = await loadOxfmtConfig({ cwd: process.cwd() })
|
|
400
396
|
* console.log(result.config)
|
|
401
397
|
* ```
|
|
402
398
|
*/
|
|
403
|
-
async function
|
|
399
|
+
async function loadOxfmtConfig(options = {}) {
|
|
404
400
|
const useCache = options.useCache !== false;
|
|
405
401
|
const cwd = resolve(options.cwd || process.cwd());
|
|
402
|
+
const filepath = options.filepath ? resolve(cwd, options.filepath) : void 0;
|
|
403
|
+
const configLookupCwd = options.configPath || options.disableNestedConfig || !filepath ? cwd : dirname(filepath);
|
|
406
404
|
const editorconfig = options.editorconfig ?? true;
|
|
407
405
|
const useEditorconfig = editorconfig !== false;
|
|
408
406
|
const isEditorconfigOptionsObject = useEditorconfig && isObject(editorconfig);
|
|
409
407
|
const onlyCwd = isEditorconfigOptionsObject ? editorconfig.onlyCwd ?? false : false;
|
|
410
408
|
const editorconfigCwd = isEditorconfigOptionsObject && editorconfig.cwd ? resolve(editorconfig.cwd) : void 0;
|
|
411
|
-
const resolveKey = getResolveCacheKey(
|
|
412
|
-
const editorconfigSearchDir = editorconfigCwd || getEditorconfigSearchDir(
|
|
409
|
+
const resolveKey = getResolveCacheKey(configLookupCwd, options.configPath);
|
|
410
|
+
const editorconfigSearchDir = editorconfigCwd || getEditorconfigSearchDir(configLookupCwd, options.configPath);
|
|
413
411
|
const editorconfigResolveKey = editorconfigCwd ? getEditorconfigResolveCacheKey(`${editorconfigCwd}::${options.configPath || ""}`) : getEditorconfigResolveCacheKey(resolveKey);
|
|
414
|
-
const resolvedPath = useCache ? await cachePromise(resolveCache, resolveKey, () => resolveOxfmtrcPath(
|
|
412
|
+
const resolvedPath = useCache ? await cachePromise(resolveCache, resolveKey, () => resolveOxfmtrcPath(configLookupCwd, options.configPath)) : await resolveOxfmtrcPath(configLookupCwd, options.configPath);
|
|
415
413
|
const editorconfigPath = useEditorconfig ? await (useCache ? cachePromise(resolveCache, editorconfigResolveKey, () => resolveEditorconfigPath(editorconfigSearchDir, onlyCwd)) : resolveEditorconfigPath(editorconfigSearchDir, onlyCwd)) : void 0;
|
|
416
414
|
const anchorDir = dirname(resolvedPath || editorconfigPath || cwd);
|
|
417
415
|
const loadTask = async () => {
|
|
@@ -500,12 +498,13 @@ function relativeSafe(from, to) {
|
|
|
500
498
|
* @param filepath - Absolute file path.
|
|
501
499
|
* @param ignoreFilePath - Ignore file path.
|
|
502
500
|
* @param useCache - Whether to use matcher cache.
|
|
501
|
+
* @param baseDir - Base directory for relative path calculation, defaults to ignore file directory.
|
|
503
502
|
* @returns True when ignored by this file.
|
|
504
503
|
*/
|
|
505
|
-
async function matchIgnoreFile(filepath, ignoreFilePath, useCache) {
|
|
504
|
+
async function matchIgnoreFile(filepath, ignoreFilePath, useCache, baseDir) {
|
|
506
505
|
const matcher = await loadIgnoreMatcher(ignoreFilePath, useCache);
|
|
507
506
|
if (!matcher) return false;
|
|
508
|
-
const relativeToIgnore = relativeSafe(dirname(ignoreFilePath), filepath);
|
|
507
|
+
const relativeToIgnore = relativeSafe(baseDir ?? dirname(ignoreFilePath), filepath);
|
|
509
508
|
if (relativeToIgnore === ".." || relativeToIgnore.startsWith("../")) return false;
|
|
510
509
|
return matcher.ignores(relativeToIgnore);
|
|
511
510
|
}
|
|
@@ -520,6 +519,62 @@ function resolveIgnoreFilePath(path, cwd) {
|
|
|
520
519
|
return isAbsolute(path) ? path : resolve(cwd, path);
|
|
521
520
|
}
|
|
522
521
|
/**
|
|
522
|
+
* Check whether a directory looks like a git repo root.
|
|
523
|
+
*
|
|
524
|
+
* A `.git` entry can be either a directory (regular repo) or a file (worktree/submodule).
|
|
525
|
+
*
|
|
526
|
+
* @param dir - Directory to inspect.
|
|
527
|
+
* @returns True when `.git` exists under the directory.
|
|
528
|
+
*/
|
|
529
|
+
async function hasGitEntry(dir) {
|
|
530
|
+
try {
|
|
531
|
+
await stat(join(dir, ".git"));
|
|
532
|
+
return true;
|
|
533
|
+
} catch (error) {
|
|
534
|
+
const code = error.code;
|
|
535
|
+
if (code === "ENOENT" || code === "ENOTDIR") return false;
|
|
536
|
+
throw error;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Find the nearest git repo root by walking up from a start directory.
|
|
541
|
+
*
|
|
542
|
+
* @param fromDir - Directory to start from.
|
|
543
|
+
* @returns Repo root directory, or undefined when no git boundary is found.
|
|
544
|
+
*/
|
|
545
|
+
async function findGitRepoRoot(fromDir) {
|
|
546
|
+
let current = fromDir;
|
|
547
|
+
while (true) {
|
|
548
|
+
if (await hasGitEntry(current)) return current;
|
|
549
|
+
const parent = dirname(current);
|
|
550
|
+
if (parent === current) return;
|
|
551
|
+
current = parent;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Collect `.gitignore` files from file directory up to git repo boundary.
|
|
556
|
+
*
|
|
557
|
+
* @param filepath - Absolute file path to test.
|
|
558
|
+
* @returns Collected ignore files and repo root when found.
|
|
559
|
+
*/
|
|
560
|
+
async function collectGitignorePaths(filepath) {
|
|
561
|
+
const fileDir = dirname(filepath);
|
|
562
|
+
const repoRoot = await findGitRepoRoot(fileDir);
|
|
563
|
+
const paths = [];
|
|
564
|
+
let current = fileDir;
|
|
565
|
+
while (true) {
|
|
566
|
+
paths.push(join(current, ".gitignore"));
|
|
567
|
+
if (repoRoot && current === repoRoot) break;
|
|
568
|
+
const parent = dirname(current);
|
|
569
|
+
if (parent === current) break;
|
|
570
|
+
current = parent;
|
|
571
|
+
}
|
|
572
|
+
return {
|
|
573
|
+
paths,
|
|
574
|
+
repoRoot
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
523
578
|
* Match `ignorePatterns` from config with support for negated patterns.
|
|
524
579
|
*
|
|
525
580
|
* @param filepath - Absolute file path.
|
|
@@ -575,13 +630,28 @@ async function isOxfmtIgnored(options) {
|
|
|
575
630
|
ignored: true,
|
|
576
631
|
reason: "ignore-path"
|
|
577
632
|
};
|
|
578
|
-
} else
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
633
|
+
} else {
|
|
634
|
+
const { paths: gitignorePaths, repoRoot } = await collectGitignorePaths(filepath);
|
|
635
|
+
for (const ignorePath of gitignorePaths) if (await matchIgnoreFile(filepath, ignorePath, useCache)) return {
|
|
636
|
+
ignored: true,
|
|
637
|
+
reason: "gitignore"
|
|
638
|
+
};
|
|
639
|
+
if (repoRoot) {
|
|
640
|
+
if (await matchIgnoreFile(filepath, join(repoRoot, ".git", "info", "exclude"), useCache, repoRoot)) return {
|
|
641
|
+
ignored: true,
|
|
642
|
+
reason: "git-info-exclude"
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
if (await matchIgnoreFile(filepath, resolve(cwd, ".prettierignore"), useCache)) return {
|
|
646
|
+
ignored: true,
|
|
647
|
+
reason: "prettierignore"
|
|
648
|
+
};
|
|
649
|
+
}
|
|
582
650
|
if (!loadConfigForIgnorePatterns) return { ignored: false };
|
|
583
|
-
const configResult = await
|
|
584
|
-
cwd
|
|
651
|
+
const configResult = await loadOxfmtConfig({
|
|
652
|
+
cwd,
|
|
653
|
+
filepath,
|
|
654
|
+
...options.disableNestedConfig === true ? { disableNestedConfig: true } : {},
|
|
585
655
|
...options.configPath ? { configPath: options.configPath } : {},
|
|
586
656
|
editorconfig: false,
|
|
587
657
|
useCache
|
|
@@ -593,27 +663,4 @@ async function isOxfmtIgnored(options) {
|
|
|
593
663
|
return { ignored: false };
|
|
594
664
|
}
|
|
595
665
|
//#endregion
|
|
596
|
-
|
|
597
|
-
/**
|
|
598
|
-
* Legacy API that returns only the merged config object.
|
|
599
|
-
*
|
|
600
|
-
* Prefer using `loadOxfmtConfigResult` when you also need resolved config metadata.
|
|
601
|
-
*
|
|
602
|
-
* @deprecated Prefer `loadOxfmtConfigResult`.
|
|
603
|
-
*
|
|
604
|
-
* @param options - Loader options.
|
|
605
|
-
* @returns Parsed and merged oxfmt options.
|
|
606
|
-
*
|
|
607
|
-
* @example
|
|
608
|
-
* ```ts
|
|
609
|
-
* import { loadOxfmtConfig } from 'load-oxfmt-config'
|
|
610
|
-
*
|
|
611
|
-
* // Deprecated: prefer loadOxfmtConfigResult.
|
|
612
|
-
* const config = await loadOxfmtConfig({ cwd: process.cwd() })
|
|
613
|
-
* ```
|
|
614
|
-
*/
|
|
615
|
-
async function loadOxfmtConfig(options = {}) {
|
|
616
|
-
return (await loadOxfmtConfigResult(options)).config;
|
|
617
|
-
}
|
|
618
|
-
//#endregion
|
|
619
|
-
export { isOxfmtIgnored, loadOxfmtConfig, loadOxfmtConfigResult, resolveOxfmtrcPath };
|
|
666
|
+
export { isOxfmtIgnored, loadOxfmtConfig, resolveOxfmtrcPath };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "load-oxfmt-config",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Load oxfmt
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "Load and resolve oxfmt configuration files, including explicit JS/TS config paths, and merge supported `.editorconfig` settings for Oxfmt.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"editorconfig",
|
|
7
7
|
"jsonc-parser",
|
|
@@ -48,20 +48,20 @@
|
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@ntnyq/tsconfig": "^3.1.0",
|
|
51
|
-
"@types/node": "^25.
|
|
51
|
+
"@types/node": "^25.8.0",
|
|
52
52
|
"@types/picomatch": "^4.0.3",
|
|
53
|
-
"@typescript/native-preview": "^7.0.0-dev.
|
|
53
|
+
"@typescript/native-preview": "^7.0.0-dev.20260517.1",
|
|
54
54
|
"bumpp": "^11.1.0",
|
|
55
55
|
"husky": "^9.1.7",
|
|
56
56
|
"nano-staged": "^1.0.2",
|
|
57
57
|
"npm-run-all2": "^8.0.4",
|
|
58
|
-
"oxfmt": "^0.
|
|
59
|
-
"oxlint": "^1.
|
|
58
|
+
"oxfmt": "^0.50.0",
|
|
59
|
+
"oxlint": "^1.65.0",
|
|
60
60
|
"tsdown": "^0.22.0",
|
|
61
|
-
"vitest": "^4.1.
|
|
61
|
+
"vitest": "^4.1.6"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
|
-
"oxfmt": ">=0.
|
|
64
|
+
"oxfmt": ">=0.50.0"
|
|
65
65
|
},
|
|
66
66
|
"nano-staged": {
|
|
67
67
|
"*.{js,ts,mjs,tsx}": "oxlint --fix",
|