@idl3/claude-control 0.1.21 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/tmux.js CHANGED
@@ -177,6 +177,8 @@ const FORMAT = [
177
177
  '#{window_id}',
178
178
  '#{pane_index}',
179
179
  '#{pane_active}',
180
+ '#{pane_id}',
181
+ '#{@cc_shell}',
180
182
  ].join(SEP);
181
183
 
182
184
  /**
@@ -222,7 +224,7 @@ export async function listPanes() {
222
224
  const parts = trimmed.split(SEP);
223
225
  if (parts.length < 9) continue;
224
226
 
225
- const [sessionName, rawIndex, windowName, rawActive, rawPid, cwd, cmd, windowId, rawPane, rawPaneActive] = parts;
227
+ const [sessionName, rawIndex, windowName, rawActive, rawPid, cwd, cmd, windowId, rawPane, rawPaneActive, paneId, ccShell] = parts;
226
228
  const windowIndex = Number(rawIndex);
227
229
  const panePid = Number(rawPid);
228
230
  const paneIndex = Number(rawPane) || 0;
@@ -239,6 +241,8 @@ export async function listPanes() {
239
241
  cmd,
240
242
  windowId: windowId ?? `${sessionName}:${windowIndex}`,
241
243
  paneIndex,
244
+ paneId: paneId ?? null, // stable tmux %N — joins to $TMUX_PANE from the hook
245
+ ccShell: ccShell === '1', // sister shell pane created for the composer >_
242
246
  });
243
247
  }
244
248
 
@@ -377,6 +381,54 @@ export async function createWindow({ cwd, name } = {}) {
377
381
  return target;
378
382
  }
379
383
 
384
+ // ---------------------------------------------------------------------------
385
+ // Split window (sister pane)
386
+ // ---------------------------------------------------------------------------
387
+
388
+ /**
389
+ * Split a window to add a sister pane running the default shell, WITHOUT
390
+ * stealing focus (`-d`), and return the new pane's target. Used to give each
391
+ * Claude session its own scratch shell next to it (composer >_).
392
+ *
393
+ * @param {{ windowTarget: string, cwd: string, size?: string }} opts
394
+ * windowTarget e.g. "0:1"; size e.g. "30%" (height of the new pane).
395
+ * @returns {Promise<string>} new pane target "session:window.pane"
396
+ */
397
+ export async function splitWindow({ windowTarget, cwd, size = '30%' } = {}) {
398
+ if (!windowTarget) throw new Error('splitWindow: windowTarget required');
399
+ if (typeof cwd !== 'string' || !cwd) throw new Error('splitWindow: cwd required');
400
+ const args = [
401
+ 'split-window',
402
+ '-d', // do not switch focus to the new pane
403
+ '-v', // stack below the source pane
404
+ '-l', size,
405
+ '-t', windowTarget,
406
+ '-c', cwd,
407
+ '-P',
408
+ '-F', '#{session_name}:#{window_index}.#{pane_index}',
409
+ ];
410
+ const { stdout } = await runTmux(args);
411
+ const target = stdout.trim();
412
+ if (!isValidTarget(target)) {
413
+ throw new Error(`splitWindow: produced invalid target: ${JSON.stringify(target)}`);
414
+ }
415
+ return target;
416
+ }
417
+
418
+ /**
419
+ * Set a pane-scoped tmux option (e.g. a `@user` marker). Used to tag the sister
420
+ * shell pane so it can be found and reused later.
421
+ *
422
+ * @param {string} target pane target
423
+ * @param {string} name option name (e.g. "@cc_shell")
424
+ * @param {string} value
425
+ * @returns {Promise<void>}
426
+ */
427
+ export async function setPaneOption(target, name, value) {
428
+ assertTarget(target);
429
+ await runTmux(['set-option', '-p', '-t', target, name, String(value)]);
430
+ }
431
+
380
432
  // ---------------------------------------------------------------------------
381
433
  // Rename window
382
434
  // ---------------------------------------------------------------------------
