eslint-plugin-oxfmt 0.21.0 → 0.22.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 +10 -1
- package/dist/index.d.mts +10 -10
- package/dist/index.mjs +29 -26
- package/package.json +10 -10
- package/workers/oxfmt.mjs +134 -40
package/README.md
CHANGED
|
@@ -22,7 +22,14 @@
|
|
|
22
22
|
|
|
23
23
|
- **ESLint**: `>= 9.0.0` (Only supports ESLint flat config)
|
|
24
24
|
- **Node.js**: `^20.19.0 || >=22.12.0`
|
|
25
|
-
- **oxfmt**: `>= 0.
|
|
25
|
+
- **oxfmt**: `>= 0.67.0`
|
|
26
|
+
|
|
27
|
+
Oxfmt 0.67.0 preserves JSDoc cast parentheses containing comments, fixes
|
|
28
|
+
CSS/SCSS/Less comment and list formatting, and moves GraphQL comments after
|
|
29
|
+
an opening brace onto their own line. Existing files may receive formatting
|
|
30
|
+
fixes after upgrading. No formatting options were renamed or removed, and
|
|
31
|
+
config merge precedence is unchanged. See the
|
|
32
|
+
[upstream release notes](https://github.com/oxc-project/oxc/releases/tag/oxfmt_v0.67.0).
|
|
26
33
|
|
|
27
34
|
## Installation
|
|
28
35
|
|
|
@@ -359,6 +366,8 @@ You can pass the Tailwind plugin options to control which attributes/functions a
|
|
|
359
366
|
}
|
|
360
367
|
```
|
|
361
368
|
|
|
369
|
+
Paths in `sortTailwindcss.config` and `sortTailwindcss.stylesheet` are resolved relative to the oxfmt config file when set in that file or its overrides. Paths set in ESLint rule options or rule-level overrides are resolved relative to ESLint `cwd`. Absolute paths are used directly.
|
|
370
|
+
|
|
362
371
|
## File-specific overrides
|
|
363
372
|
|
|
364
373
|
Use `overrides` to apply different oxfmt options per file glob (later entries win on conflicts):
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Linter, Rule } from "eslint";
|
|
1
|
+
import { Linter, Rule as Rule$1 } from "eslint";
|
|
2
2
|
import "load-oxfmt-config";
|
|
3
3
|
import "oxfmt";
|
|
4
4
|
//#region src/types.d.ts
|
|
@@ -13,18 +13,18 @@ interface PluginOxfmt {
|
|
|
13
13
|
version: string;
|
|
14
14
|
};
|
|
15
15
|
rules: {
|
|
16
|
-
oxfmt: Rule.RuleModule;
|
|
16
|
+
oxfmt: Rule$1.RuleModule;
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
19
|
//#endregion
|
|
20
20
|
//#region src/meta.d.ts
|
|
21
|
-
declare const meta: {
|
|
21
|
+
export declare const meta: {
|
|
22
22
|
name: string;
|
|
23
23
|
version: string;
|
|
24
24
|
};
|
|
25
25
|
//#endregion
|
|
26
26
|
//#region src/rules/index.d.ts
|
|
27
|
-
declare const rules: {
|
|
27
|
+
export declare const rules: {
|
|
28
28
|
oxfmt: import("eslint").Rule.RuleModule;
|
|
29
29
|
};
|
|
30
30
|
//#endregion
|
|
@@ -32,12 +32,12 @@ declare const rules: {
|
|
|
32
32
|
declare const parserPlain: Linter.Parser;
|
|
33
33
|
//#endregion
|
|
34
34
|
//#region src/configs.d.ts
|
|
35
|
-
declare const recommendedWithoutParser: Linter.Config<Linter.RulesRecord>;
|
|
36
|
-
declare const recommended: Linter.Config<Linter.RulesRecord>;
|
|
37
|
-
declare const cliParity: Linter.Config<Linter.RulesRecord>;
|
|
38
|
-
declare const configs: PluginOxfmt['configs'];
|
|
35
|
+
export declare const recommendedWithoutParser: Linter.Config<Linter.RulesRecord>;
|
|
36
|
+
export declare const recommended: Linter.Config<Linter.RulesRecord>;
|
|
37
|
+
export declare const cliParity: Linter.Config<Linter.RulesRecord>;
|
|
38
|
+
export declare const configs: PluginOxfmt['configs'];
|
|
39
39
|
//#endregion
|
|
40
40
|
//#region src/index.d.ts
|
|
41
|
-
declare const plugin: PluginOxfmt;
|
|
41
|
+
export declare const plugin: PluginOxfmt;
|
|
42
42
|
//#endregion
|
|
43
|
-
export {
|
|
43
|
+
export { plugin as default, parserPlain };
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Buffer as Buffer$1 } from "node:buffer";
|
|
1
2
|
import { join } from "node:path";
|
|
2
3
|
import { createSyncFn } from "synckit";
|
|
3
4
|
import { URL, fileURLToPath } from "node:url";
|
|
@@ -79,7 +80,7 @@ const configs = {
|
|
|
79
80
|
//#region src/meta.ts
|
|
80
81
|
const meta = {
|
|
81
82
|
name: "eslint-plugin-oxfmt",
|
|
82
|
-
version: "0.
|
|
83
|
+
version: "0.22.0"
|
|
83
84
|
};
|
|
84
85
|
//#endregion
|
|
85
86
|
//#region src/dir.ts
|
|
@@ -608,33 +609,35 @@ const rules = { oxfmt: {
|
|
|
608
609
|
cwd: context.cwd
|
|
609
610
|
});
|
|
610
611
|
if (formatResult.ignored) return;
|
|
611
|
-
if (formatResult.errors?.length)
|
|
612
|
-
const
|
|
613
|
-
|
|
614
|
-
const
|
|
615
|
-
|
|
616
|
-
|
|
612
|
+
if (formatResult.errors?.length) {
|
|
613
|
+
const sourceBytes = Buffer$1.from(sourceText);
|
|
614
|
+
for (const error of formatResult.errors) {
|
|
615
|
+
const label = error.labels?.[0];
|
|
616
|
+
if (label) {
|
|
617
|
+
const start = context.sourceCode.getLocFromIndex(sourceBytes.toString("utf8", 0, label.start).length);
|
|
618
|
+
const end = context.sourceCode.getLocFromIndex(sourceBytes.toString("utf8", 0, label.end).length);
|
|
619
|
+
context.report({
|
|
620
|
+
loc: {
|
|
621
|
+
end,
|
|
622
|
+
start
|
|
623
|
+
},
|
|
624
|
+
message: `Failed to format code: ${error.message}`
|
|
625
|
+
});
|
|
626
|
+
} else context.report({
|
|
627
|
+
message: `Failed to format code: ${error.message}`,
|
|
617
628
|
loc: {
|
|
618
|
-
end
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
end: {
|
|
627
|
-
column: 0,
|
|
628
|
-
line: 1
|
|
629
|
-
},
|
|
630
|
-
start: {
|
|
631
|
-
column: 0,
|
|
632
|
-
line: 1
|
|
629
|
+
end: {
|
|
630
|
+
column: 0,
|
|
631
|
+
line: 1
|
|
632
|
+
},
|
|
633
|
+
start: {
|
|
634
|
+
column: 0,
|
|
635
|
+
line: 1
|
|
636
|
+
}
|
|
633
637
|
}
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
else reportDifferences(context, sourceText, formatResult.code);
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
} else reportDifferences(context, sourceText, formatResult.code);
|
|
638
641
|
} catch (error) {
|
|
639
642
|
const details = error instanceof Error ? `: ${error.message}` : "";
|
|
640
643
|
context.report({
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-oxfmt",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.22.0",
|
|
5
5
|
"description": "An ESLint plugin for formatting code with oxfmt.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"eslint",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"sideEffects": false,
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"eslint": "^9.5.0 || ^10.0.0",
|
|
50
|
-
"oxfmt": ">=0.
|
|
50
|
+
"oxfmt": ">=0.67.0",
|
|
51
51
|
"svelte": "*"
|
|
52
52
|
},
|
|
53
53
|
"peerDependenciesMeta": {
|
|
@@ -58,33 +58,33 @@
|
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"generate-differences": "^0.1.1",
|
|
60
60
|
"ignore": "^7.0.8",
|
|
61
|
-
"load-oxfmt-config": "^0.
|
|
61
|
+
"load-oxfmt-config": "^0.23.0",
|
|
62
62
|
"picomatch": "^4.0.7",
|
|
63
63
|
"synckit": "^0.11.13"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"@ntnyq/eslint-config": "^7.0.0-beta.19",
|
|
67
67
|
"@types/json-schema": "^7.0.15",
|
|
68
|
-
"@types/node": "^26.
|
|
68
|
+
"@types/node": "^26.5.0",
|
|
69
69
|
"@typescript/native-preview": "^7.0.0-dev.20260707.2",
|
|
70
|
-
"bumpp": "^12.
|
|
71
|
-
"eslint": "^10.
|
|
70
|
+
"bumpp": "^12.3.0",
|
|
71
|
+
"eslint": "^10.10.0",
|
|
72
72
|
"eslint-parser-plain": "^0.1.1",
|
|
73
|
-
"eslint-plugin-oxfmt": "0.
|
|
73
|
+
"eslint-plugin-oxfmt": "0.22.0",
|
|
74
74
|
"eslint-typegen": "^2.3.1",
|
|
75
75
|
"eslint-vitest-rule-tester": "^3.1.0",
|
|
76
76
|
"husky": "^9.1.7",
|
|
77
77
|
"jsonc-eslint-parser": "^3.3.0",
|
|
78
78
|
"nano-staged": "^1.0.2",
|
|
79
79
|
"npm-run-all2": "^9.0.3",
|
|
80
|
-
"oxfmt": "^0.
|
|
80
|
+
"oxfmt": "^0.67.0",
|
|
81
81
|
"show-invisibles": "^0.0.2",
|
|
82
82
|
"svelte": "^5.57.0",
|
|
83
83
|
"tinyglobby": "^0.2.17",
|
|
84
|
-
"tsdown": "^0.
|
|
84
|
+
"tsdown": "^0.23.0",
|
|
85
85
|
"tsx": "^4.23.13",
|
|
86
86
|
"typescript": "^6.0.3",
|
|
87
|
-
"vitest": "^
|
|
87
|
+
"vitest": "^5.0.0"
|
|
88
88
|
},
|
|
89
89
|
"engines": {
|
|
90
90
|
"node": "^20.19.0 || >=22.12.0"
|
package/workers/oxfmt.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
-
import { dirname, extname, relative } from 'node:path'
|
|
3
|
+
import { dirname, extname, relative, resolve } from 'node:path'
|
|
4
4
|
import ignore from 'ignore'
|
|
5
5
|
import { isOxfmtIgnored, loadOxfmtConfig } from 'load-oxfmt-config'
|
|
6
6
|
import { format } from 'oxfmt'
|
|
@@ -8,6 +8,7 @@ import picomatch from 'picomatch'
|
|
|
8
8
|
import { runAsWorker } from 'synckit'
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
+
* Options consumed by the worker instead of the formatter.
|
|
11
12
|
* @typedef {object} PluginOnlyOptions
|
|
12
13
|
* @property {string} [cwd] - Base working directory used for path resolution.
|
|
13
14
|
* @property {string} [configPath] - Explicit path to oxfmt config file.
|
|
@@ -21,10 +22,17 @@ import { runAsWorker } from 'synckit'
|
|
|
21
22
|
*/
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
|
-
*
|
|
25
|
+
* Formatting options, ignore patterns, and file-specific overrides.
|
|
26
|
+
* @typedef {import('load-oxfmt-config').OxfmtOptions} OxfmtOptions
|
|
25
27
|
*/
|
|
26
28
|
|
|
27
29
|
/**
|
|
30
|
+
* Combined rule options accepted by the worker.
|
|
31
|
+
* @typedef {PluginOnlyOptions & import('load-oxfmt-config').LoadOxfmtConfigOptions & OxfmtOptions} PluginOptions
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Result returned when ignore handling skips a file.
|
|
28
36
|
* @typedef {object} WorkerIgnoredResult
|
|
29
37
|
* @property {true} ignored - Indicates formatting was skipped due to ignore rules.
|
|
30
38
|
* @property {import('load-oxfmt-config').IsOxfmtIgnoredResult['reason']} [reason] - Ignore reason from resolution step.
|
|
@@ -33,6 +41,7 @@ import { runAsWorker } from 'synckit'
|
|
|
33
41
|
*/
|
|
34
42
|
|
|
35
43
|
/**
|
|
44
|
+
* Result returned after attempting to format a file.
|
|
36
45
|
* @typedef {object} WorkerFormattedResult
|
|
37
46
|
* @property {false} [ignored] - False or undefined when formatting was attempted.
|
|
38
47
|
* @property {string} code - Formatted source code.
|
|
@@ -40,20 +49,31 @@ import { runAsWorker } from 'synckit'
|
|
|
40
49
|
*/
|
|
41
50
|
|
|
42
51
|
/**
|
|
52
|
+
* Worker response for either ignored or formatted source text.
|
|
43
53
|
* @typedef {WorkerIgnoredResult | WorkerFormattedResult} WorkerFormatResult
|
|
44
54
|
*/
|
|
45
55
|
|
|
46
56
|
/**
|
|
57
|
+
* Worker controls separated from formatting and file-matching options.
|
|
47
58
|
* @typedef {object} SplitOptionsResult
|
|
48
59
|
* @property {PluginOnlyOptions} pluginOptions - Plugin orchestration options.
|
|
49
|
-
* @property {
|
|
60
|
+
* @property {OxfmtOptions} formatOptions - Oxfmt options including ignorePatterns and overrides.
|
|
50
61
|
*/
|
|
51
62
|
|
|
52
63
|
/**
|
|
64
|
+
* A file-matching override loaded from config or supplied inline.
|
|
53
65
|
* @typedef {import('load-oxfmt-config').OxfmtConfigOverride} OxfmtConfigOverride
|
|
54
66
|
*/
|
|
55
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Maximum number of compiled matchers retained in each worker cache.
|
|
70
|
+
* @type {number}
|
|
71
|
+
*/
|
|
56
72
|
const MAX_CACHE_SIZE = 200
|
|
73
|
+
/**
|
|
74
|
+
* Option names consumed by worker orchestration.
|
|
75
|
+
* @type {Set<string>}
|
|
76
|
+
*/
|
|
57
77
|
const PLUGIN_ONLY_OPTIONS = new Set([
|
|
58
78
|
'configPath',
|
|
59
79
|
'cwd',
|
|
@@ -65,9 +85,15 @@ const PLUGIN_ONLY_OPTIONS = new Set([
|
|
|
65
85
|
'useConfig',
|
|
66
86
|
'withNodeModules',
|
|
67
87
|
])
|
|
68
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* Compiled override globs keyed by their ordered pattern list.
|
|
90
|
+
* @type {Map<string, import('picomatch').Matcher>}
|
|
91
|
+
*/
|
|
69
92
|
const overrideMatcherCache = new Map()
|
|
70
|
-
/**
|
|
93
|
+
/**
|
|
94
|
+
* Compiled gitignore-style rules keyed by their ordered pattern list.
|
|
95
|
+
* @type {Map<string, import('ignore').Ignore>}
|
|
96
|
+
*/
|
|
71
97
|
const ignoreMatcherCache = new Map()
|
|
72
98
|
|
|
73
99
|
/**
|
|
@@ -75,13 +101,18 @@ const ignoreMatcherCache = new Map()
|
|
|
75
101
|
* @param {string} relativePath - Relative file path used for matching.
|
|
76
102
|
* @param {import('oxfmt').FormatConfig} baseOptions - Base format options.
|
|
77
103
|
* @param {OxfmtConfigOverride[] | undefined} overrides - Override entries.
|
|
104
|
+
* @param {string} optionsBaseDir - Base directory for paths inside override options.
|
|
78
105
|
* @returns {import('oxfmt').FormatConfig} Options after override merge.
|
|
79
106
|
*/
|
|
80
|
-
function applyOverrides(relativePath, baseOptions, overrides) {
|
|
107
|
+
function applyOverrides(relativePath, baseOptions, overrides, optionsBaseDir) {
|
|
81
108
|
if (!overrides?.length) {
|
|
82
109
|
return baseOptions
|
|
83
110
|
}
|
|
84
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Format options after applying each matching override in order.
|
|
114
|
+
* @type {import('oxfmt').FormatConfig}
|
|
115
|
+
*/
|
|
85
116
|
let merged = baseOptions
|
|
86
117
|
for (const override of overrides) {
|
|
87
118
|
if (!override?.files?.length) {
|
|
@@ -99,7 +130,7 @@ function applyOverrides(relativePath, baseOptions, overrides) {
|
|
|
99
130
|
if (matches && !excluded && override.options) {
|
|
100
131
|
merged = {
|
|
101
132
|
...merged,
|
|
102
|
-
...override.options,
|
|
133
|
+
...resolveTailwindPaths(override.options, optionsBaseDir),
|
|
103
134
|
}
|
|
104
135
|
}
|
|
105
136
|
}
|
|
@@ -123,6 +154,10 @@ async function formatViaOxfmt(filename, sourceText, options = {}) {
|
|
|
123
154
|
const useConfig = pluginOptions.useConfig !== false
|
|
124
155
|
const useCache = getUseCacheOption(pluginOptions)
|
|
125
156
|
|
|
157
|
+
/**
|
|
158
|
+
* Inline ignore patterns matched relative to ESLint cwd.
|
|
159
|
+
* @type {string[] | undefined}
|
|
160
|
+
*/
|
|
126
161
|
const ruleIgnorePatterns = isStringArray(inlineFormatOptions.ignorePatterns)
|
|
127
162
|
? inlineFormatOptions.ignorePatterns
|
|
128
163
|
: undefined
|
|
@@ -138,7 +173,10 @@ async function formatViaOxfmt(filename, sourceText, options = {}) {
|
|
|
138
173
|
}
|
|
139
174
|
|
|
140
175
|
if (pluginOptions.respectOxfmtDefaultIgnores !== false && cwd) {
|
|
141
|
-
/**
|
|
176
|
+
/**
|
|
177
|
+
* Config and ignore resolution settings for the current file.
|
|
178
|
+
* @type {import('load-oxfmt-config').IsOxfmtIgnoredOptions}
|
|
179
|
+
*/
|
|
142
180
|
const ignoredOptions = {
|
|
143
181
|
configPath: pluginOptions.configPath,
|
|
144
182
|
cwd,
|
|
@@ -168,12 +206,30 @@ async function formatViaOxfmt(filename, sourceText, options = {}) {
|
|
|
168
206
|
}
|
|
169
207
|
}
|
|
170
208
|
|
|
171
|
-
/**
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
209
|
+
/**
|
|
210
|
+
* Base directory for paths supplied in inline rule options.
|
|
211
|
+
* @type {string}
|
|
212
|
+
*/
|
|
213
|
+
const inlineBaseDir = cwd ?? dirname(filename)
|
|
214
|
+
/**
|
|
215
|
+
* Base for override globs and config-derived paths, updated after discovery.
|
|
216
|
+
* @type {string}
|
|
217
|
+
*/
|
|
218
|
+
let overrideBaseDir = inlineBaseDir
|
|
219
|
+
/**
|
|
220
|
+
* Inline overrides separated from root options to preserve merge order.
|
|
221
|
+
* @type {OxfmtOptions}
|
|
222
|
+
*/
|
|
223
|
+
const { overrides: ruleOverrides, ...inlineOptionsWithoutOverrides } =
|
|
224
|
+
inlineFormatOptions
|
|
225
|
+
/**
|
|
226
|
+
* Effective formatter options with paths resolved against their source.
|
|
227
|
+
* @type {import('oxfmt').FormatConfig}
|
|
228
|
+
*/
|
|
229
|
+
let finalOptions = resolveTailwindPaths(
|
|
230
|
+
inlineOptionsWithoutOverrides,
|
|
231
|
+
inlineBaseDir,
|
|
232
|
+
)
|
|
177
233
|
|
|
178
234
|
if (useConfig) {
|
|
179
235
|
const loaded = await loadOxfmtConfig({
|
|
@@ -185,34 +241,26 @@ async function formatViaOxfmt(filename, sourceText, options = {}) {
|
|
|
185
241
|
useCache,
|
|
186
242
|
})
|
|
187
243
|
const { overrides: configOverrides, ...loadedConfig } = loaded.config
|
|
188
|
-
const { overrides: ruleOverrides, ...inlineOptionsWithoutOverrides } =
|
|
189
|
-
inlineFormatOptions
|
|
190
|
-
effectiveOverrides = [
|
|
191
|
-
...(configOverrides ?? []),
|
|
192
|
-
...(Array.isArray(ruleOverrides) ? ruleOverrides : []),
|
|
193
|
-
]
|
|
194
244
|
overrideBaseDir = loaded.dirname ?? overrideBaseDir
|
|
195
245
|
|
|
196
246
|
finalOptions = {
|
|
197
|
-
...loadedConfig,
|
|
198
|
-
...
|
|
199
|
-
}
|
|
200
|
-
} else {
|
|
201
|
-
const { overrides: ruleOverrides, ...inlineOptionsWithoutOverrides } =
|
|
202
|
-
inlineFormatOptions
|
|
203
|
-
effectiveOverrides = Array.isArray(ruleOverrides)
|
|
204
|
-
? ruleOverrides
|
|
205
|
-
: undefined
|
|
206
|
-
finalOptions = {
|
|
207
|
-
...inlineOptionsWithoutOverrides,
|
|
247
|
+
...resolveTailwindPaths(loadedConfig, overrideBaseDir),
|
|
248
|
+
...finalOptions,
|
|
208
249
|
}
|
|
250
|
+
finalOptions = applyOverrides(
|
|
251
|
+
getRelativePath(overrideBaseDir, filename),
|
|
252
|
+
finalOptions,
|
|
253
|
+
configOverrides,
|
|
254
|
+
overrideBaseDir,
|
|
255
|
+
)
|
|
209
256
|
}
|
|
210
257
|
|
|
211
258
|
const overrideRelativePath = getRelativePath(overrideBaseDir, filename)
|
|
212
259
|
finalOptions = applyOverrides(
|
|
213
260
|
overrideRelativePath,
|
|
214
261
|
finalOptions,
|
|
215
|
-
|
|
262
|
+
Array.isArray(ruleOverrides) ? ruleOverrides : undefined,
|
|
263
|
+
inlineBaseDir,
|
|
216
264
|
)
|
|
217
265
|
|
|
218
266
|
return format(filename, sourceText, finalOptions)
|
|
@@ -239,6 +287,7 @@ function getCachedIgnoreMatcher(patterns) {
|
|
|
239
287
|
* Get or create a cached picomatch matcher for oxfmt override globs.
|
|
240
288
|
* @param {string[]} patterns - Glob patterns.
|
|
241
289
|
* @returns {import('picomatch').Matcher} Compiled matcher.
|
|
290
|
+
* @throws {Error} If a pattern contains invalid glob syntax.
|
|
242
291
|
*/
|
|
243
292
|
function getCachedOverrideMatcher(patterns) {
|
|
244
293
|
const key = patterns.join('\0')
|
|
@@ -247,6 +296,10 @@ function getCachedOverrideMatcher(patterns) {
|
|
|
247
296
|
return cached
|
|
248
297
|
}
|
|
249
298
|
|
|
299
|
+
/**
|
|
300
|
+
* Match oxfmt's dotfile and literal-extglob behavior.
|
|
301
|
+
* @type {{dot: boolean, noextglob: boolean, strictBrackets: boolean}}
|
|
302
|
+
*/
|
|
250
303
|
const matcherOptions = {
|
|
251
304
|
dot: true,
|
|
252
305
|
noextglob: true,
|
|
@@ -306,6 +359,33 @@ function isStringArray(value) {
|
|
|
306
359
|
return Array.isArray(value) && value.every(item => typeof item === 'string')
|
|
307
360
|
}
|
|
308
361
|
|
|
362
|
+
/**
|
|
363
|
+
* Resolve Tailwind paths before merging options from different sources.
|
|
364
|
+
* @param {import('oxfmt').FormatConfig} options - Format options to normalize.
|
|
365
|
+
* @param {string} baseDir - Config directory or ESLint cwd for inline options.
|
|
366
|
+
* @returns {import('oxfmt').FormatConfig} Options with absolute Tailwind paths.
|
|
367
|
+
*/
|
|
368
|
+
function resolveTailwindPaths(options, baseDir) {
|
|
369
|
+
const { sortTailwindcss } = options
|
|
370
|
+
if (!sortTailwindcss || typeof sortTailwindcss !== 'object') {
|
|
371
|
+
return options
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Copy paths before resolving them to avoid mutating cached config objects.
|
|
376
|
+
* @type {import('oxfmt').SortTailwindcssConfig}
|
|
377
|
+
*/
|
|
378
|
+
const resolved = { ...sortTailwindcss }
|
|
379
|
+
if (resolved.config) {
|
|
380
|
+
resolved.config = resolve(baseDir, resolved.config)
|
|
381
|
+
}
|
|
382
|
+
if (resolved.stylesheet) {
|
|
383
|
+
resolved.stylesheet = resolve(baseDir, resolved.stylesheet)
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return { ...options, sortTailwindcss: resolved }
|
|
387
|
+
}
|
|
388
|
+
|
|
309
389
|
/**
|
|
310
390
|
* Store a value in a FIFO cache map with a bounded size.
|
|
311
391
|
* @template T Cache value type.
|
|
@@ -324,9 +404,9 @@ function setCacheEntry(cache, key, value) {
|
|
|
324
404
|
}
|
|
325
405
|
|
|
326
406
|
/**
|
|
327
|
-
* Check if a file should be ignored by provided
|
|
407
|
+
* Check if a file should be ignored by provided gitignore-style patterns.
|
|
328
408
|
* @param {string} relativePath - Relative path against pattern base.
|
|
329
|
-
* @param {string[] | undefined} ignorePatterns -
|
|
409
|
+
* @param {string[] | undefined} ignorePatterns - Ordered gitignore-style patterns.
|
|
330
410
|
* @returns {boolean} Whether file is ignored.
|
|
331
411
|
*/
|
|
332
412
|
function shouldIgnoreFile(relativePath, ignorePatterns) {
|
|
@@ -339,14 +419,20 @@ function shouldIgnoreFile(relativePath, ignorePatterns) {
|
|
|
339
419
|
}
|
|
340
420
|
|
|
341
421
|
/**
|
|
342
|
-
* Split worker
|
|
422
|
+
* Split worker controls from oxfmt options, ignore patterns, and overrides.
|
|
343
423
|
* @param {PluginOptions} [options] - Raw worker options.
|
|
344
424
|
* @returns {SplitOptionsResult} Split option buckets.
|
|
345
425
|
*/
|
|
346
426
|
function splitOptions(options = {}) {
|
|
347
|
-
/**
|
|
427
|
+
/**
|
|
428
|
+
* Options consumed by config loading and ignore orchestration.
|
|
429
|
+
* @type {Record<string, unknown>}
|
|
430
|
+
*/
|
|
348
431
|
const pluginOptions = {}
|
|
349
|
-
/**
|
|
432
|
+
/**
|
|
433
|
+
* Remaining oxfmt options, including file-matching configuration.
|
|
434
|
+
* @type {Record<string, unknown>}
|
|
435
|
+
*/
|
|
350
436
|
const formatOptions = {}
|
|
351
437
|
|
|
352
438
|
for (const [key, value] of Object.entries(options)) {
|
|
@@ -358,7 +444,7 @@ function splitOptions(options = {}) {
|
|
|
358
444
|
}
|
|
359
445
|
|
|
360
446
|
return {
|
|
361
|
-
formatOptions: /** @type {
|
|
447
|
+
formatOptions: /** @type {OxfmtOptions} */ (formatOptions),
|
|
362
448
|
pluginOptions: /** @type {PluginOnlyOptions} */ (pluginOptions),
|
|
363
449
|
}
|
|
364
450
|
}
|
|
@@ -366,11 +452,19 @@ function splitOptions(options = {}) {
|
|
|
366
452
|
/**
|
|
367
453
|
* Validate plugin-only options before dispatching to helper libraries.
|
|
368
454
|
* @param {PluginOnlyOptions} pluginOptions - Plugin-only options.
|
|
455
|
+
* @returns {void}
|
|
456
|
+
* @throws {TypeError} If a supported plugin option has an invalid value type.
|
|
369
457
|
*/
|
|
370
458
|
function validatePluginOptions(pluginOptions) {
|
|
371
|
-
/**
|
|
459
|
+
/**
|
|
460
|
+
* Plugin options validated as strings when provided.
|
|
461
|
+
* @type {('cwd' | 'configPath')[]}
|
|
462
|
+
*/
|
|
372
463
|
const stringKeys = ['configPath', 'cwd']
|
|
373
|
-
/**
|
|
464
|
+
/**
|
|
465
|
+
* Plugin switches validated as booleans when provided.
|
|
466
|
+
* @type {('disableNestedConfig' | 'respectOxfmtDefaultIgnores' | 'useConfig' | 'useCache' | 'withNodeModules')[]}
|
|
467
|
+
*/
|
|
374
468
|
const booleanKeys = [
|
|
375
469
|
'disableNestedConfig',
|
|
376
470
|
'respectOxfmtDefaultIgnores',
|