@zgeoff/format-codemod 0.0.1 → 0.0.2
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/dist/cli/expand-inputs.d.ts +4 -2
- package/dist/cli/parse-cli-args.d.ts +1 -0
- package/dist/cli.js +54 -34
- package/dist/index.js +34 -25
- package/dist/transform/collect-ast-nodes.d.ts +6 -0
- package/dist/transform/collect-child-nodes.d.ts +6 -0
- package/dist/transform/is-ast-node.d.ts +2 -0
- package/package.json +1 -1
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Deduped: overlapping patterns (a `src/**` glob plus a file inside src/) must
|
|
3
|
-
* not process — or report — the same file twice.
|
|
3
|
+
* not process — or report — the same file twice. Ignore globs filter the final
|
|
4
|
+
* list uniformly, so a file is skipped whether it arrived via a directory,
|
|
5
|
+
* a glob, or an explicit path argument.
|
|
4
6
|
*/
|
|
5
|
-
export declare function expandInputs(patterns: readonly string[]): Promise<string[]>;
|
|
7
|
+
export declare function expandInputs(patterns: readonly string[], ignore?: readonly string[]): Promise<string[]>;
|
package/dist/cli.js
CHANGED
|
@@ -20,9 +20,9 @@ function buildBenchStatsFromReports(reports, ms) {
|
|
|
20
20
|
// src/cli/expand-inputs.ts
|
|
21
21
|
import fs from "node:fs";
|
|
22
22
|
import path from "node:path";
|
|
23
|
-
async function expandInputs(patterns) {
|
|
23
|
+
async function expandInputs(patterns, ignore = []) {
|
|
24
24
|
const lists = await Promise.all(patterns.map((p) => expandPattern(p)));
|
|
25
|
-
return [...new Set(lists.flat())];
|
|
25
|
+
return [...new Set(lists.flat())].filter((file) => !isIgnored(file, ignore));
|
|
26
26
|
}
|
|
27
27
|
function expandPattern(p) {
|
|
28
28
|
if (fs.existsSync(p)) {
|
|
@@ -41,6 +41,13 @@ function isExcluded(entry) {
|
|
|
41
41
|
const p = typeof entry === "string" ? entry : path.join(entry.parentPath ?? "", entry.name);
|
|
42
42
|
return p.split(/[\\/]/u).some((seg) => seg === "node_modules" || seg === ".git");
|
|
43
43
|
}
|
|
44
|
+
function isIgnored(file, patterns) {
|
|
45
|
+
if (patterns.length === 0) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
const relative = path.relative(process.cwd(), file);
|
|
49
|
+
return patterns.some((pattern) => path.matchesGlob(file, pattern) || path.matchesGlob(relative, pattern));
|
|
50
|
+
}
|
|
44
51
|
|
|
45
52
|
// src/cli/parse-cli-args.ts
|
|
46
53
|
import { parseArgs } from "node:util";
|
|
@@ -54,7 +61,8 @@ function parseCLIArgs(argv) {
|
|
|
54
61
|
bench: { type: "boolean", default: false },
|
|
55
62
|
quiet: { type: "boolean", default: false },
|
|
56
63
|
version: { type: "boolean", default: false },
|
|
57
|
-
help: { type: "boolean", default: false }
|
|
64
|
+
help: { type: "boolean", default: false },
|
|
65
|
+
ignore: { type: "string", multiple: true, default: [] }
|
|
58
66
|
},
|
|
59
67
|
allowPositionals: true,
|
|
60
68
|
strict: true
|
|
@@ -65,6 +73,7 @@ function parseCLIArgs(argv) {
|
|
|
65
73
|
bench: values.bench,
|
|
66
74
|
help: values.help,
|
|
67
75
|
version: values.version,
|
|
76
|
+
ignore: values.ignore,
|
|
68
77
|
inputs: positionals
|
|
69
78
|
};
|
|
70
79
|
} catch (error) {
|
|
@@ -86,10 +95,11 @@ usage:
|
|
|
86
95
|
format-codemod [options] <file|dir|glob> ...
|
|
87
96
|
|
|
88
97
|
options:
|
|
89
|
-
--check
|
|
90
|
-
--dry
|
|
91
|
-
--bench
|
|
92
|
-
--quiet
|
|
98
|
+
--check exit 1 if any file would change (no writes)
|
|
99
|
+
--dry print unified diff to stdout (no writes)
|
|
100
|
+
--bench print parse stats as JSON to stderr
|
|
101
|
+
--quiet only print files that would change
|
|
102
|
+
--ignore <glob> skip files matching the glob (repeatable)
|
|
93
103
|
--version
|
|
94
104
|
--help
|
|
95
105
|
|
|
@@ -102,6 +112,7 @@ examples:
|
|
|
102
112
|
format-codemod 'src/**/*.ts'
|
|
103
113
|
format-codemod --check 'src/**/*.{ts,tsx}'
|
|
104
114
|
format-codemod --dry path/to/file.ts
|
|
115
|
+
format-codemod --ignore 'src/generated/**' .
|
|
105
116
|
`);
|
|
106
117
|
}
|
|
107
118
|
|
|
@@ -149,6 +160,36 @@ function applyEdits(src, edits) {
|
|
|
149
160
|
return segments.toReversed().join("");
|
|
150
161
|
}
|
|
151
162
|
|
|
163
|
+
// src/transform/is-ast-node.ts
|
|
164
|
+
function isASTNode(value) {
|
|
165
|
+
return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string";
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// src/transform/collect-ast-nodes.ts
|
|
169
|
+
function collectASTNodes(value) {
|
|
170
|
+
if (!Array.isArray(value)) {
|
|
171
|
+
return isASTNode(value) ? [value] : [];
|
|
172
|
+
}
|
|
173
|
+
const nodes = [];
|
|
174
|
+
for (const item of value) {
|
|
175
|
+
if (isASTNode(item)) {
|
|
176
|
+
nodes.push(item);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return nodes;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// src/transform/collect-child-nodes.ts
|
|
183
|
+
function collectChildNodes(node) {
|
|
184
|
+
const children = [];
|
|
185
|
+
for (const key of Object.keys(node)) {
|
|
186
|
+
if (key !== "loc" && key !== "parent") {
|
|
187
|
+
children.push(...collectASTNodes(node[key]));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return children;
|
|
191
|
+
}
|
|
192
|
+
|
|
152
193
|
// src/transform/plan-gap-edit.ts
|
|
153
194
|
function planGapEdit(file, prev, next) {
|
|
154
195
|
const gap = buildGap(file, prev, next);
|
|
@@ -269,7 +310,7 @@ function buildPairEdits(file, container, body) {
|
|
|
269
310
|
for (let i = 0;i < body.length - 1; i++) {
|
|
270
311
|
const prev = body[i];
|
|
271
312
|
const next = body[i + 1];
|
|
272
|
-
if (prev !== undefined && next !== undefined && (needsBlankLine(container, prev, next) || isMultiline(file.src, prev) || isMultiline(file.src, next))) {
|
|
313
|
+
if (prev !== undefined && next !== undefined && !isImportPair(prev, next) && (needsBlankLine(container, prev, next) || isMultiline(file.src, prev) || isMultiline(file.src, next))) {
|
|
273
314
|
const edit = planGapEdit(file, prev, next);
|
|
274
315
|
if (edit !== null) {
|
|
275
316
|
edits.push(edit);
|
|
@@ -278,6 +319,9 @@ function buildPairEdits(file, container, body) {
|
|
|
278
319
|
}
|
|
279
320
|
return edits;
|
|
280
321
|
}
|
|
322
|
+
function isImportPair(prev, next) {
|
|
323
|
+
return prev.type === "ImportDeclaration" && next.type === "ImportDeclaration";
|
|
324
|
+
}
|
|
281
325
|
function isMultiline(src, node) {
|
|
282
326
|
return typeof node.start === "number" && typeof node.end === "number" && src.slice(node.start, node.end).includes(`
|
|
283
327
|
`);
|
|
@@ -374,30 +418,6 @@ function isVarDecl(node) {
|
|
|
374
418
|
function isFnOrClassDecl(node) {
|
|
375
419
|
return node.type === "FunctionDeclaration" || node.type === "ClassDeclaration";
|
|
376
420
|
}
|
|
377
|
-
function collectChildNodes(node) {
|
|
378
|
-
const children = [];
|
|
379
|
-
for (const key of Object.keys(node)) {
|
|
380
|
-
if (key !== "loc" && key !== "parent") {
|
|
381
|
-
children.push(...collectASTNodes(node[key]));
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
return children;
|
|
385
|
-
}
|
|
386
|
-
function collectASTNodes(value) {
|
|
387
|
-
if (!Array.isArray(value)) {
|
|
388
|
-
return isASTNode(value) ? [value] : [];
|
|
389
|
-
}
|
|
390
|
-
const nodes = [];
|
|
391
|
-
for (const item of value) {
|
|
392
|
-
if (isASTNode(item)) {
|
|
393
|
-
nodes.push(item);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
return nodes;
|
|
397
|
-
}
|
|
398
|
-
function isASTNode(value) {
|
|
399
|
-
return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string";
|
|
400
|
-
}
|
|
401
421
|
|
|
402
422
|
// src/transform/parse-source.ts
|
|
403
423
|
import { parseSync } from "oxc-parser";
|
|
@@ -633,7 +653,7 @@ if (typeof parsedArgs === "string") {
|
|
|
633
653
|
console.error(parsedArgs);
|
|
634
654
|
process.exit(2);
|
|
635
655
|
}
|
|
636
|
-
var { mode, quiet, bench, help, version, inputs } = parsedArgs;
|
|
656
|
+
var { mode, quiet, bench, help, version, ignore, inputs } = parsedArgs;
|
|
637
657
|
if (help || inputs.length === 0 && !version) {
|
|
638
658
|
const exitCode = inputs.length === 0 ? 2 : 0;
|
|
639
659
|
printHelp();
|
|
@@ -646,7 +666,7 @@ if (version) {
|
|
|
646
666
|
process.exit(0);
|
|
647
667
|
}
|
|
648
668
|
var t0 = Date.now();
|
|
649
|
-
var files = await expandInputs(inputs);
|
|
669
|
+
var files = await expandInputs(inputs, ignore);
|
|
650
670
|
if (files.length === 0) {
|
|
651
671
|
console.error("no files matched");
|
|
652
672
|
process.exit(2);
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,36 @@ function applyEdits(src, edits) {
|
|
|
10
10
|
return segments.toReversed().join("");
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
// src/transform/is-ast-node.ts
|
|
14
|
+
function isASTNode(value) {
|
|
15
|
+
return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// src/transform/collect-ast-nodes.ts
|
|
19
|
+
function collectASTNodes(value) {
|
|
20
|
+
if (!Array.isArray(value)) {
|
|
21
|
+
return isASTNode(value) ? [value] : [];
|
|
22
|
+
}
|
|
23
|
+
const nodes = [];
|
|
24
|
+
for (const item of value) {
|
|
25
|
+
if (isASTNode(item)) {
|
|
26
|
+
nodes.push(item);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return nodes;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// src/transform/collect-child-nodes.ts
|
|
33
|
+
function collectChildNodes(node) {
|
|
34
|
+
const children = [];
|
|
35
|
+
for (const key of Object.keys(node)) {
|
|
36
|
+
if (key !== "loc" && key !== "parent") {
|
|
37
|
+
children.push(...collectASTNodes(node[key]));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return children;
|
|
41
|
+
}
|
|
42
|
+
|
|
13
43
|
// src/transform/plan-gap-edit.ts
|
|
14
44
|
function planGapEdit(file, prev, next) {
|
|
15
45
|
const gap = buildGap(file, prev, next);
|
|
@@ -130,7 +160,7 @@ function buildPairEdits(file, container, body) {
|
|
|
130
160
|
for (let i = 0;i < body.length - 1; i++) {
|
|
131
161
|
const prev = body[i];
|
|
132
162
|
const next = body[i + 1];
|
|
133
|
-
if (prev !== undefined && next !== undefined && (needsBlankLine(container, prev, next) || isMultiline(file.src, prev) || isMultiline(file.src, next))) {
|
|
163
|
+
if (prev !== undefined && next !== undefined && !isImportPair(prev, next) && (needsBlankLine(container, prev, next) || isMultiline(file.src, prev) || isMultiline(file.src, next))) {
|
|
134
164
|
const edit = planGapEdit(file, prev, next);
|
|
135
165
|
if (edit !== null) {
|
|
136
166
|
edits.push(edit);
|
|
@@ -139,6 +169,9 @@ function buildPairEdits(file, container, body) {
|
|
|
139
169
|
}
|
|
140
170
|
return edits;
|
|
141
171
|
}
|
|
172
|
+
function isImportPair(prev, next) {
|
|
173
|
+
return prev.type === "ImportDeclaration" && next.type === "ImportDeclaration";
|
|
174
|
+
}
|
|
142
175
|
function isMultiline(src, node) {
|
|
143
176
|
return typeof node.start === "number" && typeof node.end === "number" && src.slice(node.start, node.end).includes(`
|
|
144
177
|
`);
|
|
@@ -235,30 +268,6 @@ function isVarDecl(node) {
|
|
|
235
268
|
function isFnOrClassDecl(node) {
|
|
236
269
|
return node.type === "FunctionDeclaration" || node.type === "ClassDeclaration";
|
|
237
270
|
}
|
|
238
|
-
function collectChildNodes(node) {
|
|
239
|
-
const children = [];
|
|
240
|
-
for (const key of Object.keys(node)) {
|
|
241
|
-
if (key !== "loc" && key !== "parent") {
|
|
242
|
-
children.push(...collectASTNodes(node[key]));
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
return children;
|
|
246
|
-
}
|
|
247
|
-
function collectASTNodes(value) {
|
|
248
|
-
if (!Array.isArray(value)) {
|
|
249
|
-
return isASTNode(value) ? [value] : [];
|
|
250
|
-
}
|
|
251
|
-
const nodes = [];
|
|
252
|
-
for (const item of value) {
|
|
253
|
-
if (isASTNode(item)) {
|
|
254
|
-
nodes.push(item);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
return nodes;
|
|
258
|
-
}
|
|
259
|
-
function isASTNode(value) {
|
|
260
|
-
return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string";
|
|
261
|
-
}
|
|
262
271
|
|
|
263
272
|
// src/transform/parse-source.ts
|
|
264
273
|
import { parseSync } from "oxc-parser";
|