@idl3/claude-control 0.4.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/auth.js +23 -2
- package/lib/config.js +2 -1
- package/lib/json-file.js +40 -0
- package/lib/match.js +78 -2
- package/lib/mlx.js +13 -0
- package/lib/pins.js +2 -3
- package/lib/push.js +3 -2
- package/lib/resources.js +112 -52
- package/lib/sessions.js +116 -3
- package/lib/shell.js +3 -1
- package/lib/subagents.js +7 -6
- package/lib/tmux.js +26 -7
- package/lib/transcribe.js +55 -24
- package/lib/ws-heartbeat.js +32 -0
- package/package.json +1 -1
- package/server.js +189 -78
- package/web/dist/assets/{core-7jLm1R4l.js → core-CEtbx-dx.js} +1 -1
- package/web/dist/assets/index-CjJtW-Kv.css +1 -0
- package/web/dist/assets/index-DFru8Gzx.js +103 -0
- package/web/dist/index.html +2 -2
- package/web/dist/assets/index-D41aOqTB.js +0 -103
- package/web/dist/assets/index-Dv9NwX8Q.css +0 -1
package/server.js
CHANGED
|
@@ -42,7 +42,8 @@ import { listSkills, readSkill } from './lib/skills.js';
|
|
|
42
42
|
// library auto-selects the FIRST offered one (the non-secret WS_PROTOCOL label)
|
|
43
43
|
// and echoes it, so we never reflect the raw token back and need no custom
|
|
44
44
|
// handleProtocols here. checkWsToken just verifies the token is among the offers.
|
|
45
|
-
import { checkToken as authCheckToken, checkWsToken } from './lib/auth.js';
|
|
45
|
+
import { checkToken as authCheckToken, checkWsToken, safeTokenEqual } from './lib/auth.js';
|
|
46
|
+
import { pruneDeadClients } from './lib/ws-heartbeat.js';
|
|
46
47
|
|
|
47
48
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
48
49
|
// Prefer the built assistant-ui app (web/dist) when present; otherwise fall back
|
|
@@ -152,7 +153,7 @@ function checkTerminalToken(reqUrl) {
|
|
|
152
153
|
if (!CONFIG.token) return true;
|
|
153
154
|
try {
|
|
154
155
|
const u = new URL(reqUrl, 'http://localhost');
|
|
155
|
-
return u.searchParams.get('token')
|
|
156
|
+
return safeTokenEqual(u.searchParams.get('token'), CONFIG.token);
|
|
156
157
|
} catch {
|
|
157
158
|
return false;
|
|
158
159
|
}
|
|
@@ -204,6 +205,7 @@ const _tls = loadTls();
|
|
|
204
205
|
const _scheme = _tls ? 'https' : 'http';
|
|
205
206
|
|
|
206
207
|
const _handler = (req, res) => {
|
|
208
|
+
try {
|
|
207
209
|
const u = new URL(req.url, 'http://localhost');
|
|
208
210
|
|
|
209
211
|
if (u.pathname === '/api/sessions') {
|
|
@@ -388,8 +390,16 @@ const _handler = (req, res) => {
|
|
|
388
390
|
return proxyTerminalHttp(req, res, u);
|
|
389
391
|
}
|
|
390
392
|
|
|
393
|
+
// Unknown /api/* path: return JSON 404 instead of falling through to the SPA.
|
|
394
|
+
if (u.pathname.startsWith('/api/')) return endJson(res, 404, { error: 'not found' });
|
|
395
|
+
|
|
391
396
|
// static
|
|
392
397
|
serveStatic(u.pathname, res);
|
|
398
|
+
} catch (e) {
|
|
399
|
+
// eslint-disable-next-line no-console
|
|
400
|
+
console.error('[handler] uncaught error:', e?.stack || e);
|
|
401
|
+
endJson(res, 500, { error: 'internal' });
|
|
402
|
+
}
|
|
393
403
|
};
|
|
394
404
|
|
|
395
405
|
const server = _tls
|
|
@@ -420,6 +430,7 @@ function handleUpdate(res) {
|
|
|
420
430
|
}
|
|
421
431
|
|
|
422
432
|
function endJson(res, code, obj) {
|
|
433
|
+
if (res.headersSent || res.writableEnded) return;
|
|
423
434
|
const body = JSON.stringify(obj);
|
|
424
435
|
res.writeHead(code, { 'content-type': MIME['.json'], 'content-length': Buffer.byteLength(body) });
|
|
425
436
|
res.end(body);
|
|
@@ -953,6 +964,47 @@ function serveIndexHtml(res) {
|
|
|
953
964
|
});
|
|
954
965
|
}
|
|
955
966
|
|
|
967
|
+
// --- Per-target WS op serialisation ----------------------------------------
|
|
968
|
+
// Multiple browser/device clients on the same session can fire overlapping
|
|
969
|
+
// send-keys ops concurrently. Two such ops dispatched to the same tmux pane
|
|
970
|
+
// interleave keystrokes mid-sequence. We prevent this with a per-target FIFO
|
|
971
|
+
// promise chain: each send-keys op appends to the tail of its target's chain
|
|
972
|
+
// and runs only after its predecessor settles. Different targets run in
|
|
973
|
+
// parallel. Read-only ops (subscribe, capture, shell-capture, …) are NOT
|
|
974
|
+
// enqueued — they never touch the pane input buffer.
|
|
975
|
+
const _opChains = new Map(); // target → current-tail Promise
|
|
976
|
+
|
|
977
|
+
/**
|
|
978
|
+
* Enqueue `fn` behind any in-flight op on `target`.
|
|
979
|
+
*
|
|
980
|
+
* Contract:
|
|
981
|
+
* - The returned promise settles exactly as fn() settles (value / throw).
|
|
982
|
+
* - A rejected op does NOT poison the next op on the same target — the chain
|
|
983
|
+
* continues regardless of whether prev settled fulfilled or rejected.
|
|
984
|
+
* - The Map entry is deleted once the queued op is the sole tail and it has
|
|
985
|
+
* settled, preventing unbounded growth on idle targets.
|
|
986
|
+
*
|
|
987
|
+
* @param {string} target tmux pane target (the serialisation key)
|
|
988
|
+
* @param {() => Promise<any>} fn async work to serialise
|
|
989
|
+
* @returns {Promise<any>}
|
|
990
|
+
*/
|
|
991
|
+
function runSerial(target, fn) {
|
|
992
|
+
const prev = _opChains.get(target) ?? Promise.resolve();
|
|
993
|
+
// chain: run fn after prev regardless of prev's outcome
|
|
994
|
+
const tail = prev.then(fn, fn);
|
|
995
|
+
// Store the tail so the NEXT enqueue can chain behind it.
|
|
996
|
+
// Suppress any rejection on the stored promise so Node's
|
|
997
|
+
// unhandledRejection handler never fires on the chain itself —
|
|
998
|
+
// the caller's `tail` reference will surface the error to the caller.
|
|
999
|
+
const stored = tail.then(() => {}, () => {});
|
|
1000
|
+
_opChains.set(target, stored);
|
|
1001
|
+
// Clean up once this op is the last in the chain and it has settled.
|
|
1002
|
+
stored.finally(() => {
|
|
1003
|
+
if (_opChains.get(target) === stored) _opChains.delete(target);
|
|
1004
|
+
});
|
|
1005
|
+
return tail;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
956
1008
|
// --- WebSocket --------------------------------------------------------------
|
|
957
1009
|
// 1 MB cap: control messages are tiny; this prevents a single huge frame from
|
|
958
1010
|
// forcing a multi-hundred-MB string allocation in the cockpit process.
|
|
@@ -1139,20 +1191,27 @@ function ensureSubscription(id) {
|
|
|
1139
1191
|
function startPromptPoller(id, sub) {
|
|
1140
1192
|
if (sub.promptTimer) return;
|
|
1141
1193
|
sub._lastPrompt = undefined;
|
|
1194
|
+
sub._promptTicking = false;
|
|
1142
1195
|
const tick = async () => {
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
let prompt = null;
|
|
1196
|
+
if (sub._promptTicking) return;
|
|
1197
|
+
sub._promptTicking = true;
|
|
1146
1198
|
try {
|
|
1147
|
-
const
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1199
|
+
const session = sessionById(id);
|
|
1200
|
+
if (!session || !tmux.isValidTarget(session.target)) return;
|
|
1201
|
+
let prompt = null;
|
|
1202
|
+
try {
|
|
1203
|
+
const cap = await tmux.capturePane(session.target, 40);
|
|
1204
|
+
prompt = parsePanePrompt(cap);
|
|
1205
|
+
} catch {
|
|
1206
|
+
return;
|
|
1207
|
+
}
|
|
1208
|
+
const json = prompt ? JSON.stringify(prompt) : null;
|
|
1209
|
+
if (json !== sub._lastPrompt) {
|
|
1210
|
+
sub._lastPrompt = json;
|
|
1211
|
+
broadcastTo(id, { type: 'prompt', id, prompt });
|
|
1212
|
+
}
|
|
1213
|
+
} finally {
|
|
1214
|
+
sub._promptTicking = false;
|
|
1156
1215
|
}
|
|
1157
1216
|
};
|
|
1158
1217
|
sub.promptTimer = setInterval(() => tick().catch(() => {}), 2000);
|
|
@@ -1171,6 +1230,9 @@ function maybeTeardown(id) {
|
|
|
1171
1230
|
}
|
|
1172
1231
|
|
|
1173
1232
|
wss.on('connection', (ws) => {
|
|
1233
|
+
ws.isAlive = true;
|
|
1234
|
+
ws.on('pong', () => { ws.isAlive = true; });
|
|
1235
|
+
|
|
1174
1236
|
send(ws, { type: 'sessions', sessions: registry.getSessions() });
|
|
1175
1237
|
send(ws, { type: 'resources', snapshot: resources.snapshot() });
|
|
1176
1238
|
ws._subs = new Set();
|
|
@@ -1193,6 +1255,9 @@ wss.on('connection', (ws) => {
|
|
|
1193
1255
|
});
|
|
1194
1256
|
});
|
|
1195
1257
|
|
|
1258
|
+
const heartbeatInterval = setInterval(() => pruneDeadClients(wss.clients), 30000);
|
|
1259
|
+
heartbeatInterval.unref();
|
|
1260
|
+
|
|
1196
1261
|
async function handleClientMessage(ws, msg) {
|
|
1197
1262
|
switch (msg.type) {
|
|
1198
1263
|
case 'subscribe': {
|
|
@@ -1228,8 +1293,11 @@ async function handleClientMessage(ws, msg) {
|
|
|
1228
1293
|
const session = sessionById(msg.id);
|
|
1229
1294
|
if (!session) throw new Error('unknown session');
|
|
1230
1295
|
if (!tmux.isValidTarget(session.target)) throw new Error('invalid tmux target');
|
|
1231
|
-
|
|
1232
|
-
return
|
|
1296
|
+
const replyText = String(msg.text ?? '');
|
|
1297
|
+
return runSerial(session.target, async () => {
|
|
1298
|
+
await tmux.sendText(session.target, replyText);
|
|
1299
|
+
send(ws, { type: 'ack', op: 'reply', ok: true });
|
|
1300
|
+
});
|
|
1233
1301
|
}
|
|
1234
1302
|
case 'answer': {
|
|
1235
1303
|
const session = sessionById(msg.id);
|
|
@@ -1244,6 +1312,7 @@ async function handleClientMessage(ws, msg) {
|
|
|
1244
1312
|
throw new Error('stale question (already answered or changed)');
|
|
1245
1313
|
}
|
|
1246
1314
|
|
|
1315
|
+
return runSerial(session.target, async () => {
|
|
1247
1316
|
// ── Capture-driven path ──────────────────────────────────────────────
|
|
1248
1317
|
// Attempt to navigate by parsing the live picker render. Falls back to
|
|
1249
1318
|
// the static buildAnswerProgram on ANY parse failure, unknown label, or
|
|
@@ -1449,7 +1518,8 @@ async function handleClientMessage(ws, msg) {
|
|
|
1449
1518
|
console.log(`[answer] sent toolUseId=${msg.toolUseId} via dynamic path`);
|
|
1450
1519
|
}
|
|
1451
1520
|
|
|
1452
|
-
|
|
1521
|
+
send(ws, { type: 'ack', op: 'answer', ok: true });
|
|
1522
|
+
}); // end runSerial
|
|
1453
1523
|
}
|
|
1454
1524
|
case 'capture': {
|
|
1455
1525
|
const session = sessionById(msg.id);
|
|
@@ -1467,16 +1537,22 @@ async function handleClientMessage(ws, msg) {
|
|
|
1467
1537
|
const session = sessionById(msg.id);
|
|
1468
1538
|
if (!session) throw new Error('unknown session');
|
|
1469
1539
|
if (!tmux.isValidTarget(session.target)) throw new Error('invalid tmux target');
|
|
1470
|
-
|
|
1471
|
-
return
|
|
1540
|
+
const paneText = String(msg.text ?? '');
|
|
1541
|
+
return runSerial(session.target, async () => {
|
|
1542
|
+
await tmux.sendLiteral(session.target, paneText);
|
|
1543
|
+
send(ws, { type: 'ack', op: 'pane-text', ok: true });
|
|
1544
|
+
});
|
|
1472
1545
|
}
|
|
1473
1546
|
case 'pane-key': {
|
|
1474
1547
|
const session = sessionById(msg.id);
|
|
1475
1548
|
if (!session) throw new Error('unknown session');
|
|
1476
1549
|
if (!tmux.isValidTarget(session.target)) throw new Error('invalid tmux target');
|
|
1477
1550
|
if (!shell.SHELL_KEYS.has(String(msg.key ?? ''))) throw new Error('key not allowed');
|
|
1478
|
-
|
|
1479
|
-
return
|
|
1551
|
+
const paneKey = String(msg.key);
|
|
1552
|
+
return runSerial(session.target, async () => {
|
|
1553
|
+
await tmux.sendRawKeys(session.target, [paneKey]);
|
|
1554
|
+
send(ws, { type: 'ack', op: 'pane-key', ok: true });
|
|
1555
|
+
});
|
|
1480
1556
|
}
|
|
1481
1557
|
case 'promptkey': {
|
|
1482
1558
|
// Respond to a live TUI selection prompt (permission/menu). Whitelisted
|
|
@@ -1486,11 +1562,14 @@ async function handleClientMessage(ws, msg) {
|
|
|
1486
1562
|
if (!tmux.isValidTarget(session.target)) throw new Error('invalid tmux target');
|
|
1487
1563
|
const ALLOWED = new Set(['1', '2', '3', '4', '5', '6', '7', '8', '9', 'Enter', 'Escape', 'Up', 'Down']);
|
|
1488
1564
|
if (!ALLOWED.has(msg.key)) throw new Error('key not allowed');
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1565
|
+
const promptKey = msg.key;
|
|
1566
|
+
return runSerial(session.target, async () => {
|
|
1567
|
+
await tmux.sendRawKeys(session.target, [promptKey]);
|
|
1568
|
+
// Force the next poll tick to broadcast (the prompt should now change/clear).
|
|
1569
|
+
const sub = subscriptions.get(msg.id);
|
|
1570
|
+
if (sub) sub._lastPrompt = '__force__';
|
|
1571
|
+
send(ws, { type: 'ack', op: 'promptkey', ok: true });
|
|
1572
|
+
});
|
|
1494
1573
|
}
|
|
1495
1574
|
case 'promptselect': {
|
|
1496
1575
|
// Respond to a live TUI multi-select checkbox prompt (surfaced via pane-scrape
|
|
@@ -1503,57 +1582,61 @@ async function handleClientMessage(ws, msg) {
|
|
|
1503
1582
|
const labels = Array.isArray(msg.labels) ? msg.labels.map(String) : [];
|
|
1504
1583
|
if (labels.length === 0) throw new Error('no labels provided');
|
|
1505
1584
|
|
|
1506
|
-
|
|
1585
|
+
return runSerial(session.target, async () => {
|
|
1586
|
+
const SETTLE_MS = 300;
|
|
1507
1587
|
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1588
|
+
// 1. Capture current picker state.
|
|
1589
|
+
let capture;
|
|
1590
|
+
try {
|
|
1591
|
+
capture = await tmux.capturePane(session.target);
|
|
1592
|
+
} catch (captureErr) {
|
|
1593
|
+
throw new Error(`promptselect: capture failed: ${captureErr?.message}`);
|
|
1594
|
+
}
|
|
1515
1595
|
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1596
|
+
// 2. Parse into a structured picker model.
|
|
1597
|
+
const parsed = parsePicker(capture);
|
|
1598
|
+
if (parsed.confidence !== 'ok') {
|
|
1599
|
+
send(ws, {
|
|
1600
|
+
type: 'ack',
|
|
1601
|
+
op: 'promptselect',
|
|
1602
|
+
ok: false,
|
|
1603
|
+
error: 'promptselect: picker not found or low confidence — please retry',
|
|
1604
|
+
});
|
|
1605
|
+
return;
|
|
1606
|
+
}
|
|
1526
1607
|
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1608
|
+
// 3. Build a synthetic single-question descriptor (multiSelect=true) so
|
|
1609
|
+
// planStep can calculate Space-toggle + action-row Enter keys.
|
|
1610
|
+
const syntheticQuestion = {
|
|
1611
|
+
multiSelect: true,
|
|
1612
|
+
options: parsed.rows
|
|
1613
|
+
.filter((r) => r.kind === 'option')
|
|
1614
|
+
.map((r) => ({ label: r.label })),
|
|
1615
|
+
};
|
|
1616
|
+
|
|
1617
|
+
// 4. Plan keystrokes via the tested planStep function.
|
|
1618
|
+
const keys = planStep(parsed, syntheticQuestion, labels);
|
|
1619
|
+
if (!keys) {
|
|
1620
|
+
console.log(`[promptselect] planStep returned null for labels=${JSON.stringify(labels)} — low confidence`);
|
|
1621
|
+
send(ws, {
|
|
1622
|
+
type: 'ack',
|
|
1623
|
+
op: 'promptselect',
|
|
1624
|
+
ok: false,
|
|
1625
|
+
error: 'promptselect: could not map labels to picker rows — please retry',
|
|
1626
|
+
});
|
|
1627
|
+
return;
|
|
1628
|
+
}
|
|
1547
1629
|
|
|
1548
|
-
|
|
1630
|
+
console.log(`[promptselect] id=${msg.id} labels=${JSON.stringify(labels)} keys=${JSON.stringify(keys)}`);
|
|
1549
1631
|
|
|
1550
|
-
|
|
1551
|
-
|
|
1632
|
+
// 5. Send keys sequenced with settle delay (same as case 'answer' dynamic path).
|
|
1633
|
+
await tmux.sendRawKeysSequenced(session.target, keys, SETTLE_MS);
|
|
1552
1634
|
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1635
|
+
// Force the next poll tick to broadcast (the prompt should now change/clear).
|
|
1636
|
+
const promptSub = subscriptions.get(msg.id);
|
|
1637
|
+
if (promptSub) promptSub._lastPrompt = '__force__';
|
|
1638
|
+
send(ws, { type: 'ack', op: 'promptselect', ok: true });
|
|
1639
|
+
});
|
|
1557
1640
|
}
|
|
1558
1641
|
// Composer terminal mode (>_): each Claude session has its OWN sister shell
|
|
1559
1642
|
// pane in its window. Resolve the session by id → its target + cwd, then act
|
|
@@ -1561,20 +1644,29 @@ async function handleClientMessage(ws, msg) {
|
|
|
1561
1644
|
case 'shell-input': {
|
|
1562
1645
|
const s = sessionById(msg.id);
|
|
1563
1646
|
if (!s) throw new Error('unknown session');
|
|
1564
|
-
|
|
1565
|
-
return
|
|
1647
|
+
const shellInputLine = String(msg.line ?? '');
|
|
1648
|
+
return runSerial(s.target + ':shell', async () => {
|
|
1649
|
+
await shell.shellInput(s.target, s.cwd, shellInputLine);
|
|
1650
|
+
send(ws, { type: 'ack', op: 'shell-input', ok: true });
|
|
1651
|
+
});
|
|
1566
1652
|
}
|
|
1567
1653
|
case 'shell-text': {
|
|
1568
1654
|
const s = sessionById(msg.id);
|
|
1569
1655
|
if (!s) throw new Error('unknown session');
|
|
1570
|
-
|
|
1571
|
-
return
|
|
1656
|
+
const shellTextVal = String(msg.text ?? '');
|
|
1657
|
+
return runSerial(s.target + ':shell', async () => {
|
|
1658
|
+
await shell.shellText(s.target, s.cwd, shellTextVal);
|
|
1659
|
+
send(ws, { type: 'ack', op: 'shell-text', ok: true });
|
|
1660
|
+
});
|
|
1572
1661
|
}
|
|
1573
1662
|
case 'shell-key': {
|
|
1574
1663
|
const s = sessionById(msg.id);
|
|
1575
1664
|
if (!s) throw new Error('unknown session');
|
|
1576
|
-
|
|
1577
|
-
return
|
|
1665
|
+
const shellKeyVal = String(msg.key ?? '');
|
|
1666
|
+
return runSerial(s.target + ':shell', async () => {
|
|
1667
|
+
await shell.shellKey(s.target, s.cwd, shellKeyVal);
|
|
1668
|
+
send(ws, { type: 'ack', op: 'shell-key', ok: true });
|
|
1669
|
+
});
|
|
1578
1670
|
}
|
|
1579
1671
|
case 'shell-capture': {
|
|
1580
1672
|
const s = sessionById(msg.id);
|
|
@@ -1691,8 +1783,10 @@ async function main() {
|
|
|
1691
1783
|
}
|
|
1692
1784
|
|
|
1693
1785
|
function shutdown() {
|
|
1786
|
+
clearInterval(heartbeatInterval);
|
|
1694
1787
|
for (const [, sub] of subscriptions) sub.tailer?.stop();
|
|
1695
1788
|
terminal.shutdownAll();
|
|
1789
|
+
mlx.shutdown();
|
|
1696
1790
|
registry.stop();
|
|
1697
1791
|
resources.stop();
|
|
1698
1792
|
if (uploadSweepTimer) clearInterval(uploadSweepTimer);
|
|
@@ -1702,4 +1796,21 @@ function shutdown() {
|
|
|
1702
1796
|
process.on('SIGINT', shutdown);
|
|
1703
1797
|
process.on('SIGTERM', shutdown);
|
|
1704
1798
|
|
|
1705
|
-
|
|
1799
|
+
// Safety nets: log unhandled async rejections; exit on truly uncaught sync
|
|
1800
|
+
// exceptions so Node doesn't continue with a corrupted process state.
|
|
1801
|
+
process.on('unhandledRejection', (e) => {
|
|
1802
|
+
// eslint-disable-next-line no-console
|
|
1803
|
+
console.error('[unhandledRejection]', e?.stack || e);
|
|
1804
|
+
});
|
|
1805
|
+
process.on('uncaughtException', (e) => {
|
|
1806
|
+
// eslint-disable-next-line no-console
|
|
1807
|
+
console.error('[uncaughtException]', e?.stack || e);
|
|
1808
|
+
process.exit(1);
|
|
1809
|
+
});
|
|
1810
|
+
|
|
1811
|
+
// Guard: only run the server when executed directly, not when imported for testing.
|
|
1812
|
+
const _isMain = process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
|
|
1813
|
+
if (_isMain) main();
|
|
1814
|
+
|
|
1815
|
+
// Exported for unit testing only — not part of the public API.
|
|
1816
|
+
export { endJson, _handler, runSerial };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{g as Ve}from"./index-D41aOqTB.js";function xe(e){return e instanceof Map?e.clear=e.delete=e.set=function(){throw new Error("map is read-only")}:e instanceof Set&&(e.add=e.clear=e.delete=function(){throw new Error("set is read-only")}),Object.freeze(e),Object.getOwnPropertyNames(e).forEach(t=>{const i=e[t],u=typeof i;(u==="object"||u==="function")&&!Object.isFrozen(i)&&xe(i)}),e}class he{constructor(t){t.data===void 0&&(t.data={}),this.data=t.data,this.isMatchIgnored=!1}ignoreMatch(){this.isMatchIgnored=!0}}function we(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function B(e,...t){const i=Object.create(null);for(const u in e)i[u]=e[u];return t.forEach(function(u){for(const b in u)i[b]=u[b]}),i}const qe="</span>",pe=e=>!!e.scope,Qe=(e,{prefix:t})=>{if(e.startsWith("language:"))return e.replace("language:","language-");if(e.includes(".")){const i=e.split(".");return[`${t}${i.shift()}`,...i.map((u,b)=>`${u}${"_".repeat(b+1)}`)].join(" ")}return`${t}${e}`};class me{constructor(t,i){this.buffer="",this.classPrefix=i.classPrefix,t.walk(this)}addText(t){this.buffer+=we(t)}openNode(t){if(!pe(t))return;const i=Qe(t.scope,{prefix:this.classPrefix});this.span(i)}closeNode(t){pe(t)&&(this.buffer+=qe)}value(){return this.buffer}span(t){this.buffer+=`<span class="${t}">`}}const de=(e={})=>{const t={children:[]};return Object.assign(t,e),t};class te{constructor(){this.rootNode=de(),this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(t){this.top.children.push(t)}openNode(t){const i=de({scope:t});this.add(i),this.stack.push(i)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(t){return this.constructor._walk(t,this.rootNode)}static _walk(t,i){return typeof i=="string"?t.addText(i):i.children&&(t.openNode(i),i.children.forEach(u=>this._walk(t,u)),t.closeNode(i)),t}static _collapse(t){typeof t!="string"&&t.children&&(t.children.every(i=>typeof i=="string")?t.children=[t.children.join("")]:t.children.forEach(i=>{te._collapse(i)}))}}class et extends te{constructor(t){super(),this.options=t}addText(t){t!==""&&this.add(t)}startScope(t){this.openNode(t)}endScope(){this.closeNode()}__addSublanguage(t,i){const u=t.root;i&&(u.scope=`language:${i}`),this.add(u)}toHTML(){return new me(this,this.options).value()}finalize(){return this.closeAllNodes(),!0}}function P(e){return e?typeof e=="string"?e:e.source:null}function Oe(e){return C("(?=",e,")")}function tt(e){return C("(?:",e,")*")}function nt(e){return C("(?:",e,")?")}function C(...e){return e.map(i=>P(i)).join("")}function it(e){const t=e[e.length-1];return typeof t=="object"&&t.constructor===Object?(e.splice(e.length-1,1),t):{}}function ne(...e){return"("+(it(e).capture?"":"?:")+e.map(u=>P(u)).join("|")+")"}function Re(e){return new RegExp(e.toString()+"|").exec("").length-1}function st(e,t){const i=e&&e.exec(t);return i&&i.index===0}const rt=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;function ie(e,{joinWith:t}){let i=0;return e.map(u=>{i+=1;const b=i;let _=P(u),c="";for(;_.length>0;){const r=rt.exec(_);if(!r){c+=_;break}c+=_.substring(0,r.index),_=_.substring(r.index+r[0].length),r[0][0]==="\\"&&r[1]?c+="\\"+String(Number(r[1])+b):(c+=r[0],r[0]==="("&&i++)}return c}).map(u=>`(${u})`).join(t)}const ct=/\b\B/,ye="[a-zA-Z]\\w*",se="[a-zA-Z_]\\w*",Se="\\b\\d+(\\.\\d+)?",Ne="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",Ae="\\b(0b[01]+)",ot="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",at=(e={})=>{const t=/^#![ ]*\//;return e.binary&&(e.begin=C(t,/.*\b/,e.binary,/\b.*/)),B({scope:"meta",begin:t,end:/$/,relevance:0,"on:begin":(i,u)=>{i.index!==0&&u.ignoreMatch()}},e)},U={begin:"\\\\[\\s\\S]",relevance:0},lt={scope:"string",begin:"'",end:"'",illegal:"\\n",contains:[U]},ut={scope:"string",begin:'"',end:'"',illegal:"\\n",contains:[U]},ft={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},Y=function(e,t,i={}){const u=B({scope:"comment",begin:e,end:t,contains:[]},i);u.contains.push({scope:"doctag",begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)",end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0});const b=ne("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/);return u.contains.push({begin:C(/[ ]+/,"(",b,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),u},gt=Y("//","$"),ht=Y("/\\*","\\*/"),pt=Y("#","$"),dt={scope:"number",begin:Se,relevance:0},Et={scope:"number",begin:Ne,relevance:0},bt={scope:"number",begin:Ae,relevance:0},_t={scope:"regexp",begin:/\/(?=[^/\n]*\/)/,end:/\/[gimuy]*/,contains:[U,{begin:/\[/,end:/\]/,relevance:0,contains:[U]}]},Mt={scope:"title",begin:ye,relevance:0},xt={scope:"title",begin:se,relevance:0},wt={begin:"\\.\\s*"+se,relevance:0},Ot=function(e){return Object.assign(e,{"on:begin":(t,i)=>{i.data._beginMatch=t[1]},"on:end":(t,i)=>{i.data._beginMatch!==t[1]&&i.ignoreMatch()}})};var z=Object.freeze({__proto__:null,APOS_STRING_MODE:lt,BACKSLASH_ESCAPE:U,BINARY_NUMBER_MODE:bt,BINARY_NUMBER_RE:Ae,COMMENT:Y,C_BLOCK_COMMENT_MODE:ht,C_LINE_COMMENT_MODE:gt,C_NUMBER_MODE:Et,C_NUMBER_RE:Ne,END_SAME_AS_BEGIN:Ot,HASH_COMMENT_MODE:pt,IDENT_RE:ye,MATCH_NOTHING_RE:ct,METHOD_GUARD:wt,NUMBER_MODE:dt,NUMBER_RE:Se,PHRASAL_WORDS_MODE:ft,QUOTE_STRING_MODE:ut,REGEXP_MODE:_t,RE_STARTERS_RE:ot,SHEBANG:at,TITLE_MODE:Mt,UNDERSCORE_IDENT_RE:se,UNDERSCORE_TITLE_MODE:xt});function Rt(e,t){e.input[e.index-1]==="."&&t.ignoreMatch()}function yt(e,t){e.className!==void 0&&(e.scope=e.className,delete e.className)}function St(e,t){t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)",e.__beforeBegin=Rt,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords,e.relevance===void 0&&(e.relevance=0))}function Nt(e,t){Array.isArray(e.illegal)&&(e.illegal=ne(...e.illegal))}function At(e,t){if(e.match){if(e.begin||e.end)throw new Error("begin & end are not supported with match");e.begin=e.match,delete e.match}}function kt(e,t){e.relevance===void 0&&(e.relevance=1)}const Tt=(e,t)=>{if(!e.beforeMatch)return;if(e.starts)throw new Error("beforeMatch cannot be used with starts");const i=Object.assign({},e);Object.keys(e).forEach(u=>{delete e[u]}),e.keywords=i.keywords,e.begin=C(i.beforeMatch,Oe(i.begin)),e.starts={relevance:0,contains:[Object.assign(i,{endsParent:!0})]},e.relevance=0,delete i.beforeMatch},It=["of","and","for","in","not","or","if","then","parent","list","value"],Bt="keyword";function ke(e,t,i=Bt){const u=Object.create(null);return typeof e=="string"?b(i,e.split(" ")):Array.isArray(e)?b(i,e):Object.keys(e).forEach(function(_){Object.assign(u,ke(e[_],t,_))}),u;function b(_,c){t&&(c=c.map(r=>r.toLowerCase())),c.forEach(function(r){const l=r.split("|");u[l[0]]=[_,Dt(l[0],l[1])]})}}function Dt(e,t){return t?Number(t):vt(e)?0:1}function vt(e){return It.includes(e.toLowerCase())}const Ee={},v=e=>{console.error(e)},be=(e,...t)=>{console.log(`WARN: ${e}`,...t)},L=(e,t)=>{Ee[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),Ee[`${e}/${t}`]=!0)},X=new Error;function Te(e,t,{key:i}){let u=0;const b=e[i],_={},c={};for(let r=1;r<=t.length;r++)c[r+u]=b[r],_[r+u]=!0,u+=Re(t[r-1]);e[i]=c,e[i]._emit=_,e[i]._multi=!0}function Ct(e){if(Array.isArray(e.begin)){if(e.skip||e.excludeBegin||e.returnBegin)throw v("skip, excludeBegin, returnBegin not compatible with beginScope: {}"),X;if(typeof e.beginScope!="object"||e.beginScope===null)throw v("beginScope must be object"),X;Te(e,e.begin,{key:"beginScope"}),e.begin=ie(e.begin,{joinWith:""})}}function Lt(e){if(Array.isArray(e.end)){if(e.skip||e.excludeEnd||e.returnEnd)throw v("skip, excludeEnd, returnEnd not compatible with endScope: {}"),X;if(typeof e.endScope!="object"||e.endScope===null)throw v("endScope must be object"),X;Te(e,e.end,{key:"endScope"}),e.end=ie(e.end,{joinWith:""})}}function Ht(e){e.scope&&typeof e.scope=="object"&&e.scope!==null&&(e.beginScope=e.scope,delete e.scope)}function jt(e){Ht(e),typeof e.beginScope=="string"&&(e.beginScope={_wrap:e.beginScope}),typeof e.endScope=="string"&&(e.endScope={_wrap:e.endScope}),Ct(e),Lt(e)}function Pt(e){function t(c,r){return new RegExp(P(c),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(r?"g":""))}class i{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(r,l){l.position=this.position++,this.matchIndexes[this.matchAt]=l,this.regexes.push([l,r]),this.matchAt+=Re(r)+1}compile(){this.regexes.length===0&&(this.exec=()=>null);const r=this.regexes.map(l=>l[1]);this.matcherRe=t(ie(r,{joinWith:"|"}),!0),this.lastIndex=0}exec(r){this.matcherRe.lastIndex=this.lastIndex;const l=this.matcherRe.exec(r);if(!l)return null;const w=l.findIndex((j,Z)=>Z>0&&j!==void 0),M=this.matchIndexes[w];return l.splice(0,w),Object.assign(l,M)}}class u{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(r){if(this.multiRegexes[r])return this.multiRegexes[r];const l=new i;return this.rules.slice(r).forEach(([w,M])=>l.addRule(w,M)),l.compile(),this.multiRegexes[r]=l,l}resumingScanAtSamePosition(){return this.regexIndex!==0}considerAll(){this.regexIndex=0}addRule(r,l){this.rules.push([r,l]),l.type==="begin"&&this.count++}exec(r){const l=this.getMatcher(this.regexIndex);l.lastIndex=this.lastIndex;let w=l.exec(r);if(this.resumingScanAtSamePosition()&&!(w&&w.index===this.lastIndex)){const M=this.getMatcher(0);M.lastIndex=this.lastIndex+1,w=M.exec(r)}return w&&(this.regexIndex+=w.position+1,this.regexIndex===this.count&&this.considerAll()),w}}function b(c){const r=new u;return c.contains.forEach(l=>r.addRule(l.begin,{rule:l,type:"begin"})),c.terminatorEnd&&r.addRule(c.terminatorEnd,{type:"end"}),c.illegal&&r.addRule(c.illegal,{type:"illegal"}),r}function _(c,r){const l=c;if(c.isCompiled)return l;[yt,At,jt,Tt].forEach(M=>M(c,r)),e.compilerExtensions.forEach(M=>M(c,r)),c.__beforeBegin=null,[St,Nt,kt].forEach(M=>M(c,r)),c.isCompiled=!0;let w=null;return typeof c.keywords=="object"&&c.keywords.$pattern&&(c.keywords=Object.assign({},c.keywords),w=c.keywords.$pattern,delete c.keywords.$pattern),w=w||/\w+/,c.keywords&&(c.keywords=ke(c.keywords,e.case_insensitive)),l.keywordPatternRe=t(w,!0),r&&(c.begin||(c.begin=/\B|\b/),l.beginRe=t(l.begin),!c.end&&!c.endsWithParent&&(c.end=/\B|\b/),c.end&&(l.endRe=t(l.end)),l.terminatorEnd=P(l.end)||"",c.endsWithParent&&r.terminatorEnd&&(l.terminatorEnd+=(c.end?"|":"")+r.terminatorEnd)),c.illegal&&(l.illegalRe=t(c.illegal)),c.contains||(c.contains=[]),c.contains=[].concat(...c.contains.map(function(M){return Ut(M==="self"?c:M)})),c.contains.forEach(function(M){_(M,l)}),c.starts&&_(c.starts,r),l.matcher=b(l),l}if(e.compilerExtensions||(e.compilerExtensions=[]),e.contains&&e.contains.includes("self"))throw new Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return e.classNameAliases=B(e.classNameAliases||{}),_(e)}function Ie(e){return e?e.endsWithParent||Ie(e.starts):!1}function Ut(e){return e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map(function(t){return B(e,{variants:null},t)})),e.cachedVariants?e.cachedVariants:Ie(e)?B(e,{starts:e.starts?B(e.starts):null}):Object.isFrozen(e)?B(e):e}var $t="11.11.1";class Gt extends Error{constructor(t,i){super(t),this.name="HTMLInjectionError",this.html=i}}const ee=we,_e=B,Me=Symbol("nomatch"),Wt=7,Be=function(e){const t=Object.create(null),i=Object.create(null),u=[];let b=!0;const _="Could not find the language '{}', did you forget to load/include a language module?",c={disableAutodetect:!0,name:"Plain text",contains:[]};let r={ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",cssSelector:"pre code",languages:null,__emitter:et};function l(n){return r.noHighlightRe.test(n)}function w(n){let a=n.className+" ";a+=n.parentNode?n.parentNode.className:"";const h=r.languageDetectRe.exec(a);if(h){const d=T(h[1]);return d||(be(_.replace("{}",h[1])),be("Falling back to no-highlight mode for this block.",n)),d?h[1]:"no-highlight"}return a.split(/\s+/).find(d=>l(d)||T(d))}function M(n,a,h){let d="",x="";typeof a=="object"?(d=n,h=a.ignoreIllegals,x=a.language):(L("10.7.0","highlight(lang, code, ...args) has been deprecated."),L("10.7.0",`Please use highlight(code, options) instead.
|
|
1
|
+
import{g as Ve}from"./index-DFru8Gzx.js";function xe(e){return e instanceof Map?e.clear=e.delete=e.set=function(){throw new Error("map is read-only")}:e instanceof Set&&(e.add=e.clear=e.delete=function(){throw new Error("set is read-only")}),Object.freeze(e),Object.getOwnPropertyNames(e).forEach(t=>{const i=e[t],u=typeof i;(u==="object"||u==="function")&&!Object.isFrozen(i)&&xe(i)}),e}class he{constructor(t){t.data===void 0&&(t.data={}),this.data=t.data,this.isMatchIgnored=!1}ignoreMatch(){this.isMatchIgnored=!0}}function we(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function B(e,...t){const i=Object.create(null);for(const u in e)i[u]=e[u];return t.forEach(function(u){for(const b in u)i[b]=u[b]}),i}const qe="</span>",pe=e=>!!e.scope,Qe=(e,{prefix:t})=>{if(e.startsWith("language:"))return e.replace("language:","language-");if(e.includes(".")){const i=e.split(".");return[`${t}${i.shift()}`,...i.map((u,b)=>`${u}${"_".repeat(b+1)}`)].join(" ")}return`${t}${e}`};class me{constructor(t,i){this.buffer="",this.classPrefix=i.classPrefix,t.walk(this)}addText(t){this.buffer+=we(t)}openNode(t){if(!pe(t))return;const i=Qe(t.scope,{prefix:this.classPrefix});this.span(i)}closeNode(t){pe(t)&&(this.buffer+=qe)}value(){return this.buffer}span(t){this.buffer+=`<span class="${t}">`}}const de=(e={})=>{const t={children:[]};return Object.assign(t,e),t};class te{constructor(){this.rootNode=de(),this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(t){this.top.children.push(t)}openNode(t){const i=de({scope:t});this.add(i),this.stack.push(i)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(t){return this.constructor._walk(t,this.rootNode)}static _walk(t,i){return typeof i=="string"?t.addText(i):i.children&&(t.openNode(i),i.children.forEach(u=>this._walk(t,u)),t.closeNode(i)),t}static _collapse(t){typeof t!="string"&&t.children&&(t.children.every(i=>typeof i=="string")?t.children=[t.children.join("")]:t.children.forEach(i=>{te._collapse(i)}))}}class et extends te{constructor(t){super(),this.options=t}addText(t){t!==""&&this.add(t)}startScope(t){this.openNode(t)}endScope(){this.closeNode()}__addSublanguage(t,i){const u=t.root;i&&(u.scope=`language:${i}`),this.add(u)}toHTML(){return new me(this,this.options).value()}finalize(){return this.closeAllNodes(),!0}}function P(e){return e?typeof e=="string"?e:e.source:null}function Oe(e){return C("(?=",e,")")}function tt(e){return C("(?:",e,")*")}function nt(e){return C("(?:",e,")?")}function C(...e){return e.map(i=>P(i)).join("")}function it(e){const t=e[e.length-1];return typeof t=="object"&&t.constructor===Object?(e.splice(e.length-1,1),t):{}}function ne(...e){return"("+(it(e).capture?"":"?:")+e.map(u=>P(u)).join("|")+")"}function Re(e){return new RegExp(e.toString()+"|").exec("").length-1}function st(e,t){const i=e&&e.exec(t);return i&&i.index===0}const rt=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;function ie(e,{joinWith:t}){let i=0;return e.map(u=>{i+=1;const b=i;let _=P(u),c="";for(;_.length>0;){const r=rt.exec(_);if(!r){c+=_;break}c+=_.substring(0,r.index),_=_.substring(r.index+r[0].length),r[0][0]==="\\"&&r[1]?c+="\\"+String(Number(r[1])+b):(c+=r[0],r[0]==="("&&i++)}return c}).map(u=>`(${u})`).join(t)}const ct=/\b\B/,ye="[a-zA-Z]\\w*",se="[a-zA-Z_]\\w*",Se="\\b\\d+(\\.\\d+)?",Ne="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",Ae="\\b(0b[01]+)",ot="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",at=(e={})=>{const t=/^#![ ]*\//;return e.binary&&(e.begin=C(t,/.*\b/,e.binary,/\b.*/)),B({scope:"meta",begin:t,end:/$/,relevance:0,"on:begin":(i,u)=>{i.index!==0&&u.ignoreMatch()}},e)},U={begin:"\\\\[\\s\\S]",relevance:0},lt={scope:"string",begin:"'",end:"'",illegal:"\\n",contains:[U]},ut={scope:"string",begin:'"',end:'"',illegal:"\\n",contains:[U]},ft={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},Y=function(e,t,i={}){const u=B({scope:"comment",begin:e,end:t,contains:[]},i);u.contains.push({scope:"doctag",begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)",end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0});const b=ne("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/);return u.contains.push({begin:C(/[ ]+/,"(",b,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),u},gt=Y("//","$"),ht=Y("/\\*","\\*/"),pt=Y("#","$"),dt={scope:"number",begin:Se,relevance:0},Et={scope:"number",begin:Ne,relevance:0},bt={scope:"number",begin:Ae,relevance:0},_t={scope:"regexp",begin:/\/(?=[^/\n]*\/)/,end:/\/[gimuy]*/,contains:[U,{begin:/\[/,end:/\]/,relevance:0,contains:[U]}]},Mt={scope:"title",begin:ye,relevance:0},xt={scope:"title",begin:se,relevance:0},wt={begin:"\\.\\s*"+se,relevance:0},Ot=function(e){return Object.assign(e,{"on:begin":(t,i)=>{i.data._beginMatch=t[1]},"on:end":(t,i)=>{i.data._beginMatch!==t[1]&&i.ignoreMatch()}})};var z=Object.freeze({__proto__:null,APOS_STRING_MODE:lt,BACKSLASH_ESCAPE:U,BINARY_NUMBER_MODE:bt,BINARY_NUMBER_RE:Ae,COMMENT:Y,C_BLOCK_COMMENT_MODE:ht,C_LINE_COMMENT_MODE:gt,C_NUMBER_MODE:Et,C_NUMBER_RE:Ne,END_SAME_AS_BEGIN:Ot,HASH_COMMENT_MODE:pt,IDENT_RE:ye,MATCH_NOTHING_RE:ct,METHOD_GUARD:wt,NUMBER_MODE:dt,NUMBER_RE:Se,PHRASAL_WORDS_MODE:ft,QUOTE_STRING_MODE:ut,REGEXP_MODE:_t,RE_STARTERS_RE:ot,SHEBANG:at,TITLE_MODE:Mt,UNDERSCORE_IDENT_RE:se,UNDERSCORE_TITLE_MODE:xt});function Rt(e,t){e.input[e.index-1]==="."&&t.ignoreMatch()}function yt(e,t){e.className!==void 0&&(e.scope=e.className,delete e.className)}function St(e,t){t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)",e.__beforeBegin=Rt,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords,e.relevance===void 0&&(e.relevance=0))}function Nt(e,t){Array.isArray(e.illegal)&&(e.illegal=ne(...e.illegal))}function At(e,t){if(e.match){if(e.begin||e.end)throw new Error("begin & end are not supported with match");e.begin=e.match,delete e.match}}function kt(e,t){e.relevance===void 0&&(e.relevance=1)}const Tt=(e,t)=>{if(!e.beforeMatch)return;if(e.starts)throw new Error("beforeMatch cannot be used with starts");const i=Object.assign({},e);Object.keys(e).forEach(u=>{delete e[u]}),e.keywords=i.keywords,e.begin=C(i.beforeMatch,Oe(i.begin)),e.starts={relevance:0,contains:[Object.assign(i,{endsParent:!0})]},e.relevance=0,delete i.beforeMatch},It=["of","and","for","in","not","or","if","then","parent","list","value"],Bt="keyword";function ke(e,t,i=Bt){const u=Object.create(null);return typeof e=="string"?b(i,e.split(" ")):Array.isArray(e)?b(i,e):Object.keys(e).forEach(function(_){Object.assign(u,ke(e[_],t,_))}),u;function b(_,c){t&&(c=c.map(r=>r.toLowerCase())),c.forEach(function(r){const l=r.split("|");u[l[0]]=[_,Dt(l[0],l[1])]})}}function Dt(e,t){return t?Number(t):vt(e)?0:1}function vt(e){return It.includes(e.toLowerCase())}const Ee={},v=e=>{console.error(e)},be=(e,...t)=>{console.log(`WARN: ${e}`,...t)},L=(e,t)=>{Ee[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),Ee[`${e}/${t}`]=!0)},X=new Error;function Te(e,t,{key:i}){let u=0;const b=e[i],_={},c={};for(let r=1;r<=t.length;r++)c[r+u]=b[r],_[r+u]=!0,u+=Re(t[r-1]);e[i]=c,e[i]._emit=_,e[i]._multi=!0}function Ct(e){if(Array.isArray(e.begin)){if(e.skip||e.excludeBegin||e.returnBegin)throw v("skip, excludeBegin, returnBegin not compatible with beginScope: {}"),X;if(typeof e.beginScope!="object"||e.beginScope===null)throw v("beginScope must be object"),X;Te(e,e.begin,{key:"beginScope"}),e.begin=ie(e.begin,{joinWith:""})}}function Lt(e){if(Array.isArray(e.end)){if(e.skip||e.excludeEnd||e.returnEnd)throw v("skip, excludeEnd, returnEnd not compatible with endScope: {}"),X;if(typeof e.endScope!="object"||e.endScope===null)throw v("endScope must be object"),X;Te(e,e.end,{key:"endScope"}),e.end=ie(e.end,{joinWith:""})}}function Ht(e){e.scope&&typeof e.scope=="object"&&e.scope!==null&&(e.beginScope=e.scope,delete e.scope)}function jt(e){Ht(e),typeof e.beginScope=="string"&&(e.beginScope={_wrap:e.beginScope}),typeof e.endScope=="string"&&(e.endScope={_wrap:e.endScope}),Ct(e),Lt(e)}function Pt(e){function t(c,r){return new RegExp(P(c),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(r?"g":""))}class i{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(r,l){l.position=this.position++,this.matchIndexes[this.matchAt]=l,this.regexes.push([l,r]),this.matchAt+=Re(r)+1}compile(){this.regexes.length===0&&(this.exec=()=>null);const r=this.regexes.map(l=>l[1]);this.matcherRe=t(ie(r,{joinWith:"|"}),!0),this.lastIndex=0}exec(r){this.matcherRe.lastIndex=this.lastIndex;const l=this.matcherRe.exec(r);if(!l)return null;const w=l.findIndex((j,Z)=>Z>0&&j!==void 0),M=this.matchIndexes[w];return l.splice(0,w),Object.assign(l,M)}}class u{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(r){if(this.multiRegexes[r])return this.multiRegexes[r];const l=new i;return this.rules.slice(r).forEach(([w,M])=>l.addRule(w,M)),l.compile(),this.multiRegexes[r]=l,l}resumingScanAtSamePosition(){return this.regexIndex!==0}considerAll(){this.regexIndex=0}addRule(r,l){this.rules.push([r,l]),l.type==="begin"&&this.count++}exec(r){const l=this.getMatcher(this.regexIndex);l.lastIndex=this.lastIndex;let w=l.exec(r);if(this.resumingScanAtSamePosition()&&!(w&&w.index===this.lastIndex)){const M=this.getMatcher(0);M.lastIndex=this.lastIndex+1,w=M.exec(r)}return w&&(this.regexIndex+=w.position+1,this.regexIndex===this.count&&this.considerAll()),w}}function b(c){const r=new u;return c.contains.forEach(l=>r.addRule(l.begin,{rule:l,type:"begin"})),c.terminatorEnd&&r.addRule(c.terminatorEnd,{type:"end"}),c.illegal&&r.addRule(c.illegal,{type:"illegal"}),r}function _(c,r){const l=c;if(c.isCompiled)return l;[yt,At,jt,Tt].forEach(M=>M(c,r)),e.compilerExtensions.forEach(M=>M(c,r)),c.__beforeBegin=null,[St,Nt,kt].forEach(M=>M(c,r)),c.isCompiled=!0;let w=null;return typeof c.keywords=="object"&&c.keywords.$pattern&&(c.keywords=Object.assign({},c.keywords),w=c.keywords.$pattern,delete c.keywords.$pattern),w=w||/\w+/,c.keywords&&(c.keywords=ke(c.keywords,e.case_insensitive)),l.keywordPatternRe=t(w,!0),r&&(c.begin||(c.begin=/\B|\b/),l.beginRe=t(l.begin),!c.end&&!c.endsWithParent&&(c.end=/\B|\b/),c.end&&(l.endRe=t(l.end)),l.terminatorEnd=P(l.end)||"",c.endsWithParent&&r.terminatorEnd&&(l.terminatorEnd+=(c.end?"|":"")+r.terminatorEnd)),c.illegal&&(l.illegalRe=t(c.illegal)),c.contains||(c.contains=[]),c.contains=[].concat(...c.contains.map(function(M){return Ut(M==="self"?c:M)})),c.contains.forEach(function(M){_(M,l)}),c.starts&&_(c.starts,r),l.matcher=b(l),l}if(e.compilerExtensions||(e.compilerExtensions=[]),e.contains&&e.contains.includes("self"))throw new Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return e.classNameAliases=B(e.classNameAliases||{}),_(e)}function Ie(e){return e?e.endsWithParent||Ie(e.starts):!1}function Ut(e){return e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map(function(t){return B(e,{variants:null},t)})),e.cachedVariants?e.cachedVariants:Ie(e)?B(e,{starts:e.starts?B(e.starts):null}):Object.isFrozen(e)?B(e):e}var $t="11.11.1";class Gt extends Error{constructor(t,i){super(t),this.name="HTMLInjectionError",this.html=i}}const ee=we,_e=B,Me=Symbol("nomatch"),Wt=7,Be=function(e){const t=Object.create(null),i=Object.create(null),u=[];let b=!0;const _="Could not find the language '{}', did you forget to load/include a language module?",c={disableAutodetect:!0,name:"Plain text",contains:[]};let r={ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",cssSelector:"pre code",languages:null,__emitter:et};function l(n){return r.noHighlightRe.test(n)}function w(n){let a=n.className+" ";a+=n.parentNode?n.parentNode.className:"";const h=r.languageDetectRe.exec(a);if(h){const d=T(h[1]);return d||(be(_.replace("{}",h[1])),be("Falling back to no-highlight mode for this block.",n)),d?h[1]:"no-highlight"}return a.split(/\s+/).find(d=>l(d)||T(d))}function M(n,a,h){let d="",x="";typeof a=="object"?(d=n,h=a.ignoreIllegals,x=a.language):(L("10.7.0","highlight(lang, code, ...args) has been deprecated."),L("10.7.0",`Please use highlight(code, options) instead.
|
|
2
2
|
https://github.com/highlightjs/highlight.js/issues/2277`),x=n,d=a),h===void 0&&(h=!0);const S={code:d,language:x};G("before:highlight",S);const I=S.result?S.result:j(S.language,S.code,h);return I.code=S.code,G("after:highlight",I),I}function j(n,a,h,d){const x=Object.create(null);function S(s,o){return s.keywords[o]}function I(){if(!f.keywords){O.addText(E);return}let s=0;f.keywordPatternRe.lastIndex=0;let o=f.keywordPatternRe.exec(E),g="";for(;o;){g+=E.substring(s,o.index);const p=A.case_insensitive?o[0].toLowerCase():o[0],R=S(f,p);if(R){const[k,Ze]=R;if(O.addText(g),g="",x[p]=(x[p]||0)+1,x[p]<=Wt&&(F+=Ze),k.startsWith("_"))g+=o[0];else{const Je=A.classNameAliases[k]||k;N(o[0],Je)}}else g+=o[0];s=f.keywordPatternRe.lastIndex,o=f.keywordPatternRe.exec(E)}g+=E.substring(s),O.addText(g)}function W(){if(E==="")return;let s=null;if(typeof f.subLanguage=="string"){if(!t[f.subLanguage]){O.addText(E);return}s=j(f.subLanguage,E,!0,ge[f.subLanguage]),ge[f.subLanguage]=s._top}else s=J(E,f.subLanguage.length?f.subLanguage:null);f.relevance>0&&(F+=s.relevance),O.__addSublanguage(s._emitter,s.language)}function y(){f.subLanguage!=null?W():I(),E=""}function N(s,o){s!==""&&(O.startScope(o),O.addText(s),O.endScope())}function ae(s,o){let g=1;const p=o.length-1;for(;g<=p;){if(!s._emit[g]){g++;continue}const R=A.classNameAliases[s[g]]||s[g],k=o[g];R?N(k,R):(E=k,I(),E=""),g++}}function le(s,o){return s.scope&&typeof s.scope=="string"&&O.openNode(A.classNameAliases[s.scope]||s.scope),s.beginScope&&(s.beginScope._wrap?(N(E,A.classNameAliases[s.beginScope._wrap]||s.beginScope._wrap),E=""):s.beginScope._multi&&(ae(s.beginScope,o),E="")),f=Object.create(s,{parent:{value:f}}),f}function ue(s,o,g){let p=st(s.endRe,g);if(p){if(s["on:end"]){const R=new he(s);s["on:end"](o,R),R.isMatchIgnored&&(p=!1)}if(p){for(;s.endsParent&&s.parent;)s=s.parent;return s}}if(s.endsWithParent)return ue(s.parent,o,g)}function Ke(s){return f.matcher.regexIndex===0?(E+=s[0],1):(m=!0,0)}function Fe(s){const o=s[0],g=s.rule,p=new he(g),R=[g.__beforeBegin,g["on:begin"]];for(const k of R)if(k&&(k(s,p),p.isMatchIgnored))return Ke(o);return g.skip?E+=o:(g.excludeBegin&&(E+=o),y(),!g.returnBegin&&!g.excludeBegin&&(E=o)),le(g,s),g.returnBegin?0:o.length}function ze(s){const o=s[0],g=a.substring(s.index),p=ue(f,s,g);if(!p)return Me;const R=f;f.endScope&&f.endScope._wrap?(y(),N(o,f.endScope._wrap)):f.endScope&&f.endScope._multi?(y(),ae(f.endScope,s)):R.skip?E+=o:(R.returnEnd||R.excludeEnd||(E+=o),y(),R.excludeEnd&&(E=o));do f.scope&&O.closeNode(),!f.skip&&!f.subLanguage&&(F+=f.relevance),f=f.parent;while(f!==p.parent);return p.starts&&le(p.starts,s),R.returnEnd?0:o.length}function Xe(){const s=[];for(let o=f;o!==A;o=o.parent)o.scope&&s.unshift(o.scope);s.forEach(o=>O.openNode(o))}let K={};function fe(s,o){const g=o&&o[0];if(E+=s,g==null)return y(),0;if(K.type==="begin"&&o.type==="end"&&K.index===o.index&&g===""){if(E+=a.slice(o.index,o.index+1),!b){const p=new Error(`0 width match regex (${n})`);throw p.languageName=n,p.badRule=K.rule,p}return 1}if(K=o,o.type==="begin")return Fe(o);if(o.type==="illegal"&&!h){const p=new Error('Illegal lexeme "'+g+'" for mode "'+(f.scope||"<unnamed>")+'"');throw p.mode=f,p}else if(o.type==="end"){const p=ze(o);if(p!==Me)return p}if(o.type==="illegal"&&g==="")return E+=`
|
|
3
3
|
`,1;if(Q>1e5&&Q>o.index*3)throw new Error("potential infinite loop, way more iterations than matches");return E+=g,g.length}const A=T(n);if(!A)throw v(_.replace("{}",n)),new Error('Unknown language: "'+n+'"');const Ye=Pt(A);let q="",f=d||Ye;const ge={},O=new r.__emitter(r);Xe();let E="",F=0,D=0,Q=0,m=!1;try{if(A.__emitTokens)A.__emitTokens(a,O);else{for(f.matcher.considerAll();;){Q++,m?m=!1:f.matcher.considerAll(),f.matcher.lastIndex=D;const s=f.matcher.exec(a);if(!s)break;const o=a.substring(D,s.index),g=fe(o,s);D=s.index+g}fe(a.substring(D))}return O.finalize(),q=O.toHTML(),{language:n,value:q,relevance:F,illegal:!1,_emitter:O,_top:f}}catch(s){if(s.message&&s.message.includes("Illegal"))return{language:n,value:ee(a),illegal:!0,relevance:0,_illegalBy:{message:s.message,index:D,context:a.slice(D-100,D+100),mode:s.mode,resultSoFar:q},_emitter:O};if(b)return{language:n,value:ee(a),illegal:!1,relevance:0,errorRaised:s,_emitter:O,_top:f};throw s}}function Z(n){const a={value:ee(n),illegal:!1,relevance:0,_top:c,_emitter:new r.__emitter(r)};return a._emitter.addText(n),a}function J(n,a){a=a||r.languages||Object.keys(t);const h=Z(n),d=a.filter(T).filter(oe).map(y=>j(y,n,!1));d.unshift(h);const x=d.sort((y,N)=>{if(y.relevance!==N.relevance)return N.relevance-y.relevance;if(y.language&&N.language){if(T(y.language).supersetOf===N.language)return 1;if(T(N.language).supersetOf===y.language)return-1}return 0}),[S,I]=x,W=S;return W.secondBest=I,W}function De(n,a,h){const d=a&&i[a]||h;n.classList.add("hljs"),n.classList.add(`language-${d}`)}function V(n){let a=null;const h=w(n);if(l(h))return;if(G("before:highlightElement",{el:n,language:h}),n.dataset.highlighted){console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.",n);return}if(n.children.length>0&&(r.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."),console.warn("https://github.com/highlightjs/highlight.js/wiki/security"),console.warn("The element with unescaped HTML:"),console.warn(n)),r.throwUnescapedHTML))throw new Gt("One of your code blocks includes unescaped HTML.",n.innerHTML);a=n;const d=a.textContent,x=h?M(d,{language:h,ignoreIllegals:!0}):J(d);n.innerHTML=x.value,n.dataset.highlighted="yes",De(n,h,x.language),n.result={language:x.language,re:x.relevance,relevance:x.relevance},x.secondBest&&(n.secondBest={language:x.secondBest.language,relevance:x.secondBest.relevance}),G("after:highlightElement",{el:n,result:x,text:d})}function ve(n){r=_e(r,n)}const Ce=()=>{$(),L("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")};function Le(){$(),L("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.")}let re=!1;function $(){function n(){$()}if(document.readyState==="loading"){re||window.addEventListener("DOMContentLoaded",n,!1),re=!0;return}document.querySelectorAll(r.cssSelector).forEach(V)}function He(n,a){let h=null;try{h=a(e)}catch(d){if(v("Language definition for '{}' could not be registered.".replace("{}",n)),b)v(d);else throw d;h=c}h.name||(h.name=n),t[n]=h,h.rawDefinition=a.bind(null,e),h.aliases&&ce(h.aliases,{languageName:n})}function je(n){delete t[n];for(const a of Object.keys(i))i[a]===n&&delete i[a]}function Pe(){return Object.keys(t)}function T(n){return n=(n||"").toLowerCase(),t[n]||t[i[n]]}function ce(n,{languageName:a}){typeof n=="string"&&(n=[n]),n.forEach(h=>{i[h.toLowerCase()]=a})}function oe(n){const a=T(n);return a&&!a.disableAutodetect}function Ue(n){n["before:highlightBlock"]&&!n["before:highlightElement"]&&(n["before:highlightElement"]=a=>{n["before:highlightBlock"](Object.assign({block:a.el},a))}),n["after:highlightBlock"]&&!n["after:highlightElement"]&&(n["after:highlightElement"]=a=>{n["after:highlightBlock"](Object.assign({block:a.el},a))})}function $e(n){Ue(n),u.push(n)}function Ge(n){const a=u.indexOf(n);a!==-1&&u.splice(a,1)}function G(n,a){const h=n;u.forEach(function(d){d[h]&&d[h](a)})}function We(n){return L("10.7.0","highlightBlock will be removed entirely in v12.0"),L("10.7.0","Please use highlightElement now."),V(n)}Object.assign(e,{highlight:M,highlightAuto:J,highlightAll:$,highlightElement:V,highlightBlock:We,configure:ve,initHighlighting:Ce,initHighlightingOnLoad:Le,registerLanguage:He,unregisterLanguage:je,listLanguages:Pe,getLanguage:T,registerAliases:ce,autoDetection:oe,inherit:_e,addPlugin:$e,removePlugin:Ge}),e.debugMode=function(){b=!1},e.safeMode=function(){b=!0},e.versionString=$t,e.regex={concat:C,lookahead:Oe,either:ne,optional:nt,anyNumberOfTimes:tt};for(const n in z)typeof z[n]=="object"&&xe(z[n]);return Object.assign(e,z),e},H=Be({});H.newInstance=()=>Be({});var Kt=H;H.HighlightJS=H;H.default=H;const zt=Ve(Kt);export{zt as HighlightJS,zt as default};
|