@idl3/claude-control 0.1.2 → 0.1.7

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
@@ -110,6 +110,16 @@ export function isValidTarget(target) {
110
110
  // Internal helpers
111
111
  // ---------------------------------------------------------------------------
112
112
 
113
+ // We delimit `-F` format fields with US (\x1f). tmux only emits that control
114
+ // byte verbatim under a UTF-8 locale; in the C/POSIX locale (e.g. a bare launchd
115
+ // or cron environment) it sanitizes \x1f to "_", which collapses every row to a
116
+ // single field and yields zero panes. Force a UTF-8 locale for tmux so parsing
117
+ // is correct regardless of how the server was launched.
118
+ const TMUX_ENV = {
119
+ ...process.env,
120
+ LC_ALL: process.env.LC_ALL || process.env.LANG || 'en_US.UTF-8',
121
+ };
122
+
113
123
  /**
114
124
  * Run a tmux sub-command with an explicit args array.
115
125
  * @param {string[]} args
@@ -121,10 +131,7 @@ async function runTmux(args, opts = {}) {
121
131
  return execFile(bin, args, {
122
132
  timeout: opts.timeout ?? 10_000,
123
133
  maxBuffer: 4 * 1024 * 1024,
124
- // Force a UTF-8 locale: in the C/POSIX locale a launchd agent inherits, tmux
125
- // sanitizes our \x1f field separator to '_', so list parsing yields nothing.
126
- // A UTF-8 locale makes tmux emit \x1f literally. (Honor an existing locale.)
127
- env: { ...process.env, LC_ALL: process.env.LC_ALL || 'en_US.UTF-8' },
134
+ env: TMUX_ENV,
128
135
  });
129
136
  }
130
137
 
@@ -139,7 +146,7 @@ function assertTarget(target) {
139
146
  }
140
147
 
141
148
  // ---------------------------------------------------------------------------
142
- // List windows
149
+ // List panes
143
150
  // ---------------------------------------------------------------------------
144
151
 
145
152
  /**
@@ -147,8 +154,9 @@ function assertTarget(target) {
147
154
  * @property {string} sessionName
148
155
  * @property {number} windowIndex
149
156
  * @property {string} windowName
150
- * @property {string} target "sessionName:windowIndex"
151
- * @property {boolean} active
157
+ * @property {string} target "sessionName:windowIndex.paneIndex"
158
+ * @property {boolean} active window is the active window in its session
159
+ * @property {boolean} paneActive pane is the active pane in its window
152
160
  * @property {number} panePid
153
161
  * @property {string} cwd
154
162
  * @property {string} cmd
@@ -168,18 +176,23 @@ const FORMAT = [
168
176
  '#{pane_current_command}',
169
177
  '#{window_id}',
170
178
  '#{pane_index}',
179
+ '#{pane_active}',
171
180
  ].join(SEP);
172
181
 
173
182
  /**
174
- * List all tmux windows across all sessions.
175
- * Resolves to [] when no tmux server is running.
183
+ * List every tmux PANE across all sessions (one entry per pane, not per window).
184
+ * A `target` therefore identifies an exact pane
185
+ * "sessionName:windowIndex.paneIndex" — so the cockpit distinguishes multiple
186
+ * Claude panes sharing one window, and `send-keys -t <target>` always lands in
187
+ * the intended pane rather than the window's currently-active pane. Resolves to
188
+ * [] when no tmux server is running.
176
189
  *
177
190
  * @returns {Promise<Window[]>}
178
191
  */
179
- export async function listWindows() {
192
+ export async function listPanes() {
180
193
  let stdout;
181
194
  try {
182
- ({ stdout } = await runTmux(['list-windows', '-a', '-F', FORMAT]));
195
+ ({ stdout } = await runTmux(['list-panes', '-a', '-F', FORMAT]));
183
196
  } catch (err) {
184
197
  // tmux exits 1 with "no server running" or "error connecting to server"
185
198
  const msg = String(err?.message || '');
@@ -201,35 +214,43 @@ export async function listWindows() {
201
214
  throw err;
202
215
  }
203
216
 
204
- const windows = [];
217
+ const panes = [];
205
218
  for (const line of stdout.split('\n')) {
206
219
  const trimmed = line.trim();
207
220
  if (!trimmed) continue;
208
221
 
209
222
  const parts = trimmed.split(SEP);
210
- if (parts.length < 7) continue;
223
+ if (parts.length < 9) continue;
211
224
 
212
- const [sessionName, rawIndex, windowName, rawActive, rawPid, cwd, cmd, windowId, rawPane] = parts;
225
+ const [sessionName, rawIndex, windowName, rawActive, rawPid, cwd, cmd, windowId, rawPane, rawPaneActive] = parts;
213
226
  const windowIndex = Number(rawIndex);
214
227
  const panePid = Number(rawPid);
228
+ const paneIndex = Number(rawPane) || 0;
215
229
 
216
- windows.push({
230
+ panes.push({
217
231
  sessionName,
218
232
  windowIndex,
219
233
  windowName,
220
- target: `${sessionName}:${windowIndex}`,
234
+ target: `${sessionName}:${windowIndex}.${paneIndex}`,
221
235
  active: rawActive === '1',
236
+ paneActive: rawPaneActive === '1',
222
237
  panePid,
223
238
  cwd,
224
239
  cmd,
225
240
  windowId: windowId ?? `${sessionName}:${windowIndex}`,
226
- paneIndex: Number(rawPane) || 0,
241
+ paneIndex,
227
242
  });
228
243
  }
229
244
 
230
- return windows;
245
+ return panes;
231
246
  }
232
247
 
248
+ /**
249
+ * @deprecated Back-compat alias — enumerates panes (not windows). Kept so any
250
+ * external caller keeps working after the window→pane migration.
251
+ */
252
+ export const listWindows = listPanes;
253
+
233
254
  // ---------------------------------------------------------------------------
234
255
  // Session-name helpers
235
256
  // ---------------------------------------------------------------------------
package/lib/uploads.js CHANGED
@@ -40,3 +40,23 @@ export async function sweepUploads(dir, ttlMs, now = Date.now()) {
40
40
  }
41
41
  return { removed, kept };
42
42
  }
43
+
44
+ /**
45
+ * Resolve a client-supplied file path, confining it to `uploadsDir`. Returns the
46
+ * absolute path when it lives strictly inside uploadsDir, else null. Guards the
47
+ * /api/file route against serving arbitrary filesystem paths (path traversal).
48
+ *
49
+ * @param {string} raw client-supplied ?path= value
50
+ * @param {string} uploadsDir absolute uploads directory
51
+ * @returns {string|null}
52
+ */
53
+ export function resolveUploadPath(raw, uploadsDir) {
54
+ if (!raw || typeof raw !== 'string') return null;
55
+ let full;
56
+ try {
57
+ full = path.resolve(raw);
58
+ } catch {
59
+ return null;
60
+ }
61
+ return full.startsWith(uploadsDir + path.sep) ? full : null;
62
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idl3/claude-control",
3
- "version": "0.1.2",
3
+ "version": "0.1.7",
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
@@ -15,10 +15,13 @@ import { WebSocketServer } from 'ws';
15
15
  import * as tmux from './lib/tmux.js';
16
16
  import * as terminal from './lib/terminal.js';
17
17
  import { TranscriptTailer } from './lib/transcript.js';
18
- import { SessionRegistry } from './lib/sessions.js';
18
+ import { SubAgentsWatcher } from './lib/subagents.js';
19
+ import { parsePanePrompt } from './lib/prompt.js';
20
+ import { SessionRegistry, listRecentTranscripts } from './lib/sessions.js';
21
+ import { loadPins, savePins, validateTranscriptPath, pinKey } from './lib/pins.js';
19
22
  import { ResourceMonitor } from './lib/resources.js';
20
23
  import { buildAnswerProgram } from './lib/answer.js';
21
- import { sweepUploads } from './lib/uploads.js';
24
+ import { sweepUploads, resolveUploadPath } from './lib/uploads.js';
22
25
  import { getVersionInfo, currentVersion } from './lib/version.js';
23
26
  import * as push from './lib/push.js';
24
27
  import { readConfig, writeConfig } from './lib/config.js';
@@ -69,6 +72,8 @@ const CONFIG = {
69
72
  uploadsDir:
70
73
  env('UPLOADS') || path.join(os.homedir(), '.claude-control', 'uploads'),
71
74
  uploadTtlHours: Number(env('UPLOAD_TTL_HOURS')) || 24,
75
+ pinsFile:
76
+ env('PINS') || path.join(os.homedir(), '.claude-control', 'pins.json'),
72
77
  };
73
78
 
74
79
  const MIME = {
@@ -99,6 +104,10 @@ const IMAGE_MIME = {
99
104
  const registry = new SessionRegistry({ projectsRoot: CONFIG.projectsRoot, tmux });
100
105
  const resources = new ResourceMonitor({ rssLimitMB: CONFIG.rssLimitMB });
101
106
 
107
+ // Manual transcript pins (windowId.paneIndex -> transcript path). Loaded at boot,
108
+ // applied to the registry, and editable via /api/pins.
109
+ let pins = loadPins(CONFIG.pinsFile);
110
+
102
111
  /** id -> { tailer, clients:Set<ws>, pending } */
103
112
  const subscriptions = new Map();
104
113
 
@@ -175,6 +184,21 @@ const server = http.createServer((req, res) => {
175
184
  if (!checkToken(req)) return endJson(res, 401, { error: 'unauthorized' });
176
185
  return handleUpload(req, res, u);
177
186
  }
187
+ if (u.pathname === '/api/file') {
188
+ if (!checkToken(req)) return endJson(res, 401, { error: 'unauthorized' });
189
+ return handleServeFile(res, u);
190
+ }
191
+ if (u.pathname === '/api/pins') {
192
+ if (!checkToken(req)) return endJson(res, 401, { error: 'unauthorized' });
193
+ if (req.method === 'POST') return handleSetPin(req, res);
194
+ return endJson(res, 200, { pins });
195
+ }
196
+ if (u.pathname === '/api/transcripts') {
197
+ if (!checkToken(req)) return endJson(res, 401, { error: 'unauthorized' });
198
+ return listRecentTranscripts({ projectsRoot: CONFIG.projectsRoot })
199
+ .then((list) => endJson(res, 200, { transcripts: list }))
200
+ .catch((err) => endJson(res, 500, { error: String(err?.message || err) }));
201
+ }
178
202
  if (u.pathname === '/api/push/vapid') {
179
203
  if (!checkToken(req)) return endJson(res, 401, { error: 'unauthorized' });
180
204
  return endJson(res, 200, { publicKey: push.getPublicKey() });
@@ -539,6 +563,69 @@ async function proxyTerminalHttp(req, res, u) {
539
563
  req.pipe(proxyReq);
540
564
  }
541
565
 
566
+ // Serve a previously-uploaded file back to the UI by absolute path (used by the
567
+ // in-transcript image previews / lightbox). Coexists with /api/uploads/<basename>
568
+ // above; both confine strictly to uploadsDir.
569
+ const FILE_MIME = {
570
+ '.png': 'image/png',
571
+ '.jpg': 'image/jpeg',
572
+ '.jpeg': 'image/jpeg',
573
+ '.gif': 'image/gif',
574
+ '.webp': 'image/webp',
575
+ '.avif': 'image/avif',
576
+ '.bmp': 'image/bmp',
577
+ '.svg': 'image/svg+xml',
578
+ '.pdf': 'application/pdf',
579
+ };
580
+ function handleServeFile(res, u) {
581
+ const full = resolveUploadPath(u.searchParams.get('path') || '', CONFIG.uploadsDir);
582
+ // Confinement: only files strictly inside uploadsDir are served.
583
+ if (!full) {
584
+ return endJson(res, 403, { error: 'forbidden' });
585
+ }
586
+ fs.readFile(full, (err, data) => {
587
+ if (err) { res.writeHead(404); return res.end('not found'); }
588
+ const ext = path.extname(full).toLowerCase();
589
+ res.writeHead(200, {
590
+ 'content-type': FILE_MIME[ext] || 'application/octet-stream',
591
+ 'cache-control': 'private, max-age=3600',
592
+ });
593
+ res.end(data);
594
+ });
595
+ }
596
+
597
+ // Set or clear a manual transcript pin. Body: { id, transcriptPath }.
598
+ // transcriptPath null/empty clears the pin. The pin is keyed by the session's
599
+ // stable windowId.paneIndex so it survives tmux window renumbering.
600
+ async function handleSetPin(req, res) {
601
+ let body;
602
+ try {
603
+ body = await readJsonBody(req);
604
+ } catch (err) {
605
+ return endJson(res, 400, { error: String(err?.message || err) });
606
+ }
607
+ const id = typeof body?.id === 'string' ? body.id : '';
608
+ const session = sessionById(id);
609
+ if (!session) return endJson(res, 404, { error: 'unknown session' });
610
+ const key = pinKey(session.windowId, session.paneIndex);
611
+
612
+ const raw = body?.transcriptPath;
613
+ if (raw == null || raw === '') {
614
+ delete pins[key];
615
+ } else {
616
+ const full = validateTranscriptPath(raw, CONFIG.projectsRoot);
617
+ if (!full) return endJson(res, 400, { error: 'invalid transcript path' });
618
+ pins = { ...pins, [key]: full };
619
+ }
620
+ try {
621
+ savePins(CONFIG.pinsFile, pins);
622
+ } catch (err) {
623
+ return endJson(res, 500, { error: String(err?.message || err) });
624
+ }
625
+ registry.setPins(pins);
626
+ return endJson(res, 200, { ok: true, pins });
627
+ }
628
+
542
629
  function serveStatic(pathname, res) {
543
630
  const rel = pathname === '/' ? 'index.html' : pathname.replace(/^\/+/, '');
544
631
  const full = path.join(PUBLIC_DIR, rel);
@@ -547,7 +634,15 @@ function serveStatic(pathname, res) {
547
634
  res.writeHead(403); return res.end('forbidden');
548
635
  }
549
636
  fs.readFile(full, (err, data) => {
550
- if (err) { res.writeHead(404); return res.end('not found'); }
637
+ if (err) {
638
+ // SPA fallback: a missing path with no file extension is a client-side
639
+ // route (e.g. /0/1/1, a deep link to a session) — serve index.html so the
640
+ // app boots and reads the path. Real missing assets (with an extension)
641
+ // still 404.
642
+ if (!path.extname(rel)) return serveIndexHtml(res);
643
+ res.writeHead(404);
644
+ return res.end('not found');
645
+ }
551
646
  const ext = path.extname(full).toLowerCase();
552
647
  res.writeHead(200, {
553
648
  'content-type': MIME[ext] || 'application/octet-stream',
@@ -559,6 +654,18 @@ function serveStatic(pathname, res) {
559
654
  });
560
655
  }
561
656
 
657
+ // Serve the SPA shell (index.html) for client-side routes.
658
+ function serveIndexHtml(res) {
659
+ fs.readFile(path.join(PUBLIC_DIR, 'index.html'), (err, data) => {
660
+ if (err) { res.writeHead(404); return res.end('not found'); }
661
+ res.writeHead(200, {
662
+ 'content-type': MIME['.html'],
663
+ 'cache-control': 'no-store, must-revalidate',
664
+ });
665
+ res.end(data);
666
+ });
667
+ }
668
+
562
669
  // --- WebSocket --------------------------------------------------------------
563
670
  // 1 MB cap: control messages are tiny; this prevents a single huge frame from
564
671
  // forcing a multi-hundred-MB string allocation in the cockpit process.
@@ -685,14 +792,32 @@ function ensureSubscription(id) {
685
792
  if (!session.transcriptPath) {
686
793
  sub = { tailer: null, clients: new Set(), pending: null, ready: Promise.resolve() };
687
794
  subscriptions.set(id, sub);
795
+ startPromptPoller(id, sub);
688
796
  return sub;
689
797
  }
690
798
 
691
799
  const tailer = new TranscriptTailer(session.transcriptPath, { maxBuffer: CONFIG.maxBuffer });
692
- sub = { tailer, clients: new Set(), pending: null };
800
+ // Watch this session's sub-agent transcripts (Task/Agent). Discovery is polled
801
+ // when the parent transcript grows (when sub-agents spawn) + once at subscribe.
802
+ const subagents = new SubAgentsWatcher(session.transcriptPath);
803
+ sub = { tailer, subagents, clients: new Set(), pending: null };
693
804
  subscriptions.set(id, sub);
694
805
 
695
- tailer.on('append', (msgs) => broadcastTo(id, { type: 'append', id, messages: msgs }));
806
+ subagents.on('change', (entry) =>
807
+ broadcastTo(id, { type: 'subagent', id, subagent: entry }),
808
+ );
809
+
810
+ tailer.on('append', (msgs) => {
811
+ broadcastTo(id, { type: 'append', id, messages: msgs });
812
+ // A sub-agent may have just spawned (poll for its files) or finished (its
813
+ // Task tool-call produced a tool_result → mark it done).
814
+ subagents.poll();
815
+ for (const m of msgs) {
816
+ for (const b of m.blocks ?? []) {
817
+ if (b.kind === 'tool_result' && b.forId) subagents.markDone(b.forId);
818
+ }
819
+ }
820
+ });
696
821
  tailer.on('pending', (pending) => {
697
822
  sub.pending = pending;
698
823
  registry.setPending(id, !!pending);
@@ -701,16 +826,59 @@ function ensureSubscription(id) {
701
826
  tailer.on('error', (err) => broadcastTo(id, { type: 'ack', op: 'tail', ok: false, error: String(err?.message || err) }));
702
827
 
703
828
  // Kick off the bounded tail load once; all clients await this same promise so
704
- // the initial `messages` frame never races the first read.
705
- sub.ready = tailer.start();
829
+ // the initial `messages` frame never races the first read. Poll sub-agents
830
+ // after the initial load so an already-running sub-agent shows immediately.
831
+ sub.ready = tailer.start().then(() => {
832
+ subagents.poll();
833
+ // Mark already-finished sub-agents done from the EXISTING buffer: their
834
+ // parent tool_result arrived before subscribe and is never re-streamed, so
835
+ // without this they'd be stuck showing "running".
836
+ const doneIds = new Set();
837
+ for (const m of tailer.getMessages()) {
838
+ for (const b of m.blocks ?? []) {
839
+ if (b.kind === 'tool_result' && b.forId) doneIds.add(b.forId);
840
+ }
841
+ }
842
+ if (doneIds.size) subagents.markDone(doneIds);
843
+ });
706
844
  sub.ready.catch(() => {}); // errors surface via the per-subscribe await below
845
+ startPromptPoller(id, sub);
707
846
  return sub;
708
847
  }
709
848
 
849
+ // Poll the live pane for a TUI selection prompt (permission/trust/numbered menu).
850
+ // These never reach the transcript, so without this the cockpit shows a pending
851
+ // tool-call and looks stuck. Broadcasts a `prompt` frame only when it changes.
852
+ function startPromptPoller(id, sub) {
853
+ if (sub.promptTimer) return;
854
+ sub._lastPrompt = undefined;
855
+ const tick = async () => {
856
+ const session = sessionById(id);
857
+ if (!session || !tmux.isValidTarget(session.target)) return;
858
+ let prompt = null;
859
+ try {
860
+ const cap = await tmux.capturePane(session.target, 40);
861
+ prompt = parsePanePrompt(cap);
862
+ } catch {
863
+ return;
864
+ }
865
+ const json = prompt ? JSON.stringify(prompt) : null;
866
+ if (json !== sub._lastPrompt) {
867
+ sub._lastPrompt = json;
868
+ broadcastTo(id, { type: 'prompt', id, prompt });
869
+ }
870
+ };
871
+ sub.promptTimer = setInterval(() => tick().catch(() => {}), 2000);
872
+ if (sub.promptTimer.unref) sub.promptTimer.unref();
873
+ tick().catch(() => {});
874
+ }
875
+
710
876
  function maybeTeardown(id) {
711
877
  const sub = subscriptions.get(id);
712
878
  if (sub && sub.clients.size === 0) {
713
879
  if (sub.tailer) sub.tailer.stop();
880
+ if (sub.subagents) sub.subagents.stop();
881
+ if (sub.promptTimer) clearInterval(sub.promptTimer);
714
882
  subscriptions.delete(id);
715
883
  }
716
884
  }
@@ -759,6 +927,9 @@ async function handleClientMessage(ws, msg) {
759
927
  messages: sub.tailer ? sub.tailer.getMessages() : [],
760
928
  pending: sub.tailer ? sub.tailer.getPending() : null,
761
929
  });
930
+ // Snapshot any already-running sub-agents for this session.
931
+ const subs = sub.subagents ? sub.subagents.snapshot() : [];
932
+ if (subs.length) send(ws, { type: 'subagents', id: msg.id, subagents: subs });
762
933
  return;
763
934
  }
764
935
  case 'unsubscribe': {
@@ -798,6 +969,20 @@ async function handleClientMessage(ws, msg) {
798
969
  const text = await tmux.capturePane(session.target, lines);
799
970
  return send(ws, { type: 'capture', id: msg.id, text });
800
971
  }
972
+ case 'promptkey': {
973
+ // Respond to a live TUI selection prompt (permission/menu). Whitelisted
974
+ // keys only — never arbitrary text — so this can't be used to inject input.
975
+ const session = sessionById(msg.id);
976
+ if (!session) throw new Error('unknown session');
977
+ if (!tmux.isValidTarget(session.target)) throw new Error('invalid tmux target');
978
+ const ALLOWED = new Set(['1', '2', '3', '4', '5', '6', '7', '8', '9', 'Enter', 'Escape', 'Up', 'Down']);
979
+ if (!ALLOWED.has(msg.key)) throw new Error('key not allowed');
980
+ await tmux.sendRawKeys(session.target, [msg.key]);
981
+ // Force the next poll tick to broadcast (the prompt should now change/clear).
982
+ const sub = subscriptions.get(msg.id);
983
+ if (sub) sub._lastPrompt = '__force__';
984
+ return send(ws, { type: 'ack', op: 'promptkey', ok: true });
985
+ }
801
986
  default:
802
987
  return;
803
988
  }
@@ -872,6 +1057,7 @@ async function runUploadSweep() {
872
1057
  }
873
1058
 
874
1059
  async function main() {
1060
+ registry.setPins(pins); // apply persisted pins before the first refresh
875
1061
  registry.start();
876
1062
  resources.start();
877
1063
  await registry.refresh().catch(() => {});
@@ -1,3 +1,3 @@
1
- import{g as Ve}from"./index-wrjqfzbL.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-BBsn4UVr.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};