gsd-pi 2.10.0 → 2.10.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/node_modules/@gsd/native/dist/ast/index.d.ts +4 -0
- package/node_modules/@gsd/native/dist/ast/index.js +7 -0
- package/node_modules/@gsd/native/dist/ast/types.d.ts +69 -0
- package/node_modules/@gsd/native/dist/ast/types.js +1 -0
- package/node_modules/@gsd/native/{src/clipboard/index.ts → dist/clipboard/index.d.ts} +3 -15
- package/node_modules/@gsd/native/dist/clipboard/index.js +33 -0
- package/node_modules/@gsd/native/dist/clipboard/types.d.ts +7 -0
- package/node_modules/@gsd/native/dist/clipboard/types.js +1 -0
- package/node_modules/@gsd/native/dist/diff/index.d.ts +33 -0
- package/node_modules/@gsd/native/dist/diff/index.js +38 -0
- package/node_modules/@gsd/native/dist/diff/types.d.ts +23 -0
- package/node_modules/@gsd/native/dist/diff/types.js +1 -0
- package/node_modules/@gsd/native/{src/fd/index.ts → dist/fd/index.d.ts} +2 -12
- package/node_modules/@gsd/native/dist/fd/index.js +26 -0
- package/node_modules/@gsd/native/dist/fd/types.d.ts +29 -0
- package/node_modules/@gsd/native/dist/fd/types.js +1 -0
- package/node_modules/@gsd/native/{src/glob/index.ts → dist/glob/index.d.ts} +3 -19
- package/node_modules/@gsd/native/dist/glob/index.js +31 -0
- package/node_modules/@gsd/native/dist/glob/types.d.ts +50 -0
- package/node_modules/@gsd/native/dist/glob/types.js +1 -0
- package/node_modules/@gsd/native/dist/grep/index.d.ts +20 -0
- package/node_modules/@gsd/native/dist/grep/index.js +23 -0
- package/node_modules/@gsd/native/dist/grep/types.d.ts +99 -0
- package/node_modules/@gsd/native/dist/grep/types.js +1 -0
- package/node_modules/@gsd/native/dist/gsd-parser/index.d.ts +45 -0
- package/node_modules/@gsd/native/dist/gsd-parser/index.js +54 -0
- package/node_modules/@gsd/native/dist/gsd-parser/types.d.ts +55 -0
- package/node_modules/@gsd/native/dist/gsd-parser/types.js +7 -0
- package/node_modules/@gsd/native/{src/highlight/index.ts → dist/highlight/index.d.ts} +3 -19
- package/node_modules/@gsd/native/dist/highlight/index.js +33 -0
- package/node_modules/@gsd/native/dist/highlight/types.d.ts +25 -0
- package/node_modules/@gsd/native/dist/highlight/types.js +1 -0
- package/node_modules/@gsd/native/{src/html/index.ts → dist/html/index.d.ts} +1 -10
- package/node_modules/@gsd/native/dist/html/index.js +16 -0
- package/node_modules/@gsd/native/dist/html/types.d.ts +7 -0
- package/node_modules/@gsd/native/dist/html/types.js +1 -0
- package/node_modules/@gsd/native/{src/image/index.ts → dist/image/index.d.ts} +1 -14
- package/node_modules/@gsd/native/dist/image/index.js +18 -0
- package/node_modules/@gsd/native/dist/image/types.d.ts +35 -0
- package/node_modules/@gsd/native/dist/image/types.js +26 -0
- package/node_modules/@gsd/native/{src/index.ts → dist/index.d.ts} +12 -60
- package/node_modules/@gsd/native/dist/index.js +28 -0
- package/node_modules/@gsd/native/dist/native.d.ts +44 -0
- package/node_modules/@gsd/native/dist/native.js +34 -0
- package/node_modules/@gsd/native/dist/ps/index.d.ts +38 -0
- package/node_modules/@gsd/native/{src/ps/index.ts → dist/ps/index.js} +8 -13
- package/node_modules/@gsd/native/{src/ps/types.ts → dist/ps/types.d.ts} +2 -2
- package/node_modules/@gsd/native/dist/ps/types.js +1 -0
- package/node_modules/@gsd/native/{src/text/index.ts → dist/text/index.d.ts} +6 -76
- package/node_modules/@gsd/native/dist/text/index.js +66 -0
- package/node_modules/@gsd/native/dist/text/types.d.ts +27 -0
- package/node_modules/@gsd/native/dist/text/types.js +10 -0
- package/node_modules/@gsd/native/{src/ttsr/index.ts → dist/ttsr/index.d.ts} +3 -15
- package/node_modules/@gsd/native/dist/ttsr/index.js +32 -0
- package/node_modules/@gsd/native/{src/ttsr/types.ts → dist/ttsr/types.d.ts} +4 -5
- package/node_modules/@gsd/native/dist/ttsr/types.js +1 -0
- package/node_modules/@gsd/native/package.json +24 -23
- package/node_modules/@gsd/pi-coding-agent/dist/core/tools/edit-diff.d.ts +11 -5
- package/node_modules/@gsd/pi-coding-agent/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/node_modules/@gsd/pi-coding-agent/dist/core/tools/edit-diff.js +19 -142
- package/node_modules/@gsd/pi-coding-agent/dist/core/tools/edit-diff.js.map +1 -1
- package/node_modules/@gsd/pi-coding-agent/src/core/tools/edit-diff.ts +23 -157
- package/package.json +4 -2
- package/packages/native/dist/ast/index.d.ts +4 -0
- package/packages/native/dist/ast/index.js +7 -0
- package/packages/native/dist/ast/types.d.ts +69 -0
- package/packages/native/dist/ast/types.js +1 -0
- package/packages/native/dist/clipboard/index.d.ts +28 -0
- package/packages/native/dist/clipboard/index.js +33 -0
- package/packages/native/dist/clipboard/types.d.ts +7 -0
- package/packages/native/dist/clipboard/types.js +1 -0
- package/packages/native/dist/diff/index.d.ts +33 -0
- package/packages/native/dist/diff/index.js +38 -0
- package/packages/native/dist/diff/types.d.ts +23 -0
- package/packages/native/dist/diff/types.js +1 -0
- package/packages/native/dist/fd/index.d.ts +25 -0
- package/packages/native/dist/fd/index.js +26 -0
- package/packages/native/dist/fd/types.d.ts +29 -0
- package/packages/native/dist/fd/types.js +1 -0
- package/packages/native/dist/glob/index.d.ts +28 -0
- package/packages/native/dist/glob/index.js +31 -0
- package/packages/native/dist/glob/types.d.ts +50 -0
- package/packages/native/dist/glob/types.js +1 -0
- package/packages/native/dist/grep/index.d.ts +20 -0
- package/packages/native/dist/grep/index.js +23 -0
- package/packages/native/dist/grep/types.d.ts +99 -0
- package/packages/native/dist/grep/types.js +1 -0
- package/packages/native/dist/gsd-parser/index.d.ts +45 -0
- package/packages/native/dist/gsd-parser/index.js +54 -0
- package/packages/native/dist/gsd-parser/types.d.ts +55 -0
- package/packages/native/dist/gsd-parser/types.js +7 -0
- package/packages/native/dist/highlight/index.d.ts +28 -0
- package/packages/native/dist/highlight/index.js +33 -0
- package/packages/native/dist/highlight/types.d.ts +25 -0
- package/packages/native/dist/highlight/types.js +1 -0
- package/packages/native/dist/html/index.d.ts +15 -0
- package/packages/native/dist/html/index.js +16 -0
- package/packages/native/dist/html/types.d.ts +7 -0
- package/packages/native/dist/html/types.js +1 -0
- package/packages/native/dist/image/index.d.ts +15 -0
- package/packages/native/dist/image/index.js +18 -0
- package/packages/native/dist/image/types.d.ts +35 -0
- package/packages/native/dist/image/types.js +26 -0
- package/packages/native/dist/index.d.ts +40 -0
- package/packages/native/dist/index.js +28 -0
- package/packages/native/dist/native.d.ts +44 -0
- package/packages/native/dist/native.js +34 -0
- package/packages/native/dist/ps/index.d.ts +38 -0
- package/packages/native/dist/ps/index.js +47 -0
- package/packages/native/dist/ps/types.d.ts +5 -0
- package/packages/native/dist/ps/types.js +1 -0
- package/packages/native/dist/text/index.d.ts +55 -0
- package/packages/native/dist/text/index.js +66 -0
- package/packages/native/dist/text/types.d.ts +27 -0
- package/packages/native/dist/text/types.js +10 -0
- package/packages/native/dist/ttsr/index.d.ts +27 -0
- package/packages/native/dist/ttsr/index.js +32 -0
- package/packages/native/dist/ttsr/types.d.ts +9 -0
- package/packages/native/dist/ttsr/types.js +1 -0
- package/packages/native/package.json +24 -23
- package/packages/native/src/__tests__/diff.test.mjs +189 -0
- package/packages/native/src/__tests__/ttsr.test.mjs +135 -0
- package/packages/native/src/diff/index.ts +61 -0
- package/packages/native/src/diff/types.ts +24 -0
- package/packages/native/src/gsd-parser/index.ts +98 -0
- package/packages/native/src/gsd-parser/types.ts +62 -0
- package/packages/native/src/index.ts +23 -0
- package/packages/native/src/native.ts +8 -0
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.d.ts +11 -5
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.js +19 -142
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.js.map +1 -1
- package/packages/pi-coding-agent/src/core/tools/edit-diff.ts +23 -157
- package/src/resources/extensions/gsd/files.ts +9 -0
- package/src/resources/extensions/gsd/native-parser-bridge.ts +135 -0
- package/src/resources/extensions/ttsr/ttsr-manager.ts +86 -0
- package/node_modules/@gsd/native/src/__tests__/clipboard.test.mjs +0 -79
- package/node_modules/@gsd/native/src/__tests__/fd.test.mjs +0 -164
- package/node_modules/@gsd/native/src/__tests__/glob.test.mjs +0 -237
- package/node_modules/@gsd/native/src/__tests__/grep.test.mjs +0 -162
- package/node_modules/@gsd/native/src/__tests__/highlight.test.mjs +0 -156
- package/node_modules/@gsd/native/src/__tests__/html.test.mjs +0 -98
- package/node_modules/@gsd/native/src/__tests__/image.test.mjs +0 -137
- package/node_modules/@gsd/native/src/__tests__/ps.test.mjs +0 -109
- package/node_modules/@gsd/native/src/__tests__/text.test.mjs +0 -262
- package/node_modules/@gsd/native/src/ast/index.ts +0 -12
- package/node_modules/@gsd/native/src/ast/types.ts +0 -75
- package/node_modules/@gsd/native/src/clipboard/types.ts +0 -7
- package/node_modules/@gsd/native/src/fd/types.ts +0 -31
- package/node_modules/@gsd/native/src/glob/types.ts +0 -53
- package/node_modules/@gsd/native/src/grep/index.ts +0 -48
- package/node_modules/@gsd/native/src/grep/types.ts +0 -105
- package/node_modules/@gsd/native/src/highlight/types.ts +0 -25
- package/node_modules/@gsd/native/src/html/types.ts +0 -7
- package/node_modules/@gsd/native/src/image/types.ts +0 -41
- package/node_modules/@gsd/native/src/native.ts +0 -94
- package/node_modules/@gsd/native/src/text/types.ts +0 -29
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
import { test, describe } from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { createRequire } from "node:module";
|
|
4
|
-
import * as path from "node:path";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
-
import * as fs from "node:fs";
|
|
7
|
-
import * as os from "node:os";
|
|
8
|
-
|
|
9
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
-
const require = createRequire(import.meta.url);
|
|
11
|
-
|
|
12
|
-
// Load the native addon directly
|
|
13
|
-
const addonDir = path.resolve(
|
|
14
|
-
__dirname,
|
|
15
|
-
"..",
|
|
16
|
-
"..",
|
|
17
|
-
"..",
|
|
18
|
-
"..",
|
|
19
|
-
"native",
|
|
20
|
-
"addon",
|
|
21
|
-
);
|
|
22
|
-
const platformTag = `${process.platform}-${process.arch}`;
|
|
23
|
-
const candidates = [
|
|
24
|
-
path.join(addonDir, `gsd_engine.${platformTag}.node`),
|
|
25
|
-
path.join(addonDir, "gsd_engine.dev.node"),
|
|
26
|
-
];
|
|
27
|
-
|
|
28
|
-
let native;
|
|
29
|
-
for (const candidate of candidates) {
|
|
30
|
-
try {
|
|
31
|
-
native = require(candidate);
|
|
32
|
-
break;
|
|
33
|
-
} catch {
|
|
34
|
-
// try next
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (!native) {
|
|
39
|
-
console.error(
|
|
40
|
-
"Native addon not found. Run `npm run build:native -w @gsd/native` first.",
|
|
41
|
-
);
|
|
42
|
-
process.exit(1);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
describe("native glob: glob()", () => {
|
|
46
|
-
test("finds files matching a pattern", async (t) => {
|
|
47
|
-
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "gsd-glob-test-"));
|
|
48
|
-
t.after(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
|
|
49
|
-
|
|
50
|
-
fs.writeFileSync(path.join(tmpDir, "file1.ts"), "const a = 1;");
|
|
51
|
-
fs.writeFileSync(path.join(tmpDir, "file2.ts"), "const b = 2;");
|
|
52
|
-
fs.writeFileSync(path.join(tmpDir, "file3.js"), "const c = 3;");
|
|
53
|
-
|
|
54
|
-
const result = await native.glob({ pattern: "*.ts", path: tmpDir });
|
|
55
|
-
|
|
56
|
-
assert.equal(result.totalMatches, 2);
|
|
57
|
-
assert.equal(result.matches.length, 2);
|
|
58
|
-
const paths = result.matches.map((m) => m.path).sort();
|
|
59
|
-
assert.deepEqual(paths, ["file1.ts", "file2.ts"]);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
test("recursive matching into subdirectories", async (t) => {
|
|
63
|
-
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "gsd-glob-test-"));
|
|
64
|
-
t.after(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
|
|
65
|
-
|
|
66
|
-
fs.mkdirSync(path.join(tmpDir, "src"));
|
|
67
|
-
fs.mkdirSync(path.join(tmpDir, "src", "nested"));
|
|
68
|
-
fs.writeFileSync(path.join(tmpDir, "root.ts"), "");
|
|
69
|
-
fs.writeFileSync(path.join(tmpDir, "src", "a.ts"), "");
|
|
70
|
-
fs.writeFileSync(path.join(tmpDir, "src", "nested", "b.ts"), "");
|
|
71
|
-
|
|
72
|
-
const result = await native.glob({ pattern: "*.ts", path: tmpDir });
|
|
73
|
-
|
|
74
|
-
assert.equal(result.totalMatches, 3);
|
|
75
|
-
const paths = result.matches.map((m) => m.path).sort();
|
|
76
|
-
assert.ok(paths.includes("root.ts"));
|
|
77
|
-
assert.ok(paths.includes("src/a.ts"));
|
|
78
|
-
assert.ok(paths.includes("src/nested/b.ts"));
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
test("respects maxResults limit", async (t) => {
|
|
82
|
-
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "gsd-glob-test-"));
|
|
83
|
-
t.after(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
|
|
84
|
-
|
|
85
|
-
for (let i = 0; i < 10; i++) {
|
|
86
|
-
fs.writeFileSync(path.join(tmpDir, `file${i}.txt`), "");
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const result = await native.glob({
|
|
90
|
-
pattern: "*.txt",
|
|
91
|
-
path: tmpDir,
|
|
92
|
-
maxResults: 3,
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
assert.equal(result.matches.length, 3);
|
|
96
|
-
assert.equal(result.totalMatches, 3);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
test("filters by file type (directories only)", async (t) => {
|
|
100
|
-
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "gsd-glob-test-"));
|
|
101
|
-
t.after(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
|
|
102
|
-
|
|
103
|
-
fs.mkdirSync(path.join(tmpDir, "dir1"));
|
|
104
|
-
fs.mkdirSync(path.join(tmpDir, "dir2"));
|
|
105
|
-
fs.writeFileSync(path.join(tmpDir, "file.txt"), "");
|
|
106
|
-
|
|
107
|
-
const result = await native.glob({
|
|
108
|
-
pattern: "*",
|
|
109
|
-
path: tmpDir,
|
|
110
|
-
recursive: false,
|
|
111
|
-
fileType: 2, // Dir
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
assert.equal(result.totalMatches, 2);
|
|
115
|
-
const paths = result.matches.map((m) => m.path).sort();
|
|
116
|
-
assert.deepEqual(paths, ["dir1", "dir2"]);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
test("respects .gitignore", async (t) => {
|
|
120
|
-
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "gsd-glob-test-"));
|
|
121
|
-
t.after(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
|
|
122
|
-
|
|
123
|
-
// Init a git repo so .gitignore is respected
|
|
124
|
-
fs.mkdirSync(path.join(tmpDir, ".git"));
|
|
125
|
-
fs.writeFileSync(path.join(tmpDir, ".gitignore"), "ignored.txt\n");
|
|
126
|
-
fs.writeFileSync(path.join(tmpDir, "kept.txt"), "");
|
|
127
|
-
fs.writeFileSync(path.join(tmpDir, "ignored.txt"), "");
|
|
128
|
-
|
|
129
|
-
const result = await native.glob({
|
|
130
|
-
pattern: "*.txt",
|
|
131
|
-
path: tmpDir,
|
|
132
|
-
gitignore: true,
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
assert.equal(result.totalMatches, 1);
|
|
136
|
-
assert.equal(result.matches[0].path, "kept.txt");
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
test("includes gitignored files when gitignore=false", async (t) => {
|
|
140
|
-
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "gsd-glob-test-"));
|
|
141
|
-
t.after(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
|
|
142
|
-
|
|
143
|
-
fs.mkdirSync(path.join(tmpDir, ".git"));
|
|
144
|
-
fs.writeFileSync(path.join(tmpDir, ".gitignore"), "ignored.txt\n");
|
|
145
|
-
fs.writeFileSync(path.join(tmpDir, "kept.txt"), "");
|
|
146
|
-
fs.writeFileSync(path.join(tmpDir, "ignored.txt"), "");
|
|
147
|
-
|
|
148
|
-
const result = await native.glob({
|
|
149
|
-
pattern: "*.txt",
|
|
150
|
-
path: tmpDir,
|
|
151
|
-
gitignore: false,
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
assert.equal(result.totalMatches, 2);
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
test("skips node_modules by default", async (t) => {
|
|
158
|
-
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "gsd-glob-test-"));
|
|
159
|
-
t.after(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
|
|
160
|
-
|
|
161
|
-
fs.mkdirSync(path.join(tmpDir, "node_modules"));
|
|
162
|
-
fs.writeFileSync(path.join(tmpDir, "node_modules", "dep.js"), "");
|
|
163
|
-
fs.writeFileSync(path.join(tmpDir, "app.js"), "");
|
|
164
|
-
|
|
165
|
-
const result = await native.glob({
|
|
166
|
-
pattern: "*.js",
|
|
167
|
-
path: tmpDir,
|
|
168
|
-
gitignore: false,
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
assert.equal(result.totalMatches, 1);
|
|
172
|
-
assert.equal(result.matches[0].path, "app.js");
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
test("sortByMtime returns most recent first", async (t) => {
|
|
176
|
-
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "gsd-glob-test-"));
|
|
177
|
-
t.after(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
|
|
178
|
-
|
|
179
|
-
fs.writeFileSync(path.join(tmpDir, "old.txt"), "old");
|
|
180
|
-
// Ensure different mtime
|
|
181
|
-
const now = new Date();
|
|
182
|
-
fs.utimesSync(
|
|
183
|
-
path.join(tmpDir, "old.txt"),
|
|
184
|
-
new Date(now.getTime() - 5000),
|
|
185
|
-
new Date(now.getTime() - 5000),
|
|
186
|
-
);
|
|
187
|
-
fs.writeFileSync(path.join(tmpDir, "new.txt"), "new");
|
|
188
|
-
|
|
189
|
-
const result = await native.glob({
|
|
190
|
-
pattern: "*.txt",
|
|
191
|
-
path: tmpDir,
|
|
192
|
-
sortByMtime: true,
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
assert.equal(result.totalMatches, 2);
|
|
196
|
-
assert.equal(result.matches[0].path, "new.txt");
|
|
197
|
-
assert.equal(result.matches[1].path, "old.txt");
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
test("errors on non-existent path", async () => {
|
|
201
|
-
await assert.rejects(
|
|
202
|
-
() =>
|
|
203
|
-
native.glob({
|
|
204
|
-
pattern: "*.txt",
|
|
205
|
-
path: "/nonexistent/path/that/does/not/exist",
|
|
206
|
-
}),
|
|
207
|
-
/Path not found/,
|
|
208
|
-
);
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
test("returns mtime for each entry", async (t) => {
|
|
212
|
-
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "gsd-glob-test-"));
|
|
213
|
-
t.after(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
|
|
214
|
-
|
|
215
|
-
fs.writeFileSync(path.join(tmpDir, "test.txt"), "content");
|
|
216
|
-
|
|
217
|
-
const result = await native.glob({ pattern: "*.txt", path: tmpDir });
|
|
218
|
-
|
|
219
|
-
assert.equal(result.matches.length, 1);
|
|
220
|
-
assert.ok(typeof result.matches[0].mtime === "number");
|
|
221
|
-
// mtime should be within the last minute
|
|
222
|
-
const oneMinuteAgo = Date.now() - 60_000;
|
|
223
|
-
assert.ok(result.matches[0].mtime > oneMinuteAgo);
|
|
224
|
-
});
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
describe("native glob: invalidateFsScanCache()", () => {
|
|
228
|
-
test("can be called with a path", () => {
|
|
229
|
-
// Should not throw
|
|
230
|
-
native.invalidateFsScanCache("/tmp");
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
test("can be called without arguments", () => {
|
|
234
|
-
// Should not throw
|
|
235
|
-
native.invalidateFsScanCache();
|
|
236
|
-
});
|
|
237
|
-
});
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
import { test, describe } from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { createRequire } from "node:module";
|
|
4
|
-
import * as path from "node:path";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
-
import * as fs from "node:fs";
|
|
7
|
-
import * as os from "node:os";
|
|
8
|
-
|
|
9
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
-
const require = createRequire(import.meta.url);
|
|
11
|
-
|
|
12
|
-
// Load the native addon directly
|
|
13
|
-
const addonDir = path.resolve(__dirname, "..", "..", "..", "..", "native", "addon");
|
|
14
|
-
const platformTag = `${process.platform}-${process.arch}`;
|
|
15
|
-
const candidates = [
|
|
16
|
-
path.join(addonDir, `gsd_engine.${platformTag}.node`),
|
|
17
|
-
path.join(addonDir, "gsd_engine.dev.node"),
|
|
18
|
-
];
|
|
19
|
-
|
|
20
|
-
let native;
|
|
21
|
-
for (const candidate of candidates) {
|
|
22
|
-
try {
|
|
23
|
-
native = require(candidate);
|
|
24
|
-
break;
|
|
25
|
-
} catch {
|
|
26
|
-
// try next
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (!native) {
|
|
31
|
-
console.error("Native addon not found. Run `npm run build:native -w @gsd/native` first.");
|
|
32
|
-
process.exit(1);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
describe("native grep: search()", () => {
|
|
36
|
-
test("finds matches in buffer content", () => {
|
|
37
|
-
const content = Buffer.from("hello world\nfoo bar\nhello rust\n");
|
|
38
|
-
const result = native.search(content, { pattern: "hello" });
|
|
39
|
-
|
|
40
|
-
assert.equal(result.matchCount, 2);
|
|
41
|
-
assert.equal(result.matches.length, 2);
|
|
42
|
-
assert.equal(result.matches[0].line, "hello world");
|
|
43
|
-
assert.equal(result.matches[0].lineNumber, 1);
|
|
44
|
-
assert.equal(result.matches[1].line, "hello rust");
|
|
45
|
-
assert.equal(result.matches[1].lineNumber, 3);
|
|
46
|
-
assert.equal(result.limitReached, false);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
test("supports case-insensitive search", () => {
|
|
50
|
-
const content = Buffer.from("Hello World\nhello world\nHELLO\n");
|
|
51
|
-
const result = native.search(content, {
|
|
52
|
-
pattern: "hello",
|
|
53
|
-
ignoreCase: true,
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
assert.equal(result.matchCount, 3);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test("respects maxCount limit", () => {
|
|
60
|
-
const content = Buffer.from("aaa\naaa\naaa\naaa\n");
|
|
61
|
-
const result = native.search(content, {
|
|
62
|
-
pattern: "aaa",
|
|
63
|
-
maxCount: 2,
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
assert.equal(result.matches.length, 2);
|
|
67
|
-
assert.equal(result.limitReached, true);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test("returns context lines", () => {
|
|
71
|
-
const content = Buffer.from("line1\nline2\nmatch_here\nline4\nline5\n");
|
|
72
|
-
const result = native.search(content, {
|
|
73
|
-
pattern: "match_here",
|
|
74
|
-
contextBefore: 1,
|
|
75
|
-
contextAfter: 1,
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
assert.equal(result.matches.length, 1);
|
|
79
|
-
assert.equal(result.matches[0].contextBefore.length, 1);
|
|
80
|
-
assert.equal(result.matches[0].contextBefore[0].line, "line2");
|
|
81
|
-
assert.equal(result.matches[0].contextAfter.length, 1);
|
|
82
|
-
assert.equal(result.matches[0].contextAfter[0].line, "line4");
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
test("throws on invalid regex", () => {
|
|
86
|
-
const content = Buffer.from("hello");
|
|
87
|
-
assert.throws(() => {
|
|
88
|
-
native.search(content, { pattern: "[invalid" });
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
describe("native grep: grep()", () => {
|
|
94
|
-
let tmpDir;
|
|
95
|
-
|
|
96
|
-
test("searches files on disk", (t) => {
|
|
97
|
-
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "gsd-grep-test-"));
|
|
98
|
-
t.after(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
|
|
99
|
-
|
|
100
|
-
fs.writeFileSync(path.join(tmpDir, "file1.txt"), "hello world\nfoo bar\n");
|
|
101
|
-
fs.writeFileSync(path.join(tmpDir, "file2.txt"), "hello rust\nbaz qux\n");
|
|
102
|
-
fs.writeFileSync(path.join(tmpDir, "file3.log"), "no match here\n");
|
|
103
|
-
|
|
104
|
-
const result = native.grep({
|
|
105
|
-
pattern: "hello",
|
|
106
|
-
path: tmpDir,
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
assert.equal(result.totalMatches, 2);
|
|
110
|
-
assert.equal(result.filesWithMatches, 2);
|
|
111
|
-
assert.equal(result.matches.length, 2);
|
|
112
|
-
|
|
113
|
-
// Matches should be sorted by file path
|
|
114
|
-
const paths = result.matches.map((m) => m.path);
|
|
115
|
-
assert.deepEqual(paths, [...paths].sort());
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
test("respects glob filter", (t) => {
|
|
119
|
-
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "gsd-grep-test-"));
|
|
120
|
-
t.after(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
|
|
121
|
-
|
|
122
|
-
fs.writeFileSync(path.join(tmpDir, "code.ts"), "hello typescript\n");
|
|
123
|
-
fs.writeFileSync(path.join(tmpDir, "code.js"), "hello javascript\n");
|
|
124
|
-
fs.writeFileSync(path.join(tmpDir, "readme.md"), "hello markdown\n");
|
|
125
|
-
|
|
126
|
-
const result = native.grep({
|
|
127
|
-
pattern: "hello",
|
|
128
|
-
path: tmpDir,
|
|
129
|
-
glob: "*.ts",
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
assert.equal(result.totalMatches, 1);
|
|
133
|
-
assert.equal(result.matches[0].line, "hello typescript");
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
test("respects maxCount", (t) => {
|
|
137
|
-
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "gsd-grep-test-"));
|
|
138
|
-
t.after(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
|
|
139
|
-
|
|
140
|
-
for (let i = 0; i < 10; i++) {
|
|
141
|
-
fs.writeFileSync(path.join(tmpDir, `file${i}.txt`), "match_me\n");
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const result = native.grep({
|
|
145
|
-
pattern: "match_me",
|
|
146
|
-
path: tmpDir,
|
|
147
|
-
maxCount: 3,
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
assert.ok(result.matches.length <= 3);
|
|
151
|
-
assert.equal(result.limitReached, true);
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
test("errors on non-existent path", () => {
|
|
155
|
-
assert.throws(() => {
|
|
156
|
-
native.grep({
|
|
157
|
-
pattern: "test",
|
|
158
|
-
path: "/nonexistent/path/that/does/not/exist",
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
});
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import { test, describe } from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { createRequire } from "node:module";
|
|
4
|
-
import * as path from "node:path";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
-
|
|
7
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
const require = createRequire(import.meta.url);
|
|
9
|
-
|
|
10
|
-
// Load the native addon directly
|
|
11
|
-
const addonDir = path.resolve(__dirname, "..", "..", "..", "..", "native", "addon");
|
|
12
|
-
const platformTag = `${process.platform}-${process.arch}`;
|
|
13
|
-
const candidates = [
|
|
14
|
-
path.join(addonDir, `gsd_engine.${platformTag}.node`),
|
|
15
|
-
path.join(addonDir, "gsd_engine.dev.node"),
|
|
16
|
-
];
|
|
17
|
-
|
|
18
|
-
let native;
|
|
19
|
-
for (const candidate of candidates) {
|
|
20
|
-
try {
|
|
21
|
-
native = require(candidate);
|
|
22
|
-
break;
|
|
23
|
-
} catch {
|
|
24
|
-
// try next
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (!native) {
|
|
29
|
-
console.error("Native addon not found. Run `npm run build:native -w @gsd/native` first.");
|
|
30
|
-
process.exit(1);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const testColors = {
|
|
34
|
-
comment: "\x1b[38;2;106;153;85m",
|
|
35
|
-
keyword: "\x1b[38;2;197;134;192m",
|
|
36
|
-
function: "\x1b[38;2;220;220;170m",
|
|
37
|
-
variable: "\x1b[38;2;156;220;254m",
|
|
38
|
-
string: "\x1b[38;2;206;145;120m",
|
|
39
|
-
number: "\x1b[38;2;181;206;168m",
|
|
40
|
-
type: "\x1b[38;2;78;201;176m",
|
|
41
|
-
operator: "\x1b[38;2;212;212;212m",
|
|
42
|
-
punctuation: "\x1b[38;2;212;212;212m",
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
describe("native highlight: highlightCode()", () => {
|
|
46
|
-
test("highlights JavaScript code with ANSI colors", () => {
|
|
47
|
-
const code = 'const x = 42;\n';
|
|
48
|
-
const result = native.highlightCode(code, "javascript", testColors);
|
|
49
|
-
|
|
50
|
-
// Result should contain ANSI escape sequences
|
|
51
|
-
assert.ok(result.includes("\x1b["), "should contain ANSI escape codes");
|
|
52
|
-
// Result should contain the original tokens
|
|
53
|
-
assert.ok(result.includes("const"), "should contain 'const'");
|
|
54
|
-
assert.ok(result.includes("42"), "should contain '42'");
|
|
55
|
-
// Reset codes should be present
|
|
56
|
-
assert.ok(result.includes("\x1b[39m"), "should contain ANSI reset codes");
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test("returns unhighlighted code for unknown language", () => {
|
|
60
|
-
const code = "some random text\n";
|
|
61
|
-
const result = native.highlightCode(code, "nonexistent_lang_xyz", testColors);
|
|
62
|
-
|
|
63
|
-
// Plain text syntax should pass through without color codes on plain content
|
|
64
|
-
assert.ok(typeof result === "string");
|
|
65
|
-
assert.ok(result.includes("some random text"));
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
test("handles null language gracefully", () => {
|
|
69
|
-
const code = "hello world\n";
|
|
70
|
-
const result = native.highlightCode(code, null, testColors);
|
|
71
|
-
|
|
72
|
-
assert.ok(typeof result === "string");
|
|
73
|
-
assert.ok(result.includes("hello world"));
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
test("handles empty code", () => {
|
|
77
|
-
const result = native.highlightCode("", "javascript", testColors);
|
|
78
|
-
assert.equal(result, "");
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
test("handles multiline code", () => {
|
|
82
|
-
const code = 'function foo() {\n return "bar";\n}\n';
|
|
83
|
-
const result = native.highlightCode(code, "javascript", testColors);
|
|
84
|
-
|
|
85
|
-
assert.ok(result.includes("function"));
|
|
86
|
-
assert.ok(result.includes("foo"));
|
|
87
|
-
assert.ok(result.includes("return"));
|
|
88
|
-
assert.ok(result.includes("bar"));
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
test("supports optional inserted/deleted colors", () => {
|
|
92
|
-
const colorsWithDiff = {
|
|
93
|
-
...testColors,
|
|
94
|
-
inserted: "\x1b[38;2;0;255;0m",
|
|
95
|
-
deleted: "\x1b[38;2;255;0;0m",
|
|
96
|
-
};
|
|
97
|
-
const code = "+added line\n-removed line\n";
|
|
98
|
-
const result = native.highlightCode(code, "diff", colorsWithDiff);
|
|
99
|
-
|
|
100
|
-
assert.ok(typeof result === "string");
|
|
101
|
-
assert.ok(result.length > 0);
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
describe("native highlight: supportsLanguage()", () => {
|
|
106
|
-
test("returns true for known aliases", () => {
|
|
107
|
-
assert.ok(native.supportsLanguage("javascript"));
|
|
108
|
-
assert.ok(native.supportsLanguage("typescript"));
|
|
109
|
-
assert.ok(native.supportsLanguage("python"));
|
|
110
|
-
assert.ok(native.supportsLanguage("rust"));
|
|
111
|
-
assert.ok(native.supportsLanguage("go"));
|
|
112
|
-
assert.ok(native.supportsLanguage("bash"));
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
test("returns true case-insensitively", () => {
|
|
116
|
-
assert.ok(native.supportsLanguage("JavaScript"));
|
|
117
|
-
assert.ok(native.supportsLanguage("PYTHON"));
|
|
118
|
-
assert.ok(native.supportsLanguage("Rust"));
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
test("returns true for short aliases", () => {
|
|
122
|
-
assert.ok(native.supportsLanguage("ts"));
|
|
123
|
-
assert.ok(native.supportsLanguage("py"));
|
|
124
|
-
assert.ok(native.supportsLanguage("rs"));
|
|
125
|
-
assert.ok(native.supportsLanguage("rb"));
|
|
126
|
-
assert.ok(native.supportsLanguage("sh"));
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
test("returns false for completely unknown languages", () => {
|
|
130
|
-
assert.equal(native.supportsLanguage("nonexistent_lang_xyz"), false);
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
describe("native highlight: getSupportedLanguages()", () => {
|
|
135
|
-
test("returns an array of language names", () => {
|
|
136
|
-
const langs = native.getSupportedLanguages();
|
|
137
|
-
assert.ok(Array.isArray(langs));
|
|
138
|
-
assert.ok(langs.length > 0, "should have at least one language");
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
test("includes common languages", () => {
|
|
142
|
-
const langs = native.getSupportedLanguages();
|
|
143
|
-
// These are syntect default syntax names
|
|
144
|
-
assert.ok(langs.includes("JavaScript"), "should include JavaScript");
|
|
145
|
-
assert.ok(langs.includes("Python"), "should include Python");
|
|
146
|
-
assert.ok(langs.includes("Rust"), "should include Rust");
|
|
147
|
-
assert.ok(langs.includes("C"), "should include C");
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
test("returns strings", () => {
|
|
151
|
-
const langs = native.getSupportedLanguages();
|
|
152
|
-
for (const lang of langs) {
|
|
153
|
-
assert.equal(typeof lang, "string");
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
});
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { test, describe } from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { createRequire } from "node:module";
|
|
4
|
-
import * as path from "node:path";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
-
|
|
7
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
const require = createRequire(import.meta.url);
|
|
9
|
-
|
|
10
|
-
const addonDir = path.resolve(__dirname, "..", "..", "..", "..", "native", "addon");
|
|
11
|
-
const platformTag = `${process.platform}-${process.arch}`;
|
|
12
|
-
const candidates = [
|
|
13
|
-
path.join(addonDir, `gsd_engine.${platformTag}.node`),
|
|
14
|
-
path.join(addonDir, "gsd_engine.dev.node"),
|
|
15
|
-
];
|
|
16
|
-
|
|
17
|
-
let native;
|
|
18
|
-
for (const candidate of candidates) {
|
|
19
|
-
try {
|
|
20
|
-
native = require(candidate);
|
|
21
|
-
break;
|
|
22
|
-
} catch {
|
|
23
|
-
// try next
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (!native) {
|
|
28
|
-
console.error("Native addon not found. Run `npm run build:native -w @gsd/native` first.");
|
|
29
|
-
process.exit(1);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
describe("native html: htmlToMarkdown()", () => {
|
|
33
|
-
test("converts basic HTML to markdown", () => {
|
|
34
|
-
const html = "<h1>Hello</h1><p>World</p>";
|
|
35
|
-
const result = native.htmlToMarkdown(html);
|
|
36
|
-
assert.ok(result.includes("Hello"), "Should contain heading text");
|
|
37
|
-
assert.ok(result.includes("World"), "Should contain paragraph text");
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
test("converts links to markdown links", () => {
|
|
41
|
-
const html = '<p>Visit <a href="https://example.com">Example</a></p>';
|
|
42
|
-
const result = native.htmlToMarkdown(html);
|
|
43
|
-
assert.ok(result.includes("[Example]"), "Should contain markdown link text");
|
|
44
|
-
assert.ok(result.includes("(https://example.com)"), "Should contain markdown link URL");
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
test("converts lists to markdown", () => {
|
|
48
|
-
const html = "<ul><li>First</li><li>Second</li><li>Third</li></ul>";
|
|
49
|
-
const result = native.htmlToMarkdown(html);
|
|
50
|
-
assert.ok(result.includes("First"), "Should contain first item");
|
|
51
|
-
assert.ok(result.includes("Second"), "Should contain second item");
|
|
52
|
-
assert.ok(result.includes("Third"), "Should contain third item");
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test("converts bold and italic", () => {
|
|
56
|
-
const html = "<p><strong>bold</strong> and <em>italic</em></p>";
|
|
57
|
-
const result = native.htmlToMarkdown(html);
|
|
58
|
-
assert.ok(result.includes("**bold**") || result.includes("__bold__"), "Should contain bold");
|
|
59
|
-
assert.ok(result.includes("*italic*") || result.includes("_italic_"), "Should contain italic");
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
test("handles empty HTML", () => {
|
|
63
|
-
const result = native.htmlToMarkdown("");
|
|
64
|
-
assert.equal(typeof result, "string");
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
test("handles plain text", () => {
|
|
68
|
-
const result = native.htmlToMarkdown("Just plain text");
|
|
69
|
-
assert.ok(result.includes("Just plain text"), "Should preserve plain text");
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
test("accepts skipImages option", () => {
|
|
73
|
-
const html = '<h1>Title</h1><p>Content with <img src="photo.jpg" alt="photo"> image</p>';
|
|
74
|
-
const result = native.htmlToMarkdown(html, { skipImages: true });
|
|
75
|
-
assert.ok(result.includes("Title"), "Should contain heading");
|
|
76
|
-
assert.ok(result.includes("Content"), "Should contain paragraph text");
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test("accepts cleanContent option", () => {
|
|
80
|
-
const html = '<nav><a href="/home">Home</a></nav><main><h1>Article</h1><p>Body text.</p></main><footer>Copyright</footer>';
|
|
81
|
-
const result = native.htmlToMarkdown(html, { cleanContent: true });
|
|
82
|
-
assert.ok(result.includes("Article") || result.includes("Body text"), "Should contain main content");
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
test("converts code blocks", () => {
|
|
86
|
-
const html = "<pre><code>const x = 1;</code></pre>";
|
|
87
|
-
const result = native.htmlToMarkdown(html);
|
|
88
|
-
assert.ok(result.includes("const x = 1;"), "Should contain code content");
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
test("converts complex nested HTML", () => {
|
|
92
|
-
const html = '<div><h2>Section</h2><p>Text with <a href="https://example.com"><strong>bold link</strong></a>.</p><ul><li>Item one</li><li>Item two</li></ul></div>';
|
|
93
|
-
const result = native.htmlToMarkdown(html);
|
|
94
|
-
assert.ok(result.includes("Section"), "Should contain heading");
|
|
95
|
-
assert.ok(result.includes("example.com"), "Should contain link");
|
|
96
|
-
assert.ok(result.includes("one"), "Should contain list items");
|
|
97
|
-
});
|
|
98
|
-
});
|