@idl3/claude-control 0.1.20 → 0.1.21
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/answer.js +335 -9
- package/lib/claude-cli.js +170 -0
- package/lib/config.js +47 -3
- package/lib/match.js +13 -0
- package/lib/optimize.js +222 -0
- package/lib/push.js +14 -1
- package/lib/skills.js +147 -0
- package/lib/subagents.js +153 -2
- package/lib/transcribe.js +156 -0
- package/package.json +1 -1
- package/server.js +288 -16
- package/web/dist/assets/{core-BP70UsO-.js → core-CyYMg33t.js} +1 -1
- package/web/dist/assets/index-BeJg6Cs1.js +85 -0
- package/web/dist/assets/index-Dn7NDGPq.css +1 -0
- package/web/dist/index.html +2 -2
- package/web/dist/sw.js +4 -1
- package/web/dist/assets/index-D2hrAUsb.js +0 -78
- package/web/dist/assets/index-DM_QgpOD.css +0 -1
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/transcribe.js — local speech-to-text via ffmpeg + whisper.cpp.
|
|
3
|
+
*
|
|
4
|
+
* No API key, no cloud: transcodes the uploaded audio to 16kHz mono WAV with
|
|
5
|
+
* ffmpeg, then runs the whisper-cli binary (brew install whisper-cpp) against a
|
|
6
|
+
* local ggml model. Works for any browser that can record audio (incl. iOS
|
|
7
|
+
* Safari), which the Web Speech API does not.
|
|
8
|
+
*
|
|
9
|
+
* Exports:
|
|
10
|
+
* - resolveFfmpeg() / resolveWhisperBin() / resolveWhisperModel() → string | null
|
|
11
|
+
* - cleanTranscript(raw) → string (pure; strips timestamps/blank markers)
|
|
12
|
+
* - transcribe(inputPath, { lang }) → Promise<string>
|
|
13
|
+
*
|
|
14
|
+
* Binary/model resolution is overridable via env (FFMPEG_BIN, WHISPER_BIN,
|
|
15
|
+
* WHISPER_MODEL) and defaults to Homebrew + ~/.claude-control/models.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import fs from 'node:fs';
|
|
19
|
+
import path from 'node:path';
|
|
20
|
+
import os from 'node:os';
|
|
21
|
+
import { spawn, execFileSync } from 'node:child_process';
|
|
22
|
+
|
|
23
|
+
const MODELS_DIR = path.join(os.homedir(), '.claude-control', 'models');
|
|
24
|
+
|
|
25
|
+
/** Resolve a binary: env override → `which` → known fallbacks. */
|
|
26
|
+
function resolveBin(name, envVar, fallbacks) {
|
|
27
|
+
const e = process.env[envVar];
|
|
28
|
+
if (e && e.trim() && fs.existsSync(e.trim())) return e.trim();
|
|
29
|
+
try {
|
|
30
|
+
const w = execFileSync('which', [name], { encoding: 'utf8' }).trim();
|
|
31
|
+
if (w && fs.existsSync(w)) return w;
|
|
32
|
+
} catch {
|
|
33
|
+
/* not on PATH */
|
|
34
|
+
}
|
|
35
|
+
for (const f of fallbacks) if (fs.existsSync(f)) return f;
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** @returns {string | null} */
|
|
40
|
+
export function resolveFfmpeg() {
|
|
41
|
+
return resolveBin('ffmpeg', 'FFMPEG_BIN', [
|
|
42
|
+
'/opt/homebrew/bin/ffmpeg',
|
|
43
|
+
'/usr/local/bin/ffmpeg',
|
|
44
|
+
'/usr/bin/ffmpeg',
|
|
45
|
+
]);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** @returns {string | null} */
|
|
49
|
+
export function resolveWhisperBin() {
|
|
50
|
+
return resolveBin('whisper-cli', 'WHISPER_BIN', [
|
|
51
|
+
'/opt/homebrew/bin/whisper-cli',
|
|
52
|
+
'/usr/local/bin/whisper-cli',
|
|
53
|
+
]);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Resolve the ggml model: WHISPER_MODEL env → preferred names in the models
|
|
58
|
+
* dir → any `ggml-*.bin` there.
|
|
59
|
+
* @returns {string | null}
|
|
60
|
+
*/
|
|
61
|
+
export function resolveWhisperModel() {
|
|
62
|
+
const e = process.env.WHISPER_MODEL;
|
|
63
|
+
if (e && e.trim() && fs.existsSync(e.trim())) return e.trim();
|
|
64
|
+
const prefs = [
|
|
65
|
+
'ggml-base.en.bin',
|
|
66
|
+
'ggml-small.en.bin',
|
|
67
|
+
'ggml-base.bin',
|
|
68
|
+
'ggml-small.bin',
|
|
69
|
+
'ggml-tiny.en.bin',
|
|
70
|
+
];
|
|
71
|
+
for (const m of prefs) {
|
|
72
|
+
const p = path.join(MODELS_DIR, m);
|
|
73
|
+
if (fs.existsSync(p)) return p;
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
const found = fs.readdirSync(MODELS_DIR).find((n) => /^ggml-.*\.bin$/.test(n));
|
|
77
|
+
if (found) return path.join(MODELS_DIR, found);
|
|
78
|
+
} catch {
|
|
79
|
+
/* dir missing */
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Clean whisper-cli stdout into a single line: drop blank lines, drop
|
|
86
|
+
* bracketed-only markers ([BLANK_AUDIO], (silence)), collapse whitespace.
|
|
87
|
+
*
|
|
88
|
+
* @param {string} raw
|
|
89
|
+
* @returns {string}
|
|
90
|
+
*/
|
|
91
|
+
export function cleanTranscript(raw) {
|
|
92
|
+
return String(raw)
|
|
93
|
+
.split('\n')
|
|
94
|
+
.map((l) => l.trim())
|
|
95
|
+
.filter(Boolean)
|
|
96
|
+
.filter((l) => !/^[[(][^\])]*[\])]$/.test(l))
|
|
97
|
+
.join(' ')
|
|
98
|
+
.replace(/\s+/g, ' ')
|
|
99
|
+
.trim();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Spawn a binary, capture stdout/stderr, resolve on exit 0. */
|
|
103
|
+
function run(bin, args) {
|
|
104
|
+
return new Promise((resolve, reject) => {
|
|
105
|
+
const p = spawn(bin, args, { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
106
|
+
let out = '';
|
|
107
|
+
let err = '';
|
|
108
|
+
p.stdout.on('data', (d) => {
|
|
109
|
+
out += d;
|
|
110
|
+
});
|
|
111
|
+
p.stderr.on('data', (d) => {
|
|
112
|
+
err += d;
|
|
113
|
+
});
|
|
114
|
+
p.on('error', reject);
|
|
115
|
+
p.on('close', (code) =>
|
|
116
|
+
code === 0
|
|
117
|
+
? resolve({ stdout: out, stderr: err })
|
|
118
|
+
: reject(new Error(`${path.basename(bin)} exited ${code}: ${err.slice(0, 500)}`)),
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Transcribe an audio file (any ffmpeg-readable format) to text.
|
|
125
|
+
*
|
|
126
|
+
* @param {string} inputPath - path to the recorded audio file.
|
|
127
|
+
* @param {{ lang?: string }} [opts]
|
|
128
|
+
* @returns {Promise<string>}
|
|
129
|
+
*/
|
|
130
|
+
export async function transcribe(inputPath, { lang = 'en' } = {}) {
|
|
131
|
+
const ffmpeg = resolveFfmpeg();
|
|
132
|
+
const whisper = resolveWhisperBin();
|
|
133
|
+
const model = resolveWhisperModel();
|
|
134
|
+
if (!ffmpeg) throw new Error('ffmpeg not found (brew install ffmpeg)');
|
|
135
|
+
if (!whisper) throw new Error('whisper-cli not found (brew install whisper-cpp)');
|
|
136
|
+
if (!model) throw new Error(`no whisper model found in ${MODELS_DIR}`);
|
|
137
|
+
|
|
138
|
+
const wav = path.join(
|
|
139
|
+
os.tmpdir(),
|
|
140
|
+
`cc-stt-${Date.now()}-${process.pid}.wav`,
|
|
141
|
+
);
|
|
142
|
+
try {
|
|
143
|
+
await run(ffmpeg, [
|
|
144
|
+
'-nostdin', '-y',
|
|
145
|
+
'-i', inputPath,
|
|
146
|
+
'-ar', '16000', '-ac', '1', '-c:a', 'pcm_s16le',
|
|
147
|
+
'-f', 'wav', wav,
|
|
148
|
+
]);
|
|
149
|
+
const { stdout } = await run(whisper, [
|
|
150
|
+
'-m', model, '-f', wav, '-np', '-nt', '-l', lang,
|
|
151
|
+
]);
|
|
152
|
+
return cleanTranscript(stdout);
|
|
153
|
+
} finally {
|
|
154
|
+
fs.promises.unlink(wav).catch(() => {});
|
|
155
|
+
}
|
|
156
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idl3/claude-control",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.21",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Local web UI to watch and drive your Claude Code sessions running in tmux — live transcripts, reply, answer AskUserQuestion, attach files, from a browser or phone.",
|
|
6
6
|
"keywords": [
|
package/server.js
CHANGED
|
@@ -20,11 +20,15 @@ import { parsePanePrompt } from './lib/prompt.js';
|
|
|
20
20
|
import { SessionRegistry, listRecentTranscripts } from './lib/sessions.js';
|
|
21
21
|
import { loadPins, savePins, validateTranscriptPath, pinKey } from './lib/pins.js';
|
|
22
22
|
import { ResourceMonitor } from './lib/resources.js';
|
|
23
|
-
import { buildAnswerProgram } from './lib/answer.js';
|
|
23
|
+
import { buildAnswerProgram, parsePicker, planStep } from './lib/answer.js';
|
|
24
24
|
import { sweepUploads, resolveUploadPath } from './lib/uploads.js';
|
|
25
25
|
import { getVersionInfo, currentVersion } from './lib/version.js';
|
|
26
26
|
import * as push from './lib/push.js';
|
|
27
27
|
import { readConfig, writeConfig } from './lib/config.js';
|
|
28
|
+
import { optimizePrompt } from './lib/optimize.js';
|
|
29
|
+
import { complete as claudeCliComplete } from './lib/claude-cli.js';
|
|
30
|
+
import { transcribe } from './lib/transcribe.js';
|
|
31
|
+
import { listSkills } from './lib/skills.js';
|
|
28
32
|
// Note: the client offers [WS_PROTOCOL, token] as subprotocols; the `ws`
|
|
29
33
|
// library auto-selects the FIRST offered one (the non-secret WS_PROTOCOL label)
|
|
30
34
|
// and echoes it, so we never reflect the raw token back and need no custom
|
|
@@ -172,6 +176,10 @@ const server = http.createServer((req, res) => {
|
|
|
172
176
|
if (!checkToken(req)) return endJson(res, 401, { error: 'unauthorized' });
|
|
173
177
|
return endJson(res, 200, { sessions: registry.getSessions() });
|
|
174
178
|
}
|
|
179
|
+
if (u.pathname === '/api/skills') {
|
|
180
|
+
if (!checkToken(req)) return endJson(res, 401, { error: 'unauthorized' });
|
|
181
|
+
return endJson(res, 200, { skills: listSkills() });
|
|
182
|
+
}
|
|
175
183
|
if (u.pathname === '/api/health') {
|
|
176
184
|
if (!checkToken(req)) return endJson(res, 401, { error: 'unauthorized' });
|
|
177
185
|
return endJson(res, 200, { ok: true, snapshot: resources.snapshot() });
|
|
@@ -242,6 +250,16 @@ const server = http.createServer((req, res) => {
|
|
|
242
250
|
if (req.method === 'POST') return handleConfigSave(req, res);
|
|
243
251
|
return endJson(res, 405, { error: 'method not allowed' });
|
|
244
252
|
}
|
|
253
|
+
if (u.pathname === '/api/optimize') {
|
|
254
|
+
if (req.method !== 'POST') return endJson(res, 405, { error: 'method not allowed' });
|
|
255
|
+
if (!checkToken(req)) return endJson(res, 401, { error: 'unauthorized' });
|
|
256
|
+
return handleOptimize(req, res);
|
|
257
|
+
}
|
|
258
|
+
if (u.pathname === '/api/transcribe') {
|
|
259
|
+
if (req.method !== 'POST') return endJson(res, 405, { error: 'method not allowed' });
|
|
260
|
+
if (!checkToken(req)) return endJson(res, 401, { error: 'unauthorized' });
|
|
261
|
+
return handleTranscribe(req, res, u);
|
|
262
|
+
}
|
|
245
263
|
if (u.pathname === '/api/session/new') {
|
|
246
264
|
if (req.method !== 'POST') return endJson(res, 405, { error: 'method not allowed' });
|
|
247
265
|
if (!checkToken(req)) return endJson(res, 401, { error: 'unauthorized' });
|
|
@@ -462,6 +480,73 @@ async function handleConfigSave(req, res) {
|
|
|
462
480
|
}
|
|
463
481
|
}
|
|
464
482
|
|
|
483
|
+
// POST /api/optimize — token-gated prompt optimiser. Accepts { text, intent }
|
|
484
|
+
// and returns { optimized, rationale, changes, mode } from optimizePrompt.
|
|
485
|
+
// Falls back to rules-based optimization when the Claude CLI is unavailable.
|
|
486
|
+
async function handleOptimize(req, res) {
|
|
487
|
+
let body;
|
|
488
|
+
try {
|
|
489
|
+
body = await readJsonBody(req);
|
|
490
|
+
} catch (err) {
|
|
491
|
+
return endJson(res, 400, { error: 'invalid JSON body' });
|
|
492
|
+
}
|
|
493
|
+
const text = typeof body.text === 'string' ? body.text : '';
|
|
494
|
+
if (!text.trim()) return endJson(res, 400, { error: 'text required' });
|
|
495
|
+
if (text.length > 8000) return endJson(res, 400, { error: 'text exceeds 8000 character limit' });
|
|
496
|
+
const intent = typeof body.intent === 'string' ? body.intent : undefined;
|
|
497
|
+
try {
|
|
498
|
+
const result = await optimizePrompt(text, { complete: claudeCliComplete, intent });
|
|
499
|
+
return endJson(res, 200, result);
|
|
500
|
+
} catch (err) {
|
|
501
|
+
return endJson(res, 500, { error: String(err?.message || err) });
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// POST /api/transcribe — local speech-to-text. Accepts a raw audio body (the
|
|
506
|
+
// MediaRecorder blob from the voice dialog; ?ext=webm|mp4|wav names the format),
|
|
507
|
+
// caps the size, writes it to a temp file, and runs ffmpeg→whisper.cpp via
|
|
508
|
+
// lib/transcribe. Returns { ok, text }. No key, no cloud — fully local.
|
|
509
|
+
function handleTranscribe(req, res, u) {
|
|
510
|
+
const maxBytes = CONFIG.maxUploadMB * 1024 * 1024;
|
|
511
|
+
const ext =
|
|
512
|
+
(u.searchParams.get('ext') || 'webm').toLowerCase().replace(/[^a-z0-9]/g, '').slice(0, 5) ||
|
|
513
|
+
'webm';
|
|
514
|
+
const chunks = [];
|
|
515
|
+
let size = 0;
|
|
516
|
+
let aborted = false;
|
|
517
|
+
|
|
518
|
+
req.on('data', (c) => {
|
|
519
|
+
if (aborted) return;
|
|
520
|
+
size += c.length;
|
|
521
|
+
if (size > maxBytes) {
|
|
522
|
+
aborted = true;
|
|
523
|
+
endJson(res, 413, { error: `audio exceeds ${CONFIG.maxUploadMB} MB limit` });
|
|
524
|
+
req.destroy();
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
chunks.push(c);
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
req.on('end', async () => {
|
|
531
|
+
if (aborted) return;
|
|
532
|
+
if (size === 0) return endJson(res, 400, { error: 'empty audio' });
|
|
533
|
+
const tmp = path.join(os.tmpdir(), `cc-stt-in-${Date.now()}-${process.pid}.${ext}`);
|
|
534
|
+
try {
|
|
535
|
+
await fs.promises.writeFile(tmp, Buffer.concat(chunks), { mode: 0o600 });
|
|
536
|
+
const text = await transcribe(tmp);
|
|
537
|
+
endJson(res, 200, { ok: true, text });
|
|
538
|
+
} catch (err) {
|
|
539
|
+
endJson(res, 500, { error: String(err?.message || err) });
|
|
540
|
+
} finally {
|
|
541
|
+
fs.promises.unlink(tmp).catch(() => {});
|
|
542
|
+
}
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
req.on('error', () => {
|
|
546
|
+
if (!aborted) endJson(res, 400, { error: 'audio stream error' });
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
|
|
465
550
|
// POST /api/session/new — create a new tmux window in the configured (or
|
|
466
551
|
// body-overridden) cwd, then type the launch command into it via send-keys so
|
|
467
552
|
// the interactive shell resolves aliases. Security: the command is operator
|
|
@@ -1044,25 +1129,212 @@ async function handleClientMessage(ws, msg) {
|
|
|
1044
1129
|
if (msg.toolUseId !== pending.toolUseId) {
|
|
1045
1130
|
throw new Error('stale question (already answered or changed)');
|
|
1046
1131
|
}
|
|
1047
|
-
|
|
1048
|
-
//
|
|
1049
|
-
//
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1132
|
+
|
|
1133
|
+
// ── Capture-driven path ──────────────────────────────────────────────
|
|
1134
|
+
// Attempt to navigate by parsing the live picker render. Falls back to
|
|
1135
|
+
// the static buildAnswerProgram on ANY parse failure, unknown label, or
|
|
1136
|
+
// post-send verification mismatch — so it can NEVER regress the working path.
|
|
1137
|
+
//
|
|
1138
|
+
// Constants:
|
|
1139
|
+
const SETTLE_MS = 300; // ms to wait after sending keys before re-capture
|
|
1140
|
+
const MAX_RETRIES = 1; // retry attempts per question on verification failure
|
|
1141
|
+
|
|
1142
|
+
let usedDynamic = false;
|
|
1143
|
+
// Tracks whether the dynamic path has injected ANY keystroke. Once true,
|
|
1144
|
+
// the picker is in a partial/unknown state and the from-scratch static
|
|
1145
|
+
// fallback would corrupt it — so a later failure must fail loud, not retry.
|
|
1146
|
+
let sentAny = false;
|
|
1053
1147
|
try {
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1148
|
+
const questions = pending?.questions || [];
|
|
1149
|
+
const selections = msg.selections || [];
|
|
1150
|
+
|
|
1151
|
+
if (questions.length > 0) {
|
|
1152
|
+
let dynamicOk = true; // will be set false to fall back
|
|
1153
|
+
|
|
1154
|
+
for (let qi = 0; qi < questions.length && dynamicOk; qi += 1) {
|
|
1155
|
+
const question = questions[qi];
|
|
1156
|
+
const selectedLabels = selections[qi] || [];
|
|
1157
|
+
|
|
1158
|
+
let attempt = 0;
|
|
1159
|
+
let stepOk = false;
|
|
1160
|
+
|
|
1161
|
+
while (attempt <= MAX_RETRIES && !stepOk) {
|
|
1162
|
+
// 1. Capture current picker state.
|
|
1163
|
+
let capture;
|
|
1164
|
+
try {
|
|
1165
|
+
capture = await tmux.capturePane(session.target);
|
|
1166
|
+
} catch (captureErr) {
|
|
1167
|
+
console.log(`[answer/dynamic] capture failed q${qi}: ${captureErr?.message}`);
|
|
1168
|
+
dynamicOk = false;
|
|
1169
|
+
break;
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
// 2. Parse.
|
|
1173
|
+
const parsed = parsePicker(capture);
|
|
1174
|
+
if (parsed.confidence !== 'ok') {
|
|
1175
|
+
console.log(`[answer/dynamic] low confidence on q${qi} — falling back`);
|
|
1176
|
+
dynamicOk = false;
|
|
1177
|
+
break;
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
// 3. Handle the review screen (multi-question final step).
|
|
1181
|
+
if (parsed.isReview) {
|
|
1182
|
+
// We expect to be here only after the last question's action Enter.
|
|
1183
|
+
// Send Enter to confirm "Submit answers".
|
|
1184
|
+
console.log(`[answer/dynamic] review screen — sending Enter`);
|
|
1185
|
+
sentAny = true;
|
|
1186
|
+
await tmux.sendRawKeysSequenced(session.target, ['Enter'], SETTLE_MS);
|
|
1187
|
+
await new Promise((r) => setTimeout(r, SETTLE_MS));
|
|
1188
|
+
// Verify: the review screen should be gone.
|
|
1189
|
+
const afterReview = await tmux.capturePane(session.target);
|
|
1190
|
+
const reparse = parsePicker(afterReview);
|
|
1191
|
+
if (reparse.isReview) {
|
|
1192
|
+
console.log(`[answer/dynamic] review screen still up after Enter — falling back`);
|
|
1193
|
+
dynamicOk = false;
|
|
1194
|
+
}
|
|
1195
|
+
// Whether verified or not, we break out of the question loop —
|
|
1196
|
+
// we've processed all questions.
|
|
1197
|
+
break;
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
// 4. Plan keystrokes for this question.
|
|
1201
|
+
const keys = planStep(parsed, question, selectedLabels);
|
|
1202
|
+
if (!keys) {
|
|
1203
|
+
console.log(`[answer/dynamic] planStep null on q${qi} — falling back`);
|
|
1204
|
+
dynamicOk = false;
|
|
1205
|
+
break;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
console.log(
|
|
1209
|
+
`[answer/dynamic] q${qi} attempt=${attempt} keys=${JSON.stringify(keys)}`,
|
|
1210
|
+
);
|
|
1211
|
+
|
|
1212
|
+
// 5. Send keys.
|
|
1213
|
+
sentAny = true;
|
|
1214
|
+
await tmux.sendRawKeysSequenced(session.target, keys, SETTLE_MS);
|
|
1215
|
+
|
|
1216
|
+
// 6. Settle then verify.
|
|
1217
|
+
await new Promise((r) => setTimeout(r, SETTLE_MS));
|
|
1218
|
+
let afterCapture;
|
|
1219
|
+
try {
|
|
1220
|
+
afterCapture = await tmux.capturePane(session.target);
|
|
1221
|
+
} catch (captureErr) {
|
|
1222
|
+
console.log(`[answer/dynamic] post-send capture failed q${qi}: ${captureErr?.message}`);
|
|
1223
|
+
dynamicOk = false;
|
|
1224
|
+
break;
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
const afterParsed = parsePicker(afterCapture);
|
|
1228
|
+
|
|
1229
|
+
if (question.multiSelect) {
|
|
1230
|
+
// Verify: all intended labels are now checked in the re-parsed picker.
|
|
1231
|
+
// If we advanced (Next/Submit pressed), the screen changes — that's
|
|
1232
|
+
// also acceptable (confidence goes low = we moved on).
|
|
1233
|
+
if (afterParsed.confidence === 'ok' && !afterParsed.isReview) {
|
|
1234
|
+
const uncheckedTargets = selectedLabels.filter((label) =>
|
|
1235
|
+
afterParsed.rows.some(
|
|
1236
|
+
(r) => r.kind === 'option' && r.label === label && !r.checked,
|
|
1237
|
+
),
|
|
1238
|
+
);
|
|
1239
|
+
if (uncheckedTargets.length > 0) {
|
|
1240
|
+
console.log(
|
|
1241
|
+
`[answer/dynamic] verify failed q${qi}: still unchecked=${JSON.stringify(uncheckedTargets)} attempt=${attempt}`,
|
|
1242
|
+
);
|
|
1243
|
+
attempt += 1;
|
|
1244
|
+
continue; // retry
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
// Either confidence is low (screen advanced) or all checked — either
|
|
1248
|
+
// way, treat the step as done and move to the next question.
|
|
1249
|
+
stepOk = true;
|
|
1250
|
+
} else {
|
|
1251
|
+
// Single-select: after Enter, picker should advance (screen changes).
|
|
1252
|
+
// If the exact same option is still shown as selected (cursor on it),
|
|
1253
|
+
// something went wrong. Accept any screen change as advancement.
|
|
1254
|
+
if (
|
|
1255
|
+
afterParsed.confidence === 'ok' &&
|
|
1256
|
+
!afterParsed.isReview &&
|
|
1257
|
+
afterParsed.rows.some(
|
|
1258
|
+
(r) => r.cursor && r.kind === 'option' && r.label === selectedLabels[0],
|
|
1259
|
+
)
|
|
1260
|
+
) {
|
|
1261
|
+
console.log(`[answer/dynamic] single-select stuck on q${qi} attempt=${attempt}`);
|
|
1262
|
+
attempt += 1;
|
|
1263
|
+
continue;
|
|
1264
|
+
}
|
|
1265
|
+
stepOk = true;
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
if (!stepOk && attempt > MAX_RETRIES) {
|
|
1270
|
+
console.log(`[answer/dynamic] max retries exceeded on q${qi} — falling back`);
|
|
1271
|
+
dynamicOk = false;
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
// After processing all questions via dynamic path, check if we need to
|
|
1276
|
+
// handle the review screen (multi-question pickers).
|
|
1277
|
+
if (dynamicOk && questions.length > 1) {
|
|
1278
|
+
// Capture and check: we may already be on the review screen (handled
|
|
1279
|
+
// in the loop above) or may need to check.
|
|
1280
|
+
try {
|
|
1281
|
+
const finalCapture = await tmux.capturePane(session.target);
|
|
1282
|
+
const finalParsed = parsePicker(finalCapture);
|
|
1283
|
+
if (finalParsed.isReview && finalParsed.confidence === 'ok') {
|
|
1284
|
+
// Submit the review screen.
|
|
1285
|
+
console.log(`[answer/dynamic] post-loop review screen — sending Enter`);
|
|
1286
|
+
sentAny = true;
|
|
1287
|
+
await tmux.sendRawKeysSequenced(session.target, ['Enter'], SETTLE_MS);
|
|
1288
|
+
}
|
|
1289
|
+
} catch (captureErr) {
|
|
1290
|
+
// Non-fatal: we already sent the question answers; review Enter is best-effort.
|
|
1291
|
+
console.log(`[answer/dynamic] final review capture failed: ${captureErr?.message}`);
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
if (dynamicOk) {
|
|
1296
|
+
usedDynamic = true;
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
} catch (dynamicErr) {
|
|
1300
|
+
// Any unexpected error in the dynamic path — log and fall back.
|
|
1301
|
+
console.log(`[answer/dynamic] unexpected error: ${dynamicErr?.message} — falling back`);
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
// ── Static fallback ──────────────────────────────────────────────────
|
|
1305
|
+
// Only safe when the dynamic path sent NOTHING (picker still pristine). If
|
|
1306
|
+
// dynamic already injected keys then failed, the picker is in a partial
|
|
1307
|
+
// state — replaying the from-scratch static program would mis-navigate a
|
|
1308
|
+
// dirty picker and corrupt the answer. Fail loud so the user can retry.
|
|
1309
|
+
if (!usedDynamic && sentAny) {
|
|
1060
1310
|
console.error(
|
|
1061
|
-
`[answer]
|
|
1311
|
+
`[answer] dynamic path failed AFTER sending keys; NOT running static fallback (picker dirty) toolUseId=${msg.toolUseId}`,
|
|
1062
1312
|
);
|
|
1063
|
-
|
|
1313
|
+
return send(ws, {
|
|
1314
|
+
type: 'ack',
|
|
1315
|
+
op: 'answer',
|
|
1316
|
+
ok: false,
|
|
1317
|
+
error: 'answer injection failed mid-picker — please retry',
|
|
1318
|
+
});
|
|
1064
1319
|
}
|
|
1065
|
-
|
|
1320
|
+
if (!usedDynamic) {
|
|
1321
|
+
const keys = buildAnswerProgram(pending, msg.selections || []);
|
|
1322
|
+
console.log(
|
|
1323
|
+
`[answer] toolUseId=${msg.toolUseId} target=${session.target} keys=${JSON.stringify(keys)} (static fallback)`,
|
|
1324
|
+
);
|
|
1325
|
+
try {
|
|
1326
|
+
await tmux.sendRawKeysSequenced(session.target, keys);
|
|
1327
|
+
} catch (err) {
|
|
1328
|
+
console.error(
|
|
1329
|
+
`[answer] FAILED toolUseId=${msg.toolUseId} target=${session.target}: ${String(err?.message || err)}`,
|
|
1330
|
+
);
|
|
1331
|
+
throw err;
|
|
1332
|
+
}
|
|
1333
|
+
console.log(`[answer] sent toolUseId=${msg.toolUseId} (${keys.length} keys)`);
|
|
1334
|
+
} else {
|
|
1335
|
+
console.log(`[answer] sent toolUseId=${msg.toolUseId} via dynamic path`);
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1066
1338
|
return send(ws, { type: 'ack', op: 'answer', ok: true });
|
|
1067
1339
|
}
|
|
1068
1340
|
case 'capture': {
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{g as Ve}from"./index-D2hrAUsb.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-BeJg6Cs1.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};
|