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