@@ -416,6 +468,22 @@ export async function sendText(target, text) {
416
468
  await runTmux(['send-keys', '-t', target, 'Enter']);
417
469
  }
418
470
 
471
+ /**
472
+ * Send literal text WITHOUT a trailing Enter — for raw keystroke passthrough,
473
+ * where each character (or a paste) is forwarded as the user types and the pane
474
+ * itself is the echo. `-l` means no key-name interpretation, so this can't inject
475
+ * control keys (those go through sendRawKeys with the SHELL_KEYS allow-list).
476
+ *
477
+ * @param {string} target
478
+ * @param {string} text
479
+ * @returns {Promise<void>}
480
+ */
481
+ export async function sendLiteral(target, text) {
482
+ assertTarget(target);
483
+ if (!text) return;
484
+ await runTmux(['send-keys', '-t', target, '-l', text]);
485
+ }
486
+
419
487
  // ---------------------------------------------------------------------------
420
488
  // Send raw key names (no -l)
421
489
  // ---------------------------------------------------------------------------
@@ -468,16 +536,14 @@ export async function sendRawKeysSequenced(target, keys, delayMs = 160) {
468
536
  * @param {number} [lines=40] How many history lines above the visible area to include.
469
537
  * @returns {Promise<string>}
470
538
  */
471
- export async function capturePane(target, lines = 40) {
539
+ export async function capturePane(target, lines = 40, escapes = false) {
472
540
  assertTarget(target);
473
- const { stdout } = await runTmux([
474
- 'capture-pane',
475
- '-t', target,
476
- '-p', // print to stdout
477
- // NOTE: no '-e' — the UI renders the capture as plain text (LivePane <pre>,
478
- // AskModal peek), so ANSI escapes would show as literal garbage. Strip them
479
- // at the source by capturing without escape sequences.
480
- '-S', `-${lines}`, // start N lines above visible area
481
- ]);
541
+ const args = ['capture-pane', '-t', target, '-p'];
542
+ // `-e` keeps ANSI/SGR sequences so the client can render terminal colors. Off
543
+ // by default: LivePane / AskModal render plain text (escapes would show as
544
+ // garbage). The composer terminal view opts in to get a themed, colored pane.
545
+ if (escapes) args.push('-e');
546
+ args.push('-S', `-${lines}`); // start N lines above the visible area
547
+ const { stdout } = await runTmux(args);
482
548
  return stdout;
483
549
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idl3/claude-control",
3
- "version": "0.1.21",
3
+ "version": "0.2.0",
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": [
@@ -22,6 +22,8 @@
22
22
  "files": [
23
23
  "server.js",
24
24
  "lib/",
25
+ "hooks/",
26
+ "scripts/",
25
27
  "public/",
26
28
  "web/dist/",
27
29
  "bin/",
@@ -32,6 +34,8 @@
32
34
  "start": "node server.js",
33
35
  "dev": "node --watch server.js",
34
36
  "test": "node --test",
37
+ "eval:optimise": "node scripts/eval-optimize.mjs",
38
+ "install-hook": "node scripts/install-pane-hook.mjs",
35
39
  "build:web": "cd web && npm install && npm run build",
36
40
  "build": "npm run build:web",
37
41
  "prepack": "npm run build"
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * eval-optimize.mjs — offline scorecard for the prompt-optimiser acceptance gate.
4
+ * Runs lib/optimize.js → evaluateRewrite over the deterministic fixture set and
5
+ * prints a per-case pass/fail table plus an aggregate. Exits non-zero on any
6
+ * mismatch so it can gate CI / catch regressions in the guard logic.
7
+ *
8
+ * Run: npm run eval:optimise
9
+ */
10
+ import { evaluateRewrite } from '../lib/optimize.js';
11
+ import { OPTIMIZE_CASES } from '../test/fixtures/optimize-cases.mjs';
12
+
13
+ let pass = 0;
14
+ const rows = [];
15
+ for (const c of OPTIMIZE_CASES) {
16
+ const ev = evaluateRewrite(c.draft, c.optimized);
17
+ const verdictOk = ev.ok === c.expectOk;
18
+ // If the case pins expected violations, require they all fired.
19
+ const violOk =
20
+ !c.expectViolations || c.expectViolations.every((v) => ev.violations.includes(v));
21
+ const ok = verdictOk && violOk;
22
+ if (ok) pass += 1;
23
+ rows.push({
24
+ name: c.name,
25
+ ok,
26
+ got: ev.ok ? 'accept' : `reject(${ev.violations.join(',')})`,
27
+ want: c.expectOk ? 'accept' : `reject(${(c.expectViolations || []).join(',') || 'any'})`,
28
+ ratio: ev.metrics.lengthRatio,
29
+ overlap: ev.metrics.contentOverlap,
30
+ });
31
+ }
32
+
33
+ const W = Math.max(...rows.map((r) => r.name.length));
34
+ console.log('Prompt-optimiser eval — acceptance gate\n');
35
+ for (const r of rows) {
36
+ console.log(
37
+ `${r.ok ? '✓' : '✗'} ${r.name.padEnd(W)} got=${r.got} want=${r.want} ` +
38
+ `ratio=${r.ratio} overlap=${r.overlap}`,
39
+ );
40
+ }
41
+ const total = OPTIMIZE_CASES.length;
42
+ console.log(`\n${pass}/${total} cases passed`);
43
+ if (pass !== total) {
44
+ console.error('EVAL FAILED — guard logic regressed');
45
+ process.exit(1);
46
+ }
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * install-pane-hook.mjs — idempotently register the pane-recording hook
4
+ * (hooks/record-pane.mjs) as a Claude Code SessionStart + SessionEnd hook in
5
+ * ~/.claude/settings.json. Lets Claude Control bind each tmux pane to its EXACT
6
+ * transcript with zero guessing.
7
+ *
8
+ * Safe to re-run: detects an existing record-pane hook (by command substring)
9
+ * and leaves the file untouched if already installed. Preserves all other hooks.
10
+ */
11
+ import { readFile, writeFile, mkdir, copyFile } from 'node:fs/promises';
12
+ import { homedir } from 'node:os';
13
+ import path from 'node:path';
14
+ import { fileURLToPath } from 'node:url';
15
+
16
+ const SETTINGS = path.join(homedir(), '.claude', 'settings.json');
17
+ const SRC_SCRIPT = path.resolve(fileURLToPath(import.meta.url), '..', '..', 'hooks', 'record-pane.mjs');
18
+ // Deploy to ~/.claude/scripts/ and reference it by $HOME — IDENTICAL to the
19
+ // atlas-toolbox olam-skills hook (members/idl3/hooks/record-pane.json), so the
20
+ // two install paths produce the same settings entry and never double-register.
21
+ const DEST_SCRIPT = path.join(homedir(), '.claude', 'scripts', 'record-pane.mjs');
22
+ const COMMAND = 'node "$HOME/.claude/scripts/record-pane.mjs"';
23
+ const EVENTS = ['SessionStart', 'SessionEnd'];
24
+ const MARKER = 'record-pane.mjs';
25
+
26
+ async function readSettings() {
27
+ try {
28
+ return JSON.parse(await readFile(SETTINGS, 'utf8'));
29
+ } catch (err) {
30
+ if (err.code === 'ENOENT') return {};
31
+ throw new Error(`Could not parse ${SETTINGS}: ${err.message}`);
32
+ }
33
+ }
34
+
35
+ function alreadyInstalled(groups) {
36
+ return (groups || []).some((g) =>
37
+ (g.hooks || []).some((h) => typeof h.command === 'string' && h.command.includes(MARKER)),
38
+ );
39
+ }
40
+
41
+ async function main() {
42
+ // Deploy the script to ~/.claude/scripts/ (idempotent — always refresh it).
43
+ await mkdir(path.dirname(DEST_SCRIPT), { recursive: true });
44
+ await copyFile(SRC_SCRIPT, DEST_SCRIPT);
45
+
46
+ const settings = await readSettings();
47
+ settings.hooks ??= {};
48
+ let changed = false;
49
+
50
+ for (const event of EVENTS) {
51
+ const groups = (settings.hooks[event] ??= []);
52
+ if (alreadyInstalled(groups)) continue;
53
+ groups.push({ hooks: [{ type: 'command', command: COMMAND }] });
54
+ changed = true;
55
+ }
56
+
57
+ if (!changed) {
58
+ console.log(`✓ pane-recording hook already installed (${SETTINGS})`);
59
+ return;
60
+ }
61
+
62
+ await mkdir(path.dirname(SETTINGS), { recursive: true });
63
+ await writeFile(SETTINGS, `${JSON.stringify(settings, null, 2)}\n`, 'utf8');
64
+ console.log(`✓ installed pane-recording hook → ${SETTINGS}`);
65
+ console.log(` command: ${COMMAND}`);
66
+ console.log(' Applies to Claude sessions started from now on.');
67
+ }
68
+
69
+ main().catch((err) => {
70
+ console.error(`✗ ${err.message}`);
71
+ process.exit(1);
72
+ });
package/server.js CHANGED
@@ -14,6 +14,7 @@ import { WebSocketServer } from 'ws';
14
14
 
15
15
  import * as tmux from './lib/tmux.js';
16
16
  import * as terminal from './lib/terminal.js';
17
+ import * as shell from './lib/shell.js';
17
18
  import { TranscriptTailer } from './lib/transcript.js';
18
19
  import { SubAgentsWatcher } from './lib/subagents.js';
19
20
  import { parsePanePrompt } from './lib/prompt.js';
@@ -25,8 +26,16 @@ import { sweepUploads, resolveUploadPath } from './lib/uploads.js';
25
26
  import { getVersionInfo, currentVersion } from './lib/version.js';
26
27
  import * as push from './lib/push.js';
27
28
  import { readConfig, writeConfig } from './lib/config.js';
28
- import { optimizePrompt } from './lib/optimize.js';
29
+ import { optimizePrompt, rulesOptimize } from './lib/optimize.js';
29
30
  import { complete as claudeCliComplete } from './lib/claude-cli.js';
31
+ import * as mlx from './lib/mlx.js';
32
+ import {
33
+ MLX_MODELS,
34
+ CLAUDE_MODELS,
35
+ detectMachine,
36
+ recommendMlxModel,
37
+ recommendClaudeModel,
38
+ } from './lib/models.js';
30
39
  import { transcribe } from './lib/transcribe.js';
31
40
  import { listSkills } from './lib/skills.js';
32
41
  // Note: the client offers [WS_PROTOCOL, token] as subprotocols; the `ws`
@@ -255,6 +264,19 @@ const server = http.createServer((req, res) => {
255
264
  if (!checkToken(req)) return endJson(res, 401, { error: 'unauthorized' });
256
265
  return handleOptimize(req, res);
257
266
  }
267
+ if (u.pathname === '/api/models') {
268
+ if (!checkToken(req)) return endJson(res, 401, { error: 'unauthorized' });
269
+ const machine = detectMachine();
270
+ return endJson(res, 200, {
271
+ machine,
272
+ // Mark which MLX models are already in the local HF cache so the UI can
273
+ // show downloaded vs. will-download (avoids a surprise multi-GB fetch).
274
+ mlxModels: MLX_MODELS.map((m) => ({ ...m, installed: mlx.isModelCached(m.id) })),
275
+ claudeModels: CLAUDE_MODELS,
276
+ recommendedMlxModel: recommendMlxModel(machine.ramGB),
277
+ recommendedClaudeModel: recommendClaudeModel(),
278
+ });
279
+ }
258
280
  if (u.pathname === '/api/transcribe') {
259
281
  if (req.method !== 'POST') return endJson(res, 405, { error: 'method not allowed' });
260
282
  if (!checkToken(req)) return endJson(res, 401, { error: 'unauthorized' });
@@ -474,6 +496,13 @@ async function handleConfigSave(req, res) {
474
496
  }
475
497
  try {
476
498
  const saved = writeConfig(body);
499
+ // If the MLX backend is active, (re)warm the selected model now — this
500
+ // restarts the local server with the new model and starts any needed
501
+ // download in the background, so the user doesn't hit a cold stall (or a
502
+ // wrong-model hang) on their next ✨ enhance.
503
+ if (saved.optimizeBackend === 'mlx' && mlx.resolveMlxPython()) {
504
+ mlx.warm();
505
+ }
477
506
  return endJson(res, 200, saved);
478
507
  } catch (err) {
479
508
  return endJson(res, 400, { error: String(err?.message || err) });
@@ -495,13 +524,37 @@ async function handleOptimize(req, res) {
495
524
  if (text.length > 8000) return endJson(res, 400, { error: 'text exceeds 8000 character limit' });
496
525
  const intent = typeof body.intent === 'string' ? body.intent : undefined;
497
526
  try {
498
- const result = await optimizePrompt(text, { complete: claudeCliComplete, intent });
527
+ const result = await runOptimize(text, intent);
499
528
  return endJson(res, 200, result);
500
529
  } catch (err) {
501
530
  return endJson(res, 500, { error: String(err?.message || err) });
502
531
  }
503
532
  }
504
533
 
534
+ // Run the enhancer through the configured backend chain, recording WHICH backend
535
+ // actually produced the result so the UI can label it accurately:
536
+ // - 'mlx' → try local MLX, then claude -p, then rules.
537
+ // - 'claude' → try claude -p, then rules.
538
+ // - 'rules' → deterministic rules optimiser only.
539
+ // optimizePrompt returns mode:'rules' when its injected complete() fails, so a
540
+ // non-'llm' mode means that backend fell through → try the next.
541
+ async function runOptimize(text, intent) {
542
+ const cfg = readConfig();
543
+ const backend = cfg.optimizeBackend;
544
+ if (backend === 'rules') {
545
+ return { ...rulesOptimize(text), backend: 'rules' };
546
+ }
547
+ const order = backend === 'claude' ? ['claude'] : ['mlx', 'claude'];
548
+ for (const b of order) {
549
+ const complete = b === 'mlx' ? (p) => mlx.complete(p) : claudeCliComplete;
550
+ const r = await optimizePrompt(text, { complete, intent });
551
+ if (r.mode === 'llm') {
552
+ return { ...r, backend: b, model: b === 'mlx' ? cfg.mlxModel : cfg.optimizeModel };
553
+ }
554
+ }
555
+ return { ...rulesOptimize(text), backend: 'rules' };
556
+ }
557
+
505
558
  // POST /api/transcribe — local speech-to-text. Accepts a raw audio body (the
506
559
  // MediaRecorder blob from the voice dialog; ?ext=webm|mp4|wav names the format),
507
560
  // caps the size, writes it to a temp file, and runs ffmpeg→whisper.cpp via
@@ -1342,9 +1395,28 @@ async function handleClientMessage(ws, msg) {
1342
1395
  if (!session) throw new Error('unknown session');
1343
1396
  if (!tmux.isValidTarget(session.target)) throw new Error('invalid tmux target');
1344
1397
  const lines = Math.max(1, Math.min(10000, Number(msg.lines) || 40));
1345
- const text = await tmux.capturePane(session.target, lines);
1398
+ // Terminal-pane rows opt into ANSI escapes so colours render; the plain
1399
+ // LivePane omits the flag (escapes would show as garbage there).
1400
+ const text = await tmux.capturePane(session.target, lines, !!msg.escapes);
1346
1401
  return send(ws, { type: 'capture', id: msg.id, text });
1347
1402
  }
1403
+ // Interactive terminal panes: forward keystrokes to ANY pane by id (the
1404
+ // selected one). Mirrors the cc-shell shell-* ops but target-addressed.
1405
+ case 'pane-text': {
1406
+ const session = sessionById(msg.id);
1407
+ if (!session) throw new Error('unknown session');
1408
+ if (!tmux.isValidTarget(session.target)) throw new Error('invalid tmux target');
1409
+ await tmux.sendLiteral(session.target, String(msg.text ?? ''));
1410
+ return send(ws, { type: 'ack', op: 'pane-text', ok: true });
1411
+ }
1412
+ case 'pane-key': {
1413
+ const session = sessionById(msg.id);
1414
+ if (!session) throw new Error('unknown session');
1415
+ if (!tmux.isValidTarget(session.target)) throw new Error('invalid tmux target');
1416
+ if (!shell.SHELL_KEYS.has(String(msg.key ?? ''))) throw new Error('key not allowed');
1417
+ await tmux.sendRawKeys(session.target, [String(msg.key)]);
1418
+ return send(ws, { type: 'ack', op: 'pane-key', ok: true });
1419
+ }
1348
1420
  case 'promptkey': {
1349
1421
  // Respond to a live TUI selection prompt (permission/menu). Whitelisted
1350
1422
  // keys only — never arbitrary text — so this can't be used to inject input.
@@ -1359,6 +1431,33 @@ async function handleClientMessage(ws, msg) {
1359
1431
  if (sub) sub._lastPrompt = '__force__';
1360
1432
  return send(ws, { type: 'ack', op: 'promptkey', ok: true });
1361
1433
  }
1434
+ // Composer terminal mode (>_): each Claude session has its OWN sister shell
1435
+ // pane in its window. Resolve the session by id → its target + cwd, then act
1436
+ // on (or lazily create) that window's sister shell.
1437
+ case 'shell-input': {
1438
+ const s = sessionById(msg.id);
1439
+ if (!s) throw new Error('unknown session');
1440
+ await shell.shellInput(s.target, s.cwd, String(msg.line ?? ''));
1441
+ return send(ws, { type: 'ack', op: 'shell-input', ok: true });
1442
+ }
1443
+ case 'shell-text': {
1444
+ const s = sessionById(msg.id);
1445
+ if (!s) throw new Error('unknown session');
1446
+ await shell.shellText(s.target, s.cwd, String(msg.text ?? ''));
1447
+ return send(ws, { type: 'ack', op: 'shell-text', ok: true });
1448
+ }
1449
+ case 'shell-key': {
1450
+ const s = sessionById(msg.id);
1451
+ if (!s) throw new Error('unknown session');
1452
+ await shell.shellKey(s.target, s.cwd, String(msg.key ?? ''));
1453
+ return send(ws, { type: 'ack', op: 'shell-key', ok: true });
1454
+ }
1455
+ case 'shell-capture': {
1456
+ const s = sessionById(msg.id);
1457
+ if (!s) throw new Error('unknown session');
1458
+ const text = await shell.shellCapture(s.target, s.cwd, msg.lines);
1459
+ return send(ws, { type: 'shell-output', id: msg.id, text });
1460
+ }
1362
1461
  default:
1363
1462
  return;
1364
1463
  }
@@ -1454,6 +1553,16 @@ async function main() {
1454
1553
  } else {
1455
1554
  console.log(' (no COCKPIT_TOKEN set — relying on 127.0.0.1 bind. This UI can type into your sessions.)');
1456
1555
  }
1556
+ // Pre-warm the local MLX enhancer so the first ✨ enhance is fast (best-effort;
1557
+ // only when that backend is selected and an mlx python is available).
1558
+ try {
1559
+ if (readConfig().optimizeBackend === 'mlx' && mlx.resolveMlxPython()) {
1560
+ mlx.warm();
1561
+ console.log(' (pre-warming local MLX enhancer model…)');
1562
+ }
1563
+ } catch {
1564
+ /* best-effort */
1565
+ }
1457
1566
  });
1458
1567
  }
1459
1568
 
@@ -1,3 +1,3 @@
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,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;")}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-DwmU8Yna.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,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;")}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};