@node-cli/comments 0.1.0 → 0.2.1
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/__tests__/glob.test.js +25 -17
- package/dist/__tests__/glob.test.js.map +1 -1
- package/dist/__tests__/lib.test.js +107 -26
- package/dist/__tests__/lib.test.js.map +1 -1
- package/dist/glob.d.ts +0 -1
- package/dist/glob.js +18 -149
- package/dist/glob.js.map +1 -1
- package/dist/lib.js +267 -86
- package/dist/lib.js.map +1 -1
- package/package.json +6 -3
|
@@ -2,21 +2,29 @@ import fs from "node:fs";
|
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { describe, expect, it } from "vitest";
|
|
5
|
-
import {
|
|
5
|
+
import { expandGlobs } from "../glob.js";
|
|
6
6
|
import { parseAndTransformComments } from "../lib.js";
|
|
7
7
|
describe("glob utilities & additional lib branches", function() {
|
|
8
|
-
it("
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
//
|
|
16
|
-
var
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
expect(
|
|
8
|
+
it("explicit globstar required for deep matches (no implicit augmentation)", function() {
|
|
9
|
+
// create temp structure.
|
|
10
|
+
var root = fs.mkdtempSync(path.join(os.tmpdir(), "comments-glob-simplify-"));
|
|
11
|
+
fs.mkdirSync(path.join(root, "nested"));
|
|
12
|
+
var a = path.join(root, "a.ts");
|
|
13
|
+
var b = path.join(root, "nested", "b.ts");
|
|
14
|
+
fs.writeFileSync(a, "// a", "utf8");
|
|
15
|
+
fs.writeFileSync(b, "// b", "utf8");
|
|
16
|
+
var shallow = expandGlobs([
|
|
17
|
+
"".concat(root, "/*.ts")
|
|
18
|
+
]);
|
|
19
|
+
expect(shallow).toContain(a);
|
|
20
|
+
expect(shallow).not.toContain(b); // no implicit deep variant
|
|
21
|
+
var deep = expandGlobs([
|
|
22
|
+
"".concat(root, "/**/*.ts")
|
|
23
|
+
]);
|
|
24
|
+
expect(deep).toEqual(expect.arrayContaining([
|
|
25
|
+
a,
|
|
26
|
+
b
|
|
27
|
+
]));
|
|
20
28
|
});
|
|
21
29
|
it("expandGlobs matches literals and wildcards including ?", function() {
|
|
22
30
|
var root = fs.mkdtempSync(path.join(os.tmpdir(), "comments-glob2-"));
|
|
@@ -92,7 +100,7 @@ describe("glob utilities & additional lib branches", function() {
|
|
|
92
100
|
var root = fs.mkdtempSync(path.join(os.tmpdir(), "comments-glob-lit-"));
|
|
93
101
|
var file = path.join(root, "only.ts");
|
|
94
102
|
fs.writeFileSync(file, "// only", "utf8");
|
|
95
|
-
// duplicate patterns plus a nonexistent literal
|
|
103
|
+
// duplicate patterns plus a nonexistent literal.
|
|
96
104
|
var patterns = [
|
|
97
105
|
file,
|
|
98
106
|
file,
|
|
@@ -120,14 +128,14 @@ describe("glob utilities & additional lib branches", function() {
|
|
|
120
128
|
wrapLineComments: true,
|
|
121
129
|
mergeLineComments: false
|
|
122
130
|
}).transformed;
|
|
123
|
-
// At least one blank line (line with only '*') preserved around fence
|
|
131
|
+
// At least one blank line (line with only '*') preserved around fence.
|
|
124
132
|
var starBlankCount = out.split(/\n/).filter(function(l) {
|
|
125
133
|
return /^\s*\*\s*$/.test(l);
|
|
126
134
|
}).length;
|
|
127
135
|
expect(starBlankCount).toBeGreaterThanOrEqual(1);
|
|
128
|
-
// Fenced code block retained
|
|
136
|
+
// Fenced code block retained.
|
|
129
137
|
expect(out).toContain("```sh");
|
|
130
|
-
// Second paragraph ended with period added
|
|
138
|
+
// Second paragraph ended with period added.
|
|
131
139
|
expect(/Second paragraph without period\./.test(out)).toBe(true);
|
|
132
140
|
});
|
|
133
141
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/__tests__/glob.test.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { describe, expect, it } from \"vitest\";\nimport {
|
|
1
|
+
{"version":3,"sources":["../../src/__tests__/glob.test.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { describe, expect, it } from \"vitest\";\nimport { expandGlobs } from \"../glob.js\";\nimport { parseAndTransformComments } from \"../lib.js\";\n\ndescribe(\"glob utilities & additional lib branches\", () => {\n\tit(\"explicit globstar required for deep matches (no implicit augmentation)\", () => {\n\t\t// create temp structure.\n\t\tconst root = fs.mkdtempSync(\n\t\t\tpath.join(os.tmpdir(), \"comments-glob-simplify-\"),\n\t\t);\n\t\tfs.mkdirSync(path.join(root, \"nested\"));\n\t\tconst a = path.join(root, \"a.ts\");\n\t\tconst b = path.join(root, \"nested\", \"b.ts\");\n\t\tfs.writeFileSync(a, \"// a\", \"utf8\");\n\t\tfs.writeFileSync(b, \"// b\", \"utf8\");\n\t\tconst shallow = expandGlobs([`${root}/*.ts`]);\n\t\texpect(shallow).toContain(a);\n\t\texpect(shallow).not.toContain(b); // no implicit deep variant\n\t\tconst deep = expandGlobs([`${root}/**/*.ts`]);\n\t\texpect(deep).toEqual(expect.arrayContaining([a, b]));\n\t});\n\n\tit(\"expandGlobs matches literals and wildcards including ?\", () => {\n\t\tconst root = fs.mkdtempSync(path.join(os.tmpdir(), \"comments-glob2-\"));\n\t\tconst files = [\"a.ts\", \"ab.ts\", \"abc.ts\", \"note.md\"]; // to test ? wildcard and *\n\t\tfor (const f of files) {\n\t\t\tfs.writeFileSync(path.join(root, f), \"// x\", \"utf8\");\n\t\t}\n\t\tconst patterns = [\n\t\t\tpath.join(root, \"a?.ts\"), // should match ab.ts only\n\t\t\tpath.join(root, \"a*.ts\"), // matches a.ts, ab.ts, abc.ts\n\t\t\tpath.join(root, \"note.md\"), // literal\n\t\t];\n\t\tconst expanded = expandGlobs(patterns)\n\t\t\t.map((p) => path.basename(p))\n\t\t\t.sort();\n\t\texpect(expanded).toEqual([\"a.ts\", \"ab.ts\", \"abc.ts\", \"note.md\"].sort());\n\t});\n\n\tit(\"expandGlobs handles symlinks when followSymlinks true\", () => {\n\t\tconst root = fs.mkdtempSync(path.join(os.tmpdir(), \"comments-glob-sym-\"));\n\t\tconst target = path.join(root, \"target.ts\");\n\t\tfs.writeFileSync(target, \"// target\", \"utf8\");\n\t\tconst link = path.join(root, \"link.ts\");\n\t\ttry {\n\t\t\tfs.symlinkSync(target, link);\n\t\t} catch {\n\t\t\t// Some file systems may not allow symlinks (CI on Windows); skip gracefully.\n\t\t\treturn;\n\t\t}\n\t\tconst pattern = path.join(root, \"*.ts\");\n\t\tconst noFollow = expandGlobs([pattern], { followSymlinks: false });\n\t\texpect(noFollow).toContain(target);\n\t\texpect(noFollow).not.toContain(link);\n\t\tconst withFollow = expandGlobs([pattern], { followSymlinks: true });\n\t\texpect(withFollow).toContain(target);\n\t\texpect(withFollow).toContain(link);\n\t});\n\n\tit(\"expandGlobs handles file literals, duplicate patterns and nonexistent paths\", () => {\n\t\tconst root = fs.mkdtempSync(path.join(os.tmpdir(), \"comments-glob-lit-\"));\n\t\tconst file = path.join(root, \"only.ts\");\n\t\tfs.writeFileSync(file, \"// only\", \"utf8\");\n\t\t// duplicate patterns plus a nonexistent literal.\n\t\tconst patterns = [file, file, path.join(root, \"missing.ts\")];\n\t\tconst out = expandGlobs(patterns);\n\t\texpect(out).toEqual([file]); // only once\n\t});\n\n\tit(\"lib buildJsDoc preserves blank line separation and fences (edge branch)\", () => {\n\t\tconst input = [\n\t\t\t\"/**\",\n\t\t\t\" * First paragraph line\",\n\t\t\t\" *\",\n\t\t\t\" * ```sh\",\n\t\t\t\" * echo hi\",\n\t\t\t\" * ```\",\n\t\t\t\" *\",\n\t\t\t\" * Second paragraph without period\",\n\t\t\t\" */\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(input, {\n\t\t\twidth: 60,\n\t\t\twrapLineComments: true,\n\t\t\tmergeLineComments: false,\n\t\t}).transformed;\n\t\t// At least one blank line (line with only '*') preserved around fence.\n\t\tconst starBlankCount = out\n\t\t\t.split(/\\n/)\n\t\t\t.filter((l) => /^\\s*\\*\\s*$/.test(l)).length;\n\t\texpect(starBlankCount).toBeGreaterThanOrEqual(1);\n\t\t// Fenced code block retained.\n\t\texpect(out).toContain(\"```sh\");\n\t\t// Second paragraph ended with period added.\n\t\texpect(/Second paragraph without period\\./.test(out)).toBe(true);\n\t});\n});\n"],"names":["fs","os","path","describe","expect","it","expandGlobs","parseAndTransformComments","root","mkdtempSync","join","tmpdir","mkdirSync","a","b","writeFileSync","shallow","toContain","not","deep","toEqual","arrayContaining","files","f","patterns","expanded","map","p","basename","sort","target","link","symlinkSync","pattern","noFollow","followSymlinks","withFollow","file","out","input","width","wrapLineComments","mergeLineComments","transformed","starBlankCount","split","filter","l","test","length","toBeGreaterThanOrEqual","toBe"],"mappings":"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"}
|
|
@@ -54,7 +54,7 @@ import fs from "node:fs";
|
|
|
54
54
|
import os from "node:os";
|
|
55
55
|
import path from "node:path";
|
|
56
56
|
import { describe, expect, it } from "vitest";
|
|
57
|
-
import {
|
|
57
|
+
import { expandGlobs } from "../glob.js";
|
|
58
58
|
import { diffLines, parseAndTransformComments } from "../lib.js";
|
|
59
59
|
var baseOpts = {
|
|
60
60
|
width: 60,
|
|
@@ -99,7 +99,7 @@ describe("parseAndTransformComments", function() {
|
|
|
99
99
|
var input = "/**\n * Before\n * ```js\n * const x= 1; \n * ```\n * After\n */";
|
|
100
100
|
var res = parseAndTransformComments(input, baseOpts).transformed;
|
|
101
101
|
expect(/```js/.test(res)).toBe(true);
|
|
102
|
-
// ensure spacing inside fence not normalized
|
|
102
|
+
// ensure spacing inside fence not normalized.
|
|
103
103
|
expect(/const {2}x= {2}1;/.test(res)).toBe(true);
|
|
104
104
|
});
|
|
105
105
|
it("does not merge directive or license groups", function() {
|
|
@@ -114,13 +114,13 @@ describe("parseAndTransformComments", function() {
|
|
|
114
114
|
mergeLineComments: true
|
|
115
115
|
}));
|
|
116
116
|
expect(/eslint-disable/.test(res.transformed)).toBe(true);
|
|
117
|
-
// Should not have merged into a jsdoc (no /** directly before const)
|
|
117
|
+
// Should not have merged into a jsdoc (no /** directly before const).
|
|
118
118
|
expect(/\/\*\*/.test(res.transformed)).toBe(false);
|
|
119
119
|
});
|
|
120
120
|
it("list items are not reflowed into a paragraph", function() {
|
|
121
121
|
var input = "/**\n * First line explaining.\n * - item one more words here\n * - item two\n */";
|
|
122
122
|
var res = parseAndTransformComments(input, baseOpts).transformed;
|
|
123
|
-
// each list item remains on its own line with leading dash
|
|
123
|
+
// each list item remains on its own line with leading dash.
|
|
124
124
|
var lines = res.split(/\n/).filter(function(l) {
|
|
125
125
|
return /- item/.test(l);
|
|
126
126
|
});
|
|
@@ -144,21 +144,23 @@ describe("parseAndTransformComments", function() {
|
|
|
144
144
|
" */"
|
|
145
145
|
].join("\n");
|
|
146
146
|
var out = parseAndTransformComments(input, baseOpts).transformed;
|
|
147
|
-
// Heading preserved, not merged into previous paragraph
|
|
147
|
+
// Heading preserved, not merged into previous paragraph.
|
|
148
148
|
expect(out).toMatch(/Overview:/);
|
|
149
|
-
// Visually indented code line kept as-is (no extra wrapping collapse)
|
|
149
|
+
// Visually indented code line kept as-is (no extra wrapping collapse).
|
|
150
150
|
expect(out).toMatch(/const\s{3}x = 1;/);
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
151
|
+
/**
|
|
152
|
+
* Trailing blank before closing is optional after recent trimming change. (we
|
|
153
|
+
* only keep it when multiple paragraphs exist). Assert closing exists.
|
|
154
|
+
* Closing delimiter should be on its own line; allow optional leading
|
|
155
|
+
* space(s).
|
|
156
|
+
*/ expect(/\n\s*\*\/$/.test(out)).toBe(true);
|
|
157
|
+
// Numeric list lines preserved.
|
|
155
158
|
expect(out).toMatch(/1\. first/);
|
|
156
159
|
expect(out).toMatch(/2\. second/);
|
|
157
|
-
// Trailing paragraph got terminal period
|
|
160
|
+
// Trailing paragraph got terminal period.
|
|
158
161
|
expect(out).toMatch(/Another paragraph without period\./);
|
|
159
162
|
});
|
|
160
|
-
it("glob expansion matches
|
|
161
|
-
// Create a truly temporary isolated directory outside source tree
|
|
163
|
+
it("glob expansion matches deep files only with explicit globstar", function() {
|
|
162
164
|
var tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "comments-glob-"));
|
|
163
165
|
var a = path.join(tmpRoot, "a.ts");
|
|
164
166
|
var nestedDir = path.join(tmpRoot, "nested");
|
|
@@ -168,21 +170,26 @@ describe("parseAndTransformComments", function() {
|
|
|
168
170
|
var b = path.join(nestedDir, "b.ts");
|
|
169
171
|
fs.writeFileSync(a, "// file a", "utf8");
|
|
170
172
|
fs.writeFileSync(b, "// file b", "utf8");
|
|
171
|
-
|
|
173
|
+
// Shallow pattern should only see top-level a.ts.
|
|
174
|
+
var shallow = expandGlobs([
|
|
172
175
|
"".concat(tmpRoot, "/*.ts")
|
|
173
|
-
];
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
var
|
|
179
|
-
|
|
176
|
+
]).sort();
|
|
177
|
+
expect(shallow).toEqual([
|
|
178
|
+
a
|
|
179
|
+
]);
|
|
180
|
+
// Deep pattern matches both.
|
|
181
|
+
var deep = expandGlobs([
|
|
182
|
+
"".concat(tmpRoot, "/**/*.ts")
|
|
183
|
+
]).sort();
|
|
184
|
+
expect(deep).toEqual([
|
|
180
185
|
a,
|
|
181
186
|
b
|
|
182
187
|
].sort());
|
|
183
188
|
});
|
|
184
|
-
|
|
185
|
-
|
|
189
|
+
/**
|
|
190
|
+
* Added test for preserving multi-line // comment groups that should NOT merge
|
|
191
|
+
* when preceded by code.
|
|
192
|
+
*/ it("does not merge an inline explanatory multi-line // comment group following code", function() {
|
|
186
193
|
var src = [
|
|
187
194
|
"function demo() {",
|
|
188
195
|
" const x = 1; // keep",
|
|
@@ -229,19 +236,93 @@ describe("parseAndTransformComments", function() {
|
|
|
229
236
|
wrapLineComments: true,
|
|
230
237
|
mergeLineComments: true
|
|
231
238
|
}).transformed;
|
|
232
|
-
// Should be converted to a JSDoc (first and last lines delimiters)
|
|
239
|
+
// Should be converted to a JSDoc (first and last lines delimiters).
|
|
233
240
|
var lines = out.split(/\n/);
|
|
234
241
|
expect(lines[0].trim()).toBe("/**");
|
|
235
242
|
expect(lines[lines.length - 1].trim()).toBe("*/");
|
|
236
|
-
// Ensure representative internal lines are present (now without leading //)
|
|
243
|
+
// Ensure representative internal lines are present (now without leading //).
|
|
237
244
|
expect(out).toContain("* JSDoc block extraction:");
|
|
238
245
|
expect(out).toContain("* Pattern explanation:");
|
|
239
|
-
// Arrow lines preserved
|
|
246
|
+
// Arrow lines preserved.
|
|
240
247
|
var arrowLineCount = lines.filter(function(l) {
|
|
241
248
|
return /->/.test(l);
|
|
242
249
|
}).length;
|
|
243
250
|
expect(arrowLineCount).toBeGreaterThanOrEqual(5);
|
|
244
251
|
});
|
|
252
|
+
it("does not insert period before list introduced by single lowercase word + colon", function() {
|
|
253
|
+
var input = [
|
|
254
|
+
"/**",
|
|
255
|
+
" * Some utilities have logging capabilities that needs to be",
|
|
256
|
+
" * tested a little bit differently:",
|
|
257
|
+
" * - mocking process.exit",
|
|
258
|
+
" * - console.log",
|
|
259
|
+
" * - inquirer.prompt",
|
|
260
|
+
" */"
|
|
261
|
+
].join("\n");
|
|
262
|
+
var out = parseAndTransformComments(input, baseOpts).transformed;
|
|
263
|
+
// Ensure no stray period after 'be'.
|
|
264
|
+
expect(out).not.toMatch(/needs to be\./);
|
|
265
|
+
// Ensure list items unchanged.
|
|
266
|
+
expect(out).toMatch(/- mocking process\.exit/);
|
|
267
|
+
});
|
|
268
|
+
it("does not add stray period before lowercase colon line inside jsdoc", function() {
|
|
269
|
+
var input = [
|
|
270
|
+
"/**",
|
|
271
|
+
" * Some utilities have logging capabilities that needs to be",
|
|
272
|
+
" * tested a little bit differently:",
|
|
273
|
+
" * - one",
|
|
274
|
+
" * - two",
|
|
275
|
+
" */"
|
|
276
|
+
].join("\n");
|
|
277
|
+
var out = parseAndTransformComments(input, baseOpts).transformed;
|
|
278
|
+
expect(out).not.toMatch(/needs to be\./);
|
|
279
|
+
});
|
|
280
|
+
it("does not append periods to every line of a merged // comment group", function() {
|
|
281
|
+
var original = [
|
|
282
|
+
"// We only want to add terminal punctuation once at the end of the merged",
|
|
283
|
+
"// paragraph, not after every original line (which can create spurious",
|
|
284
|
+
"// periods mid-sentence when lines were simple wraps). We also avoid",
|
|
285
|
+
"// appending a period if the final line ends with a colon introducing a",
|
|
286
|
+
"// list."
|
|
287
|
+
].join("\n");
|
|
288
|
+
var out = parseAndTransformComments(original, {
|
|
289
|
+
width: 160,
|
|
290
|
+
wrapLineComments: true,
|
|
291
|
+
mergeLineComments: true
|
|
292
|
+
}).transformed;
|
|
293
|
+
// Ensure it became a JSDoc block.
|
|
294
|
+
expect(out.startsWith("/**")).toBe(true);
|
|
295
|
+
// Should not contain stray periods after former line breaks.
|
|
296
|
+
expect(out).not.toMatch(/merged\./);
|
|
297
|
+
expect(out).not.toMatch(/spurious\./);
|
|
298
|
+
expect(out).not.toMatch(/introducing a\./);
|
|
299
|
+
// Should still retain existing legitimate period after 'wraps).' and final
|
|
300
|
+
// 'list.'
|
|
301
|
+
expect(out).toMatch(/wraps\)\./);
|
|
302
|
+
expect(out).toMatch(/list\./);
|
|
303
|
+
});
|
|
304
|
+
it("merges a large explanatory // group after a statement into JSDoc", function() {
|
|
305
|
+
var src = [
|
|
306
|
+
"const value = compute();",
|
|
307
|
+
"// We only want to add terminal punctuation once at the end of the merged",
|
|
308
|
+
"// paragraph, not after every original line (which can create spurious",
|
|
309
|
+
"// periods mid-sentence when lines were simple wraps). We also avoid",
|
|
310
|
+
"// appending a period if the final line ends with a colon introducing a",
|
|
311
|
+
"// list.",
|
|
312
|
+
"function next() {}"
|
|
313
|
+
].join("\n");
|
|
314
|
+
var out = parseAndTransformComments(src, {
|
|
315
|
+
width: 160,
|
|
316
|
+
wrapLineComments: true,
|
|
317
|
+
mergeLineComments: true
|
|
318
|
+
}).transformed;
|
|
319
|
+
// Expect merged into a JSDoc immediately after the statement.
|
|
320
|
+
var re = /compute\(\);\n\/\*\*[\s\S]*?\n\s*\*\//;
|
|
321
|
+
expect(re.test(out)).toBe(true);
|
|
322
|
+
// Ensure only one sentence-final period appended (present on final 'list.'
|
|
323
|
+
// already).
|
|
324
|
+
expect(out.match(/merged\./)).toBeNull();
|
|
325
|
+
});
|
|
245
326
|
});
|
|
246
327
|
|
|
247
328
|
//# sourceMappingURL=lib.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/__tests__/lib.test.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { describe, expect, it } from \"vitest\";\nimport { augmentPatterns, expandGlobs } from \"../glob.js\";\nimport { diffLines, parseAndTransformComments } from \"../lib.js\";\n\nconst baseOpts = {\n\twidth: 60,\n\twrapLineComments: true,\n\tmergeLineComments: false,\n};\n\ndescribe(\"parseAndTransformComments\", () => {\n\tit(\"reflows a simple jsdoc and adds period\", () => {\n\t\tconst input = \"/**\\n * This function does something\\n * important\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts);\n\t\texpect(res.transformed).toContain(\"does something important.\");\n\t});\n\n\tit(\"normalizes NOTE capitalization\", () => {\n\t\tconst input = \"/**\\n * note: edge case\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts);\n\t\texpect(/NOTE: edge case/.test(res.transformed)).toBe(true);\n\t});\n\n\tit(\"wraps single line comments\", () => {\n\t\tconst input =\n\t\t\t\"// this is a very long comment that should be wrapped across multiple lines to satisfy width\";\n\t\tconst res = parseAndTransformComments(input, baseOpts);\n\t\texpect(res.transformed.split(/\\n/).length).toBeGreaterThan(1);\n\t});\n\n\tit(\"merges groups of line comments into jsdoc\", () => {\n\t\tconst input = [\n\t\t\t\"// first line\",\n\t\t\t\"// second line\",\n\t\t\t\"// third line\",\n\t\t\t\"const x = 1;\",\n\t\t].join(\"\\n\");\n\t\tconst res = parseAndTransformComments(input, {\n\t\t\t...baseOpts,\n\t\t\tmergeLineComments: true,\n\t\t});\n\t\texpect(/\\/\\*\\*/.test(res.transformed)).toBe(true);\n\t});\n\n\tit(\"is idempotent (second pass unchanged)\", () => {\n\t\tconst input = \"/**\\n * Example doc that will be normalized\\n */\";\n\t\tconst first = parseAndTransformComments(input, baseOpts).transformed;\n\t\tconst second = parseAndTransformComments(first, baseOpts).transformed;\n\t\texpect(diffLines(first, second)).toBe(\"\");\n\t});\n\n\tit(\"preserves code fence blocks\", () => {\n\t\tconst input =\n\t\t\t\"/**\\n * Before\\n * ```js\\n * const x= 1; \\n * ```\\n * After\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts).transformed;\n\t\texpect(/```js/.test(res)).toBe(true);\n\t\t// ensure spacing inside fence not normalized\n\t\texpect(/const {2}x= {2}1;/.test(res)).toBe(true);\n\t});\n\n\tit(\"does not merge directive or license groups\", () => {\n\t\tconst input = [\n\t\t\t\"// eslint-disable-next-line\",\n\t\t\t\"// second line should prevent merge due to directive\",\n\t\t\t\"const y = 2;\",\n\t\t\t\"// Copyright 2024 Example\",\n\t\t\t\"// another line\",\n\t\t].join(\"\\n\");\n\t\tconst res = parseAndTransformComments(input, {\n\t\t\t...baseOpts,\n\t\t\tmergeLineComments: true,\n\t\t});\n\t\texpect(/eslint-disable/.test(res.transformed)).toBe(true);\n\t\t// Should not have merged into a jsdoc (no /** directly before const)\n\t\texpect(/\\/\\*\\*/.test(res.transformed)).toBe(false);\n\t});\n\n\tit(\"list items are not reflowed into a paragraph\", () => {\n\t\tconst input =\n\t\t\t\"/**\\n * First line explaining.\\n * - item one more words here\\n * - item two\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts).transformed;\n\t\t// each list item remains on its own line with leading dash\n\t\tconst lines = res.split(/\\n/).filter((l) => /- item/.test(l));\n\t\texpect(lines.length).toBe(2);\n\t});\n\n\tit(\"tag lines are preserved\", () => {\n\t\tconst input =\n\t\t\t\"/**\\n * short description\\n * @param x value\\n * @returns something\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts).transformed;\n\t\texpect(/@param x value/.test(res)).toBe(true);\n\t\texpect(/@returns something/.test(res)).toBe(true);\n\t});\n\n\tit(\"handles heading-like lines with colon and visually indented code & numeric lists\", () => {\n\t\tconst input = [\n\t\t\t\"/**\",\n\t\t\t\" * Overview:\",\n\t\t\t\" * const x = 1;\",\n\t\t\t\" * 1. first\",\n\t\t\t\" * 2. second\",\n\t\t\t\" *\", // blank separation\n\t\t\t\" * Another paragraph without period\",\n\t\t\t\" */\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(input, baseOpts).transformed;\n\t\t// Heading preserved, not merged into previous paragraph\n\t\texpect(out).toMatch(/Overview:/);\n\t\t// Visually indented code line kept as-is (no extra wrapping collapse)\n\t\texpect(out).toMatch(/const\\s{3}x = 1;/);\n\t\t// Ensure final blank line before closing preserved (one line ending with ' *')\n\t\tconst trailingBlank = /\\n \\*\\n\\*\\/$/.test(out.replace(/\\r/g, \"\"));\n\t\texpect(trailingBlank).toBe(true);\n\t\t// Numeric list lines preserved\n\t\texpect(out).toMatch(/1\\. first/);\n\t\texpect(out).toMatch(/2\\. second/);\n\t\t// Trailing paragraph got terminal period\n\t\texpect(out).toMatch(/Another paragraph without period\\./);\n\t});\n\n\tit(\"glob expansion matches created files\", () => {\n\t\t// Create a truly temporary isolated directory outside source tree\n\t\tconst tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), \"comments-glob-\"));\n\t\tconst a = path.join(tmpRoot, \"a.ts\");\n\t\tconst nestedDir = path.join(tmpRoot, \"nested\");\n\t\tfs.mkdirSync(nestedDir, { recursive: true });\n\t\tconst b = path.join(nestedDir, \"b.ts\");\n\t\tfs.writeFileSync(a, \"// file a\", \"utf8\");\n\t\tfs.writeFileSync(b, \"// file b\", \"utf8\");\n\t\tconst patterns = [`${tmpRoot}/*.ts`];\n\t\tconst augmented = augmentPatterns(patterns);\n\t\texpect(augmented.some((p) => p.includes(\"**/*.ts\"))).toBe(true);\n\t\tconst expanded = expandGlobs(patterns);\n\t\texpect(expanded.sort()).toEqual([a, b].sort());\n\t});\n\n\t// Added test for preserving multi-line // comment groups that should NOT merge when preceded by code.\n\tit(\"does not merge an inline explanatory multi-line // comment group following code\", () => {\n\t\tconst src = [\n\t\t\t\"function demo() {\",\n\t\t\t\" const x = 1; // keep\",\n\t\t\t\" // first line explains next block\",\n\t\t\t\" // still explaining\",\n\t\t\t\" // final line\",\n\t\t\t\" return x; // done\",\n\t\t\t\"}\",\n\t\t\t\"\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(src, {\n\t\t\tmergeLineComments: true,\n\t\t\twrapLineComments: true,\n\t\t\twidth: 80,\n\t\t}).transformed;\n\t\texpect(out).toContain(\" // first line explains next block\");\n\t\texpect(out).toContain(\" // still explaining\");\n\t\texpect(out).toContain(\" // final line\");\n\t\texpect(out).not.toContain(\"/**\");\n\t});\n\n\tit(\"converts the multi-line explanatory block from lib.ts into a multi-line JSDoc, preserving lines\", () => {\n\t\tconst snippet = [\n\t\t\t\"// JSDoc block extraction:\",\n\t\t\t\"// Previous pattern used a lazy dot-all: ([\\\\s\\\\S]*?) which could, under\",\n\t\t\t\"// pathological inputs, produce excessive backtracking. We replace it with a\",\n\t\t\t\"// tempered pattern that advances linearly by never letting the inner part\",\n\t\t\t\"// consume a closing '*/'. This avoids catastrophic behavior while keeping\",\n\t\t\t\"// correctness.\",\n\t\t\t\"// Pattern explanation:\",\n\t\t\t\"// (^ [\\\\t ]* ) -> capture indentation at start of line (multiline mode)\",\n\t\t\t\"// /\\\\*\\\\* -> opening delimiter\",\n\t\t\t\"// ( -> capture group 2 body\",\n\t\t\t\"// (?:[^*] -> any non-* char\",\n\t\t\t\"// |\\\\*(?!/) -> or a * not followed by /\",\n\t\t\t\"// )* -> repeated greedily (cannot cross closing */)\",\n\t\t\t\"// )\",\n\t\t\t\"// \\\\n?[\\\\t ]*\\\\*/ -> optional newline + trailing indent + closing */\",\n\t\t\t\"// The greedy repetition is safe because the inner alternatives are mutually\",\n\t\t\t\"// exclusive and each consumes at least one char without overlapping on the\",\n\t\t\t\"// closing sentinel.\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(snippet, {\n\t\t\twidth: 100,\n\t\t\twrapLineComments: true,\n\t\t\tmergeLineComments: true,\n\t\t}).transformed;\n\t\t// Should be converted to a JSDoc (first and last lines delimiters)\n\t\tconst lines = out.split(/\\n/);\n\t\texpect(lines[0].trim()).toBe(\"/**\");\n\t\texpect(lines[lines.length - 1].trim()).toBe(\"*/\");\n\t\t// Ensure representative internal lines are present (now without leading //)\n\t\texpect(out).toContain(\"* JSDoc block extraction:\");\n\t\texpect(out).toContain(\"* Pattern explanation:\");\n\t\t// Arrow lines preserved\n\t\tconst arrowLineCount = lines.filter((l) => /->/.test(l)).length;\n\t\texpect(arrowLineCount).toBeGreaterThanOrEqual(5);\n\t});\n});\n"],"names":["fs","os","path","describe","expect","it","augmentPatterns","expandGlobs","diffLines","parseAndTransformComments","baseOpts","width","wrapLineComments","mergeLineComments","input","res","transformed","toContain","test","toBe","split","length","toBeGreaterThan","join","first","second","lines","filter","l","out","toMatch","trailingBlank","replace","tmpRoot","mkdtempSync","tmpdir","a","nestedDir","mkdirSync","recursive","b","writeFileSync","patterns","augmented","some","p","includes","expanded","sort","toEqual","src","not","snippet","trim","arrowLineCount","toBeGreaterThanOrEqual"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/__tests__/lib.test.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { describe, expect, it } from \"vitest\";\nimport { expandGlobs } from \"../glob.js\";\nimport { diffLines, parseAndTransformComments } from \"../lib.js\";\n\nconst baseOpts = {\n\twidth: 60,\n\twrapLineComments: true,\n\tmergeLineComments: false,\n};\n\ndescribe(\"parseAndTransformComments\", () => {\n\tit(\"reflows a simple jsdoc and adds period\", () => {\n\t\tconst input = \"/**\\n * This function does something\\n * important\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts);\n\t\texpect(res.transformed).toContain(\"does something important.\");\n\t});\n\n\tit(\"normalizes NOTE capitalization\", () => {\n\t\tconst input = \"/**\\n * note: edge case\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts);\n\t\texpect(/NOTE: edge case/.test(res.transformed)).toBe(true);\n\t});\n\n\tit(\"wraps single line comments\", () => {\n\t\tconst input =\n\t\t\t\"// this is a very long comment that should be wrapped across multiple lines to satisfy width\";\n\t\tconst res = parseAndTransformComments(input, baseOpts);\n\t\texpect(res.transformed.split(/\\n/).length).toBeGreaterThan(1);\n\t});\n\n\tit(\"merges groups of line comments into jsdoc\", () => {\n\t\tconst input = [\n\t\t\t\"// first line\",\n\t\t\t\"// second line\",\n\t\t\t\"// third line\",\n\t\t\t\"const x = 1;\",\n\t\t].join(\"\\n\");\n\t\tconst res = parseAndTransformComments(input, {\n\t\t\t...baseOpts,\n\t\t\tmergeLineComments: true,\n\t\t});\n\t\texpect(/\\/\\*\\*/.test(res.transformed)).toBe(true);\n\t});\n\n\tit(\"is idempotent (second pass unchanged)\", () => {\n\t\tconst input = \"/**\\n * Example doc that will be normalized\\n */\";\n\t\tconst first = parseAndTransformComments(input, baseOpts).transformed;\n\t\tconst second = parseAndTransformComments(first, baseOpts).transformed;\n\t\texpect(diffLines(first, second)).toBe(\"\");\n\t});\n\n\tit(\"preserves code fence blocks\", () => {\n\t\tconst input =\n\t\t\t\"/**\\n * Before\\n * ```js\\n * const x= 1; \\n * ```\\n * After\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts).transformed;\n\t\texpect(/```js/.test(res)).toBe(true);\n\t\t// ensure spacing inside fence not normalized.\n\t\texpect(/const {2}x= {2}1;/.test(res)).toBe(true);\n\t});\n\n\tit(\"does not merge directive or license groups\", () => {\n\t\tconst input = [\n\t\t\t\"// eslint-disable-next-line\",\n\t\t\t\"// second line should prevent merge due to directive\",\n\t\t\t\"const y = 2;\",\n\t\t\t\"// Copyright 2024 Example\",\n\t\t\t\"// another line\",\n\t\t].join(\"\\n\");\n\t\tconst res = parseAndTransformComments(input, {\n\t\t\t...baseOpts,\n\t\t\tmergeLineComments: true,\n\t\t});\n\t\texpect(/eslint-disable/.test(res.transformed)).toBe(true);\n\t\t// Should not have merged into a jsdoc (no /** directly before const).\n\t\texpect(/\\/\\*\\*/.test(res.transformed)).toBe(false);\n\t});\n\n\tit(\"list items are not reflowed into a paragraph\", () => {\n\t\tconst input =\n\t\t\t\"/**\\n * First line explaining.\\n * - item one more words here\\n * - item two\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts).transformed;\n\t\t// each list item remains on its own line with leading dash.\n\t\tconst lines = res.split(/\\n/).filter((l) => /- item/.test(l));\n\t\texpect(lines.length).toBe(2);\n\t});\n\n\tit(\"tag lines are preserved\", () => {\n\t\tconst input =\n\t\t\t\"/**\\n * short description\\n * @param x value\\n * @returns something\\n */\";\n\t\tconst res = parseAndTransformComments(input, baseOpts).transformed;\n\t\texpect(/@param x value/.test(res)).toBe(true);\n\t\texpect(/@returns something/.test(res)).toBe(true);\n\t});\n\n\tit(\"handles heading-like lines with colon and visually indented code & numeric lists\", () => {\n\t\tconst input = [\n\t\t\t\"/**\",\n\t\t\t\" * Overview:\",\n\t\t\t\" * const x = 1;\",\n\t\t\t\" * 1. first\",\n\t\t\t\" * 2. second\",\n\t\t\t\" *\", // blank separation\n\t\t\t\" * Another paragraph without period\",\n\t\t\t\" */\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(input, baseOpts).transformed;\n\t\t// Heading preserved, not merged into previous paragraph.\n\t\texpect(out).toMatch(/Overview:/);\n\t\t// Visually indented code line kept as-is (no extra wrapping collapse).\n\t\texpect(out).toMatch(/const\\s{3}x = 1;/);\n\t\t/**\n\t\t * Trailing blank before closing is optional after recent trimming change. (we\n\t\t * only keep it when multiple paragraphs exist). Assert closing exists.\n\t\t * Closing delimiter should be on its own line; allow optional leading\n\t\t * space(s).\n\t\t */\n\t\texpect(/\\n\\s*\\*\\/$/.test(out)).toBe(true);\n\t\t// Numeric list lines preserved.\n\t\texpect(out).toMatch(/1\\. first/);\n\t\texpect(out).toMatch(/2\\. second/);\n\t\t// Trailing paragraph got terminal period.\n\t\texpect(out).toMatch(/Another paragraph without period\\./);\n\t});\n\n\tit(\"glob expansion matches deep files only with explicit globstar\", () => {\n\t\tconst tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), \"comments-glob-\"));\n\t\tconst a = path.join(tmpRoot, \"a.ts\");\n\t\tconst nestedDir = path.join(tmpRoot, \"nested\");\n\t\tfs.mkdirSync(nestedDir, { recursive: true });\n\t\tconst b = path.join(nestedDir, \"b.ts\");\n\t\tfs.writeFileSync(a, \"// file a\", \"utf8\");\n\t\tfs.writeFileSync(b, \"// file b\", \"utf8\");\n\t\t// Shallow pattern should only see top-level a.ts.\n\t\tconst shallow = expandGlobs([`${tmpRoot}/*.ts`]).sort();\n\t\texpect(shallow).toEqual([a]);\n\t\t// Deep pattern matches both.\n\t\tconst deep = expandGlobs([`${tmpRoot}/**/*.ts`]).sort();\n\t\texpect(deep).toEqual([a, b].sort());\n\t});\n\n\t/**\n\t * Added test for preserving multi-line // comment groups that should NOT merge\n\t * when preceded by code.\n\t */\n\tit(\"does not merge an inline explanatory multi-line // comment group following code\", () => {\n\t\tconst src = [\n\t\t\t\"function demo() {\",\n\t\t\t\" const x = 1; // keep\",\n\t\t\t\" // first line explains next block\",\n\t\t\t\" // still explaining\",\n\t\t\t\" // final line\",\n\t\t\t\" return x; // done\",\n\t\t\t\"}\",\n\t\t\t\"\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(src, {\n\t\t\tmergeLineComments: true,\n\t\t\twrapLineComments: true,\n\t\t\twidth: 80,\n\t\t}).transformed;\n\t\texpect(out).toContain(\" // first line explains next block\");\n\t\texpect(out).toContain(\" // still explaining\");\n\t\texpect(out).toContain(\" // final line\");\n\t\texpect(out).not.toContain(\"/**\");\n\t});\n\n\tit(\"converts the multi-line explanatory block from lib.ts into a multi-line JSDoc, preserving lines\", () => {\n\t\tconst snippet = [\n\t\t\t\"// JSDoc block extraction:\",\n\t\t\t\"// Previous pattern used a lazy dot-all: ([\\\\s\\\\S]*?) which could, under\",\n\t\t\t\"// pathological inputs, produce excessive backtracking. We replace it with a\",\n\t\t\t\"// tempered pattern that advances linearly by never letting the inner part\",\n\t\t\t\"// consume a closing '*/'. This avoids catastrophic behavior while keeping\",\n\t\t\t\"// correctness.\",\n\t\t\t\"// Pattern explanation:\",\n\t\t\t\"// (^ [\\\\t ]* ) -> capture indentation at start of line (multiline mode)\",\n\t\t\t\"// /\\\\*\\\\* -> opening delimiter\",\n\t\t\t\"// ( -> capture group 2 body\",\n\t\t\t\"// (?:[^*] -> any non-* char\",\n\t\t\t\"// |\\\\*(?!/) -> or a * not followed by /\",\n\t\t\t\"// )* -> repeated greedily (cannot cross closing */)\",\n\t\t\t\"// )\",\n\t\t\t\"// \\\\n?[\\\\t ]*\\\\*/ -> optional newline + trailing indent + closing */\",\n\t\t\t\"// The greedy repetition is safe because the inner alternatives are mutually\",\n\t\t\t\"// exclusive and each consumes at least one char without overlapping on the\",\n\t\t\t\"// closing sentinel.\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(snippet, {\n\t\t\twidth: 100,\n\t\t\twrapLineComments: true,\n\t\t\tmergeLineComments: true,\n\t\t}).transformed;\n\t\t// Should be converted to a JSDoc (first and last lines delimiters).\n\t\tconst lines = out.split(/\\n/);\n\t\texpect(lines[0].trim()).toBe(\"/**\");\n\t\texpect(lines[lines.length - 1].trim()).toBe(\"*/\");\n\t\t// Ensure representative internal lines are present (now without leading //).\n\t\texpect(out).toContain(\"* JSDoc block extraction:\");\n\t\texpect(out).toContain(\"* Pattern explanation:\");\n\t\t// Arrow lines preserved.\n\t\tconst arrowLineCount = lines.filter((l) => /->/.test(l)).length;\n\t\texpect(arrowLineCount).toBeGreaterThanOrEqual(5);\n\t});\n\n\tit(\"does not insert period before list introduced by single lowercase word + colon\", () => {\n\t\tconst input = [\n\t\t\t\"/**\",\n\t\t\t\" * Some utilities have logging capabilities that needs to be\",\n\t\t\t\" * tested a little bit differently:\",\n\t\t\t\" * - mocking process.exit\",\n\t\t\t\" * - console.log\",\n\t\t\t\" * - inquirer.prompt\",\n\t\t\t\" */\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(input, baseOpts).transformed;\n\t\t// Ensure no stray period after 'be'.\n\t\texpect(out).not.toMatch(/needs to be\\./);\n\t\t// Ensure list items unchanged.\n\t\texpect(out).toMatch(/- mocking process\\.exit/);\n\t});\n\n\tit(\"does not add stray period before lowercase colon line inside jsdoc\", () => {\n\t\tconst input = [\n\t\t\t\"/**\",\n\t\t\t\" * Some utilities have logging capabilities that needs to be\",\n\t\t\t\" * tested a little bit differently:\",\n\t\t\t\" * - one\",\n\t\t\t\" * - two\",\n\t\t\t\" */\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(input, baseOpts).transformed;\n\t\texpect(out).not.toMatch(/needs to be\\./);\n\t});\n\n\tit(\"does not append periods to every line of a merged // comment group\", () => {\n\t\tconst original = [\n\t\t\t\"// We only want to add terminal punctuation once at the end of the merged\",\n\t\t\t\"// paragraph, not after every original line (which can create spurious\",\n\t\t\t\"// periods mid-sentence when lines were simple wraps). We also avoid\",\n\t\t\t\"// appending a period if the final line ends with a colon introducing a\",\n\t\t\t\"// list.\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(original, {\n\t\t\twidth: 160, // keep wide to avoid secondary wrapping noise\n\t\t\twrapLineComments: true,\n\t\t\tmergeLineComments: true,\n\t\t}).transformed;\n\t\t// Ensure it became a JSDoc block.\n\t\texpect(out.startsWith(\"/**\")).toBe(true);\n\t\t// Should not contain stray periods after former line breaks.\n\t\texpect(out).not.toMatch(/merged\\./);\n\t\texpect(out).not.toMatch(/spurious\\./);\n\t\texpect(out).not.toMatch(/introducing a\\./);\n\t\t// Should still retain existing legitimate period after 'wraps).' and final\n\t\t// 'list.'\n\t\texpect(out).toMatch(/wraps\\)\\./);\n\t\texpect(out).toMatch(/list\\./);\n\t});\n\n\tit(\"merges a large explanatory // group after a statement into JSDoc\", () => {\n\t\tconst src = [\n\t\t\t\"const value = compute();\",\n\t\t\t\"// We only want to add terminal punctuation once at the end of the merged\",\n\t\t\t\"// paragraph, not after every original line (which can create spurious\",\n\t\t\t\"// periods mid-sentence when lines were simple wraps). We also avoid\",\n\t\t\t\"// appending a period if the final line ends with a colon introducing a\",\n\t\t\t\"// list.\",\n\t\t\t\"function next() {}\",\n\t\t].join(\"\\n\");\n\t\tconst out = parseAndTransformComments(src, {\n\t\t\twidth: 160,\n\t\t\twrapLineComments: true,\n\t\t\tmergeLineComments: true,\n\t\t}).transformed;\n\t\t// Expect merged into a JSDoc immediately after the statement.\n\t\tconst re = /compute\\(\\);\\n\\/\\*\\*[\\s\\S]*?\\n\\s*\\*\\//;\n\t\texpect(re.test(out)).toBe(true);\n\t\t// Ensure only one sentence-final period appended (present on final 'list.'\n\t\t// already).\n\t\texpect(out.match(/merged\\./)).toBeNull();\n\t});\n});\n"],"names":["fs","os","path","describe","expect","it","expandGlobs","diffLines","parseAndTransformComments","baseOpts","width","wrapLineComments","mergeLineComments","input","res","transformed","toContain","test","toBe","split","length","toBeGreaterThan","join","first","second","lines","filter","l","out","toMatch","tmpRoot","mkdtempSync","tmpdir","a","nestedDir","mkdirSync","recursive","b","writeFileSync","shallow","sort","toEqual","deep","src","not","snippet","trim","arrowLineCount","toBeGreaterThanOrEqual","original","startsWith","re","match","toBeNull"],"mappings":"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"}
|
package/dist/glob.d.ts
CHANGED
package/dist/glob.js
CHANGED
|
@@ -1,143 +1,20 @@
|
|
|
1
|
-
function _array_like_to_array(arr, len) {
|
|
2
|
-
if (len == null || len > arr.length) len = arr.length;
|
|
3
|
-
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
4
|
-
return arr2;
|
|
5
|
-
}
|
|
6
|
-
function _array_with_holes(arr) {
|
|
7
|
-
if (Array.isArray(arr)) return arr;
|
|
8
|
-
}
|
|
9
|
-
function _iterable_to_array_limit(arr, i) {
|
|
10
|
-
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
11
|
-
if (_i == null) return;
|
|
12
|
-
var _arr = [];
|
|
13
|
-
var _n = true;
|
|
14
|
-
var _d = false;
|
|
15
|
-
var _s, _e;
|
|
16
|
-
try {
|
|
17
|
-
for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
|
|
18
|
-
_arr.push(_s.value);
|
|
19
|
-
if (i && _arr.length === i) break;
|
|
20
|
-
}
|
|
21
|
-
} catch (err) {
|
|
22
|
-
_d = true;
|
|
23
|
-
_e = err;
|
|
24
|
-
} finally{
|
|
25
|
-
try {
|
|
26
|
-
if (!_n && _i["return"] != null) _i["return"]();
|
|
27
|
-
} finally{
|
|
28
|
-
if (_d) throw _e;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return _arr;
|
|
32
|
-
}
|
|
33
|
-
function _non_iterable_rest() {
|
|
34
|
-
throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
35
|
-
}
|
|
36
|
-
function _sliced_to_array(arr, i) {
|
|
37
|
-
return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
|
|
38
|
-
}
|
|
39
|
-
function _unsupported_iterable_to_array(o, minLen) {
|
|
40
|
-
if (!o) return;
|
|
41
|
-
if (typeof o === "string") return _array_like_to_array(o, minLen);
|
|
42
|
-
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
43
|
-
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
44
|
-
if (n === "Map" || n === "Set") return Array.from(n);
|
|
45
|
-
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
|
|
46
|
-
}
|
|
47
1
|
import fs from "node:fs";
|
|
48
2
|
import path from "node:path";
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
var extra = [];
|
|
53
|
-
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
54
|
-
try {
|
|
55
|
-
for(var _iterator = patterns[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
56
|
-
var p = _step.value;
|
|
57
|
-
if (p.includes("**")) {
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
var m = /^(.*)\/([^/]+)$/.exec(p);
|
|
61
|
-
if (!m) {
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
var _m = _sliced_to_array(m, 3), _ = _m[0], dir = _m[1], file = _m[2];
|
|
65
|
-
if (file.includes("*")) {
|
|
66
|
-
// if pattern is like dir/*.ts add deep variant.
|
|
67
|
-
if (!patterns.includes("".concat(dir, "/**/").concat(file))) {
|
|
68
|
-
extra.push("".concat(dir, "/**/").concat(file));
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
} catch (err) {
|
|
73
|
-
_didIteratorError = true;
|
|
74
|
-
_iteratorError = err;
|
|
75
|
-
} finally{
|
|
76
|
-
try {
|
|
77
|
-
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
78
|
-
_iterator.return();
|
|
79
|
-
}
|
|
80
|
-
} finally{
|
|
81
|
-
if (_didIteratorError) {
|
|
82
|
-
throw _iteratorError;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return patterns.concat(extra);
|
|
87
|
-
}
|
|
88
|
-
function escapeRegex(str) {
|
|
89
|
-
return str.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
90
|
-
}
|
|
91
|
-
function toRegex(pattern) {
|
|
3
|
+
import micromatch from "micromatch";
|
|
4
|
+
var WILDCARD_CHARS = /[!*?]/; // Detects basic glob characters
|
|
5
|
+
function patternRoot(pattern) {
|
|
92
6
|
if (!WILDCARD_CHARS.test(pattern)) {
|
|
93
|
-
return
|
|
94
|
-
regex: null,
|
|
95
|
-
root: path.dirname(pattern) || "."
|
|
96
|
-
};
|
|
7
|
+
return path.dirname(pattern) || ".";
|
|
97
8
|
}
|
|
98
|
-
// Determine walk root: substring up to first wildcard then dirname.
|
|
99
9
|
var firstWildcard = pattern.search(/[*!?]/);
|
|
100
10
|
var rootPart = firstWildcard === -1 ? pattern : pattern.slice(0, firstWildcard);
|
|
101
11
|
if (!rootPart.endsWith("/")) {
|
|
102
12
|
rootPart = path.dirname(rootPart);
|
|
103
13
|
}
|
|
104
14
|
if (!rootPart.length) {
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
// Build regex: convert pattern path separators to '/'.
|
|
108
|
-
var norm = pattern.replace(/\\/g, "/");
|
|
109
|
-
var rx = "";
|
|
110
|
-
for(var i = 0; i < norm.length;){
|
|
111
|
-
if (norm[i] === "*") {
|
|
112
|
-
if (norm[i + 1] === "*") {
|
|
113
|
-
// '**'.
|
|
114
|
-
i += 2;
|
|
115
|
-
// collapse subsequent /** or trailing /
|
|
116
|
-
if (norm[i] === "/") {
|
|
117
|
-
// match zero or more directories.
|
|
118
|
-
rx += "(?:.*?/)?";
|
|
119
|
-
i++;
|
|
120
|
-
} else {
|
|
121
|
-
rx += ".*";
|
|
122
|
-
}
|
|
123
|
-
continue;
|
|
124
|
-
}
|
|
125
|
-
rx += "[^/]*";
|
|
126
|
-
i++;
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
if (norm[i] === "?") {
|
|
130
|
-
rx += "[^/]";
|
|
131
|
-
i++;
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
rx += escapeRegex(norm[i]);
|
|
135
|
-
i++;
|
|
15
|
+
return ".";
|
|
136
16
|
}
|
|
137
|
-
return
|
|
138
|
-
regex: new RegExp("^".concat(rx, "$")),
|
|
139
|
-
root: rootPart
|
|
140
|
-
};
|
|
17
|
+
return rootPart;
|
|
141
18
|
}
|
|
142
19
|
function walk(root, followSymlinks) {
|
|
143
20
|
var results = [];
|
|
@@ -208,37 +85,29 @@ function walk(root, followSymlinks) {
|
|
|
208
85
|
}
|
|
209
86
|
export function expandGlobs(patterns) {
|
|
210
87
|
var options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
|
|
211
|
-
var augmented = augmentPatterns(patterns);
|
|
212
|
-
var compiled = augmented.map(function(p) {
|
|
213
|
-
var _toRegex = toRegex(p), regex = _toRegex.regex, root = _toRegex.root;
|
|
214
|
-
return {
|
|
215
|
-
pattern: p,
|
|
216
|
-
regex: regex,
|
|
217
|
-
root: root
|
|
218
|
-
};
|
|
219
|
-
});
|
|
220
88
|
var seen = new Set();
|
|
221
89
|
var out = [];
|
|
222
90
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
223
91
|
try {
|
|
224
|
-
for(var _iterator =
|
|
225
|
-
var
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
92
|
+
for(var _iterator = patterns[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
93
|
+
var pattern = _step.value;
|
|
94
|
+
// Literal file (no metachars).
|
|
95
|
+
if (!WILDCARD_CHARS.test(pattern)) {
|
|
96
|
+
if (fs.existsSync(pattern) && fs.statSync(pattern).isFile() && !seen.has(pattern)) {
|
|
97
|
+
seen.add(pattern);
|
|
98
|
+
out.push(pattern);
|
|
232
99
|
}
|
|
233
100
|
continue;
|
|
234
101
|
}
|
|
235
|
-
var
|
|
102
|
+
var root = patternRoot(pattern);
|
|
103
|
+
var files = walk(root, options.followSymlinks || false);
|
|
104
|
+
var mmPattern = pattern.replace(/\\/g, "/");
|
|
236
105
|
var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
|
237
106
|
try {
|
|
238
107
|
for(var _iterator1 = files[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
|
|
239
108
|
var f = _step1.value;
|
|
240
|
-
var
|
|
241
|
-
if (
|
|
109
|
+
var normalized = f.replace(/\\/g, "/");
|
|
110
|
+
if (micromatch.isMatch(normalized, mmPattern)) {
|
|
242
111
|
if (!seen.has(f)) {
|
|
243
112
|
seen.add(f);
|
|
244
113
|
out.push(f);
|