@pinfix/plugin 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/channel-server.js +375 -0
- package/dist/chunk-WYYKYDGW.js +483 -0
- package/dist/index.cjs +521 -0
- package/dist/index.d.cts +9 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +8 -0
- package/dist/overlay.iife.global.js +7930 -0
- package/dist/rspack.cjs +520 -0
- package/dist/rspack.d.cts +6 -0
- package/dist/rspack.d.ts +6 -0
- package/dist/rspack.js +9 -0
- package/dist/vite.cjs +520 -0
- package/dist/vite.d.cts +6 -0
- package/dist/vite.d.ts +6 -0
- package/dist/vite.js +9 -0
- package/dist/webpack.cjs +520 -0
- package/dist/webpack.d.cts +6 -0
- package/dist/webpack.d.ts +6 -0
- package/dist/webpack.js +9 -0
- package/package.json +71 -0
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { createUnplugin } from "unplugin";
|
|
3
|
+
|
|
4
|
+
// src/transform.ts
|
|
5
|
+
import { parse } from "@babel/parser";
|
|
6
|
+
import _traverse from "@babel/traverse";
|
|
7
|
+
import MagicString from "magic-string";
|
|
8
|
+
|
|
9
|
+
// ../shared/dist/index.js
|
|
10
|
+
var WS_PORT_DEFAULT = 24816;
|
|
11
|
+
var DATA_ATTR = "data-pinfix-source";
|
|
12
|
+
var VUE_BUILTINS = /* @__PURE__ */ new Set([
|
|
13
|
+
"template",
|
|
14
|
+
"slot",
|
|
15
|
+
"transition",
|
|
16
|
+
"transition-group",
|
|
17
|
+
"keep-alive",
|
|
18
|
+
"teleport",
|
|
19
|
+
"suspense",
|
|
20
|
+
"component",
|
|
21
|
+
"fragment"
|
|
22
|
+
]);
|
|
23
|
+
|
|
24
|
+
// src/transform.ts
|
|
25
|
+
import { readFileSync } from "fs";
|
|
26
|
+
import { parse as vueParse } from "@vue/compiler-dom";
|
|
27
|
+
var traverse = _traverse.default || _traverse;
|
|
28
|
+
function transformCode(code, id, absolutePath, options) {
|
|
29
|
+
const [filePath, query] = id.split("?", 2);
|
|
30
|
+
const params = new URLSearchParams(query || "");
|
|
31
|
+
if (filePath.endsWith(".vue") && (params.get("lang") === "tsx" || params.get("lang") === "jsx")) {
|
|
32
|
+
return transformJsx(code, id, absolutePath, options);
|
|
33
|
+
}
|
|
34
|
+
if (filePath.endsWith(".vue") && (!query || params.get("type") === "template")) {
|
|
35
|
+
return transformVue(code, filePath, options);
|
|
36
|
+
}
|
|
37
|
+
if (/\.(jsx|tsx)$/.test(filePath)) {
|
|
38
|
+
return transformJsx(code, id, absolutePath, options);
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
function transformJsx(code, id, absolutePath, options) {
|
|
43
|
+
let originalSource;
|
|
44
|
+
try {
|
|
45
|
+
const filePath = absolutePath || id;
|
|
46
|
+
originalSource = readFileSync(filePath.split("?")[0], "utf-8");
|
|
47
|
+
} catch {
|
|
48
|
+
originalSource = code;
|
|
49
|
+
}
|
|
50
|
+
let ast;
|
|
51
|
+
try {
|
|
52
|
+
ast = parse(code, {
|
|
53
|
+
sourceType: "module",
|
|
54
|
+
plugins: ["jsx", "typescript", "decorators-legacy"]
|
|
55
|
+
});
|
|
56
|
+
} catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
let originalAst = null;
|
|
60
|
+
if (originalSource !== code) {
|
|
61
|
+
try {
|
|
62
|
+
originalAst = parse(originalSource, {
|
|
63
|
+
sourceType: "module",
|
|
64
|
+
plugins: ["jsx", "typescript", "decorators-legacy"]
|
|
65
|
+
});
|
|
66
|
+
} catch {
|
|
67
|
+
originalAst = null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const originalPositions = /* @__PURE__ */ new Map();
|
|
71
|
+
if (originalAst) {
|
|
72
|
+
const tagCounts2 = /* @__PURE__ */ new Map();
|
|
73
|
+
traverse(originalAst, {
|
|
74
|
+
JSXOpeningElement(path) {
|
|
75
|
+
const node = path.node;
|
|
76
|
+
const loc = node.loc?.start;
|
|
77
|
+
if (!loc) return;
|
|
78
|
+
const name = getJsxName(node.name);
|
|
79
|
+
const count = (tagCounts2.get(name) || 0) + 1;
|
|
80
|
+
tagCounts2.set(name, count);
|
|
81
|
+
originalPositions.set(`${name}#${count}`, { line: loc.line, column: loc.column + 1 });
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
const s = new MagicString(code);
|
|
86
|
+
let hasChanges = false;
|
|
87
|
+
const tagCounts = /* @__PURE__ */ new Map();
|
|
88
|
+
const escapeTags = options?.escapeTags ?? [];
|
|
89
|
+
traverse(ast, {
|
|
90
|
+
JSXOpeningElement(path) {
|
|
91
|
+
const node = path.node;
|
|
92
|
+
const loc = node.loc?.start;
|
|
93
|
+
if (!loc) return;
|
|
94
|
+
const name = getJsxName(node.name);
|
|
95
|
+
if (isEscaped(name, escapeTags)) return;
|
|
96
|
+
const count = (tagCounts.get(name) || 0) + 1;
|
|
97
|
+
tagCounts.set(name, count);
|
|
98
|
+
let line = loc.line;
|
|
99
|
+
let column = loc.column + 1;
|
|
100
|
+
const origPos = originalPositions.get(`${name}#${count}`);
|
|
101
|
+
if (origPos) {
|
|
102
|
+
line = origPos.line;
|
|
103
|
+
column = origPos.column;
|
|
104
|
+
}
|
|
105
|
+
const attrStr = ` ${DATA_ATTR}="${id}:${line}:${column}"`;
|
|
106
|
+
const nameEnd = node.name.end;
|
|
107
|
+
s.appendLeft(nameEnd, attrStr);
|
|
108
|
+
hasChanges = true;
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
if (!hasChanges) return null;
|
|
112
|
+
return { code: s.toString(), map: s.generateMap({ source: id, hires: true, includeContent: true }) };
|
|
113
|
+
}
|
|
114
|
+
function getJsxName(node) {
|
|
115
|
+
if (node.type === "JSXIdentifier") return node.name;
|
|
116
|
+
if (node.type === "JSXMemberExpression") {
|
|
117
|
+
return getJsxName(node.object) + "." + node.property.name;
|
|
118
|
+
}
|
|
119
|
+
if (node.type === "JSXNamespacedName") {
|
|
120
|
+
return node.namespace.name + ":" + node.name.name;
|
|
121
|
+
}
|
|
122
|
+
return "unknown";
|
|
123
|
+
}
|
|
124
|
+
function isEscaped(tagName, escapeTags) {
|
|
125
|
+
return escapeTags.some(
|
|
126
|
+
(tag) => typeof tag === "string" ? tag === tagName : tag.test(tagName)
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
function transformVue(code, id, options) {
|
|
130
|
+
const ast = vueParse(code, { comments: true });
|
|
131
|
+
const templateNode = ast.children.find(
|
|
132
|
+
(node) => node.type === 1 && node.tag === "template"
|
|
133
|
+
);
|
|
134
|
+
if (!templateNode) return null;
|
|
135
|
+
const s = new MagicString(code);
|
|
136
|
+
let hasChanges = false;
|
|
137
|
+
const escapeTags = options?.escapeTags ?? [];
|
|
138
|
+
function walkNode(node) {
|
|
139
|
+
if (node.type !== 1) return;
|
|
140
|
+
const tagName = node.tag;
|
|
141
|
+
if (!VUE_BUILTINS.has(tagName) && !isEscaped(tagName, escapeTags)) {
|
|
142
|
+
const line = node.loc.start.line;
|
|
143
|
+
const column = node.loc.start.column;
|
|
144
|
+
const insertPos = node.loc.start.offset + 1 + tagName.length;
|
|
145
|
+
const attrStr = ` ${DATA_ATTR}="${id}:${line}:${column}"`;
|
|
146
|
+
s.appendLeft(insertPos, attrStr);
|
|
147
|
+
hasChanges = true;
|
|
148
|
+
}
|
|
149
|
+
if (node.children) {
|
|
150
|
+
for (const child of node.children) {
|
|
151
|
+
walkNode(child);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
for (const child of templateNode.children) {
|
|
156
|
+
walkNode(child);
|
|
157
|
+
}
|
|
158
|
+
if (!hasChanges) return null;
|
|
159
|
+
return { code: s.toString(), map: s.generateMap({ source: id, hires: true, includeContent: true }) };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// src/server.ts
|
|
163
|
+
import { spawn } from "child_process";
|
|
164
|
+
import { existsSync, watchFile, unwatchFile, readFileSync as readFileSync2, unlinkSync } from "fs";
|
|
165
|
+
import { resolve, dirname } from "path";
|
|
166
|
+
import { fileURLToPath } from "url";
|
|
167
|
+
var channelProc = null;
|
|
168
|
+
var currentOptions = null;
|
|
169
|
+
var watchedServerBin = null;
|
|
170
|
+
var restartTimer = null;
|
|
171
|
+
function getRuntimeDir() {
|
|
172
|
+
return typeof __dirname === "string" ? __dirname : dirname(fileURLToPath(import.meta.url));
|
|
173
|
+
}
|
|
174
|
+
function cleanStalePid(cwd) {
|
|
175
|
+
const pidFile = resolve(cwd, "node_modules", ".cache", "pinfix", "server.pid");
|
|
176
|
+
if (!existsSync(pidFile)) return;
|
|
177
|
+
try {
|
|
178
|
+
const pid = parseInt(readFileSync2(pidFile, "utf-8").trim(), 10);
|
|
179
|
+
if (!isNaN(pid)) {
|
|
180
|
+
try {
|
|
181
|
+
process.kill(pid, 0);
|
|
182
|
+
process.kill(pid, "SIGTERM");
|
|
183
|
+
} catch {
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
} catch {
|
|
187
|
+
}
|
|
188
|
+
try {
|
|
189
|
+
unlinkSync(pidFile);
|
|
190
|
+
} catch {
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function getServerBin() {
|
|
194
|
+
return resolve(getRuntimeDir(), "channel-server.js");
|
|
195
|
+
}
|
|
196
|
+
function spawnChannelServer(options, serverBin) {
|
|
197
|
+
if (!existsSync(serverBin)) {
|
|
198
|
+
options.onError?.(`channel-server entry not found: ${serverBin}`);
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
try {
|
|
202
|
+
const proc = spawn(process.execPath, [serverBin], {
|
|
203
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
204
|
+
env: {
|
|
205
|
+
...process.env,
|
|
206
|
+
PINFIX_PORT: String(options.port),
|
|
207
|
+
PINFIX_CWD: options.cwd
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
proc.stderr?.on("data", (d) => {
|
|
211
|
+
const msg = d.toString().trim();
|
|
212
|
+
if (msg) options.onLog?.(msg);
|
|
213
|
+
});
|
|
214
|
+
proc.on("error", () => {
|
|
215
|
+
options.onError?.("channel-server failed to start");
|
|
216
|
+
});
|
|
217
|
+
proc.on("exit", () => {
|
|
218
|
+
if (channelProc === proc) channelProc = null;
|
|
219
|
+
});
|
|
220
|
+
channelProc = proc;
|
|
221
|
+
return proc;
|
|
222
|
+
} catch {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
function watchChannelServer(serverBin) {
|
|
227
|
+
if (watchedServerBin === serverBin) return;
|
|
228
|
+
unwatchChannelServer();
|
|
229
|
+
watchedServerBin = serverBin;
|
|
230
|
+
watchFile(serverBin, { interval: 500 }, (curr, prev) => {
|
|
231
|
+
if (curr.mtimeMs === prev.mtimeMs) return;
|
|
232
|
+
scheduleChannelServerRestart();
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
function unwatchChannelServer() {
|
|
236
|
+
if (!watchedServerBin) return;
|
|
237
|
+
unwatchFile(watchedServerBin);
|
|
238
|
+
watchedServerBin = null;
|
|
239
|
+
}
|
|
240
|
+
function scheduleChannelServerRestart() {
|
|
241
|
+
if (!currentOptions) return;
|
|
242
|
+
if (restartTimer) clearTimeout(restartTimer);
|
|
243
|
+
restartTimer = setTimeout(() => {
|
|
244
|
+
restartTimer = null;
|
|
245
|
+
restartChannelServer();
|
|
246
|
+
}, 150);
|
|
247
|
+
}
|
|
248
|
+
function restartChannelServer() {
|
|
249
|
+
if (!currentOptions) return;
|
|
250
|
+
const options = currentOptions;
|
|
251
|
+
const serverBin = getServerBin();
|
|
252
|
+
options.onLog?.("channel-server changed, restarting");
|
|
253
|
+
if (channelProc && !channelProc.killed) {
|
|
254
|
+
const oldProc = channelProc;
|
|
255
|
+
channelProc = null;
|
|
256
|
+
oldProc.once("exit", () => {
|
|
257
|
+
spawnChannelServer(options, serverBin);
|
|
258
|
+
});
|
|
259
|
+
oldProc.kill();
|
|
260
|
+
setTimeout(() => {
|
|
261
|
+
if (oldProc.exitCode === null && oldProc.signalCode === null) {
|
|
262
|
+
oldProc.kill("SIGKILL");
|
|
263
|
+
}
|
|
264
|
+
}, 1e3);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
spawnChannelServer(options, serverBin);
|
|
268
|
+
}
|
|
269
|
+
function startChannelServer(options) {
|
|
270
|
+
cleanStalePid(options.cwd);
|
|
271
|
+
currentOptions = options;
|
|
272
|
+
const serverBin = getServerBin();
|
|
273
|
+
if (options.watch) watchChannelServer(serverBin);
|
|
274
|
+
if (channelProc && !channelProc.killed) return channelProc;
|
|
275
|
+
return spawnChannelServer(options, serverBin);
|
|
276
|
+
}
|
|
277
|
+
function stopChannelServer() {
|
|
278
|
+
if (restartTimer) {
|
|
279
|
+
clearTimeout(restartTimer);
|
|
280
|
+
restartTimer = null;
|
|
281
|
+
}
|
|
282
|
+
unwatchChannelServer();
|
|
283
|
+
currentOptions = null;
|
|
284
|
+
if (channelProc && !channelProc.killed) {
|
|
285
|
+
channelProc.kill();
|
|
286
|
+
channelProc = null;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// src/inject.ts
|
|
291
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
292
|
+
import { resolve as resolve2, dirname as dirname2 } from "path";
|
|
293
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
294
|
+
function getRuntimeDir2() {
|
|
295
|
+
return typeof __dirname === "string" ? __dirname : dirname2(fileURLToPath2(import.meta.url));
|
|
296
|
+
}
|
|
297
|
+
function getClientBundle(onError) {
|
|
298
|
+
const clientPath = resolve2(getRuntimeDir2(), "overlay.iife.global.js");
|
|
299
|
+
try {
|
|
300
|
+
return readFileSync3(clientPath, "utf-8");
|
|
301
|
+
} catch (err) {
|
|
302
|
+
onError?.(
|
|
303
|
+
`overlay bundle not found at ${clientPath}; run pinfix build before using the plugin (${err.message})`
|
|
304
|
+
);
|
|
305
|
+
return "";
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
function getInjectionScript(options) {
|
|
309
|
+
const clientCode = getClientBundle(options.onError);
|
|
310
|
+
if (!clientCode) return "";
|
|
311
|
+
return [
|
|
312
|
+
`<script>`,
|
|
313
|
+
`window.__PINFIX_WS_URL__ = ${JSON.stringify(options.wsUrl)};`,
|
|
314
|
+
`window.__PINFIX_PROMPT__ = ${JSON.stringify(options.prompt)};`,
|
|
315
|
+
`window.__PINFIX_HOTKEY__ = ${JSON.stringify(options.hotkey || "alt+shift+z")};`,
|
|
316
|
+
`window.__PINFIX_FAB__ = ${JSON.stringify(options.fab !== false)};`,
|
|
317
|
+
clientCode,
|
|
318
|
+
`</script>`
|
|
319
|
+
].join("\n");
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// src/index.ts
|
|
323
|
+
import { resolve as resolve3, dirname as dirname3 } from "path";
|
|
324
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
325
|
+
function injectHtml(html, script) {
|
|
326
|
+
if (!script || html.includes("__PINFIX_WS_URL__")) return html;
|
|
327
|
+
return html.replace("<head>", `<head>
|
|
328
|
+
${script}`);
|
|
329
|
+
}
|
|
330
|
+
var unplugin = createUnplugin((options = {}) => {
|
|
331
|
+
const port = options.port ?? WS_PORT_DEFAULT;
|
|
332
|
+
let root = options.root ?? process.cwd();
|
|
333
|
+
const wsUrl = `ws://localhost:${port}`;
|
|
334
|
+
const debug = options.debug ?? false;
|
|
335
|
+
const logError = (msg) => console.warn(`[pinfix] ${msg}`);
|
|
336
|
+
function setupWebpackLikeCompiler(compiler) {
|
|
337
|
+
let serverStarted = false;
|
|
338
|
+
const startServer = () => {
|
|
339
|
+
if (serverStarted) return;
|
|
340
|
+
serverStarted = true;
|
|
341
|
+
startChannelServer({
|
|
342
|
+
port,
|
|
343
|
+
cwd: root,
|
|
344
|
+
watch: true,
|
|
345
|
+
onLog: debug ? (msg) => console.log(`[pinfix] ${msg}`) : void 0,
|
|
346
|
+
onError: debug ? (msg) => console.warn(`[pinfix] ${msg}`) : void 0
|
|
347
|
+
});
|
|
348
|
+
};
|
|
349
|
+
if (compiler.watchMode || process.env.WEBPACK_SERVE === "true" || process.env.RSPACK_SERVE === "true") {
|
|
350
|
+
startServer();
|
|
351
|
+
}
|
|
352
|
+
compiler.hooks?.watchRun?.tap("pinfix", startServer);
|
|
353
|
+
if (compiler.hooks?.shutdown) {
|
|
354
|
+
compiler.hooks.shutdown.tap("pinfix", stopChannelServer);
|
|
355
|
+
} else {
|
|
356
|
+
process.on("exit", stopChannelServer);
|
|
357
|
+
}
|
|
358
|
+
compiler.hooks?.compilation?.tap("pinfix", (compilation) => {
|
|
359
|
+
const script = getInjectionScript({ wsUrl, prompt: options.prompt ?? "", hotkey: options.hotkey, fab: options.fab, onError: logError });
|
|
360
|
+
const htmlPluginCtors = new Set(
|
|
361
|
+
(compiler.options?.plugins ?? []).map((plugin) => plugin?.constructor).filter((ctor) => typeof ctor?.getHooks === "function" || typeof ctor?.getCompilationHooks === "function")
|
|
362
|
+
);
|
|
363
|
+
for (const HtmlPlugin of htmlPluginCtors) {
|
|
364
|
+
const hooks = HtmlPlugin.getHooks?.(compilation) ?? HtmlPlugin.getCompilationHooks?.(compilation);
|
|
365
|
+
if (!hooks?.beforeEmit?.tapPromise) continue;
|
|
366
|
+
hooks.beforeEmit.tapPromise({ name: "pinfix" }, async (data) => {
|
|
367
|
+
if (typeof data.html === "string") {
|
|
368
|
+
data.html = injectHtml(data.html, script);
|
|
369
|
+
}
|
|
370
|
+
return data;
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
if (compilation.hooks?.processAssets) {
|
|
374
|
+
const CompilerRuntime = compiler.webpack ?? compiler.rspack;
|
|
375
|
+
const stage = CompilerRuntime?.Compilation?.PROCESS_ASSETS_STAGE_REPORT ?? 5e3;
|
|
376
|
+
compilation.hooks.processAssets.tapAsync(
|
|
377
|
+
{ name: "pinfix", stage },
|
|
378
|
+
(assets, cb) => {
|
|
379
|
+
if (!script) {
|
|
380
|
+
cb();
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
const RawSource = CompilerRuntime?.sources?.RawSource;
|
|
384
|
+
for (const name of Object.keys(assets)) {
|
|
385
|
+
if (!name.endsWith(".html")) continue;
|
|
386
|
+
const source = assets[name].source();
|
|
387
|
+
if (typeof source !== "string") continue;
|
|
388
|
+
const newHtml = injectHtml(source, script);
|
|
389
|
+
if (newHtml === source) continue;
|
|
390
|
+
if (typeof compilation.updateAsset === "function" && RawSource) {
|
|
391
|
+
compilation.updateAsset(name, new RawSource(newHtml));
|
|
392
|
+
} else {
|
|
393
|
+
assets[name] = {
|
|
394
|
+
source: () => newHtml,
|
|
395
|
+
size: () => newHtml.length
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
cb();
|
|
400
|
+
}
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
return {
|
|
406
|
+
name: "pinfix",
|
|
407
|
+
enforce: "pre",
|
|
408
|
+
transformInclude(id) {
|
|
409
|
+
const [filePath] = id.split("?", 2);
|
|
410
|
+
return /\.(jsx|tsx|vue)$/.test(filePath);
|
|
411
|
+
},
|
|
412
|
+
transform(code, id) {
|
|
413
|
+
let relativePath = id;
|
|
414
|
+
const [absFilePath] = id.split("?", 2);
|
|
415
|
+
if (absFilePath.startsWith(root)) {
|
|
416
|
+
const rel = absFilePath.slice(root.length);
|
|
417
|
+
relativePath = (rel.startsWith("/") ? rel.slice(1) : rel) + (id.includes("?") ? "?" + id.split("?")[1] : "");
|
|
418
|
+
}
|
|
419
|
+
const relFile = relativePath.split("?")[0];
|
|
420
|
+
if (options.match && !options.match.test(relFile)) return null;
|
|
421
|
+
if (options.exclude && options.exclude.test(relFile)) return null;
|
|
422
|
+
return transformCode(code, relativePath, id, { escapeTags: options.escapeTags });
|
|
423
|
+
},
|
|
424
|
+
// === Vite-specific hooks ===
|
|
425
|
+
vite: {
|
|
426
|
+
configResolved(config) {
|
|
427
|
+
root = config.root;
|
|
428
|
+
},
|
|
429
|
+
config() {
|
|
430
|
+
return {
|
|
431
|
+
define: {
|
|
432
|
+
__PINFIX_WS_URL__: JSON.stringify(wsUrl),
|
|
433
|
+
__PINFIX_PROMPT__: JSON.stringify(options.prompt ?? ""),
|
|
434
|
+
__PINFIX_HOTKEY__: JSON.stringify(options.hotkey ?? "alt+shift+z"),
|
|
435
|
+
__PINFIX_FAB__: JSON.stringify(options.fab !== false)
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
},
|
|
439
|
+
transformIndexHtml(html) {
|
|
440
|
+
const injected = getInjectionScript({ wsUrl, prompt: options.prompt ?? "", hotkey: options.hotkey, fab: options.fab, onError: logError });
|
|
441
|
+
if (injected) {
|
|
442
|
+
return html.replace("<head>", `<head>
|
|
443
|
+
${injected}`);
|
|
444
|
+
}
|
|
445
|
+
const script = `<script type="module" src="/@pinfix/overlay.js"></script>`;
|
|
446
|
+
return html.replace("</body>", `${script}
|
|
447
|
+
</body>`);
|
|
448
|
+
},
|
|
449
|
+
configureServer(server) {
|
|
450
|
+
startChannelServer({
|
|
451
|
+
port,
|
|
452
|
+
cwd: root,
|
|
453
|
+
watch: true,
|
|
454
|
+
onLog: debug ? (msg) => server.config.logger.info(`[pinfix] ${msg}`) : void 0,
|
|
455
|
+
onError: debug ? (msg) => server.config.logger.warn(`[pinfix] ${msg}`) : void 0
|
|
456
|
+
});
|
|
457
|
+
server.httpServer?.on("close", stopChannelServer);
|
|
458
|
+
server.middlewares.use((req, res, next) => {
|
|
459
|
+
if (req.url === "/@pinfix/overlay.js") {
|
|
460
|
+
const clientDir = resolve3(dirname3(fileURLToPath3(import.meta.url)), "../client");
|
|
461
|
+
res.setHeader("Content-Type", "application/javascript");
|
|
462
|
+
res.end(`import "${clientDir}/overlay.ts";`);
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
next();
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
// === Webpack/Rspack-specific hooks ===
|
|
470
|
+
webpack(compiler) {
|
|
471
|
+
setupWebpackLikeCompiler(compiler);
|
|
472
|
+
},
|
|
473
|
+
rspack(compiler) {
|
|
474
|
+
setupWebpackLikeCompiler(compiler);
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
});
|
|
478
|
+
var src_default = unplugin;
|
|
479
|
+
|
|
480
|
+
export {
|
|
481
|
+
unplugin,
|
|
482
|
+
src_default
|
|
483
|
+
};
|