@zntc/web 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/LICENSE +21 -0
- package/README.md +48 -0
- package/dist/dev-controller.d.ts +80 -0
- package/dist/html-env.d.ts +27 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +1124 -0
- package/dist/inject.d.ts +17 -0
- package/dist/style/css-modules.d.ts +52 -0
- package/dist/style/css-parser.d.ts +15 -0
- package/dist/style/loader.d.ts +28 -0
- package/dist/style/postcss.d.ts +68 -0
- package/dist/style/sass.d.ts +52 -0
- package/dist/url.d.ts +2 -0
- package/package.json +62 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1124 @@
|
|
|
1
|
+
import { Buffer as Buffer$1 } from "node:buffer";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
var createHash$1 = createHash;
|
|
4
|
+
import { watch as fsWatch, readdirSync, existsSync, mkdirSync, readFileSync, writeFileSync, cpSync, mkdtempSync, rmSync, symlinkSync } from "node:fs";
|
|
5
|
+
var readFileSync$1 = readFileSync;
|
|
6
|
+
var writeFileSync$1 = writeFileSync;
|
|
7
|
+
var readFileSync$2 = readFileSync;
|
|
8
|
+
var writeFileSync$2 = writeFileSync;
|
|
9
|
+
var readFileSync$3 = readFileSync;
|
|
10
|
+
var writeFileSync$3 = writeFileSync;
|
|
11
|
+
var readFileSync$4 = readFileSync;
|
|
12
|
+
var writeFileSync$4 = writeFileSync;
|
|
13
|
+
var existsSync$1 = existsSync;
|
|
14
|
+
var mkdirSync$1 = mkdirSync;
|
|
15
|
+
var writeFileSync$5 = writeFileSync;
|
|
16
|
+
import { resolve as resolvePath, join, basename, dirname, relative, sep, extname } from "node:path";
|
|
17
|
+
var resolve = resolvePath;
|
|
18
|
+
var join$1 = join;
|
|
19
|
+
var resolve$1 = resolvePath;
|
|
20
|
+
var basename$1 = basename;
|
|
21
|
+
var join$2 = join;
|
|
22
|
+
var join$3 = join;
|
|
23
|
+
var basename$2 = basename;
|
|
24
|
+
var dirname$1 = dirname;
|
|
25
|
+
var basename$3 = basename;
|
|
26
|
+
var relative$1 = relative;
|
|
27
|
+
var sep$1 = sep;
|
|
28
|
+
var dirname$2 = dirname;
|
|
29
|
+
var join$4 = join;
|
|
30
|
+
var relative$2 = relative;
|
|
31
|
+
var resolve$2 = resolvePath;
|
|
32
|
+
var sep$2 = sep;
|
|
33
|
+
import { createRequire } from "node:module";
|
|
34
|
+
import { tmpdir } from "node:os";
|
|
35
|
+
import { loadEnv, prepareAppDevSync } from "@zntc/core";
|
|
36
|
+
//#region protocol.ts
|
|
37
|
+
const HMR_MSG = Object.freeze({ Connected: "connected", CssUpdate: "css-update", ClearError: "clear-error", Error: "error", FullReload: "full-reload" }),APP_DEV_HMR_CLIENT_PATH = "/__zntc_app_dev_hmr__",APP_DEV_HMR_WS_PATH = "/__hmr",HMR_WS_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
|
38
|
+
function normalizeHmrErrors(errors) {
|
|
39
|
+
if (!Array.isArray(errors) || errors.length === 0) {
|
|
40
|
+
return [{ file: "", message: "Unknown build error" }];
|
|
41
|
+
}
|
|
42
|
+
return errors.map((error) => {
|
|
43
|
+
const e = (error ?? {}),file = typeof e.location?.file == "string" ? e.location.file : "",message = String(e.text ?? e.message ?? error);
|
|
44
|
+
return { file, message };
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
const HMR_RN_MSG = Object.freeze({ UpdateStart: "hmr:update-start", Update: "hmr:update", UpdateDone: "hmr:update-done", Reload: "hmr:reload", Error: "hmr:error", Log: "log" });
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region ws-frame.ts
|
|
50
|
+
const TEXT_FRAME_FIN_OPCODE = 0x81,PAYLOAD_LEN_SHORT_MAX = 125,PAYLOAD_LEN_EXTENDED_16 = 126,PAYLOAD_LEN_EXTENDED_64 = 127,PAYLOAD_LEN_16BIT_MAX = 65535;
|
|
51
|
+
function buildTextFrame(text) {
|
|
52
|
+
const payload = Buffer$1.from(text);
|
|
53
|
+
return Buffer$1.concat([buildTextHeader(payload.length), payload]);
|
|
54
|
+
}
|
|
55
|
+
function buildTextHeader(payloadLength) {
|
|
56
|
+
if (payloadLength <= PAYLOAD_LEN_SHORT_MAX) {
|
|
57
|
+
return Buffer$1.from([TEXT_FRAME_FIN_OPCODE, payloadLength]);
|
|
58
|
+
}
|
|
59
|
+
if (payloadLength <= PAYLOAD_LEN_16BIT_MAX) {
|
|
60
|
+
const header = Buffer$1.allocUnsafe(4);
|
|
61
|
+
header[0] = TEXT_FRAME_FIN_OPCODE;
|
|
62
|
+
header[1] = PAYLOAD_LEN_EXTENDED_16;
|
|
63
|
+
header.writeUInt16BE(payloadLength, 2);
|
|
64
|
+
return header;
|
|
65
|
+
}
|
|
66
|
+
const header = Buffer$1.allocUnsafe(10);
|
|
67
|
+
header[0] = TEXT_FRAME_FIN_OPCODE;
|
|
68
|
+
header[1] = PAYLOAD_LEN_EXTENDED_64;
|
|
69
|
+
header.writeBigUInt64BE(BigInt(payloadLength), 2);
|
|
70
|
+
return header;
|
|
71
|
+
}
|
|
72
|
+
function writeTextFrame(socket,text) {
|
|
73
|
+
if (socket.destroyed)return;
|
|
74
|
+
socket.write(buildTextFrame(text));
|
|
75
|
+
}
|
|
76
|
+
function computeAcceptKey(secWebSocketKey) {
|
|
77
|
+
return createHash("sha1").update(`${secWebSocketKey}${HMR_WS_GUID}`).digest("base64");
|
|
78
|
+
}
|
|
79
|
+
function buildHandshakeResponse(secWebSocketKey) {
|
|
80
|
+
return ["HTTP/1.1 101 Switching Protocols", "Upgrade: websocket", "Connection: Upgrade", `Sec-WebSocket-Accept: ${computeAcceptKey(secWebSocketKey)}`, "", ""].join("\r\n");
|
|
81
|
+
}
|
|
82
|
+
function parseTextFrame(buffer) {
|
|
83
|
+
if (buffer.length < 2)return null;
|
|
84
|
+
const byte0 = buffer[0],byte1 = buffer[1];
|
|
85
|
+
;
|
|
86
|
+
;
|
|
87
|
+
;
|
|
88
|
+
if (!((byte0 & 0x80) !== 0) || (byte0 & 0x0f) !== 0x1 || !((byte1 & 0x80) !== 0))return null;
|
|
89
|
+
let payloadLen = byte1 & 0x7f,offset = 2;
|
|
90
|
+
if (payloadLen === PAYLOAD_LEN_EXTENDED_16) {
|
|
91
|
+
if (buffer.length < 4)return null;
|
|
92
|
+
payloadLen = buffer.readUInt16BE(2);
|
|
93
|
+
offset = 4;
|
|
94
|
+
} else if (payloadLen === PAYLOAD_LEN_EXTENDED_64) {
|
|
95
|
+
if (buffer.length < 10)return null;
|
|
96
|
+
const big = buffer.readBigUInt64BE(2);
|
|
97
|
+
if (big > BigInt(Number.MAX_SAFE_INTEGER))return null;
|
|
98
|
+
payloadLen = Number(big);
|
|
99
|
+
offset = 10;
|
|
100
|
+
}
|
|
101
|
+
if (buffer.length < offset + 4 + payloadLen)return null;
|
|
102
|
+
const maskKey = buffer.subarray(offset, offset + 4),payload = Buffer$1.allocUnsafe(payloadLen);
|
|
103
|
+
for (let i = 0; i < payloadLen; i++) {
|
|
104
|
+
payload[i] = buffer[offset + 4 + i] ^ maskKey[i % 4];
|
|
105
|
+
}
|
|
106
|
+
return { text: payload.toString("utf-8"), consumed: offset + 4 + payloadLen };
|
|
107
|
+
}
|
|
108
|
+
//#endregion
|
|
109
|
+
//#region watcher.ts
|
|
110
|
+
const DEFAULT_DEBOUNCE_MS = 30;
|
|
111
|
+
function createWatcher(options) {
|
|
112
|
+
const debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS,recursive = options.recursive ?? true,watch = options.watch ?? fsWatch,watchers = [],dirty = new Set();
|
|
113
|
+
let timer = null,closed = false;
|
|
114
|
+
function flush() {
|
|
115
|
+
timer = null;
|
|
116
|
+
if (closed || dirty.size === 0)return;
|
|
117
|
+
const snapshot = new Set(dirty);
|
|
118
|
+
dirty.clear();
|
|
119
|
+
options.onDirty(snapshot);
|
|
120
|
+
}
|
|
121
|
+
function scheduleFlush() {
|
|
122
|
+
if (timer || closed)return;
|
|
123
|
+
timer = setTimeout(flush, debounceMs);
|
|
124
|
+
}
|
|
125
|
+
function safeClose(watcher) {
|
|
126
|
+
try {
|
|
127
|
+
watcher.close();
|
|
128
|
+
} catch {
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
for (const path of options.paths) {
|
|
132
|
+
const abs = resolvePath(path);
|
|
133
|
+
try {
|
|
134
|
+
const watcher = watch(abs, { recursive }, (_eventType, filename) => {
|
|
135
|
+
if (closed)return;
|
|
136
|
+
if (typeof filename == "string" && filename.length > 0) {
|
|
137
|
+
dirty.add(resolvePath(abs, filename));
|
|
138
|
+
} else {
|
|
139
|
+
dirty.add(abs);
|
|
140
|
+
}
|
|
141
|
+
scheduleFlush();
|
|
142
|
+
});
|
|
143
|
+
watcher.on("error", (err) => {
|
|
144
|
+
if (closed)return;
|
|
145
|
+
options.onError?.(err, abs);
|
|
146
|
+
safeClose(watcher);
|
|
147
|
+
});
|
|
148
|
+
watchers.push(watcher);
|
|
149
|
+
} catch (err) {
|
|
150
|
+
options.onError?.(err, abs);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return { close() {
|
|
154
|
+
if (closed)return;
|
|
155
|
+
closed = true;
|
|
156
|
+
if (timer) {
|
|
157
|
+
clearTimeout(timer);
|
|
158
|
+
timer = null;
|
|
159
|
+
}
|
|
160
|
+
for (const watcher of watchers)safeClose(watcher);
|
|
161
|
+
}, get dirtyPaths() {
|
|
162
|
+
return dirty;
|
|
163
|
+
} };
|
|
164
|
+
}
|
|
165
|
+
//#endregion
|
|
166
|
+
//#region hmr-channel.ts
|
|
167
|
+
function extractErrorText(error) {
|
|
168
|
+
const e = (error ?? {});
|
|
169
|
+
return ((typeof e.stack == "string" && e.stack) || (typeof e.message == "string" && e.message) || String(error));
|
|
170
|
+
}
|
|
171
|
+
function createHmrChannel() {
|
|
172
|
+
const nodeSockets = new Set(),bunClients = new Set(),incomingHandlers = [],connectedText = JSON.stringify({ type: HMR_MSG.Connected });
|
|
173
|
+
let currentError = null,currentErrorText = null;
|
|
174
|
+
function broadcastText(text) {
|
|
175
|
+
for (const socket of nodeSockets)writeTextFrame(socket, text);
|
|
176
|
+
for (const ws of bunClients)ws.send(text);
|
|
177
|
+
}
|
|
178
|
+
function greetNode(socket) {
|
|
179
|
+
writeTextFrame(socket, connectedText);
|
|
180
|
+
if (currentErrorText)writeTextFrame(socket, currentErrorText);
|
|
181
|
+
}
|
|
182
|
+
function greetBun(ws) {
|
|
183
|
+
ws.send(connectedText);
|
|
184
|
+
if (currentErrorText)ws.send(currentErrorText);
|
|
185
|
+
}
|
|
186
|
+
return { accept(req,socket) {
|
|
187
|
+
const key = req.headers["sec-websocket-key"];
|
|
188
|
+
if (typeof key != "string") {
|
|
189
|
+
socket.destroy();
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
socket.write(buildHandshakeResponse(key));
|
|
193
|
+
nodeSockets.add(socket);
|
|
194
|
+
let recvBuffer = Buffer.alloc(0);
|
|
195
|
+
socket.on("data", (chunk) => {
|
|
196
|
+
if (incomingHandlers.length === 0)return;
|
|
197
|
+
recvBuffer = (recvBuffer.length === 0 ? chunk : Buffer.concat([recvBuffer, chunk]));
|
|
198
|
+
while (recvBuffer.length > 0) {
|
|
199
|
+
const parsed = parseTextFrame(recvBuffer);
|
|
200
|
+
if (!parsed)break;
|
|
201
|
+
recvBuffer = recvBuffer.subarray(parsed.consumed);
|
|
202
|
+
for (const handler of incomingHandlers) {
|
|
203
|
+
try {
|
|
204
|
+
handler(parsed.text, socket);
|
|
205
|
+
} catch {
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
socket.on("close", () => nodeSockets.delete(socket));
|
|
211
|
+
socket.on("error", () => nodeSockets.delete(socket));
|
|
212
|
+
greetNode(socket);
|
|
213
|
+
}, addBunClient(ws) {
|
|
214
|
+
bunClients.add(ws);
|
|
215
|
+
greetBun(ws);
|
|
216
|
+
}, removeBunClient(ws) {
|
|
217
|
+
bunClients.delete(ws);
|
|
218
|
+
}, onIncoming(handler) {
|
|
219
|
+
incomingHandlers.push(handler);
|
|
220
|
+
}, broadcast(message) {
|
|
221
|
+
broadcastText(JSON.stringify(message));
|
|
222
|
+
}, reportError(errors) {
|
|
223
|
+
currentError = { type: HMR_MSG.Error, errors: normalizeHmrErrors(errors), timestamp: Date.now() };
|
|
224
|
+
currentErrorText = JSON.stringify(currentError);
|
|
225
|
+
broadcastText(currentErrorText);
|
|
226
|
+
}, reportThrownError(error) {
|
|
227
|
+
this.reportError([{ text: extractErrorText(error) }]);
|
|
228
|
+
}, clearError() {
|
|
229
|
+
currentError = null;
|
|
230
|
+
currentErrorText = null;
|
|
231
|
+
}, get clientCount() {
|
|
232
|
+
return nodeSockets.size + bunClients.size;
|
|
233
|
+
} };
|
|
234
|
+
}
|
|
235
|
+
//#endregion
|
|
236
|
+
//#region url.ts
|
|
237
|
+
function joinUrl(base,rel) {
|
|
238
|
+
if (!base)return rel;
|
|
239
|
+
return `${base}${rel}`;
|
|
240
|
+
}
|
|
241
|
+
//#endregion
|
|
242
|
+
//#region loader.ts
|
|
243
|
+
function requireFromAppRoot(root,fallbackRequire,specifier) {
|
|
244
|
+
const requireFromRoot = createRequire(join(root, "package.json"));
|
|
245
|
+
return requireFromAppOrFallback(requireFromRoot, fallbackRequire, specifier);
|
|
246
|
+
}
|
|
247
|
+
function requireFromAppOrFallback(requireFromApp,fallbackRequire,specifier) {
|
|
248
|
+
try {
|
|
249
|
+
return requireFromApp(specifier);
|
|
250
|
+
} catch (err) {
|
|
251
|
+
const code = err?.code;
|
|
252
|
+
if (code !== "MODULE_NOT_FOUND" && code !== "ERR_MODULE_NOT_FOUND")throw err;
|
|
253
|
+
return fallbackRequire(specifier);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
const RETURN_TRUE = () => true;
|
|
257
|
+
function readEntriesOrEmpty(dir) {
|
|
258
|
+
try {
|
|
259
|
+
return readdirSync(dir, { withFileTypes: true });
|
|
260
|
+
} catch (err) {
|
|
261
|
+
if (err.code === "ENOENT")return [];
|
|
262
|
+
throw err;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
function walkFiles(dir,skipResolved,predicate,out) {
|
|
266
|
+
for (const entry of readEntriesOrEmpty(dir)) {
|
|
267
|
+
if (entry.name === "node_modules" || entry.name === ".git")continue;
|
|
268
|
+
const path = join(dir, entry.name);
|
|
269
|
+
if (entry.isDirectory()) {
|
|
270
|
+
if (skipResolved && resolve(path) === skipResolved)continue;
|
|
271
|
+
walkFiles(path, skipResolved, predicate, out);
|
|
272
|
+
} else if (entry.isFile() && predicate(path)) {
|
|
273
|
+
out.push(path);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
function collectAppFiles(dir,options={}) {
|
|
278
|
+
const skipResolved = options.skipDir ? resolve(options.skipDir) : null,predicate = options.predicate ?? RETURN_TRUE,files = [];
|
|
279
|
+
walkFiles(dir, skipResolved, predicate, files);
|
|
280
|
+
return files;
|
|
281
|
+
}
|
|
282
|
+
//#endregion
|
|
283
|
+
//#region postcss.ts
|
|
284
|
+
const POSTCSS_CONFIG_NAMES = ["postcss.config.mjs", "postcss.config.js", "postcss.config.cjs", "postcss.config.json", ".postcssrc", ".postcssrc.json", ".postcssrc.js", ".postcssrc.cjs", ".postcssrc.mjs"],isCssFile = (path) => path.endsWith(".css");
|
|
285
|
+
function isPostcssConfigFile(path) {
|
|
286
|
+
return POSTCSS_CONFIG_NAMES.includes(basename(path));
|
|
287
|
+
}
|
|
288
|
+
function findPostcssConfig(root) {
|
|
289
|
+
for (const name of POSTCSS_CONFIG_NAMES) {
|
|
290
|
+
const path = join$1(root, name);
|
|
291
|
+
if (existsSync(path))return path;
|
|
292
|
+
}
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
295
|
+
function collectPostcssMessages(messages,deps,dirDeps) {
|
|
296
|
+
if (!messages)return;
|
|
297
|
+
for (const message of messages) {
|
|
298
|
+
if (message.type === "dependency" && typeof message.file == "string") {
|
|
299
|
+
deps.add(resolve$1(message.file));
|
|
300
|
+
}
|
|
301
|
+
if (message.type === "dir-dependency") {
|
|
302
|
+
const dir = (typeof message.dir == "string" && message.dir) || (typeof message.directory == "string" && message.directory);
|
|
303
|
+
if (dir)dirDeps.add(resolve$1(dir));
|
|
304
|
+
}
|
|
305
|
+
if (message.type === "context-dependency" && typeof message.file == "string") {
|
|
306
|
+
deps.add(resolve$1(message.file));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
function logPostcssProcessed(logLevel,count,configFile) {
|
|
311
|
+
if (logLevel === "silent")return;
|
|
312
|
+
console.error(`[postcss] processed ${count} CSS file(s) using ${basename(configFile ?? "postcss config")}`);
|
|
313
|
+
}
|
|
314
|
+
async function loadPostcssConfig(root,configEnv,fallbackRequire) {
|
|
315
|
+
const postcssrc = requireFromAppRoot(root, fallbackRequire, "postcss-load-config"),postcssModule = requireFromAppRoot(root, fallbackRequire, "postcss"),postcss = (postcssModule.default ?? postcssModule),config = await postcssrc({ cwd: root, env: configEnv.mode }, root).catch((err) => {
|
|
316
|
+
if (err?.message?.includes("No PostCSS Config found"))return null;
|
|
317
|
+
throw err;
|
|
318
|
+
});
|
|
319
|
+
if (!config)return null;
|
|
320
|
+
const plugins = config.plugins ?? [];
|
|
321
|
+
if (plugins.length === 0)return null;
|
|
322
|
+
return { postcss, plugins, options: config.options ?? {}, configFile: config.file ?? null };
|
|
323
|
+
}
|
|
324
|
+
async function runPostcssIfConfigured(root,cssDir,skipDir,configEnv,logLevel,fallbackRequire) {
|
|
325
|
+
const loaded = await loadPostcssConfig(root, configEnv, fallbackRequire);
|
|
326
|
+
if (!loaded)return;
|
|
327
|
+
const cssFiles = collectAppFiles(cssDir, { skipDir, predicate: isCssFile });
|
|
328
|
+
await Promise.all(cssFiles.map(async (file) => {
|
|
329
|
+
const input = readFileSync(file, "utf8"),result = await loaded.postcss(loaded.plugins).process(input, { ...loaded.options, from: file, to: file });
|
|
330
|
+
writeFileSync(file, result.css);
|
|
331
|
+
if (result.map)writeFileSync(`${file}.map`, result.map.toString());
|
|
332
|
+
}));
|
|
333
|
+
logPostcssProcessed(logLevel, cssFiles.length, loaded.configFile);
|
|
334
|
+
}
|
|
335
|
+
async function runPostcssForAppDev(options) {
|
|
336
|
+
const { root:root, outdir:outdir, configEnv:configEnv, logLevel:logLevel, base:base, changedPath:changedPath=null, fallbackRequire:fallbackRequire } = options,deps = new Set(),dirDeps = new Set();
|
|
337
|
+
let primaryHref = null;
|
|
338
|
+
const configPath = findPostcssConfig(root);
|
|
339
|
+
if (!configPath) {
|
|
340
|
+
const first = collectAppFiles(root, { skipDir: outdir, predicate: isCssFile })[0];
|
|
341
|
+
if (first)primaryHref = joinUrl(base, relative(root, first));
|
|
342
|
+
return { deps, dirDeps, primaryHref, processed: 0 };
|
|
343
|
+
}
|
|
344
|
+
const loaded = await loadPostcssConfig(root, configEnv, fallbackRequire);
|
|
345
|
+
if (!loaded)return { deps, dirDeps, primaryHref, processed: 0 };
|
|
346
|
+
deps.add(resolve$1(loaded.configFile ?? configPath));
|
|
347
|
+
mkdirSync(outdir, { recursive: true });
|
|
348
|
+
const allCssFiles = collectAppFiles(root, { skipDir: outdir, predicate: isCssFile }),targets = changedPath && changedPath.endsWith(".css") && allCssFiles.includes(changedPath) ? [changedPath] : allCssFiles;
|
|
349
|
+
await Promise.all(targets.map(async (file) => {
|
|
350
|
+
const outputRel = relative(root, file),outputPath = join$1(outdir, outputRel);
|
|
351
|
+
mkdirSync(dirname(outputPath), { recursive: true });
|
|
352
|
+
const input = readFileSync(file, "utf8"),result = await loaded.postcss(loaded.plugins).process(input, { ...loaded.options, from: file, to: outputPath });
|
|
353
|
+
writeFileSync(outputPath, result.css);
|
|
354
|
+
if (result.map)writeFileSync(`${outputPath}.map`, result.map.toString());
|
|
355
|
+
deps.add(resolve$1(file));
|
|
356
|
+
collectPostcssMessages(result.messages, deps, dirDeps);
|
|
357
|
+
}));
|
|
358
|
+
if (allCssFiles.length > 0)primaryHref = joinUrl(base, relative(root, allCssFiles[0]));
|
|
359
|
+
logPostcssProcessed(logLevel, targets.length, loaded.configFile);
|
|
360
|
+
return { deps, dirDeps, primaryHref, processed: targets.length };
|
|
361
|
+
}
|
|
362
|
+
//#endregion
|
|
363
|
+
//#region inject.ts
|
|
364
|
+
function injectIntoDevHtml(outdir,build) {
|
|
365
|
+
const htmlPath = join$2(outdir, "index.html");
|
|
366
|
+
let html;
|
|
367
|
+
try {
|
|
368
|
+
html = readFileSync$1(htmlPath, "utf8");
|
|
369
|
+
} catch (err) {
|
|
370
|
+
if (err?.code === "ENOENT")return;
|
|
371
|
+
throw err;
|
|
372
|
+
}
|
|
373
|
+
const tag = build(html);
|
|
374
|
+
if (!tag)return;
|
|
375
|
+
const next = html.includes("</head>") ? html.replace("</head>", `${tag}\n</head>`) : html.replace("<script", `${tag}\n<script`);
|
|
376
|
+
writeFileSync$1(htmlPath, next);
|
|
377
|
+
}
|
|
378
|
+
function injectAppDevHmrClient(outdir) {
|
|
379
|
+
injectIntoDevHtml(outdir, (html) => {
|
|
380
|
+
if (html.includes(APP_DEV_HMR_CLIENT_PATH))return null;
|
|
381
|
+
return `<script type="module" src="${APP_DEV_HMR_CLIENT_PATH}"></script>`;
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
function injectAppDevBundleCssLinks(outdir,base,bundleResult) {
|
|
385
|
+
injectIntoDevHtml(outdir, (html) => {
|
|
386
|
+
const cssHrefs = [];
|
|
387
|
+
for (const file of bundleResult?.outputFiles ?? []) {
|
|
388
|
+
if (!file?.path || !isCssFile(file.path))continue;
|
|
389
|
+
const href = joinUrl(base, basename$1(file.path));
|
|
390
|
+
if (!html.includes(`href="${href}"`) && !html.includes(`href='${href}'`))cssHrefs.push(href);
|
|
391
|
+
}
|
|
392
|
+
if (cssHrefs.length === 0)return null;
|
|
393
|
+
return cssHrefs.map((href) => `<link rel="stylesheet" href="${href}">`).join("\n");
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
function injectAppDevPipelineCssLinks(outdir,base,cssRelPaths) {
|
|
397
|
+
if (cssRelPaths.length === 0)return;
|
|
398
|
+
injectIntoDevHtml(outdir, (html) => {
|
|
399
|
+
const tags = [];
|
|
400
|
+
for (const rel of cssRelPaths) {
|
|
401
|
+
const href = joinUrl(base, rel.replaceAll(sep, "/"));
|
|
402
|
+
if (html.includes(`href="${href}"`) || html.includes(`href='${href}'`))continue;
|
|
403
|
+
tags.push(`<link rel="stylesheet" href="${href}">`);
|
|
404
|
+
}
|
|
405
|
+
return tags.length === 0 ? null : tags.join("\n");
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
//#endregion
|
|
409
|
+
//#region html-env.ts
|
|
410
|
+
const DEFAULT_HTML_ENV_PREFIX = "ZNTC_";
|
|
411
|
+
const TOKEN_RE = /<%=\s*([A-Za-z_][A-Za-z0-9_]*)\s*%>/g,HTML_ESCAPE = { "&": "&", "<": "<", ">": ">", "\"": """ };
|
|
412
|
+
function escapeHtml(value) {
|
|
413
|
+
return value.replace(/[&<>"]/g, (c) => HTML_ESCAPE[c]);
|
|
414
|
+
}
|
|
415
|
+
function transformHtmlEnvTokens(html,env,prefix=DEFAULT_HTML_ENV_PREFIX) {
|
|
416
|
+
const warnings = [],next = html.replace(TOKEN_RE, (match, key) => {
|
|
417
|
+
if (!key.startsWith(prefix)) {
|
|
418
|
+
warnings.push(`token "${match}" uses key "${key}" without allowed prefix "${prefix}" — kept as-is`);
|
|
419
|
+
return match;
|
|
420
|
+
}
|
|
421
|
+
const value = env[key];
|
|
422
|
+
if (value === undefined) {
|
|
423
|
+
warnings.push(`"${key}" not found in environment — replaced with empty string`);
|
|
424
|
+
return "";
|
|
425
|
+
}
|
|
426
|
+
return escapeHtml(value);
|
|
427
|
+
});
|
|
428
|
+
return { html: next, changed: next !== html, warnings };
|
|
429
|
+
}
|
|
430
|
+
function applyHtmlEnvTokens(outdir,env,prefix=DEFAULT_HTML_ENV_PREFIX) {
|
|
431
|
+
const htmlPath = join$3(outdir, "index.html");
|
|
432
|
+
let html;
|
|
433
|
+
try {
|
|
434
|
+
html = readFileSync$2(htmlPath, "utf8");
|
|
435
|
+
} catch (err) {
|
|
436
|
+
if (err?.code === "ENOENT")return { warnings: [] };
|
|
437
|
+
throw err;
|
|
438
|
+
}
|
|
439
|
+
const result = transformHtmlEnvTokens(html, env, prefix);
|
|
440
|
+
if (result.changed)writeFileSync$2(htmlPath, result.html);
|
|
441
|
+
return { warnings: result.warnings };
|
|
442
|
+
}
|
|
443
|
+
//#endregion
|
|
444
|
+
//#region css-parser.ts
|
|
445
|
+
function skipCssString(css,start,quote) {
|
|
446
|
+
let i = start + 1;
|
|
447
|
+
while (i < css.length) {
|
|
448
|
+
if (css[i] === "\\" && i + 1 < css.length) {
|
|
449
|
+
i += 2;
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
if (css[i] === quote)return i + 1;
|
|
453
|
+
i += 1;
|
|
454
|
+
}
|
|
455
|
+
return css.length;
|
|
456
|
+
}
|
|
457
|
+
function skipCssUrl(css,start) {
|
|
458
|
+
let i = start;
|
|
459
|
+
while (i < css.length) {
|
|
460
|
+
if ((css[i] === "\"" || css[i] === "'") && css[i - 1] !== "\\") {
|
|
461
|
+
i = skipCssString(css, i, css[i]);
|
|
462
|
+
continue;
|
|
463
|
+
}
|
|
464
|
+
if (css[i] === ")")return i + 1;
|
|
465
|
+
i += 1;
|
|
466
|
+
}
|
|
467
|
+
return css.length;
|
|
468
|
+
}
|
|
469
|
+
function startsWithCssIdent(css,offset,value) {
|
|
470
|
+
return css.slice(offset, offset + value.length).toLowerCase() === value;
|
|
471
|
+
}
|
|
472
|
+
function isCssIdentStart(ch) {
|
|
473
|
+
return ch === "_" || (ch >= "A" && ch <= "Z") || (ch >= "a" && ch <= "z");
|
|
474
|
+
}
|
|
475
|
+
function isCssIdent(ch) {
|
|
476
|
+
return isCssIdentStart(ch) || ch === "-" || (ch >= "0" && ch <= "9");
|
|
477
|
+
}
|
|
478
|
+
//#endregion
|
|
479
|
+
//#region sass.ts
|
|
480
|
+
const CSS_PREPROCESSOR_EXTENSIONS = new Set([".scss", ".sass"]);
|
|
481
|
+
const MODULE_PREPROCESSOR_RE = /\.module\.(?:scss|sass)$/;
|
|
482
|
+
function isCssPreprocessorFile(path) {
|
|
483
|
+
return CSS_PREPROCESSOR_EXTENSIONS.has(extname(path));
|
|
484
|
+
}
|
|
485
|
+
function isCssModulePreprocessorFile(path) {
|
|
486
|
+
return MODULE_PREPROCESSOR_RE.test(path);
|
|
487
|
+
}
|
|
488
|
+
function cssPreprocessorOutputPath(file) {
|
|
489
|
+
return file.replace(/\.(?:scss|sass)$/, ".css");
|
|
490
|
+
}
|
|
491
|
+
function cssPreprocessorProxyPath(file) {
|
|
492
|
+
return `${cssPreprocessorOutputPath(file)}.js`;
|
|
493
|
+
}
|
|
494
|
+
function loadSassCompiler(root,fallbackRequire) {
|
|
495
|
+
return requireFromAppRoot(root, fallbackRequire, "sass");
|
|
496
|
+
}
|
|
497
|
+
function compileSassFile(sass,file,loadRoot) {
|
|
498
|
+
return sass.compile(file, { style: "expanded", loadPaths: [dirname$1(file), loadRoot], sourceMap: false });
|
|
499
|
+
}
|
|
500
|
+
const STYLE_REFERENCE_RE = /\.(?:html|mjs|cjs|js|jsx|ts|tsx)$/;
|
|
501
|
+
function isStyleReferenceSource(path) {
|
|
502
|
+
return STYLE_REFERENCE_RE.test(path);
|
|
503
|
+
}
|
|
504
|
+
function rewriteSassReferences(sourceFiles) {
|
|
505
|
+
;
|
|
506
|
+
for (const source of sourceFiles) {
|
|
507
|
+
const input = readFileSync$3(source, "utf8");
|
|
508
|
+
if (!input.includes(".scss") && !input.includes(".sass"))continue;
|
|
509
|
+
const toExt = /\.html?$/i.test(source) ? ".css" : ".css.js",output = input.replace(/(["'])([^"']+\.(?:scss|sass))([?#][^"']*)?\1/g, (_match, quote, spec, suffix = "") => `${quote}${spec.replace(/\.(?:scss|sass)$/, toExt)}${suffix}${quote}`);
|
|
510
|
+
if (output !== input)writeFileSync$3(source, output);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
function buildCssPreprocessorProxy(cssPath) {
|
|
514
|
+
const cssImport = `./${basename$2(cssPath)}`;
|
|
515
|
+
return `import ${JSON.stringify(cssImport)};\n`;
|
|
516
|
+
}
|
|
517
|
+
function transformCssPreprocessors(root,files,sourceFiles,logLevel,fallbackRequire,options={}) {
|
|
518
|
+
if (files.length === 0)return [];
|
|
519
|
+
const { dirtyOnly:dirtyOnly=null, dirtySources:dirtySources=null } = options,targets = dirtyOnly ? files.filter((f) => dirtyOnly.has(f)) : files;
|
|
520
|
+
if (targets.length === 0)return files.map(cssPreprocessorOutputPath);
|
|
521
|
+
let sass;
|
|
522
|
+
try {
|
|
523
|
+
sass = loadSassCompiler(root, fallbackRequire);
|
|
524
|
+
} catch (err) {
|
|
525
|
+
const code = err?.code,message = code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND" ? "Sass/SCSS support requires the optional `sass` package. Install it with `bun add -d sass` or `npm install -D sass`." : `Failed to load sass: ${err?.message ?? err}`;
|
|
526
|
+
throw new Error(message);
|
|
527
|
+
}
|
|
528
|
+
for (const file of targets) {
|
|
529
|
+
const result = compileSassFile(sass, file, root),cssPath = cssPreprocessorOutputPath(file);
|
|
530
|
+
writeFileSync$3(cssPath, result.css);
|
|
531
|
+
writeFileSync$3(cssPreprocessorProxyPath(file), buildCssPreprocessorProxy(cssPath));
|
|
532
|
+
}
|
|
533
|
+
rewriteSassReferences(dirtySources ?? sourceFiles);
|
|
534
|
+
if (logLevel !== "silent") {
|
|
535
|
+
console.error(`[sass] processed ${targets.length} Sass/SCSS file(s)`);
|
|
536
|
+
}
|
|
537
|
+
return files.map(cssPreprocessorOutputPath);
|
|
538
|
+
}
|
|
539
|
+
//#endregion
|
|
540
|
+
//#region css-modules.ts
|
|
541
|
+
function isCssModuleFile(path) {
|
|
542
|
+
return basename$3(path).endsWith(".module.css");
|
|
543
|
+
}
|
|
544
|
+
function cssModuleGeneratedCssPath(file) {
|
|
545
|
+
return file.replace(/\.module\.css$/, ".module.zntc.css");
|
|
546
|
+
}
|
|
547
|
+
function cssModuleProxyPath(file) {
|
|
548
|
+
return `${file}.js`;
|
|
549
|
+
}
|
|
550
|
+
const SAFE_LOCAL_RE = /[^a-zA-Z0-9_]/g;
|
|
551
|
+
function cssModuleLocalName(root,file,local) {
|
|
552
|
+
const rel = relative$1(root, file).replaceAll(sep$1, "/"),fileName = basename$3(file, ".module.css").replace(SAFE_LOCAL_RE, "_");
|
|
553
|
+
return cssModuleLocalNameWithCachedFile(rel, fileName, local);
|
|
554
|
+
}
|
|
555
|
+
function cssModuleLocalNameWithCachedFile(rel,fileName,local) {
|
|
556
|
+
const safeLocal = local.replace(SAFE_LOCAL_RE, "_"),hash = createHash$1("sha1").update(`${rel}:${local}`).digest("base64url").slice(0, 8);
|
|
557
|
+
return `${fileName}_${safeLocal}__${hash}`;
|
|
558
|
+
}
|
|
559
|
+
function scanCssModuleClassTokens(css) {
|
|
560
|
+
const tokens = [];
|
|
561
|
+
let i = 0;
|
|
562
|
+
while (i < css.length) {
|
|
563
|
+
const ch = css[i],next = css[i + 1] ?? "";
|
|
564
|
+
if ((ch === "\"" || ch === "'") && css[i - 1] !== "\\") {
|
|
565
|
+
i = skipCssString(css, i, ch);
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
if (ch === "/" && next === "*") {
|
|
569
|
+
const end = css.indexOf("*/", i + 2);
|
|
570
|
+
i = end === -1 ? css.length : end + 2;
|
|
571
|
+
continue;
|
|
572
|
+
}
|
|
573
|
+
if (startsWithCssIdent(css, i, "url(")) {
|
|
574
|
+
i = skipCssUrl(css, i + 4);
|
|
575
|
+
continue;
|
|
576
|
+
}
|
|
577
|
+
if (ch === "." && isCssIdentStart(next)) {
|
|
578
|
+
let end = i + 2;
|
|
579
|
+
while (end < css.length && isCssIdent(css[end]))end += 1;
|
|
580
|
+
tokens.push({ start: i, end, local: css.slice(i + 1, end) });
|
|
581
|
+
i = end;
|
|
582
|
+
continue;
|
|
583
|
+
}
|
|
584
|
+
i += 1;
|
|
585
|
+
}
|
|
586
|
+
return tokens;
|
|
587
|
+
}
|
|
588
|
+
function collectCssModuleClasses(css) {
|
|
589
|
+
return [...new Set(scanCssModuleClassTokens(css).map((token) => token.local))];
|
|
590
|
+
}
|
|
591
|
+
function rewriteCssModuleClasses(css,mapping) {
|
|
592
|
+
return rewriteCssModuleClassesWithTokens(css, scanCssModuleClassTokens(css), mapping);
|
|
593
|
+
}
|
|
594
|
+
const VALID_EXPORT_NAME_RE = /^[$A-Z_a-z][$\w]*$/,CSS_MODULE_RESERVED_EXPORTS = new Set(["arguments", "await", "break", "case", "catch", "class", "const", "continue", "debugger", "default", "delete", "do", "else", "enum", "export", "extends", "false", "finally", "for", "function", "if", "implements", "import", "in", "instanceof", "interface", "let", "new", "null", "package", "private", "protected", "public", "return", "static", "super", "switch", "this", "throw", "true", "try", "typeof", "var", "void", "while", "with", "yield"]);
|
|
595
|
+
function isValidExportName(name) {
|
|
596
|
+
return VALID_EXPORT_NAME_RE.test(name) && !CSS_MODULE_RESERVED_EXPORTS.has(name);
|
|
597
|
+
}
|
|
598
|
+
function buildCssModuleProxy(generatedCssPath,mapping) {
|
|
599
|
+
const cssImport = `./${basename$3(generatedCssPath)}`,stylesJson = JSON.stringify(mapping),named = Object.keys(mapping).filter(isValidExportName).map((name) => `export const ${name} = ${JSON.stringify(mapping[name])};`).join("\n");
|
|
600
|
+
return [`import ${JSON.stringify(cssImport)};`, `const styles = ${stylesJson};`, "export default styles;", named, ""].filter(Boolean).join("\n");
|
|
601
|
+
}
|
|
602
|
+
function rewriteCssModuleReferences(sourceFiles) {
|
|
603
|
+
;
|
|
604
|
+
for (const source of sourceFiles) {
|
|
605
|
+
if (/\.html?$/i.test(source))continue;
|
|
606
|
+
const input = readFileSync$4(source, "utf8");
|
|
607
|
+
if (!input.includes(".module.css"))continue;
|
|
608
|
+
const output = input.replace(/(["'])([^"']+\.module\.css)([?#][^"']*)?\1/g, (_match, quote, spec, suffix = "") => `${quote}${spec}.js${suffix}${quote}`);
|
|
609
|
+
if (output !== input)writeFileSync$4(source, output);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
function transformCssModules(root,moduleFiles,styleSources,logLevel,options={}) {
|
|
613
|
+
if (moduleFiles.length === 0)return [];
|
|
614
|
+
const { dirtyOnly:dirtyOnly=null, dirtySources:dirtySources=null } = options,targets = dirtyOnly ? moduleFiles.filter((f) => dirtyOnly.has(f)) : moduleFiles;
|
|
615
|
+
if (targets.length === 0)return moduleFiles.map(cssModuleGeneratedCssPath);
|
|
616
|
+
for (const file of targets) {
|
|
617
|
+
const css = readFileSync$4(file, "utf8"),tokens = scanCssModuleClassTokens(css),rel = relative$1(root, file).replaceAll(sep$1, "/"),fileName = basename$3(file, ".module.css").replace(SAFE_LOCAL_RE, "_"),mapping = {};
|
|
618
|
+
for (const token of tokens) {
|
|
619
|
+
if (!mapping[token.local]) {
|
|
620
|
+
mapping[token.local] = cssModuleLocalNameWithCachedFile(rel, fileName, token.local);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
const rewrittenCss = rewriteCssModuleClassesWithTokens(css, tokens, mapping),generatedCssPath = cssModuleGeneratedCssPath(file);
|
|
624
|
+
writeFileSync$4(generatedCssPath, rewrittenCss);
|
|
625
|
+
writeFileSync$4(cssModuleProxyPath(file), buildCssModuleProxy(generatedCssPath, mapping));
|
|
626
|
+
}
|
|
627
|
+
rewriteCssModuleReferences(dirtySources ?? styleSources);
|
|
628
|
+
if (logLevel !== "silent") {
|
|
629
|
+
console.error(`[css-modules] processed ${targets.length} CSS module file(s)`);
|
|
630
|
+
}
|
|
631
|
+
return moduleFiles.map(cssModuleGeneratedCssPath);
|
|
632
|
+
}
|
|
633
|
+
function rewriteCssModuleClassesWithTokens(css,tokens,mapping) {
|
|
634
|
+
let out = "",offset = 0;
|
|
635
|
+
for (const token of tokens) {
|
|
636
|
+
const scoped = mapping[token.local];
|
|
637
|
+
if (!scoped)continue;
|
|
638
|
+
out += css.slice(offset, token.start);
|
|
639
|
+
out += `.${scoped}`;
|
|
640
|
+
offset = token.end;
|
|
641
|
+
}
|
|
642
|
+
out += css.slice(offset);
|
|
643
|
+
return out;
|
|
644
|
+
}
|
|
645
|
+
//#endregion
|
|
646
|
+
//#region dev-controller.ts
|
|
647
|
+
const postcssTempRoots = new Set();
|
|
648
|
+
let postcssCleanupRegistered = false;
|
|
649
|
+
function normalizeBase(base) {
|
|
650
|
+
if (!base)return "/";
|
|
651
|
+
let normalized = base.startsWith("/") ? base : `/${base}`;
|
|
652
|
+
if (!normalized.endsWith("/"))normalized = `${normalized}/`;
|
|
653
|
+
return normalized;
|
|
654
|
+
}
|
|
655
|
+
function mirrorFile(srcAbs,dstAbs) {
|
|
656
|
+
mkdirSync$1(dirname$2(dstAbs), { recursive: true });
|
|
657
|
+
cpSync(srcAbs, dstAbs);
|
|
658
|
+
}
|
|
659
|
+
function mirrorPipelineCssToOutdir(pipelineRoot,outdir,absPaths) {
|
|
660
|
+
const rels = [];
|
|
661
|
+
for (const abs of absPaths) {
|
|
662
|
+
const rel = relative$2(pipelineRoot, abs);
|
|
663
|
+
mirrorFile(abs, join$4(outdir, rel));
|
|
664
|
+
rels.push(rel);
|
|
665
|
+
}
|
|
666
|
+
return rels;
|
|
667
|
+
}
|
|
668
|
+
function generatedPeerPaths(srcPath) {
|
|
669
|
+
if (isCssPreprocessorFile(srcPath)) {
|
|
670
|
+
return [cssPreprocessorOutputPath(srcPath), cssPreprocessorProxyPath(srcPath)];
|
|
671
|
+
}
|
|
672
|
+
if (isCssModuleFile(srcPath)) {
|
|
673
|
+
return [cssModuleGeneratedCssPath(srcPath), cssModuleProxyPath(srcPath)];
|
|
674
|
+
}
|
|
675
|
+
return [];
|
|
676
|
+
}
|
|
677
|
+
function syncDirtyFilesIntoTempRoot(root,tempRoot,dirtyPaths) {
|
|
678
|
+
for (const abs of dirtyPaths) {
|
|
679
|
+
const rel = relative$2(root, abs);
|
|
680
|
+
if (!rel || rel.startsWith(".."))continue;
|
|
681
|
+
const dst = join$4(tempRoot, rel);
|
|
682
|
+
if (existsSync$1(abs)) {
|
|
683
|
+
mirrorFile(abs, dst);
|
|
684
|
+
} else if (existsSync$1(dst)) {
|
|
685
|
+
rmSync(dst, { force: true });
|
|
686
|
+
for (const peer of generatedPeerPaths(dst)) {
|
|
687
|
+
if (existsSync$1(peer))rmSync(peer, { force: true });
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
function registerPostcssTempRoot(tempRoot) {
|
|
693
|
+
postcssTempRoots.add(tempRoot);
|
|
694
|
+
if (postcssCleanupRegistered)return;
|
|
695
|
+
postcssCleanupRegistered = true;
|
|
696
|
+
const cleanupAll = () => {
|
|
697
|
+
for (const root of postcssTempRoots)rmSync(root, { recursive: true, force: true });
|
|
698
|
+
postcssTempRoots.clear();
|
|
699
|
+
};
|
|
700
|
+
process.once("exit", cleanupAll);
|
|
701
|
+
process.once("SIGINT", () => {
|
|
702
|
+
cleanupAll();
|
|
703
|
+
process.exit(130);
|
|
704
|
+
});
|
|
705
|
+
process.once("SIGTERM", () => {
|
|
706
|
+
cleanupAll();
|
|
707
|
+
process.exit(143);
|
|
708
|
+
});
|
|
709
|
+
}
|
|
710
|
+
function cleanupPostcssTempRoot(tempRoot) {
|
|
711
|
+
postcssTempRoots.delete(tempRoot);
|
|
712
|
+
rmSync(tempRoot, { recursive: true, force: true });
|
|
713
|
+
}
|
|
714
|
+
function copyAppRootForPostcss(root,outdir,phase,cliNodeModules) {
|
|
715
|
+
const tempRoot = mkdtempSync(join$4(tmpdir(), `zntc-postcss-${phase}-`));
|
|
716
|
+
registerPostcssTempRoot(tempRoot);
|
|
717
|
+
const skip = new Set([resolve$2(outdir), resolve$2(tempRoot), resolve$2(join$4(root, "node_modules")), resolve$2(join$4(root, ".git")), resolve$2(join$4(root, "dist")), resolve$2(join$4(root, ".zntc-dev"))]);
|
|
718
|
+
cpSync(root, tempRoot, { recursive: true, dereference: false, filter(source) {
|
|
719
|
+
const abs = resolve$2(source);
|
|
720
|
+
if (abs === resolve$2(root))return true;
|
|
721
|
+
for (const ignored of skip) {
|
|
722
|
+
if (abs === ignored || abs.startsWith(`${ignored}${sep$2}`))return false;
|
|
723
|
+
}
|
|
724
|
+
return true;
|
|
725
|
+
} });
|
|
726
|
+
const appNodeModules = join$4(root, "node_modules"),nodeModulesTarget = existsSync$1(appNodeModules) ? appNodeModules : cliNodeModules;
|
|
727
|
+
if (existsSync$1(nodeModulesTarget)) {
|
|
728
|
+
symlinkSync(nodeModulesTarget, join$4(tempRoot, "node_modules"), "dir");
|
|
729
|
+
}
|
|
730
|
+
return tempRoot;
|
|
731
|
+
}
|
|
732
|
+
async function prepareAppCssPipelineRoot(root,outdir,configEnv,logLevel,phase,deps,options={}) {
|
|
733
|
+
const { existingTempRoot:existingTempRoot=null, dirtyPaths:dirtyPaths=null, cache:cache=null } = options,{ fallbackRequire:fallbackRequire, cliNodeModules:cliNodeModules } = deps,configPath = findPostcssConfig(root),stylePipelineFiles = cache?.stylePipelineFiles ?? collectAppFiles(root, { skipDir: outdir, predicate: (path) => isCssPreprocessorFile(path) || isCssModuleFile(path) }),preprocessorFiles = stylePipelineFiles.filter(isCssPreprocessorFile),moduleFiles = stylePipelineFiles.filter(isCssModuleFile),needsSource = preprocessorFiles.length > 0 || moduleFiles.length > 0;
|
|
734
|
+
if (!configPath && !needsSource)return null;
|
|
735
|
+
const tempRoot = existingTempRoot ?? copyAppRootForPostcss(root, outdir, phase, cliNodeModules),isIncremental = existingTempRoot && dirtyPaths;
|
|
736
|
+
if (isIncremental && dirtyPaths) {
|
|
737
|
+
syncDirtyFilesIntoTempRoot(root, tempRoot, dirtyPaths);
|
|
738
|
+
}
|
|
739
|
+
const toTemp = (path) => join$4(tempRoot, relative$2(root, path)),styleSourceFiles = !needsSource ? [] : (cache?.styleSourceFiles ?? collectAppFiles(tempRoot, { predicate: isStyleReferenceSource }));
|
|
740
|
+
let dirtySassSet = null,dirtyModuleSet = null,dirtySourceList = null;
|
|
741
|
+
if (isIncremental && dirtyPaths) {
|
|
742
|
+
const dirtyTempPaths = dirtyPaths.map(toTemp);
|
|
743
|
+
dirtySassSet = new Set(dirtyTempPaths.filter((p) => isCssPreprocessorFile(p)));
|
|
744
|
+
dirtyModuleSet = new Set(dirtyTempPaths.filter((p) => isCssModuleFile(p)));
|
|
745
|
+
for (const sassDirty of dirtySassSet) {
|
|
746
|
+
const cssOut = cssPreprocessorOutputPath(sassDirty);
|
|
747
|
+
if (isCssModuleFile(cssOut))dirtyModuleSet.add(cssOut);
|
|
748
|
+
}
|
|
749
|
+
dirtySourceList = dirtyTempPaths.filter((p) => isStyleReferenceSource(p) && existsSync$1(p));
|
|
750
|
+
}
|
|
751
|
+
const sassOutputs = transformCssPreprocessors(tempRoot, preprocessorFiles.map(toTemp), styleSourceFiles, logLevel, fallbackRequire, isIncremental ? { dirtyOnly: dirtySassSet, dirtySources: dirtySourceList } : undefined),postcssRelevant = !isIncremental || (dirtyPaths !== null && dirtyPaths.some((p) => isCssFile(p) || isCssPreprocessorFile(p) || isPostcssConfigFile(p)));
|
|
752
|
+
if (postcssRelevant) {
|
|
753
|
+
await runPostcssIfConfigured(tempRoot, tempRoot, null, configEnv, logLevel, fallbackRequire);
|
|
754
|
+
}
|
|
755
|
+
const generatedModuleFiles = preprocessorFiles.map(cssPreprocessorOutputPath).filter(isCssModuleFile),moduleOutputs = transformCssModules(tempRoot, [...moduleFiles, ...generatedModuleFiles].map(toTemp), styleSourceFiles, logLevel, isIncremental ? { dirtyOnly: dirtyModuleSet, dirtySources: dirtySourceList } : undefined),moduleInputCssPaths = new Set(generatedModuleFiles.map((p) => join$4(tempRoot, relative$2(root, p)))),generatedCssAbsPaths = [...sassOutputs.filter((p) => !moduleInputCssPaths.has(p)), ...moduleOutputs];
|
|
756
|
+
return { tempRoot, generatedCssAbsPaths, cache: { stylePipelineFiles, styleSourceFiles } };
|
|
757
|
+
}
|
|
758
|
+
function createAppDevController(opts,root,configEnv,deps) {
|
|
759
|
+
const { fallbackRequire:fallbackRequire } = deps,outdir = resolve$2(opts.outdir || join$4(root, ".zntc-dev")),base = normalizeBase(opts.base ?? opts.publicPath ?? "/");
|
|
760
|
+
let cssDeps = new Set(),cssDirDeps = new Set(),primaryHref = null,pipelineRoot = null,pipelineCache = null,hasPipelineCss = false,htmlEnvCache = null;
|
|
761
|
+
const warnedHtmlEnv = new Set();
|
|
762
|
+
return { root, outdir, base, async prepare(dirtyPaths=null) {
|
|
763
|
+
const reuseRoot = pipelineRoot && dirtyPaths != null;
|
|
764
|
+
if (pipelineRoot && !reuseRoot) {
|
|
765
|
+
cleanupPostcssTempRoot(pipelineRoot);
|
|
766
|
+
pipelineRoot = null;
|
|
767
|
+
pipelineCache = null;
|
|
768
|
+
}
|
|
769
|
+
if (reuseRoot && dirtyPaths && dirtyPaths.some((p) => isCssPreprocessorFile(p) || isCssModuleFile(p))) {
|
|
770
|
+
pipelineCache = null;
|
|
771
|
+
}
|
|
772
|
+
const pipeline = await prepareAppCssPipelineRoot(root, outdir, configEnv, opts.logLevel, "dev", deps, reuseRoot ? { existingTempRoot: pipelineRoot, dirtyPaths, cache: pipelineCache } : undefined);
|
|
773
|
+
pipelineRoot = pipeline?.tempRoot ?? null;
|
|
774
|
+
pipelineCache = pipeline?.cache ?? null;
|
|
775
|
+
hasPipelineCss = (pipeline?.generatedCssAbsPaths.length ?? 0) > 0;
|
|
776
|
+
const prepareRoot = pipelineRoot ?? root,envDir = opts.envDir ? resolve$2(opts.envDir) : prepareRoot,prepared = prepareAppDevSync({ root: prepareRoot, outdir, entryHtml: opts.entryHtml ?? "index.html", publicDir: opts.publicDir === undefined ? "public" : opts.publicDir, base, mode: configEnv.mode, envDir, envPrefixes: opts.envPrefixes ? Array.from(opts.envPrefixes) : undefined }),htmlEnv = htmlEnvCache && htmlEnvCache.mode === configEnv.mode && htmlEnvCache.dir === envDir ? htmlEnvCache.env : (htmlEnvCache = { mode: configEnv.mode, dir: envDir, env: loadEnv(configEnv.mode, envDir, ["ZNTC_"]) }).env,{ warnings:htmlWarnings } = applyHtmlEnvTokens(outdir, htmlEnv);
|
|
777
|
+
if (opts.logLevel !== "silent") {
|
|
778
|
+
for (const w of htmlWarnings) {
|
|
779
|
+
if (warnedHtmlEnv.has(w))continue;
|
|
780
|
+
warnedHtmlEnv.add(w);
|
|
781
|
+
console.error(`[html-env] ${w}`);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
injectAppDevHmrClient(outdir);
|
|
785
|
+
if (pipeline && pipeline.generatedCssAbsPaths.length > 0 && pipelineRoot) {
|
|
786
|
+
const sassOrModuleDirty = !reuseRoot || (dirtyPaths !== null && dirtyPaths.some((p) => isCssPreprocessorFile(p) || isCssModuleFile(p))),rels = sassOrModuleDirty ? mirrorPipelineCssToOutdir(pipelineRoot, outdir, pipeline.generatedCssAbsPaths) : pipeline.generatedCssAbsPaths.map((p) => relative$2(pipelineRoot ?? root, p));
|
|
787
|
+
injectAppDevPipelineCssLinks(outdir, base, rels);
|
|
788
|
+
}
|
|
789
|
+
return prepared;
|
|
790
|
+
}, async afterBundle({ changedPath:changedPath=null }={}) {
|
|
791
|
+
const result = await runPostcssForAppDev({ root, outdir, configEnv, logLevel: opts.logLevel, base, changedPath, fallbackRequire });
|
|
792
|
+
cssDeps = result.deps;
|
|
793
|
+
cssDirDeps = result.dirDeps;
|
|
794
|
+
primaryHref = result.primaryHref;
|
|
795
|
+
return result;
|
|
796
|
+
}, injectBundleCssLinks(bundleResult) {
|
|
797
|
+
if (hasPipelineCss)return;
|
|
798
|
+
injectAppDevBundleCssLinks(outdir, base, bundleResult);
|
|
799
|
+
}, isPostcssConfig(absPath) {
|
|
800
|
+
return isPostcssConfigFile(absPath);
|
|
801
|
+
}, isCssOnlyChange(absPath) {
|
|
802
|
+
if (isCssModuleFile(absPath) || isCssModulePreprocessorFile(absPath))return false;
|
|
803
|
+
if (isCssFile(absPath) || isCssPreprocessorFile(absPath))return true;
|
|
804
|
+
if (cssDeps.has(absPath))return true;
|
|
805
|
+
for (const dir of cssDirDeps) {
|
|
806
|
+
if (absPath === dir || absPath.startsWith(`${dir}${sep$2}`))return true;
|
|
807
|
+
}
|
|
808
|
+
return false;
|
|
809
|
+
}, isSassOnlyChange(absPath) {
|
|
810
|
+
return isCssPreprocessorFile(absPath) && !isCssModulePreprocessorFile(absPath);
|
|
811
|
+
}, async rebuildScssIncremental(absPath) {
|
|
812
|
+
if (!pipelineRoot)return null;
|
|
813
|
+
if (findPostcssConfig(root))return null;
|
|
814
|
+
const srcTemp = join$4(pipelineRoot, relative$2(root, absPath));
|
|
815
|
+
mirrorFile(absPath, srcTemp);
|
|
816
|
+
const sass = loadSassCompiler(root, fallbackRequire),result = compileSassFile(sass, srcTemp, pipelineRoot),cssTempPath = cssPreprocessorOutputPath(srcTemp);
|
|
817
|
+
writeFileSync$5(cssTempPath, result.css);
|
|
818
|
+
const cssRel = relative$2(pipelineRoot, cssTempPath);
|
|
819
|
+
mirrorFile(cssTempPath, join$4(outdir, cssRel));
|
|
820
|
+
return joinUrl(base, cssRel.replaceAll(sep$2, "/"));
|
|
821
|
+
}, hrefFor(absPath) {
|
|
822
|
+
if (absPath.endsWith(".css"))return joinUrl(base, relative$2(root, absPath));
|
|
823
|
+
return primaryHref ?? joinUrl(base, "style.css");
|
|
824
|
+
} };
|
|
825
|
+
}
|
|
826
|
+
//#endregion
|
|
827
|
+
//#region dev-overlay-client.mjs
|
|
828
|
+
const APP_DEV_HMR_CLIENT = `
|
|
829
|
+
const socketProtocol = location.protocol === "https:" ? "wss:" : "ws:";
|
|
830
|
+
let overlay = null;
|
|
831
|
+
let closeOverlayOnEsc = null;
|
|
832
|
+
function hideOverlay() {
|
|
833
|
+
if (closeOverlayOnEsc) document.removeEventListener("keydown", closeOverlayOnEsc);
|
|
834
|
+
closeOverlayOnEsc = null;
|
|
835
|
+
if (overlay && overlay.parentNode) overlay.parentNode.removeChild(overlay);
|
|
836
|
+
overlay = null;
|
|
837
|
+
}
|
|
838
|
+
function normalizeErrors(errors) {
|
|
839
|
+
if (!Array.isArray(errors) || errors.length === 0) {
|
|
840
|
+
return [{ file: "", message: "Unknown build error" }];
|
|
841
|
+
}
|
|
842
|
+
return errors.map((error) => {
|
|
843
|
+
if (typeof error === "string") return { file: "", message: error };
|
|
844
|
+
return {
|
|
845
|
+
file: error && typeof error.file === "string" ? error.file : "",
|
|
846
|
+
message: error && typeof error.message === "string" ? error.message : String(error),
|
|
847
|
+
};
|
|
848
|
+
});
|
|
849
|
+
}
|
|
850
|
+
function normalizeRuntimeError(error, file) {
|
|
851
|
+
if (error && typeof error.stack === "string" && error.stack) {
|
|
852
|
+
return { file: file || "", message: error.stack };
|
|
853
|
+
}
|
|
854
|
+
if (error && typeof error.message === "string" && error.message) {
|
|
855
|
+
const name = typeof error.name === "string" && error.name ? error.name : "Error";
|
|
856
|
+
return { file: file || "", message: name + ": " + error.message };
|
|
857
|
+
}
|
|
858
|
+
return { file: file || "", message: String(error || "Unknown runtime error") };
|
|
859
|
+
}
|
|
860
|
+
const sourceMapCache = new Map();
|
|
861
|
+
const sourceMapVlqChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
862
|
+
function displaySourceName(source) {
|
|
863
|
+
if (!source) return "";
|
|
864
|
+
const clean = String(source).split("?")[0].split("#")[0];
|
|
865
|
+
const slash = Math.max(clean.lastIndexOf("/"), clean.lastIndexOf("\\\\"));
|
|
866
|
+
return slash >= 0 ? clean.slice(slash + 1) : clean;
|
|
867
|
+
}
|
|
868
|
+
function decodeSourceMapVlq(segment) {
|
|
869
|
+
const values = [];
|
|
870
|
+
let result = 0;
|
|
871
|
+
let shift = 0;
|
|
872
|
+
for (const ch of segment) {
|
|
873
|
+
let digit = sourceMapVlqChars.indexOf(ch);
|
|
874
|
+
if (digit < 0) return values;
|
|
875
|
+
const continuation = digit & 32;
|
|
876
|
+
digit &= 31;
|
|
877
|
+
result += digit << shift;
|
|
878
|
+
if (continuation) {
|
|
879
|
+
shift += 5;
|
|
880
|
+
continue;
|
|
881
|
+
}
|
|
882
|
+
const negative = result & 1;
|
|
883
|
+
const value = result >> 1;
|
|
884
|
+
values.push(negative ? -value : value);
|
|
885
|
+
result = 0;
|
|
886
|
+
shift = 0;
|
|
887
|
+
}
|
|
888
|
+
return values;
|
|
889
|
+
}
|
|
890
|
+
function parseSourceMapMappings(map) {
|
|
891
|
+
if (map.__zntcParsedMappings) return map.__zntcParsedMappings;
|
|
892
|
+
let source = 0;
|
|
893
|
+
let originalLine = 0;
|
|
894
|
+
let originalColumn = 0;
|
|
895
|
+
let name = 0;
|
|
896
|
+
const parsed = [];
|
|
897
|
+
for (const line of String(map.mappings || "").split(";")) {
|
|
898
|
+
let generatedColumn = 0;
|
|
899
|
+
const segments = [];
|
|
900
|
+
for (const segment of line.split(",")) {
|
|
901
|
+
if (!segment) continue;
|
|
902
|
+
const values = decodeSourceMapVlq(segment);
|
|
903
|
+
if (values.length === 0) continue;
|
|
904
|
+
generatedColumn += values[0];
|
|
905
|
+
if (values.length >= 4) {
|
|
906
|
+
source += values[1];
|
|
907
|
+
originalLine += values[2];
|
|
908
|
+
originalColumn += values[3];
|
|
909
|
+
if (values.length >= 5) name += values[4];
|
|
910
|
+
segments.push({ generatedColumn, source, originalLine, originalColumn });
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
parsed.push(segments);
|
|
914
|
+
}
|
|
915
|
+
Object.defineProperty(map, "__zntcParsedMappings", { value: parsed });
|
|
916
|
+
return parsed;
|
|
917
|
+
}
|
|
918
|
+
function findOriginalPosition(map, line, column) {
|
|
919
|
+
const segments = parseSourceMapMappings(map)[line - 1];
|
|
920
|
+
if (!segments || segments.length === 0) return null;
|
|
921
|
+
let lo = 0;
|
|
922
|
+
let hi = segments.length - 1;
|
|
923
|
+
let best = null;
|
|
924
|
+
while (lo <= hi) {
|
|
925
|
+
const mid = (lo + hi) >> 1;
|
|
926
|
+
const segment = segments[mid];
|
|
927
|
+
if (segment.generatedColumn <= column) {
|
|
928
|
+
best = segment;
|
|
929
|
+
lo = mid + 1;
|
|
930
|
+
} else {
|
|
931
|
+
hi = mid - 1;
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
best = best || segments[0];
|
|
935
|
+
const source = map.sources && map.sources[best.source];
|
|
936
|
+
if (!source) return null;
|
|
937
|
+
const columnOffset = Math.max(0, column - best.generatedColumn);
|
|
938
|
+
return {
|
|
939
|
+
source: displaySourceName(source),
|
|
940
|
+
line: best.originalLine + 1,
|
|
941
|
+
column: best.originalColumn + columnOffset,
|
|
942
|
+
};
|
|
943
|
+
}
|
|
944
|
+
async function loadSourceMapForGeneratedUrl(url) {
|
|
945
|
+
const generatedUrl = new URL(url, location.href).href;
|
|
946
|
+
if (sourceMapCache.has(generatedUrl)) return sourceMapCache.get(generatedUrl);
|
|
947
|
+
const safeJson = async (response) => {
|
|
948
|
+
try { return await response.json(); } catch (_) { return null; }
|
|
949
|
+
};
|
|
950
|
+
const promise = (async () => {
|
|
951
|
+
const direct = await fetch(generatedUrl + ".map", { cache: "no-store" }).catch(() => null);
|
|
952
|
+
if (direct && direct.ok) return safeJson(direct);
|
|
953
|
+
const jsResponse = await fetch(generatedUrl, { cache: "no-store" }).catch(() => null);
|
|
954
|
+
if (!jsResponse || !jsResponse.ok) return null;
|
|
955
|
+
const code = await jsResponse.text();
|
|
956
|
+
const match =
|
|
957
|
+
code.match(/\\/\\/[#@]\\s*sourceMappingURL=([^\\n\\r]+)/) ||
|
|
958
|
+
code.match(/\\/\\*[#@]\\s*sourceMappingURL=([^*]+)\\*\\//);
|
|
959
|
+
if (!match) return null;
|
|
960
|
+
const ref = match[1].trim();
|
|
961
|
+
if (ref.startsWith("data:")) {
|
|
962
|
+
const comma = ref.indexOf(",");
|
|
963
|
+
if (comma < 0) return null;
|
|
964
|
+
const meta = ref.slice(0, comma);
|
|
965
|
+
const data = ref.slice(comma + 1);
|
|
966
|
+
try {
|
|
967
|
+
const json = meta.includes(";base64") ? atob(data) : decodeURIComponent(data);
|
|
968
|
+
return JSON.parse(json);
|
|
969
|
+
} catch (_) {
|
|
970
|
+
return null;
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
const mapResponse = await fetch(new URL(ref, generatedUrl).href, { cache: "no-store" }).catch(() => null);
|
|
974
|
+
return mapResponse && mapResponse.ok ? safeJson(mapResponse) : null;
|
|
975
|
+
})();
|
|
976
|
+
sourceMapCache.set(generatedUrl, promise);
|
|
977
|
+
return promise;
|
|
978
|
+
}
|
|
979
|
+
async function mapGeneratedLocation(url, line, column) {
|
|
980
|
+
const map = await loadSourceMapForGeneratedUrl(url);
|
|
981
|
+
return map ? findOriginalPosition(map, line, column) : null;
|
|
982
|
+
}
|
|
983
|
+
async function mapLocationText(text) {
|
|
984
|
+
if (!text) return text;
|
|
985
|
+
const match = String(text).match(/(https?:\\/\\/[^\\s)]+):(\\d+):(\\d+)/);
|
|
986
|
+
if (!match) return text;
|
|
987
|
+
const mapped = await mapGeneratedLocation(match[1], Number(match[2]), Number(match[3]));
|
|
988
|
+
if (!mapped) return text;
|
|
989
|
+
return String(text).replace(match[0], mapped.source + ":" + mapped.line + ":" + mapped.column);
|
|
990
|
+
}
|
|
991
|
+
async function mapStackTrace(stack) {
|
|
992
|
+
if (typeof stack !== "string") return stack;
|
|
993
|
+
const lines = await Promise.all(stack.split("\\n").map(mapLocationText));
|
|
994
|
+
return lines.join("\\n");
|
|
995
|
+
}
|
|
996
|
+
async function normalizeRuntimeErrorWithSourceMap(error, file) {
|
|
997
|
+
const item = normalizeRuntimeError(error, file);
|
|
998
|
+
item.file = await mapLocationText(item.file);
|
|
999
|
+
item.message = await mapStackTrace(item.message);
|
|
1000
|
+
return item;
|
|
1001
|
+
}
|
|
1002
|
+
async function showRuntimeOverlay(error, file) {
|
|
1003
|
+
let item;
|
|
1004
|
+
try {
|
|
1005
|
+
item = await normalizeRuntimeErrorWithSourceMap(error, file);
|
|
1006
|
+
} catch (_) {
|
|
1007
|
+
item = normalizeRuntimeError(error, file);
|
|
1008
|
+
}
|
|
1009
|
+
showOverlay([item], "Runtime Error");
|
|
1010
|
+
}
|
|
1011
|
+
function showOverlay(errors, titleText = "Build Error") {
|
|
1012
|
+
hideOverlay();
|
|
1013
|
+
const items = normalizeErrors(errors);
|
|
1014
|
+
overlay = document.createElement("div");
|
|
1015
|
+
overlay.id = "zntc-error-overlay";
|
|
1016
|
+
const root = overlay.attachShadow({ mode: "open" });
|
|
1017
|
+
const style = document.createElement("style");
|
|
1018
|
+
style.textContent = ":host{position:fixed;inset:0;z-index:2147483647;display:block;--font:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;--red:#fb7185;--text:#f8fafc;--blue:#93c5fd;--window:#181818;}" +
|
|
1019
|
+
".backdrop{position:fixed;inset:0;overflow:auto;padding:32px;box-sizing:border-box;background:rgba(0,0,0,.66);font:14px/1.5 var(--font);color:var(--text);}" +
|
|
1020
|
+
".window{max-width:980px;margin:0 auto;background:var(--window);border-top:8px solid var(--red);border-radius:6px 6px 8px 8px;box-shadow:0 19px 38px rgba(0,0,0,.30),0 15px 12px rgba(0,0,0,.22);overflow:hidden;}" +
|
|
1021
|
+
".header{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:18px 20px;border-bottom:1px solid rgba(255,255,255,.12);}" +
|
|
1022
|
+
".title{font-size:18px;font-weight:700;color:#fecdd3;}" +
|
|
1023
|
+
".close{width:30px;height:30px;border:1px solid rgba(255,255,255,.25);border-radius:4px;background:#111827;color:var(--text);cursor:pointer;font:18px/1 var(--font);}" +
|
|
1024
|
+
".card{padding:18px 20px;border-top:1px solid rgba(255,255,255,.08);}" +
|
|
1025
|
+
".file{margin-bottom:10px;color:var(--blue);word-break:break-all;}" +
|
|
1026
|
+
".message{margin:0;white-space:pre-wrap;color:#fff;word-break:break-word;font:14px/1.5 var(--font);}";
|
|
1027
|
+
const backdrop = document.createElement("div");
|
|
1028
|
+
backdrop.className = "backdrop";
|
|
1029
|
+
const panel = document.createElement("div");
|
|
1030
|
+
panel.className = "window";
|
|
1031
|
+
panel.onclick = (event) => event.stopPropagation();
|
|
1032
|
+
const header = document.createElement("div");
|
|
1033
|
+
header.className = "header";
|
|
1034
|
+
const title = document.createElement("div");
|
|
1035
|
+
title.className = "title";
|
|
1036
|
+
title.textContent = titleText;
|
|
1037
|
+
const close = document.createElement("button");
|
|
1038
|
+
close.type = "button";
|
|
1039
|
+
close.textContent = "x";
|
|
1040
|
+
close.className = "close";
|
|
1041
|
+
close.setAttribute("aria-label", "Close error overlay");
|
|
1042
|
+
close.onclick = hideOverlay;
|
|
1043
|
+
header.appendChild(title);
|
|
1044
|
+
header.appendChild(close);
|
|
1045
|
+
panel.appendChild(header);
|
|
1046
|
+
for (const item of items) {
|
|
1047
|
+
const card = document.createElement("div");
|
|
1048
|
+
card.className = "card";
|
|
1049
|
+
if (item.file) {
|
|
1050
|
+
const file = document.createElement("div");
|
|
1051
|
+
file.className = "file";
|
|
1052
|
+
file.textContent = item.file;
|
|
1053
|
+
card.appendChild(file);
|
|
1054
|
+
}
|
|
1055
|
+
const message = document.createElement("pre");
|
|
1056
|
+
message.className = "message";
|
|
1057
|
+
message.textContent = item.message;
|
|
1058
|
+
card.appendChild(message);
|
|
1059
|
+
panel.appendChild(card);
|
|
1060
|
+
}
|
|
1061
|
+
backdrop.appendChild(panel);
|
|
1062
|
+
root.appendChild(style);
|
|
1063
|
+
root.appendChild(backdrop);
|
|
1064
|
+
closeOverlayOnEsc = (event) => {
|
|
1065
|
+
if (event.key === "Escape" || event.code === "Escape") hideOverlay();
|
|
1066
|
+
};
|
|
1067
|
+
document.addEventListener("keydown", closeOverlayOnEsc);
|
|
1068
|
+
(document.body || document.documentElement).appendChild(overlay);
|
|
1069
|
+
}
|
|
1070
|
+
globalThis.__zntc_show_error_overlay = showOverlay;
|
|
1071
|
+
globalThis.__zntc_clear_error_overlay = hideOverlay;
|
|
1072
|
+
if (!globalThis.__zntc_runtime_listeners_attached) {
|
|
1073
|
+
globalThis.__zntc_runtime_listeners_attached = true;
|
|
1074
|
+
window.addEventListener("error", (event) => {
|
|
1075
|
+
const file = event.filename ? event.filename + ":" + event.lineno + ":" + event.colno : "";
|
|
1076
|
+
showRuntimeOverlay(event.error || event.message, file);
|
|
1077
|
+
});
|
|
1078
|
+
window.addEventListener("unhandledrejection", (event) => {
|
|
1079
|
+
showRuntimeOverlay(event.reason, "");
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
const socket = new WebSocket(socketProtocol + "//" + location.host + "${APP_DEV_HMR_WS_PATH}");
|
|
1083
|
+
socket.addEventListener("message", (event) => {
|
|
1084
|
+
const msg = JSON.parse(event.data);
|
|
1085
|
+
if (msg.type === "${HMR_MSG.Error}") {
|
|
1086
|
+
showOverlay(msg.errors);
|
|
1087
|
+
return;
|
|
1088
|
+
}
|
|
1089
|
+
if (msg.type === "${HMR_MSG.ClearError}") {
|
|
1090
|
+
hideOverlay();
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
1093
|
+
if (msg.type === "${HMR_MSG.FullReload}") {
|
|
1094
|
+
hideOverlay();
|
|
1095
|
+
location.reload();
|
|
1096
|
+
return;
|
|
1097
|
+
}
|
|
1098
|
+
if (msg.type !== "${HMR_MSG.CssUpdate}") return;
|
|
1099
|
+
hideOverlay();
|
|
1100
|
+
const stamp = msg.timestamp || Date.now();
|
|
1101
|
+
const links = Array.from(document.querySelectorAll('link[rel="stylesheet"]'));
|
|
1102
|
+
let updated = false;
|
|
1103
|
+
for (const link of links) {
|
|
1104
|
+
const href = link.getAttribute("href");
|
|
1105
|
+
if (!href) continue;
|
|
1106
|
+
const current = new URL(href, location.href);
|
|
1107
|
+
const target = new URL(msg.href || current.pathname, location.href);
|
|
1108
|
+
if (msg.href && current.pathname !== target.pathname) continue;
|
|
1109
|
+
const next = new URL(current.href);
|
|
1110
|
+
next.searchParams.set("t", String(stamp));
|
|
1111
|
+
const replacement = link.cloneNode();
|
|
1112
|
+
replacement.href = next.href;
|
|
1113
|
+
replacement.onload = () => link.remove();
|
|
1114
|
+
replacement.onerror = () => location.reload();
|
|
1115
|
+
link.after(replacement);
|
|
1116
|
+
updated = true;
|
|
1117
|
+
}
|
|
1118
|
+
if (!updated) location.reload();
|
|
1119
|
+
});
|
|
1120
|
+
`;
|
|
1121
|
+
//#endregion
|
|
1122
|
+
//#region index.ts
|
|
1123
|
+
export { APP_DEV_HMR_CLIENT_PATH, APP_DEV_HMR_WS_PATH, createHmrChannel, createWatcher, HMR_MSG, injectAppDevBundleCssLinks, injectAppDevHmrClient, injectAppDevPipelineCssLinks, injectIntoDevHtml, DEFAULT_HTML_ENV_PREFIX, applyHtmlEnvTokens, transformHtmlEnvTokens, joinUrl, isCssIdent, isCssIdentStart, skipCssString, skipCssUrl, startsWithCssIdent, collectAppFiles, requireFromAppOrFallback, collectPostcssMessages, findPostcssConfig, isCssFile, isPostcssConfigFile, loadPostcssConfig, logPostcssProcessed, POSTCSS_CONFIG_NAMES, runPostcssForAppDev, runPostcssIfConfigured, buildCssPreprocessorProxy, CSS_PREPROCESSOR_EXTENSIONS, compileSassFile, cssPreprocessorOutputPath, cssPreprocessorProxyPath, isCssModulePreprocessorFile, isCssPreprocessorFile, isStyleReferenceSource, loadSassCompiler, rewriteSassReferences, transformCssPreprocessors, buildCssModuleProxy, collectCssModuleClasses, cssModuleGeneratedCssPath, cssModuleLocalName, cssModuleProxyPath, isCssModuleFile, isValidExportName, rewriteCssModuleClasses, rewriteCssModuleReferences, scanCssModuleClassTokens, transformCssModules, cleanupPostcssTempRoot, createAppDevController, prepareAppCssPipelineRoot, APP_DEV_HMR_CLIENT };
|
|
1124
|
+
//#endregion
|