Compare commits

..

No commits in common. "main" and "v0.7.1" have entirely different histories.
main ... v0.7.1

27 changed files with 85 additions and 1613 deletions

654
app.py
View file

@ -3,7 +3,7 @@ from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Request, HTTPExcept
from fastapi.responses import HTMLResponse, RedirectResponse, PlainTextResponse, FileResponse, JSONResponse
from fastapi.staticfiles import StaticFiles
import json, re, secrets, string, time, os, threading, asyncio, hashlib
from collections import defaultdict, deque
from collections import defaultdict
from typing import Optional
app = FastAPI()
@ -15,11 +15,6 @@ application = app # alias if you prefer "application"
app.mount("/static", StaticFiles(directory=os.path.join(os.path.dirname(os.path.abspath(__file__)), "vendor")),
name="vendor")
# Minimum gap between accepted pings, per connection. A ping is one inbound message
# fanned out to every peer, so this bounds that amplification. Low enough that rapid
# human clicking gets through.
PING_MIN_INTERVAL = 0.15
# Languages offered in the editor dropdown. This is a security boundary as much as a
# feature list: the value is interpolated into a module URL client-side, so it must
# never be free-form. Keep in sync with vendor/fetch.sh.
@ -45,111 +40,6 @@ DOC_ID_RE = re.compile(r"^[a-zA-Z0-9_-]{1,64}$")
def is_valid_doc_id(doc_id: str) -> bool:
return bool(DOC_ID_RE.match(doc_id))
# --- Operational transform core ------------------------------------------------
# An op is a single splice: at `pos`, remove `dele` code units, insert `ins`. Every
# textarea interaction - typing, deleting, pasting, Tab, autocorrect - reduces to one
# splice, so this is the whole edit vocabulary. Ops travel over the wire instead of
# document snapshots because two snapshots taken concurrently cannot be combined: one
# has to win, which is what used to drop a peer's text and yank carets between lines.
#
# Offsets are UTF-16 code units, because that is what a textarea reports and what JS
# string indexing uses. Python indexes by code point; the two diverge only on pads
# holding astral characters (emoji), which is what splice()'s second path is for.
#
# diffOp/applyOp/transform in the client mirror this. The two copies MUST agree:
# test_ot.py fuzzes convergence, and every update carries the server's length so a
# disagreement resyncs instead of silently drifting.
MAX_OP_LOG = 256 # ops kept per room, for rebasing edits from stale clients
MAX_OP_LOG_BYTES = 262144 # ...and a size ceiling, so one big paste cannot pin memory
def count_astral(s: str) -> int:
"""Chars needing two UTF-16 code units. isascii() is a flag on the string object,
so the common case is O(1) and never walks the document."""
if s.isascii():
return 0
return sum(1 for ch in s if ord(ch) > 0xFFFF)
def u16len(s: str) -> int:
return len(s) + count_astral(s)
def splice(text: str, op, u16: bool):
"""Apply an op; returns (new_text, removed_text).
`u16` says the text holds astral characters, so code-unit offsets no longer line up
with Python's code-point indexing and the splice has to happen in UTF-16 space. That
path costs an encode/decode of the document, which is why it is gated rather than
unconditional."""
pos, dele, ins = op
if not u16:
return text[:pos] + ins + text[pos + dele:], text[pos:pos + dele]
b = text.encode("utf-16-le")
lo, hi = pos * 2, (pos + dele) * 2
return ((b[:lo] + ins.encode("utf-16-le") + b[hi:]).decode("utf-16-le"),
b[lo:hi].decode("utf-16-le"))
def transform(a, b, a_first: bool):
"""Rewrite op `a` so it applies to a text that already has op `b` applied.
`a_first` says whether `a` precedes `b` in the server's total order - which is not the
same question as which one is already applied. The server rebases an incoming op onto
ops it has already ordered (a_first=False); a client rebases an op the server has
already ordered onto its own uncommitted edits (a_first=True). Both sides must agree
on the resulting order or their documents drift apart, so the flag is required rather
than defaulted."""
apos, adel, ains = a
bpos, bdel, bins = b
aend, bend = apos + adel, bpos + bdel
# Two pure inserts at one position do not overlap - only the order of the two
# insertions is ambiguous - so settle it on the server's ordering. Without this each
# side puts the other's text first and two people typing at the same spot diverge
# immediately.
if adel == 0 and bdel == 0 and apos == bpos:
return a if a_first else (apos + u16len(bins), 0, ains)
if bend <= apos: # b entirely before a
return (apos + u16len(bins) - bdel, adel, ains)
if aend <= bpos: # b entirely after a
return a
# The two edits touch the same characters. A single splice cannot express the honest
# result - a's surviving fragments are no longer contiguous - so clamp, identically on
# both sides so they still converge. Only reachable when two people edit the same
# characters inside one round trip, where any answer is arbitrary.
if apos < bpos:
return (apos, bpos - apos, ains)
return (bpos + u16len(bins), max(0, aend - bend), ains)
def parse_op(data):
"""Validate a wire op into (pos, dele, ins), or None. Structural checks only: the
range is checked after rebasing, since these offsets describe the client's older
version of the text, and the size limit is checked against the resulting document so
that an oversize paste gets told it was too large rather than malformed."""
if not isinstance(data, dict):
return None
pos, dele, ins = data.get("pos"), data.get("del"), data.get("ins")
# bool subclasses int, so True would otherwise pass as position 1
if isinstance(pos, bool) or isinstance(dele, bool):
return None
if not isinstance(pos, int) or not isinstance(dele, int) or not isinstance(ins, str):
return None
if pos < 0 or dele < 0:
return None
if "\x00" in ins: # matches the POST / check
return None
try:
ins.encode("utf-8") # rejects lone surrogates, which cannot be stored
except UnicodeEncodeError:
return None
return (pos, dele, ins)
# --- end operational transform core --------------------------------------------
# test_ot.py slices the block between these two markers and execs it, so that the
# fuzzer can run on a bare python with no fastapi installed. Keep them in place.
def get_client_ip(conn) -> str:
# Only honor proxy headers when explicitly opted in — otherwise attackers
# can spoof them to bypass per-IP limits.
@ -298,15 +188,10 @@ def record_auth_failure(client_ip: str):
HTML = """<!doctype html>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>aukpad</title>
<style>
:root {
/* Integer px, not a ratio. 14px * 1.4 = 19.6px, and a fractional line box makes the
real per-line advance 19.5938 rather than 19.6 - a 4.4px error by line 700 for any
code that computes a line's position, and a source of rounding divergence between
the textarea and the <pre> layers. 20px divides cleanly at 1x/1.25x/1.5x/2x. */
--line-h: 20px;
--line-h: 1.4;
--bg: #fbfbfb;
--text: #111;
--border: #ddd;
@ -324,8 +209,6 @@ HTML = """<!doctype html>
--hl-title: #6f42c1;
--hl-attr: #e36209;
--hl-meta: #6a737d;
--ping: #ff0000;
--ping-alpha: .5;
}
[data-theme="dark"] {
--bg: #17181E;
@ -345,17 +228,12 @@ HTML = """<!doctype html>
--hl-title: #d2a8ff;
--hl-attr: #ffa657;
--hl-meta: #8b949e;
--ping: #ff0000;
--ping-alpha: .5;
}
* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; padding: 0; background-color: var(--bg); color: var(--text); }
body { font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Apple Color Emoji","Segoe UI Emoji";
max-width: 1000px; margin: 0 auto; padding: 1rem; display: flex; flex-direction: column;
height: 100vh; height: 100dvh; /* dvh excludes iOS Safari's dynamic toolbar; 100vh is the fallback */
box-sizing: border-box; }
header { display:flex; justify-content:space-between; align-items:center; gap:.5rem; margin-bottom: .5rem; flex-shrink: 0; }
#padname { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
max-width: 1000px; margin: 0 auto; padding: 1rem; display: flex; flex-direction: column; height: 100vh; box-sizing: border-box; }
header { display:flex; justify-content:space-between; align-items:center; margin-bottom: .5rem; flex-shrink: 0; }
a,button { padding:.35rem 0; text-decoration:none; border:1px solid var(--border); border-radius:4px; background:var(--btn-bg); color:var(--text); cursor:pointer; font-size:.9rem; font-weight:bold; min-width:2rem; text-align:center; display:inline-block; }
a:hover,button:hover { background:var(--btn-hover); }
/* Icon buttons: inline SVG so glyphs render the same on every platform */
@ -363,85 +241,30 @@ HTML = """<!doctype html>
#lang { height:2rem; max-width:7.5rem; padding:0 .35rem; border:1px solid var(--border); border-radius:4px;
background:var(--btn-bg); color:var(--text); font-size:.8rem; font-family:inherit; cursor:pointer; }
#lang:disabled { opacity:.5; cursor:default; }
/* Three groups: pad content | new pad | app UI. .25rem flex gap + .75rem = 1rem,
i.e. half of the 2rem icon box. */
#newpad, #theme-btn { margin-left:.75rem; }
.ic { width:1.05rem; height:1.05rem; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round; pointer-events:none; }
/* Flex row so pad name, status and peer badge share one centre line. Baseline
alignment cannot do this: #peers is an inline-flex box, whose baseline comes
from its own first item rather than from the text beside it. */
#meta { display:flex; align-items:center; gap:.5rem; min-width:0; }
#status { font-size:.9rem; opacity:.7; white-space:nowrap; }
#status { font-size:.9rem; opacity:.7; margin-left:.5rem; }
#status::before { content:""; display:inline-block; width:.55em; height:.55em; border-radius:50%; margin-right:.35rem; background:#ef4444; }
#status.connected::before { background:#22c55e; }
/* Reads as a button to match the header, but it is a status badge: no hover, no pointer. */
/* Bare status readout, no chrome. #meta's align-items:center keeps it on the
header centre line, so no vertical-align is needed. */
#peers { display:none; align-items:center; gap:.3rem; flex-shrink:0;
color:#22c55e; font-size:.9rem; font-weight:700; line-height:1.4; }
#peers .ic-sm { width:1.05rem; height:1.05rem; } /* scoped: the notice icon stays .9rem */
#wrap { display:grid; grid-template-columns: max-content 1fr; grid-template-rows: 1fr auto;
border:1px solid var(--border); border-radius:4px; overflow:hidden; flex: 1; }
#peers { font-size:.95rem; font-weight:bold; margin-left:.5rem; margin-right:.3rem; color:#22c55e; display:none; }
#wrap { display:grid; grid-template-columns: max-content 1fr; border:1px solid var(--border); border-radius:4px; overflow:hidden;
flex: 1; }
#gutter, #t, #hl { font: 14px/var(--line-h) ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; }
#gutter { padding:.5rem .75rem; text-align:right; color:var(--gutter-color); background:var(--gutter-bg); border-right:1px solid var(--gutter-border);
user-select:none; min-width: 3ch; white-space: pre; height: 100%; overflow: hidden;
cursor:pointer; }
user-select:none; min-width: 3ch; white-space: pre; height: 100%; overflow: hidden; }
/* Highlight overlay. #t and #hl must render glyph-for-glyph identically: any
difference in padding, white-space or tab-size shows up as drifting colors. */
/* #edit owns the background so that #t and #hl can both be transparent. That is what
lets the ping layer sit underneath them and read as a highlight behind the text
rather than a tint over it - and it works in both .hl states, where which of the
two text layers is the visible one flips. */
#edit { position:relative; overflow:hidden; background:var(--bg); }
#edit { position:relative; overflow:hidden; }
#t, #hl { padding:.5rem .75rem; border:0; margin:0; white-space:pre; tab-size:4; }
#t { position:absolute; inset:0; width:100%; height:100%; resize:none; outline:0;
overflow:auto; background:transparent; color:var(--text); }
#hl { position:absolute; inset:0; overflow:hidden; pointer-events:none; background:transparent; color:var(--text); }
overflow:auto; background:var(--bg); color:var(--text); }
#hl { position:absolute; inset:0; overflow:hidden; pointer-events:none; background:var(--bg); color:var(--text); }
#hl code { font: inherit; padding:0; background:none; }
/* First child of #edit, so it paints beneath the text layers. */
#pings { position:absolute; inset:0; overflow:hidden; pointer-events:none; }
#pings-in { position:absolute; inset:0; }
.ping { position:absolute; left:0; right:0; background:var(--ping); opacity:var(--ping-alpha);
animation:ping-fade 5s forwards; }
@keyframes ping-fade { 0%, 70% { opacity:var(--ping-alpha); } 100% { opacity:0; } }
@media (prefers-reduced-motion: reduce) { .ping { animation-duration:5s; } }
/* Shown when a ping lands outside the viewport. The one interactive element in the
#edit stack, so unlike #pings it keeps its pointer events. Resets the global
a,button rule, which would otherwise force min-width:2rem and inline-block. */
/* --sbw is the textarea's vertical scrollbar width, kept current by syncExtent();
without it the pill sits on top of the scrollbar. */
#pingjump { display:none; position:absolute; right:calc(.75rem + var(--sbw, 0px)); top:.75rem; z-index:5;
align-items:center; gap:.5rem; padding:.5rem .85rem; min-width:0;
border:1px solid var(--border); border-radius:6px; background:var(--panel-bg);
color:var(--text); box-shadow:0 4px 12px rgba(0,0,0,.1);
font-size:1.05rem; font-weight:600; cursor:pointer; }
/* Solid, not var(--ping-alpha): the bar is translucent because it sits behind text,
but the dot needs to read as the same colour at a glance. */
#pingjump .dot { width:.65rem; height:.65rem; border-radius:50%; background:var(--ping); flex-shrink:0; }
/* Scoped: .ic-sm is shared with the notice bar and the peer count. */
#pingjump .ic-sm { width:1.15rem; height:1.15rem; }
/* A .show class, not the hidden attribute: this id rule would outrank [hidden]. */
#pingjump.show { display:inline-flex; }
#pingjump.up .ic-sm { transform:rotate(180deg); }
/* Only while highlighting is live; without .hl the editor is byte-identical to
the plain version, which is the fallback for every failure path. */
#wrap.hl #t { color:transparent; background:transparent; caret-color:var(--text); }
#wrap.hl #t::placeholder { color:var(--gutter-color); }
#wrap.hl #t::selection { background:rgba(59,130,246,.35); }
pre { margin: 0; }
/* Footer bar of the editor rather than loose text under it: it sits inside #wrap,
so it inherits the box's border and rounded corners. */
#notice { grid-column: 1 / -1; position:relative; display:flex; gap:.5rem;
align-items:center; justify-content:center; text-align:center;
margin:0; padding:.4rem 2rem; border-top:1px solid var(--border);
background:var(--gutter-bg); font-size:.75rem; line-height:1.5;
color:var(--text); cursor:pointer; }
.ic-sm { width:.9rem; height:.9rem; flex-shrink:0; }
/* Reset the global a,button rule: this is a bare glyph, not a control.
Absolute so it stays at the right edge without offsetting the centred text. */
#notice button { all:unset; position:absolute; right:.5rem; top:50%; transform:translateY(-50%);
cursor:pointer; padding:0 .2rem; font-size:1rem; line-height:1.1; }
#notice button:focus-visible { outline:2px solid currentColor; border-radius:3px; }
/* highlight.js tokens, mapped onto the theme variables above so dark/light just works */
.hljs-comment, .hljs-quote { color:var(--hl-comment); font-style:italic; }
.hljs-keyword, .hljs-selector-tag, .hljs-literal, .hljs-type, .hljs-doctag { color:var(--hl-keyword); }
@ -456,8 +279,7 @@ HTML = """<!doctype html>
#lock-btn.locked { background:#dbeafe; border-color:#3b82f6; }
[data-theme="dark"] #lock-btn.locked { background:#1e3a5f; border-color:#3b82f6; }
#pw-panel { display:none; position:absolute; top:2.5rem; right:0; background:var(--panel-bg); border:1px solid var(--border);
border-radius:6px; padding:.75rem; box-shadow:0 4px 12px rgba(0,0,0,.1); z-index:10;
min-width:230px; max-width:calc(100vw - 2rem); }
border-radius:6px; padding:.75rem; box-shadow:0 4px 12px rgba(0,0,0,.1); z-index:10; min-width:230px; }
#pw-panel.open { display:block; }
#pw-panel label { font-size:.8rem; font-weight:bold; display:block; margin-bottom:.4rem; }
#pw-panel input { width:100%; padding:.35rem .5rem; border:1px solid var(--border); border-radius:4px;
@ -468,34 +290,13 @@ HTML = """<!doctype html>
#pw-overlay { display:none; position:fixed; inset:0; background:var(--overlay-bg); z-index:100;
align-items:center; justify-content:center; }
#pw-overlay.open { display:flex; }
#pw-box { background:var(--panel-bg); border-radius:8px; padding:1.5rem; width:300px; max-width:calc(100vw - 2rem); }
#pw-box { background:var(--panel-bg); border-radius:8px; padding:1.5rem; width:300px; }
#pw-box h2 { margin:0 0 .75rem; font-size:1rem; }
#auth-input { width:100%; padding:.45rem .6rem; border:1px solid var(--border); border-radius:4px;
font-size:1rem; margin-bottom:.5rem; font-family:inherit; display:block; background:var(--btn-bg); color:var(--text); }
#auth-error { color:#ef4444; font-size:.85rem; margin-bottom:.5rem; display:none; }
#auth-submit { width:100%; padding:.45rem; background:#000; color:#fff; border:none;
border-radius:4px; font-size:.95rem; cursor:pointer; }
/* --- Narrow screens: header stacks into two rows, pad name + status above,
controls below. Giving #meta a 100% flex-basis is what forces the wrap;
header's existing gap:.5rem then doubles as the row gap. Because the
controls get a full row, nothing has to be hidden or narrowed to fit. --- */
@media (max-width: 640px) {
body { padding:.5rem; }
header { flex-wrap:wrap; }
#meta { flex:1 0 100%; }
#newpad, #theme-btn { margin-left:.4rem; }
#notice { padding:.4rem 1.75rem; }
}
/* --- Touch devices: 16px fields, because iOS Safari force-zooms into anything
smaller on focus and never zooms back out. Button sizes are unchanged. --- */
@media (pointer: coarse) {
/* All three together, or the overlay desyncs. 24px keeps the line box integral at
16px the way 20px does at 14px. */
#gutter, #t, #hl { font-size:16px; line-height:24px; }
#pw-panel input { font-size:1rem; }
}
</style>
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false"><defs>
<symbol id="i-copy" viewBox="0 0 24 24"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></symbol>
@ -504,22 +305,17 @@ HTML = """<!doctype html>
<symbol id="i-lock" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></symbol>
<symbol id="i-moon" viewBox="0 0 24 24"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/></symbol>
<symbol id="i-sun" viewBox="0 0 24 24"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M6.3 17.7l-1.4 1.4M19.1 4.9l-1.4 1.4"/></symbol>
<symbol id="i-user" viewBox="0 0 24 24"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></symbol>
<symbol id="i-chevron" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></symbol>
<symbol id="i-info" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4M12 8h.01"/></symbol>
</defs></svg>
<header>
<div id="meta">
<strong id="padname"></strong><span id="status">disconnected</span><span id="peers"><svg class="ic ic-sm" aria-hidden="true"><use href="#i-user"/></svg><span id="peer-count"></span></span>
<div>
<strong id="padname"></strong><span id="peers"></span><span id="status">disconnected</span>
</div>
<div style="position:relative; display:flex; align-items:center; gap:.25rem;">
<!-- Acts on this pad's content -->
<select id="lang" title="Syntax highlighting for this pad" aria-label="Syntax highlighting" disabled></select>
<button id="copy" class="ibtn" onclick="copyToClipboard()" title="Copy to clipboard" aria-label="Copy to clipboard"><svg class="ic"><use href="#i-copy"/></svg></button>
<button id="lock-btn" class="ibtn" onclick="togglePwPanel()" title="No password click to set one"><svg class="ic"><use href="#i-lock"/></svg></button>
<!-- Leaves this pad -->
<a id="newpad" class="ibtn" href="/" target="_blank" title="Opens a new pad in a new tab" aria-label="New pad"><svg class="ic"><use href="#i-plus"/></svg></a>
<!-- App-level UI -->
<button id="lock-btn" class="ibtn" onclick="togglePwPanel()" title="No password click to set one"><svg class="ic"><use href="#i-lock"/></svg></button>
<button id="theme-btn" class="ibtn" onclick="toggleTheme()" title="Toggle dark/light mode" aria-label="Toggle dark/light mode"><svg class="ic"><use href="#i-moon"/></svg></button>
<a id="info" class="ibtn" href="/system/info" title="System info" aria-label="System info"><svg class="ic"><use href="#i-info"/></svg></a>
<div id="pw-panel">
@ -537,20 +333,11 @@ HTML = """<!doctype html>
<div id="wrap">
<pre id="gutter">1</pre>
<div id="edit">
<div id="pings" aria-hidden="true"><div id="pings-in"></div></div>
<pre id="hl" aria-hidden="true"><code></code></pre>
<textarea id="t" spellcheck="false" autocomplete="off" autocorrect="off" autocapitalize="off"
placeholder="Start typing…"></textarea>
<button id="pingjump" type="button"><span class="dot" aria-hidden="true"></span><span id="pingjump-txt"></span><svg class="ic ic-sm" aria-hidden="true"><use href="#i-chevron"/></svg></button>
</div>
<p id="notice" onclick="hideNotice()" title="Click to dismiss">
<svg class="ic ic-sm" aria-hidden="true"><use href="#i-info"/></svg>
<span>Content is deleted after __RETENTION_HOURS__ hours of inactivity and can be accessed
by the server and anyone with the link and optional password.</span>
<button type="button" aria-label="Dismiss notice">&times;</button>
</p>
</div>
<div id="pw-overlay">
<div id="pw-box">
<h2>This pad is password protected</h2>
@ -594,116 +381,17 @@ function toggleTheme() {
});
})();
// Bottom notice: click anywhere on it to dismiss, remembered across pads and reloads.
function hideNotice() {
$("#notice").style.display = "none";
try { localStorage.setItem("notice", "off"); } catch (e) {}
}
(function() {
try { if (localStorage.getItem("notice") === "off") $("#notice").style.display = "none"; }
catch (e) {} // private mode / storage disabled: just leave the notice up
})();
// Derive docId from path; redirect root to random
let docId = decodeURIComponent(location.pathname.replace(/(^\\/|\\/$)/g, ""));
if (!docId) { location.replace("/" + rand() + "/"); }
$("#padname").textContent = "/"+docId+"/";
// Set client-side rather than server-side: the pad page is one shared HTML constant,
// so interpolating per request would mean rebuilding it on every hit.
document.title = docId + " - aukpad";
let ws, ver = 0, clientId = Math.random().toString(36).slice(2), debounce;
let isProtected = false, isAuthed = false;
let reconnectTimer = null, reconnectDelay = 500;
// --- Sync state ---
// Invariant: shadow -> sent -> ta.value, each step being one splice.
// shadow the server text this client knows about, at version `ver`
// sent shadow with the op currently in flight applied, i.e. what the server will
// hold once it acks. Equal to shadow when nothing is in flight.
// Ops are never stored, only derived by diffing these three strings. That is what keeps
// the state machine small enough to reason about: there is no operation queue.
let shadow = "", sent = "", inflight = false, resyncing = false;
// --- Operational transform core (mirror of the Python side; the two MUST agree) ---
// An op is one splice {pos, del, ins} in UTF-16 code units, which is what textarea
// offsets and JS string indices already use, so nothing is converted on this side.
const isHigh = c => c >= 0xD800 && c <= 0xDBFF;
const isLow = c => c >= 0xDC00 && c <= 0xDFFF;
// The single changed region between two texts: common prefix, common suffix, and
// whatever is left in the middle. Every textarea interaction produces exactly one.
function diffOp(a, b) {
if (a === b) return null;
let s = 0;
const min = Math.min(a.length, b.length);
while (s < min && a[s] === b[s]) s++;
let ae = a.length, be = b.length;
while (ae > s && be > s && a[ae-1] === b[be-1]) { ae--; be--; }
// Never split a surrogate pair: a lone surrogate has no UTF-8 encoding, so the server
// would reject the op instead of syncing it. Nudge the boundaries outward instead.
if (s > 0 && isLow(a.charCodeAt(s)) && isHigh(a.charCodeAt(s-1))) s--;
if (ae < a.length && isLow(a.charCodeAt(ae)) && isHigh(a.charCodeAt(ae-1))) { ae++; be++; }
return {pos: s, del: ae - s, ins: b.slice(s, be)};
}
function applyOp(text, op) {
return text.slice(0, op.pos) + op.ins + text.slice(op.pos + op.del);
}
// Rewrite op `a` so it applies to a text that already has op `b` applied. `aFirst` says
// whether `a` precedes `b` in the server's total order, which is a different question
// from which of the two is already applied: here it is always the op the server has
// ordered that comes first, and the server applies the identical rule.
function transform(a, b, aFirst) {
const aEnd = a.pos + a.del, bEnd = b.pos + b.del;
// Two pure inserts at one position do not overlap - only the order of the two
// insertions is ambiguous - so settle it on the server's ordering. Without this each
// side puts the other's text first and two people typing at the same spot diverge
// immediately.
if (!a.del && !b.del && a.pos === b.pos)
return aFirst ? a : {pos: a.pos + b.ins.length, del: 0, ins: a.ins};
if (bEnd <= a.pos) return {pos: a.pos + b.ins.length - b.del, del: a.del, ins: a.ins};
if (aEnd <= b.pos) return a;
// Same-characters overlap, which one splice cannot express faithfully. Clamp exactly
// as the server does; the length tripwire below catches anything this gets wrong.
if (a.pos < b.pos) return {pos: a.pos, del: b.pos - a.pos, ins: a.ins};
return {pos: b.pos + b.ins.length, del: Math.max(0, aEnd - bEnd), ins: a.ins};
}
// Our picture of the server is wrong, so stop guessing and ask for a snapshot. Cheap to
// trigger and self-healing, which is what lets transform() clamp overlaps crudely rather
// than carry the machinery needed to always be exactly right. Blocks sending meanwhile:
// an op diffed against a bad shadow would be nonsense.
function resync() {
if (resyncing || ws?.readyState !== 1) return;
resyncing = true;
ws.send(JSON.stringify({type: "resync"}));
}
// Send edits: one op in flight at a time, so the server always has a base version to
// rebase against. Anything typed while it is in flight is picked up by the next diff.
function flush() {
if (inflight || resyncing || ws?.readyState !== 1 || !isAuthed) return;
const op = diffOp(shadow, ta.value);
if (!op) return;
ws.send(JSON.stringify({type: "edit", base: ver, op, clientId}));
sent = ta.value;
inflight = true;
}
// Transient message in the status slot. There is no error surface in the editor, which
// is how a refused edit used to pass unnoticed.
let notifyTimer = null;
function notify(text) {
const el = $("#status");
el.textContent = text;
clearTimeout(notifyTimer);
notifyTimer = setTimeout(() => {
el.textContent = ws?.readyState === 1 ? "connected" : "disconnected";
}, 4000);
}
// dirty: local edits the server has not acknowledged. Guards the reconnect path
// from overwriting text typed while the socket was down.
let dirty = false, reconnectTimer = null, reconnectDelay = 500;
const urlPw = new URLSearchParams(location.search).get("pw") || "";
// --- Line numbers ---
@ -717,85 +405,12 @@ function updateGutter() {
gutter.textContent = s;
}
ta.addEventListener("input", refresh);
// The textarea's horizontal scrollbar eats into its client height, so it can scroll
// further than the mirrors, which have overflow:hidden and no scrollbar. At the bottom
// they clamp and lag behind by the scrollbar's height. Give them matching bottom padding
// so their scrollable extents line up. Recomputed on input and resize, the only times a
// horizontal scrollbar can appear or vanish.
function syncExtent() {
const sb = ta.offsetHeight - ta.clientHeight; // 0 when there is no h-scrollbar
const pad = parseFloat(getComputedStyle(ta).paddingBottom) + sb;
gutter.style.paddingBottom = pad + "px";
hl.style.paddingBottom = pad + "px";
// Same idea horizontally, for anything anchored to the editor's right edge.
document.documentElement.style.setProperty("--sbw", (ta.offsetWidth - ta.clientWidth) + "px");
}
window.addEventListener("resize", () => { syncExtent(); syncScroll(); });
function syncScroll() {
gutter.scrollTop = ta.scrollTop;
// The overlay needs horizontal sync too: white-space:pre means long lines
// scroll sideways, and the gutter never does.
hl.scrollTop = ta.scrollTop; hl.scrollLeft = ta.scrollLeft;
// Pings sit at document coordinates; move the wrapper rather than every bar.
pingsIn.style.transform = "translateY(" + (-ta.scrollTop) + "px)";
// Only drop the notice if the document shrank past the line it points at.
if (jumpLine && jumpLine > lineCount()) hideJump();
}
// --- Line ping: click a line number to flash that line for every peer ---
// Read from computed style, never hardcoded: the touch media query switches the
// editor font from 14px to 16px, so a literal line height would be wrong on mobile.
const pingsIn = $("#pings-in");
const lineH = () => parseFloat(getComputedStyle(ta).lineHeight);
const padTop = () => parseFloat(getComputedStyle(ta).paddingTop);
const lineCount = () => ta.value.split("\\n").length;
gutter.addEventListener("click", (e) => {
if (!isAuthed || ws?.readyState !== 1) return;
const y = e.clientY - gutter.getBoundingClientRect().top + ta.scrollTop - padTop();
const line = Math.floor(y / lineH()) + 1;
if (line < 1 || line > lineCount()) return; // e.g. clicked below the last line
ws.send(JSON.stringify({type: "ping", line}));
});
function showPing(line) {
// Re-pinging a visible line restarts it rather than stacking a second bar.
const prev = pingsIn.querySelector('[data-line="' + line + '"]');
if (prev) prev.remove();
const el = document.createElement("div");
el.className = "ping";
el.dataset.line = line;
el.style.top = (padTop() + (line - 1) * lineH()) + "px";
el.style.height = lineH() + "px";
el.addEventListener("animationend", () => el.remove());
pingsIn.appendChild(el);
}
// --- Ping notice ---
// Raised for every ping, for every peer, whether or not the line is on screen: on a long
// pad the bar alone is easy to miss. Click it to jump to the line and re-flash it.
const jump = $("#pingjump");
let jumpLine = 0, jumpTimer = null;
function showJump(line) {
jumpLine = line;
$("#pingjump-txt").textContent = "Ping on line " + line;
jump.classList.toggle("up", padTop() + (line - 1) * lineH() < ta.scrollTop);
jump.classList.add("show");
clearTimeout(jumpTimer);
jumpTimer = setTimeout(hideJump, 10000);
}
function hideJump() { jump.classList.remove("show"); jumpLine = 0; }
jump.addEventListener("click", () => {
const line = jumpLine;
hideJump();
ta.scrollTop = Math.max(0, padTop() + (line - 1) * lineH() - (ta.clientHeight - lineH()) / 2);
syncScroll();
showPing(line); // re-flash: the original bar may have almost faded by now
});
ta.addEventListener("scroll", syncScroll);
// Also sync on keydown for immediate response
ta.addEventListener("keydown", () => { setTimeout(syncScroll, 0); });
@ -872,7 +487,6 @@ function scheduleHl() {
// Re-render gutter and highlighting together.
function refresh() {
updateGutter();
syncExtent();
if (ta.value.length > HL_MAX) {
wrap.classList.remove("hl");
langSel.disabled = true;
@ -954,13 +568,6 @@ function submitAuth() {
}
}
function setPeers(n) {
const el = $("#peers");
$("#peer-count").textContent = n; // never el.textContent: it would wipe the <svg>
el.title = n + (n === 1 ? " peer" : " peers") + " connected";
el.style.display = "inline-flex";
}
// --- WS connect + sync ---
function connect(){
isAuthed = false;
@ -977,7 +584,7 @@ function connect(){
if (msg.type === "init") {
isProtected = !!msg.protected;
updateLockBtn();
if (msg.peers !== undefined) setPeers(msg.peers);
if (msg.peers !== undefined) { const el = $("#peers"); el.textContent = msg.peers; el.style.display = "inline"; }
if (isProtected && !isAuthed) {
if (urlPw) {
ws.send(JSON.stringify({type: "auth", password: urlPw}));
@ -987,17 +594,15 @@ function connect(){
} else {
isAuthed = true;
hideOverlay();
// One path for the first snapshot, the post-auth snapshot and every resync.
// Edits the server has never seen survive: keep the textarea as it is and let the
// next diff carry them onto the fresh snapshot rather than pushing a stale copy.
const local = diffOp(shadow, ta.value);
shadow = sent = msg.text;
ver = msg.ver;
inflight = resyncing = false;
if (!local) ta.value = msg.text;
if (dirty && ta.value !== msg.text) {
// Reconnected with unsent edits: push them rather than lose them.
ws.send(JSON.stringify({type: "edit", ver, text: ta.value, clientId}));
} else {
ta.value = msg.text;
}
refresh();
applyLang(msg.lang || "");
flush();
// ?pw= on an unprotected pad sets the password instead of unlocking.
// Guard on !isProtected: the server re-sends init after a successful
// auth, and that init lands here too without the guard every unlock
@ -1016,55 +621,17 @@ function connect(){
const errEl = $("#auth-error");
errEl.textContent = msg.message;
errEl.style.display = "block";
} else {
// An edit was refused - it would have pushed the pad over the size limit. Roll
// back to the server's text and release the send slot: leaving the two diverged
// is what used to make the limit look like random text loss.
inflight = false;
ta.value = sent = shadow;
refresh();
notify(msg.message);
}
} else if (msg.type === "update" && isAuthed) {
if (msg.ver <= ver) return; // stale: a snapshot already covered it
if (msg.ver > ver + 1) { resync(); return; } // we missed one
if (msg.clientId === clientId) {
// Our own edit, echoed back: the ack. It carries the op as the server actually
// applied it, which is not necessarily the op we sent - it may have been rebased
// onto edits we had not seen when we sent it.
shadow = applyOp(shadow, msg.op);
ver = msg.ver;
inflight = false;
if (shadow !== sent) resync(); // our model of the server was wrong
else flush(); // push whatever was typed since
} else {
// Rebase the remote op past our own uncommitted edits - the one in flight and
// anything typed since - so it lands where the server put it, relative to text
// the server has not seen yet. Nothing else in the document is touched, which is
// the whole reason the caret stays where it is.
const mine = diffOp(shadow, sent), buffered = diffOp(sent, ta.value);
shadow = applyOp(shadow, msg.op);
ver = msg.ver;
// The remote op was ordered before anything of ours that is still local, so it
// comes first in both rebases.
let r = mine ? transform(msg.op, mine, true) : msg.op;
sent = applyOp(sent, r);
if (buffered) r = transform(r, buffered, true);
// setRangeText is the native splice: the spec shifts the selection by the length
// delta for us, and the browser's undo stack survives - both of which assigning
// to .value destroys. It fires no input event, so there is no echo back to the
// server, but that also means the gutter and overlay need refreshing by hand.
ta.setRangeText(r.ins, r.pos, r.pos + r.del, "preserve");
refresh();
}
// Divergence tripwire. shadow is exactly what we believe the server holds, so this
// is valid whether or not we have local edits outstanding.
if (shadow.length !== msg.len) resync();
} else if (msg.type === "update" && isAuthed && msg.ver > ver && msg.clientId !== clientId) {
const {selectionStart:s, selectionEnd:e} = ta;
const oldText = ta.value;
ta.value = msg.text; ver = msg.ver; refresh();
ta.selectionStart = adjustCursor(oldText, msg.text, s);
ta.selectionEnd = adjustCursor(oldText, msg.text, e);
} else if (msg.type === "peers_changed") {
setPeers(msg.count);
} else if (msg.type === "ping") {
showPing(msg.line);
showJump(msg.line);
const el = $("#peers");
el.textContent = msg.count;
el.style.display = "inline";
} else if (msg.type === "lang_changed") {
applyLang(msg.lang || "");
} else if (msg.type === "protected_changed") {
@ -1119,6 +686,25 @@ async function copyToClipboard() {
setTimeout(() => setIcon(btn, "copy"), 1500);
}
// Adjust cursor position after a remote text update.
// Finds the single changed region (common prefix + suffix),
// then shifts the cursor accordingly:
// - change is after cursor no movement
// - change is before cursor shift by length delta
// - cursor was inside the changed region place at end of new content
function adjustCursor(oldText, newText, pos) {
let start = 0;
const minLen = Math.min(oldText.length, newText.length);
while (start < minLen && oldText[start] === newText[start]) start++;
if (pos <= start) return pos; // change is entirely after cursor
let oldEnd = oldText.length, newEnd = newText.length;
while (oldEnd > start && newEnd > start && oldText[oldEnd - 1] === newText[newEnd - 1]) {
oldEnd--; newEnd--;
}
if (pos >= oldEnd) return pos + (newEnd - oldEnd); // change is before cursor
return newEnd; // cursor was inside changed region
}
connect();
// Handle Tab key to insert 4 spaces instead of navigation
@ -1134,19 +720,20 @@ ta.addEventListener("keydown", (e) => {
}
});
// Send edits (coalesced). Short window: the payload is a splice now rather than the
// whole document, and the less local text is sitting unsent, the smaller the window in
// which two people's edits can overlap at all.
// Send edits (debounced)
ta.addEventListener("input", () => {
dirty = true;
clearTimeout(debounce);
debounce = setTimeout(flush, 30);
debounce = setTimeout(() => {
if (ws?.readyState === 1 && isAuthed) {
ws.send(JSON.stringify({type:"edit", ver, text: ta.value, clientId}));
dirty = false;
}
}, 120);
});
</script>
"""
# RETENTION_HOURS is fixed at startup, so bake it in once rather than per request.
HTML = HTML.replace("__RETENTION_HOURS__", str(RETENTION_HOURS))
@app.get("/favicon.ico", include_in_schema=False)
def favicon():
return FileResponse("favicon.ico")
@ -1194,7 +781,6 @@ def get_system_info():
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>aukpad - System Info</title>
<style>
:root {{
@ -1253,8 +839,6 @@ def get_system_info():
<li>optional syntax highlighting (24 languages) from a per-pad dropdown, shared with everyone on the pad;
highlight.js is vendored locally and loaded lazily, so a plain pad fetches nothing</li>
<li>line numbers; Tab inserts 4 spaces</li>
<li>click a line number to &quot;ping&quot; it that line flashes for five seconds
for everyone on the pad</li>
<li>dark / light mode (auto-detects system preference, manual toggle)</li>
<li>copy-to-clipboard and "new pad" buttons, live peer count in the header</li>
</ul>
@ -1500,20 +1084,6 @@ def get_raw_pad_content(doc_id: str, request: Request, pw: str = ""):
update_room_access_time(doc_id)
return PlainTextResponse(room["text"])
def init_payload(room: dict, authed: bool) -> dict:
"""The full-snapshot message. Used for the first connect, after a successful unlock,
and for every resync, so a client resets its sync state through one code path."""
return {
"type": "init",
"text": room["text"] if authed else "",
"ver": room["ver"],
"protected": room["pw_hash"] is not None,
"peers": len(room["peers"]),
# Withheld until authed: the language is content metadata and would tell
# someone sitting at the unlock overlay what kind of file this is.
"lang": room.get("lang") if authed else None,
}
async def _broadcast(doc_id: str, message: dict, exclude: WebSocket | None = None, authed_only: bool = False):
room = rooms.get(doc_id)
if not room: return
@ -1583,13 +1153,21 @@ async def ws(doc_id: str, ws: WebSocket):
await _broadcast(doc_id, {"type": "peers_changed", "count": len(room["peers"])})
# Per-connection auth state: already authed if pad has no password
last_ping = 0.0 # per-connection ping throttle; see the "ping" branch below
authed = room["pw_hash"] is None
if authed:
room["authed_peers"].add(ws)
# Send init; withhold text if protected and not yet authed
await ws.send_text(json.dumps(init_payload(room, authed)))
await ws.send_text(json.dumps({
"type": "init",
"text": room["text"] if authed else "",
"ver": room["ver"],
"protected": room["pw_hash"] is not None,
"peers": len(room["peers"]),
# Withheld until authed: the language is content metadata and would tell
# someone sitting at the unlock overlay what kind of file this is.
"lang": room.get("lang") if authed else None,
}))
try:
while True:
msg = await ws.receive_text()
@ -1600,7 +1178,10 @@ async def ws(doc_id: str, ws: WebSocket):
authed = True
room["authed_peers"].add(ws)
await ws.send_text(json.dumps({"type": "auth_ok"}))
await ws.send_text(json.dumps(init_payload(room, True)))
await ws.send_text(json.dumps({
"type": "init", "text": room["text"], "ver": room["ver"], "protected": False,
"lang": room.get("lang"),
}))
else:
if not check_auth_rate_limit(client_ip):
await ws.send_text(json.dumps({"type": "error", "message": "Too many failed attempts. Try again later."}))
@ -1613,7 +1194,10 @@ async def ws(doc_id: str, ws: WebSocket):
authed = True
room["authed_peers"].add(ws)
await ws.send_text(json.dumps({"type": "auth_ok"}))
await ws.send_text(json.dumps(init_payload(room, True)))
await ws.send_text(json.dumps({
"type": "init", "text": room["text"], "ver": room["ver"], "protected": True,
"lang": room.get("lang"),
}))
else:
record_auth_failure(client_ip)
await ws.send_text(json.dumps({"type": "error", "message": "Wrong password"}))
@ -1624,80 +1208,27 @@ async def ws(doc_id: str, ws: WebSocket):
continue
if data.get("type") == "edit":
op = parse_op(data.get("op"))
base = data.get("base")
if op is None or isinstance(base, bool) or not isinstance(base, int) or base < 0:
await ws.send_text(json.dumps({"type": "error", "message": "Malformed edit"}))
continue
new_text = str(data.get("text", ""))
# Derived state, initialized on the first edit rather than in the three
# places a room gets built. Both are then O(1) to read and to maintain,
# which is what keeps a keystroke off the length of the document.
log = room.setdefault("ops", deque(maxlen=MAX_OP_LOG))
astral = room.setdefault("astral", count_astral(room["text"]))
nbytes = room.setdefault("bytes", len(room["text"].encode("utf-8")))
# Rebase onto everything that landed since the client's base version. If
# the log no longer reaches that far back the client cannot be rebased and
# has to start from a snapshot - the same path a room restored from cache
# takes, since its op history did not survive.
if base < room["ver"] - len(log):
await ws.send_text(json.dumps(init_payload(room, True)))
continue
for v, prev in log:
if v > base:
# The logged op was ordered first, so the incoming one follows it.
op = transform(op, prev, False)
if op[0] + op[1] > len(room["text"]) + astral:
await ws.send_text(json.dumps(init_payload(room, True)))
continue
try:
new_text, removed = splice(room["text"], op, astral > 0)
delta = len(op[2].encode("utf-8")) - len(removed.encode("utf-8"))
except UnicodeEncodeError:
# A clamped op split a surrogate pair, so the result is not storable.
# Rare, and cheaper to resync than to repair.
await ws.send_text(json.dumps(init_payload(room, True)))
continue
if nbytes + delta > MAX_TEXT_SIZE:
# The client rolls its own text back to ours, so the two cannot
# diverge silently the way they used to when this was ignored.
# Check text size limit
if len(new_text.encode('utf-8')) > MAX_TEXT_SIZE:
await ws.send_text(json.dumps({"type": "error", "message": f"Text too large. Max size: {MAX_TEXT_SIZE} bytes"}))
continue
room["text"] = new_text
room["bytes"] = nbytes + delta
room["astral"] = astral - count_astral(removed) + count_astral(op[2])
room["ver"] += 1
room["last_access"] = time.time()
log.append((room["ver"], op))
while len(log) > 1 and sum(len(o[2]) for _, o in log) > MAX_OP_LOG_BYTES:
log.popleft()
# Save to cache
save_room_data_to_cache(doc_id, room)
# Goes to everyone including the author: the author recognises its own
# clientId and treats the echo as the ack, which carries the op as it was
# actually applied - rebased, if it arrived stale. `len` is the divergence
# tripwire: a client whose own length disagrees asks for a snapshot.
await _broadcast(doc_id, {
"type": "update",
"op": {"pos": op[0], "del": op[1], "ins": op[2]},
"text": room["text"],
"ver": room["ver"],
"len": len(room["text"]) + room["astral"],
"clientId": data.get("clientId"),
}, authed_only=True)
elif data.get("type") == "resync":
# A client whose shadow no longer matches us asks for a fresh snapshot.
# Unthrottled on purpose: unlike a ping this fans out to nobody, so the
# cost lands on the asker's own connection, same as hitting /raw.
await ws.send_text(json.dumps(init_payload(room, True)))
elif data.get("type") == "set_password":
pw = str(data.get("password", ""))
if pw:
@ -1720,21 +1251,6 @@ async def ws(doc_id: str, ws: WebSocket):
save_room_data_to_cache(doc_id, room)
await _broadcast(doc_id, {"type": "lang_changed", "lang": room["lang"]}, authed_only=True)
elif data.get("type") == "ping":
# Flash a line for everyone. Stateless: nothing is stored, so there is
# nothing to drift, expire or clean up on disconnect.
now = time.monotonic()
if now - last_ping < PING_MIN_INTERVAL:
continue # one inbound message fans out to every peer - throttle it
last_ping = now
line = data.get("line")
# bool subclasses int, so True would otherwise pass as line 1
if isinstance(line, bool) or not isinstance(line, int):
continue
if not 1 <= line <= room["text"].count("\n") + 1:
continue
await _broadcast(doc_id, {"type": "ping", "line": line}, authed_only=True)
except WebSocketDisconnect:
pass
finally:

29
vendor/fetch.sh vendored
View file

@ -1,29 +0,0 @@
#!/usr/bin/env bash
# Re-download the vendored highlight.js ES modules.
#
# Run by hand when bumping HLJS_VERSION; the result is committed to git. This is
# deliberately NOT part of the Docker build — baking the files into the image is
# what keeps the app free of any network dependency at runtime.
set -euo pipefail
HLJS_VERSION="${HLJS_VERSION:-11.9.0}"
BASE="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/${HLJS_VERSION}/es"
DEST="$(cd "$(dirname "$0")" && pwd)/hljs"
# Keep this list in sync with LANGS in app.py.
LANGS=(accesslog apache bash cpp css diff dockerfile go graphql http ini
java javascript json markdown nginx php powershell python rust sql
typescript xml yaml)
mkdir -p "$DEST/languages"
echo "highlight.js ${HLJS_VERSION} -> $DEST"
curl -fsS "$BASE/core.min.js" -o "$DEST/core.min.js"
printf ' %-14s %6s bytes\n' core.min.js "$(wc -c < "$DEST/core.min.js")"
for lang in "${LANGS[@]}"; do
curl -fsS "$BASE/languages/${lang}.min.js" -o "$DEST/languages/${lang}.min.js"
printf ' %-14s %6s bytes\n' "$lang" "$(wc -c < "$DEST/languages/${lang}.min.js")"
done
echo "total: $(du -sh "$DEST" | cut -f1) in $(find "$DEST" -type f | wc -l) files"

View file

@ -1,307 +0,0 @@
/*!
Highlight.js v11.9.0 (git: f47103d4f1)
(c) 2006-2023 undefined and other contributors
License: BSD-3-Clause
*/
function e(t){return t instanceof Map?t.clear=t.delete=t.set=()=>{
throw Error("map is read-only")}:t instanceof Set&&(t.add=t.clear=t.delete=()=>{
throw Error("set is read-only")
}),Object.freeze(t),Object.getOwnPropertyNames(t).forEach((n=>{
const i=t[n],s=typeof i;"object"!==s&&"function"!==s||Object.isFrozen(i)||e(i)
})),t}class t{constructor(e){
void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1}
ignoreMatch(){this.isMatchIgnored=!0}}function n(e){
return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;")
}function i(e,...t){const n=Object.create(null);for(const t in e)n[t]=e[t]
;return t.forEach((e=>{for(const t in e)n[t]=e[t]})),n}const s=e=>!!e.scope
;class r{constructor(e,t){
this.buffer="",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){
this.buffer+=n(e)}openNode(e){if(!s(e))return;const t=((e,{prefix:t})=>{
if(e.startsWith("language:"))return e.replace("language:","language-")
;if(e.includes(".")){const n=e.split(".")
;return[`${t}${n.shift()}`,...n.map(((e,t)=>`${e}${"_".repeat(t+1)}`))].join(" ")
}return`${t}${e}`})(e.scope,{prefix:this.classPrefix});this.span(t)}
closeNode(e){s(e)&&(this.buffer+="</span>")}value(){return this.buffer}span(e){
this.buffer+=`<span class="${e}">`}}const o=(e={})=>{const t={children:[]}
;return Object.assign(t,e),t};class a{constructor(){
this.rootNode=o(),this.stack=[this.rootNode]}get top(){
return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){
this.top.children.push(e)}openNode(e){const t=o({scope:e})
;this.add(t),this.stack.push(t)}closeNode(){
if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){
for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}
walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){
return"string"==typeof t?e.addText(t):t.children&&(e.openNode(t),
t.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){
"string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{
a._collapse(e)})))}}class c extends a{constructor(e){super(),this.options=e}
addText(e){""!==e&&this.add(e)}startScope(e){this.openNode(e)}endScope(){
this.closeNode()}__addSublanguage(e,t){const n=e.root
;t&&(n.scope="language:"+t),this.add(n)}toHTML(){
return new r(this,this.options).value()}finalize(){
return this.closeAllNodes(),!0}}function l(e){
return e?"string"==typeof e?e:e.source:null}function g(e){return h("(?=",e,")")}
function u(e){return h("(?:",e,")*")}function d(e){return h("(?:",e,")?")}
function h(...e){return e.map((e=>l(e))).join("")}function f(...e){const t=(e=>{
const t=e[e.length-1]
;return"object"==typeof t&&t.constructor===Object?(e.splice(e.length-1,1),t):{}
})(e);return"("+(t.capture?"":"?:")+e.map((e=>l(e))).join("|")+")"}
function p(e){return RegExp(e.toString()+"|").exec("").length-1}
const b=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./
;function m(e,{joinWith:t}){let n=0;return e.map((e=>{n+=1;const t=n
;let i=l(e),s="";for(;i.length>0;){const e=b.exec(i);if(!e){s+=i;break}
s+=i.substring(0,e.index),
i=i.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?s+="\\"+(Number(e[1])+t):(s+=e[0],
"("===e[0]&&n++)}return s})).map((e=>`(${e})`)).join(t)}
const E="[a-zA-Z]\\w*",x="[a-zA-Z_]\\w*",w="\\b\\d+(\\.\\d+)?",y="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",_="\\b(0b[01]+)",O={
begin:"\\\\[\\s\\S]",relevance:0},k={scope:"string",begin:"'",end:"'",
illegal:"\\n",contains:[O]},v={scope:"string",begin:'"',end:'"',illegal:"\\n",
contains:[O]},N=(e,t,n={})=>{const s=i({scope:"comment",begin:e,end:t,
contains:[]},n);s.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 r=f("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 s.contains.push({begin:h(/[ ]+/,"(",r,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),s
},S=N("//","$"),M=N("/\\*","\\*/"),R=N("#","$");var A=Object.freeze({
__proto__:null,APOS_STRING_MODE:k,BACKSLASH_ESCAPE:O,BINARY_NUMBER_MODE:{
scope:"number",begin:_,relevance:0},BINARY_NUMBER_RE:_,COMMENT:N,
C_BLOCK_COMMENT_MODE:M,C_LINE_COMMENT_MODE:S,C_NUMBER_MODE:{scope:"number",
begin:y,relevance:0},C_NUMBER_RE:y,END_SAME_AS_BEGIN:e=>Object.assign(e,{
"on:begin":(e,t)=>{t.data._beginMatch=e[1]},"on:end":(e,t)=>{
t.data._beginMatch!==e[1]&&t.ignoreMatch()}}),HASH_COMMENT_MODE:R,IDENT_RE:E,
MATCH_NOTHING_RE:/\b\B/,METHOD_GUARD:{begin:"\\.\\s*"+x,relevance:0},
NUMBER_MODE:{scope:"number",begin:w,relevance:0},NUMBER_RE:w,
PHRASAL_WORDS_MODE:{
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/
},QUOTE_STRING_MODE:v,REGEXP_MODE:{scope:"regexp",begin:/\/(?=[^/\n]*\/)/,
end:/\/[gimuy]*/,contains:[O,{begin:/\[/,end:/\]/,relevance:0,contains:[O]}]},
RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",
SHEBANG:(e={})=>{const t=/^#![ ]*\//
;return e.binary&&(e.begin=h(t,/.*\b/,e.binary,/\b.*/)),i({scope:"meta",begin:t,
end:/$/,relevance:0,"on:begin":(e,t)=>{0!==e.index&&t.ignoreMatch()}},e)},
TITLE_MODE:{scope:"title",begin:E,relevance:0},UNDERSCORE_IDENT_RE:x,
UNDERSCORE_TITLE_MODE:{scope:"title",begin:x,relevance:0}});function j(e,t){
"."===e.input[e.index-1]&&t.ignoreMatch()}function I(e,t){
void 0!==e.className&&(e.scope=e.className,delete e.className)}function T(e,t){
t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)",
e.__beforeBegin=j,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords,
void 0===e.relevance&&(e.relevance=0))}function L(e,t){
Array.isArray(e.illegal)&&(e.illegal=f(...e.illegal))}function B(e,t){
if(e.match){
if(e.begin||e.end)throw Error("begin & end are not supported with match")
;e.begin=e.match,delete e.match}}function P(e,t){
void 0===e.relevance&&(e.relevance=1)}const D=(e,t)=>{if(!e.beforeMatch)return
;if(e.starts)throw Error("beforeMatch cannot be used with starts")
;const n=Object.assign({},e);Object.keys(e).forEach((t=>{delete e[t]
})),e.keywords=n.keywords,e.begin=h(n.beforeMatch,g(n.begin)),e.starts={
relevance:0,contains:[Object.assign(n,{endsParent:!0})]
},e.relevance=0,delete n.beforeMatch
},H=["of","and","for","in","not","or","if","then","parent","list","value"],C="keyword"
;function $(e,t,n=C){const i=Object.create(null)
;return"string"==typeof e?s(n,e.split(" ")):Array.isArray(e)?s(n,e):Object.keys(e).forEach((n=>{
Object.assign(i,$(e[n],t,n))})),i;function s(e,n){
t&&(n=n.map((e=>e.toLowerCase()))),n.forEach((t=>{const n=t.split("|")
;i[n[0]]=[e,U(n[0],n[1])]}))}}function U(e,t){
return t?Number(t):(e=>H.includes(e.toLowerCase()))(e)?0:1}const z={},W=e=>{
console.error(e)},X=(e,...t)=>{console.log("WARN: "+e,...t)},G=(e,t)=>{
z[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),z[`${e}/${t}`]=!0)
},K=Error();function F(e,t,{key:n}){let i=0;const s=e[n],r={},o={}
;for(let e=1;e<=t.length;e++)o[e+i]=s[e],r[e+i]=!0,i+=p(t[e-1])
;e[n]=o,e[n]._emit=r,e[n]._multi=!0}function Z(e){(e=>{
e.scope&&"object"==typeof e.scope&&null!==e.scope&&(e.beginScope=e.scope,
delete e.scope)})(e),"string"==typeof e.beginScope&&(e.beginScope={
_wrap:e.beginScope}),"string"==typeof e.endScope&&(e.endScope={_wrap:e.endScope
}),(e=>{if(Array.isArray(e.begin)){
if(e.skip||e.excludeBegin||e.returnBegin)throw W("skip, excludeBegin, returnBegin not compatible with beginScope: {}"),
K
;if("object"!=typeof e.beginScope||null===e.beginScope)throw W("beginScope must be object"),
K;F(e,e.begin,{key:"beginScope"}),e.begin=m(e.begin,{joinWith:""})}})(e),(e=>{
if(Array.isArray(e.end)){
if(e.skip||e.excludeEnd||e.returnEnd)throw W("skip, excludeEnd, returnEnd not compatible with endScope: {}"),
K
;if("object"!=typeof e.endScope||null===e.endScope)throw W("endScope must be object"),
K;F(e,e.end,{key:"endScope"}),e.end=m(e.end,{joinWith:""})}})(e)}function V(e){
function t(t,n){
return RegExp(l(t),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(n?"g":""))
}class n{constructor(){
this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}
addRule(e,t){
t.position=this.position++,this.matchIndexes[this.matchAt]=t,this.regexes.push([t,e]),
this.matchAt+=p(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null)
;const e=this.regexes.map((e=>e[1]));this.matcherRe=t(m(e,{joinWith:"|"
}),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex
;const t=this.matcherRe.exec(e);if(!t)return null
;const n=t.findIndex(((e,t)=>t>0&&void 0!==e)),i=this.matchIndexes[n]
;return t.splice(0,n),Object.assign(t,i)}}class s{constructor(){
this.rules=[],this.multiRegexes=[],
this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){
if(this.multiRegexes[e])return this.multiRegexes[e];const t=new n
;return this.rules.slice(e).forEach((([e,n])=>t.addRule(e,n))),
t.compile(),this.multiRegexes[e]=t,t}resumingScanAtSamePosition(){
return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,t){
this.rules.push([e,t]),"begin"===t.type&&this.count++}exec(e){
const t=this.getMatcher(this.regexIndex);t.lastIndex=this.lastIndex
;let n=t.exec(e)
;if(this.resumingScanAtSamePosition())if(n&&n.index===this.lastIndex);else{
const t=this.getMatcher(0);t.lastIndex=this.lastIndex+1,n=t.exec(e)}
return n&&(this.regexIndex+=n.position+1,
this.regexIndex===this.count&&this.considerAll()),n}}
if(e.compilerExtensions||(e.compilerExtensions=[]),
e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.")
;return e.classNameAliases=i(e.classNameAliases||{}),function n(r,o){const a=r
;if(r.isCompiled)return a
;[I,B,Z,D].forEach((e=>e(r,o))),e.compilerExtensions.forEach((e=>e(r,o))),
r.__beforeBegin=null,[T,L,P].forEach((e=>e(r,o))),r.isCompiled=!0;let c=null
;return"object"==typeof r.keywords&&r.keywords.$pattern&&(r.keywords=Object.assign({},r.keywords),
c=r.keywords.$pattern,
delete r.keywords.$pattern),c=c||/\w+/,r.keywords&&(r.keywords=$(r.keywords,e.case_insensitive)),
a.keywordPatternRe=t(c,!0),
o&&(r.begin||(r.begin=/\B|\b/),a.beginRe=t(a.begin),r.end||r.endsWithParent||(r.end=/\B|\b/),
r.end&&(a.endRe=t(a.end)),
a.terminatorEnd=l(a.end)||"",r.endsWithParent&&o.terminatorEnd&&(a.terminatorEnd+=(r.end?"|":"")+o.terminatorEnd)),
r.illegal&&(a.illegalRe=t(r.illegal)),
r.contains||(r.contains=[]),r.contains=[].concat(...r.contains.map((e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((t=>i(e,{
variants:null},t)))),e.cachedVariants?e.cachedVariants:q(e)?i(e,{
starts:e.starts?i(e.starts):null
}):Object.isFrozen(e)?i(e):e))("self"===e?r:e)))),r.contains.forEach((e=>{n(e,a)
})),r.starts&&n(r.starts,o),a.matcher=(e=>{const t=new s
;return e.contains.forEach((e=>t.addRule(e.begin,{rule:e,type:"begin"
}))),e.terminatorEnd&&t.addRule(e.terminatorEnd,{type:"end"
}),e.illegal&&t.addRule(e.illegal,{type:"illegal"}),t})(a),a}(e)}function q(e){
return!!e&&(e.endsWithParent||q(e.starts))}class J extends Error{
constructor(e,t){super(e),this.name="HTMLInjectionError",this.html=t}}
const Y=n,Q=i,ee=Symbol("nomatch"),te=n=>{
const i=Object.create(null),s=Object.create(null),r=[];let o=!0
;const a="Could not find the language '{}', did you forget to load/include a language module?",l={
disableAutodetect:!0,name:"Plain text",contains:[]};let p={
ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i,
languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",
cssSelector:"pre code",languages:null,__emitter:c};function b(e){
return p.noHighlightRe.test(e)}function m(e,t,n){let i="",s=""
;"object"==typeof t?(i=e,
n=t.ignoreIllegals,s=t.language):(G("10.7.0","highlight(lang, code, ...args) has been deprecated."),
G("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"),
s=e,i=t),void 0===n&&(n=!0);const r={code:i,language:s};N("before:highlight",r)
;const o=r.result?r.result:E(r.language,r.code,n)
;return o.code=r.code,N("after:highlight",o),o}function E(e,n,s,r){
const c=Object.create(null);function l(){if(!N.keywords)return void M.addText(R)
;let e=0;N.keywordPatternRe.lastIndex=0;let t=N.keywordPatternRe.exec(R),n=""
;for(;t;){n+=R.substring(e,t.index)
;const s=_.case_insensitive?t[0].toLowerCase():t[0],r=(i=s,N.keywords[i]);if(r){
const[e,i]=r
;if(M.addText(n),n="",c[s]=(c[s]||0)+1,c[s]<=7&&(A+=i),e.startsWith("_"))n+=t[0];else{
const n=_.classNameAliases[e]||e;u(t[0],n)}}else n+=t[0]
;e=N.keywordPatternRe.lastIndex,t=N.keywordPatternRe.exec(R)}var i
;n+=R.substring(e),M.addText(n)}function g(){null!=N.subLanguage?(()=>{
if(""===R)return;let e=null;if("string"==typeof N.subLanguage){
if(!i[N.subLanguage])return void M.addText(R)
;e=E(N.subLanguage,R,!0,S[N.subLanguage]),S[N.subLanguage]=e._top
}else e=x(R,N.subLanguage.length?N.subLanguage:null)
;N.relevance>0&&(A+=e.relevance),M.__addSublanguage(e._emitter,e.language)
})():l(),R=""}function u(e,t){
""!==e&&(M.startScope(t),M.addText(e),M.endScope())}function d(e,t){let n=1
;const i=t.length-1;for(;n<=i;){if(!e._emit[n]){n++;continue}
const i=_.classNameAliases[e[n]]||e[n],s=t[n];i?u(s,i):(R=s,l(),R=""),n++}}
function h(e,t){
return e.scope&&"string"==typeof e.scope&&M.openNode(_.classNameAliases[e.scope]||e.scope),
e.beginScope&&(e.beginScope._wrap?(u(R,_.classNameAliases[e.beginScope._wrap]||e.beginScope._wrap),
R=""):e.beginScope._multi&&(d(e.beginScope,t),R="")),N=Object.create(e,{parent:{
value:N}}),N}function f(e,n,i){let s=((e,t)=>{const n=e&&e.exec(t)
;return n&&0===n.index})(e.endRe,i);if(s){if(e["on:end"]){const i=new t(e)
;e["on:end"](n,i),i.isMatchIgnored&&(s=!1)}if(s){
for(;e.endsParent&&e.parent;)e=e.parent;return e}}
if(e.endsWithParent)return f(e.parent,n,i)}function b(e){
return 0===N.matcher.regexIndex?(R+=e[0],1):(T=!0,0)}function m(e){
const t=e[0],i=n.substring(e.index),s=f(N,e,i);if(!s)return ee;const r=N
;N.endScope&&N.endScope._wrap?(g(),
u(t,N.endScope._wrap)):N.endScope&&N.endScope._multi?(g(),
d(N.endScope,e)):r.skip?R+=t:(r.returnEnd||r.excludeEnd||(R+=t),
g(),r.excludeEnd&&(R=t));do{
N.scope&&M.closeNode(),N.skip||N.subLanguage||(A+=N.relevance),N=N.parent
}while(N!==s.parent);return s.starts&&h(s.starts,e),r.returnEnd?0:t.length}
let w={};function y(i,r){const a=r&&r[0];if(R+=i,null==a)return g(),0
;if("begin"===w.type&&"end"===r.type&&w.index===r.index&&""===a){
if(R+=n.slice(r.index,r.index+1),!o){const t=Error(`0 width match regex (${e})`)
;throw t.languageName=e,t.badRule=w.rule,t}return 1}
if(w=r,"begin"===r.type)return(e=>{
const n=e[0],i=e.rule,s=new t(i),r=[i.__beforeBegin,i["on:begin"]]
;for(const t of r)if(t&&(t(e,s),s.isMatchIgnored))return b(n)
;return i.skip?R+=n:(i.excludeBegin&&(R+=n),
g(),i.returnBegin||i.excludeBegin||(R=n)),h(i,e),i.returnBegin?0:n.length})(r)
;if("illegal"===r.type&&!s){
const e=Error('Illegal lexeme "'+a+'" for mode "'+(N.scope||"<unnamed>")+'"')
;throw e.mode=N,e}if("end"===r.type){const e=m(r);if(e!==ee)return e}
if("illegal"===r.type&&""===a)return 1
;if(I>1e5&&I>3*r.index)throw Error("potential infinite loop, way more iterations than matches")
;return R+=a,a.length}const _=O(e)
;if(!_)throw W(a.replace("{}",e)),Error('Unknown language: "'+e+'"')
;const k=V(_);let v="",N=r||k;const S={},M=new p.__emitter(p);(()=>{const e=[]
;for(let t=N;t!==_;t=t.parent)t.scope&&e.unshift(t.scope)
;e.forEach((e=>M.openNode(e)))})();let R="",A=0,j=0,I=0,T=!1;try{
if(_.__emitTokens)_.__emitTokens(n,M);else{for(N.matcher.considerAll();;){
I++,T?T=!1:N.matcher.considerAll(),N.matcher.lastIndex=j
;const e=N.matcher.exec(n);if(!e)break;const t=y(n.substring(j,e.index),e)
;j=e.index+t}y(n.substring(j))}return M.finalize(),v=M.toHTML(),{language:e,
value:v,relevance:A,illegal:!1,_emitter:M,_top:N}}catch(t){
if(t.message&&t.message.includes("Illegal"))return{language:e,value:Y(n),
illegal:!0,relevance:0,_illegalBy:{message:t.message,index:j,
context:n.slice(j-100,j+100),mode:t.mode,resultSoFar:v},_emitter:M};if(o)return{
language:e,value:Y(n),illegal:!1,relevance:0,errorRaised:t,_emitter:M,_top:N}
;throw t}}function x(e,t){t=t||p.languages||Object.keys(i);const n=(e=>{
const t={value:Y(e),illegal:!1,relevance:0,_top:l,_emitter:new p.__emitter(p)}
;return t._emitter.addText(e),t})(e),s=t.filter(O).filter(v).map((t=>E(t,e,!1)))
;s.unshift(n);const r=s.sort(((e,t)=>{
if(e.relevance!==t.relevance)return t.relevance-e.relevance
;if(e.language&&t.language){if(O(e.language).supersetOf===t.language)return 1
;if(O(t.language).supersetOf===e.language)return-1}return 0})),[o,a]=r,c=o
;return c.secondBest=a,c}function w(e){let t=null;const n=(e=>{
let t=e.className+" ";t+=e.parentNode?e.parentNode.className:""
;const n=p.languageDetectRe.exec(t);if(n){const t=O(n[1])
;return t||(X(a.replace("{}",n[1])),
X("Falling back to no-highlight mode for this block.",e)),t?n[1]:"no-highlight"}
return t.split(/\s+/).find((e=>b(e)||O(e)))})(e);if(b(n))return
;if(N("before:highlightElement",{el:e,language:n
}),e.dataset.highlighted)return void console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.",e)
;if(e.children.length>0&&(p.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(e)),p.throwUnescapedHTML))throw new J("One of your code blocks includes unescaped HTML.",e.innerHTML)
;t=e;const i=t.textContent,r=n?m(i,{language:n,ignoreIllegals:!0}):x(i)
;e.innerHTML=r.value,e.dataset.highlighted="yes",((e,t,n)=>{const i=t&&s[t]||n
;e.classList.add("hljs"),e.classList.add("language-"+i)
})(e,n,r.language),e.result={language:r.language,re:r.relevance,
relevance:r.relevance},r.secondBest&&(e.secondBest={
language:r.secondBest.language,relevance:r.secondBest.relevance
}),N("after:highlightElement",{el:e,result:r,text:i})}let y=!1;function _(){
"loading"!==document.readyState?document.querySelectorAll(p.cssSelector).forEach(w):y=!0
}function O(e){return e=(e||"").toLowerCase(),i[e]||i[s[e]]}
function k(e,{languageName:t}){"string"==typeof e&&(e=[e]),e.forEach((e=>{
s[e.toLowerCase()]=t}))}function v(e){const t=O(e)
;return t&&!t.disableAutodetect}function N(e,t){const n=e;r.forEach((e=>{
e[n]&&e[n](t)}))}
"undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",(()=>{
y&&_()}),!1),Object.assign(n,{highlight:m,highlightAuto:x,highlightAll:_,
highlightElement:w,
highlightBlock:e=>(G("10.7.0","highlightBlock will be removed entirely in v12.0"),
G("10.7.0","Please use highlightElement now."),w(e)),configure:e=>{p=Q(p,e)},
initHighlighting:()=>{
_(),G("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")},
initHighlightingOnLoad:()=>{
_(),G("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.")
},registerLanguage:(e,t)=>{let s=null;try{s=t(n)}catch(t){
if(W("Language definition for '{}' could not be registered.".replace("{}",e)),
!o)throw t;W(t),s=l}
s.name||(s.name=e),i[e]=s,s.rawDefinition=t.bind(null,n),s.aliases&&k(s.aliases,{
languageName:e})},unregisterLanguage:e=>{delete i[e]
;for(const t of Object.keys(s))s[t]===e&&delete s[t]},
listLanguages:()=>Object.keys(i),getLanguage:O,registerAliases:k,
autoDetection:v,inherit:Q,addPlugin:e=>{(e=>{
e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=t=>{
e["before:highlightBlock"](Object.assign({block:t.el},t))
}),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=t=>{
e["after:highlightBlock"](Object.assign({block:t.el},t))})})(e),r.push(e)},
removePlugin:e=>{const t=r.indexOf(e);-1!==t&&r.splice(t,1)}}),n.debugMode=()=>{
o=!1},n.safeMode=()=>{o=!0},n.versionString="11.9.0",n.regex={concat:h,
lookahead:g,either:f,optional:d,anyNumberOfTimes:u}
;for(const t in A)"object"==typeof A[t]&&e(A[t]);return Object.assign(n,A),n
},ne=te({});ne.newInstance=()=>te({});export{ne as default};

View file

@ -1,13 +0,0 @@
/*! `accesslog` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict";return e=>{
const n=e.regex,a=["GET","POST","HEAD","PUT","DELETE","CONNECT","OPTIONS","PATCH","TRACE"]
;return{name:"Apache Access Log",contains:[{className:"number",
begin:/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(:\d{1,5})?\b/,relevance:5},{
className:"number",begin:/\b\d+\b/,relevance:0},{className:"string",
begin:n.concat(/"/,n.either(...a)),end:/"/,keywords:a,illegal:/\n/,relevance:5,
contains:[{begin:/HTTP\/[12]\.\d'/,relevance:5}]},{className:"string",
begin:/\[\d[^\]\n]{8,}\]/,illegal:/\n/,relevance:1},{className:"string",
begin:/\[/,end:/\]/,illegal:/\n/,relevance:0},{className:"string",
begin:/"Mozilla\/\d\.\d \(/,end:/"/,illegal:/\n/,relevance:3},{
className:"string",begin:/"/,end:/"/,illegal:/\n/,relevance:0}]}}})()
;export default hljsGrammar;

View file

@ -1,14 +0,0 @@
/*! `apache` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict";return e=>{const a={className:"number",
begin:/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(:\d{1,5})?/};return{
name:"Apache config",aliases:["apacheconf"],case_insensitive:!0,
contains:[e.HASH_COMMENT_MODE,{className:"section",begin:/<\/?/,end:/>/,
contains:[a,{className:"number",begin:/:\d{1,5}/
},e.inherit(e.QUOTE_STRING_MODE,{relevance:0})]},{className:"attribute",
begin:/\w+/,relevance:0,keywords:{
_:["order","deny","allow","setenv","rewriterule","rewriteengine","rewritecond","documentroot","sethandler","errordocument","loadmodule","options","header","listen","serverroot","servername"]
},starts:{end:/$/,relevance:0,keywords:{literal:"on off all deny allow"},
contains:[{className:"meta",begin:/\s\[/,end:/\]$/},{className:"variable",
begin:/[\$%]\{/,end:/\}/,contains:["self",{className:"number",begin:/[$%]\d+/}]
},a,{className:"number",begin:/\b\d+/},e.QUOTE_STRING_MODE]}}],illegal:/\S/}}
})();export default hljsGrammar;

View file

@ -1,20 +0,0 @@
/*! `bash` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict";return e=>{const s=e.regex,t={},a={
begin:/\$\{/,end:/\}/,contains:["self",{begin:/:-/,contains:[t]}]}
;Object.assign(t,{className:"variable",variants:[{
begin:s.concat(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},a]});const n={
className:"subst",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE]},i={
begin:/<<-?\s*(?=\w+)/,starts:{contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/,
end:/(\w+)/,className:"string"})]}},c={className:"string",begin:/"/,end:/"/,
contains:[e.BACKSLASH_ESCAPE,t,n]};n.contains.push(c);const o={begin:/\$?\(\(/,
end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,t]
},r=e.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10
}),l={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,
contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{
name:"Bash",aliases:["sh"],keywords:{$pattern:/\b[a-z][a-z0-9._-]+\b/,
keyword:["if","then","else","elif","fi","for","while","until","in","do","done","case","esac","function","select"],
literal:["true","false"],
built_in:["break","cd","continue","eval","exec","exit","export","getopts","hash","pwd","readonly","return","shift","test","times","trap","umask","unset","alias","bind","builtin","caller","command","declare","echo","enable","help","let","local","logout","mapfile","printf","read","readarray","source","type","typeset","ulimit","unalias","set","shopt","autoload","bg","bindkey","bye","cap","chdir","clone","comparguments","compcall","compctl","compdescribe","compfiles","compgroups","compquote","comptags","comptry","compvalues","dirs","disable","disown","echotc","echoti","emulate","fc","fg","float","functions","getcap","getln","history","integer","jobs","kill","limit","log","noglob","popd","print","pushd","pushln","rehash","sched","setcap","setopt","stat","suspend","ttyctl","unfunction","unhash","unlimit","unsetopt","vared","wait","whence","where","which","zcompile","zformat","zftp","zle","zmodload","zparseopts","zprof","zpty","zregexparse","zsocket","zstyle","ztcp","chcon","chgrp","chown","chmod","cp","dd","df","dir","dircolors","ln","ls","mkdir","mkfifo","mknod","mktemp","mv","realpath","rm","rmdir","shred","sync","touch","truncate","vdir","b2sum","base32","base64","cat","cksum","comm","csplit","cut","expand","fmt","fold","head","join","md5sum","nl","numfmt","od","paste","ptx","pr","sha1sum","sha224sum","sha256sum","sha384sum","sha512sum","shuf","sort","split","sum","tac","tail","tr","tsort","unexpand","uniq","wc","arch","basename","chroot","date","dirname","du","echo","env","expr","factor","groups","hostid","id","link","logname","nice","nohup","nproc","pathchk","pinky","printenv","printf","pwd","readlink","runcon","seq","sleep","stat","stdbuf","stty","tee","test","timeout","tty","uname","unlink","uptime","users","who","whoami","yes"]
},contains:[r,e.SHEBANG(),l,o,e.HASH_COMMENT_MODE,i,{match:/(\/[a-z._-]+)+/},c,{
match:/\\"/},{className:"string",begin:/'/,end:/'/},{match:/\\'/},t]}}})()
;export default hljsGrammar;

View file

@ -1,46 +0,0 @@
/*! `cpp` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict";return e=>{
const t=e.regex,a=e.COMMENT("//","$",{contains:[{begin:/\\\n/}]
}),n="decltype\\(auto\\)",r="[a-zA-Z_]\\w*::",i="(?!struct)("+n+"|"+t.optional(r)+"[a-zA-Z_]\\w*"+t.optional("<[^<>]+>")+")",s={
className:"type",begin:"\\b[a-z\\d_]*_t\\b"},c={className:"string",variants:[{
begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{
begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)",
end:"'",illegal:"."},e.END_SAME_AS_BEGIN({
begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},o={
className:"number",variants:[{begin:"\\b(0b[01']+)"},{
begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)"
},{
begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"
}],relevance:0},l={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{
keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include"
},contains:[{begin:/\\\n/,relevance:0},e.inherit(c,{className:"string"}),{
className:"string",begin:/<.*?>/},a,e.C_BLOCK_COMMENT_MODE]},d={
className:"title",begin:t.optional(r)+e.IDENT_RE,relevance:0
},u=t.optional(r)+e.IDENT_RE+"\\s*\\(",p={
type:["bool","char","char16_t","char32_t","char8_t","double","float","int","long","short","void","wchar_t","unsigned","signed","const","static"],
keyword:["alignas","alignof","and","and_eq","asm","atomic_cancel","atomic_commit","atomic_noexcept","auto","bitand","bitor","break","case","catch","class","co_await","co_return","co_yield","compl","concept","const_cast|10","consteval","constexpr","constinit","continue","decltype","default","delete","do","dynamic_cast|10","else","enum","explicit","export","extern","false","final","for","friend","goto","if","import","inline","module","mutable","namespace","new","noexcept","not","not_eq","nullptr","operator","or","or_eq","override","private","protected","public","reflexpr","register","reinterpret_cast|10","requires","return","sizeof","static_assert","static_cast|10","struct","switch","synchronized","template","this","thread_local","throw","transaction_safe","transaction_safe_dynamic","true","try","typedef","typeid","typename","union","using","virtual","volatile","while","xor","xor_eq"],
literal:["NULL","false","nullopt","nullptr","true"],built_in:["_Pragma"],
_type_hints:["any","auto_ptr","barrier","binary_semaphore","bitset","complex","condition_variable","condition_variable_any","counting_semaphore","deque","false_type","future","imaginary","initializer_list","istringstream","jthread","latch","lock_guard","multimap","multiset","mutex","optional","ostringstream","packaged_task","pair","promise","priority_queue","queue","recursive_mutex","recursive_timed_mutex","scoped_lock","set","shared_future","shared_lock","shared_mutex","shared_timed_mutex","shared_ptr","stack","string_view","stringstream","timed_mutex","thread","true_type","tuple","unique_lock","unique_ptr","unordered_map","unordered_multimap","unordered_multiset","unordered_set","variant","vector","weak_ptr","wstring","wstring_view"]
},_={className:"function.dispatch",relevance:0,keywords:{
_hint:["abort","abs","acos","apply","as_const","asin","atan","atan2","calloc","ceil","cerr","cin","clog","cos","cosh","cout","declval","endl","exchange","exit","exp","fabs","floor","fmod","forward","fprintf","fputs","free","frexp","fscanf","future","invoke","isalnum","isalpha","iscntrl","isdigit","isgraph","islower","isprint","ispunct","isspace","isupper","isxdigit","labs","launder","ldexp","log","log10","make_pair","make_shared","make_shared_for_overwrite","make_tuple","make_unique","malloc","memchr","memcmp","memcpy","memset","modf","move","pow","printf","putchar","puts","realloc","scanf","sin","sinh","snprintf","sprintf","sqrt","sscanf","std","stderr","stdin","stdout","strcat","strchr","strcmp","strcpy","strcspn","strlen","strncat","strncmp","strncpy","strpbrk","strrchr","strspn","strstr","swap","tan","tanh","terminate","to_underlying","tolower","toupper","vfprintf","visit","vprintf","vsprintf"]
},
begin:t.concat(/\b/,/(?!decltype)/,/(?!if)/,/(?!for)/,/(?!switch)/,/(?!while)/,e.IDENT_RE,t.lookahead(/(<[^<>]+>|)\s*\(/))
},m=[_,l,s,a,e.C_BLOCK_COMMENT_MODE,o,c],g={variants:[{begin:/=/,end:/;/},{
begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}],
keywords:p,contains:m.concat([{begin:/\(/,end:/\)/,keywords:p,
contains:m.concat(["self"]),relevance:0}]),relevance:0},f={className:"function",
begin:"("+i+"[\\*&\\s]+)+"+u,returnBegin:!0,end:/[{;=]/,excludeEnd:!0,
keywords:p,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:n,keywords:p,relevance:0},{
begin:u,returnBegin:!0,contains:[d],relevance:0},{begin:/::/,relevance:0},{
begin:/:/,endsWithParent:!0,contains:[c,o]},{relevance:0,match:/,/},{
className:"params",begin:/\(/,end:/\)/,keywords:p,relevance:0,
contains:[a,e.C_BLOCK_COMMENT_MODE,c,o,s,{begin:/\(/,end:/\)/,keywords:p,
relevance:0,contains:["self",a,e.C_BLOCK_COMMENT_MODE,c,o,s]}]
},s,a,e.C_BLOCK_COMMENT_MODE,l]};return{name:"C++",
aliases:["cc","c++","h++","hpp","hh","hxx","cxx"],keywords:p,illegal:"</",
classNameAliases:{"function.dispatch":"built_in"},
contains:[].concat(g,f,_,m,[l,{
begin:"\\b(deque|list|queue|priority_queue|pair|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array|tuple|optional|variant|function)\\s*<(?!<)",
end:">",keywords:p,contains:["self",s]},{begin:e.IDENT_RE+"::",keywords:p},{
match:[/\b(?:enum(?:\s+(?:class|struct))?|class|struct|union)/,/\s+/,/\w+/],
className:{1:"keyword",3:"title.class"}}])}}})();export default hljsGrammar;

File diff suppressed because one or more lines are too long

View file

@ -1,9 +0,0 @@
/*! `diff` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict";return e=>{const a=e.regex;return{
name:"Diff",aliases:["patch"],contains:[{className:"meta",relevance:10,
match:a.either(/^@@ +-\d+,\d+ +\+\d+,\d+ +@@/,/^\*\*\* +\d+,\d+ +\*\*\*\*$/,/^--- +\d+,\d+ +----$/)
},{className:"comment",variants:[{
begin:a.either(/Index: /,/^index/,/={3,}/,/^-{3}/,/^\*{3} /,/^\+{3}/,/^diff --git/),
end:/$/},{match:/^\*{15}$/}]},{className:"addition",begin:/^\+/,end:/$/},{
className:"deletion",begin:/^-/,end:/$/},{className:"addition",begin:/^!/,
end:/$/}]}}})();export default hljsGrammar;

View file

@ -1,8 +0,0 @@
/*! `dockerfile` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict";return e=>({name:"Dockerfile",
aliases:["docker"],case_insensitive:!0,
keywords:["from","maintainer","expose","env","arg","user","onbuild","stopsignal"],
contains:[e.HASH_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.NUMBER_MODE,{
beginKeywords:"run cmd entrypoint volume add copy workdir label healthcheck shell",
starts:{end:/[^\\]$/,subLanguage:"bash"}}],illegal:"</"})})()
;export default hljsGrammar;

View file

@ -1,14 +0,0 @@
/*! `go` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict";return e=>{const n={
keyword:["break","case","chan","const","continue","default","defer","else","fallthrough","for","func","go","goto","if","import","interface","map","package","range","return","select","struct","switch","type","var"],
type:["bool","byte","complex64","complex128","error","float32","float64","int8","int16","int32","int64","string","uint8","uint16","uint32","uint64","int","uint","uintptr","rune"],
literal:["true","false","iota","nil"],
built_in:["append","cap","close","complex","copy","imag","len","make","new","panic","print","println","real","recover","delete"]
};return{name:"Go",aliases:["golang"],keywords:n,illegal:"</",
contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"string",
variants:[e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,{begin:"`",end:"`"}]},{
className:"number",variants:[{begin:e.C_NUMBER_RE+"[i]",relevance:1
},e.C_NUMBER_MODE]},{begin:/:=/},{className:"function",beginKeywords:"func",
end:"\\s*(\\{|$)",excludeEnd:!0,contains:[e.TITLE_MODE,{className:"params",
begin:/\(/,end:/\)/,endsParent:!0,keywords:n,illegal:/["']/}]}]}}})()
;export default hljsGrammar;

View file

@ -1,12 +0,0 @@
/*! `graphql` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict";return e=>{const a=e.regex;return{
name:"GraphQL",aliases:["gql"],case_insensitive:!0,disableAutodetect:!1,
keywords:{
keyword:["query","mutation","subscription","type","input","schema","directive","interface","union","scalar","fragment","enum","on"],
literal:["true","false","null"]},
contains:[e.HASH_COMMENT_MODE,e.QUOTE_STRING_MODE,e.NUMBER_MODE,{
scope:"punctuation",match:/[.]{3}/,relevance:0},{scope:"punctuation",
begin:/[\!\(\)\:\=\[\]\{\|\}]{1}/,relevance:0},{scope:"variable",begin:/\$/,
end:/\W/,excludeEnd:!0,relevance:0},{scope:"meta",match:/@\w+/,excludeEnd:!0},{
scope:"symbol",begin:a.concat(/[_A-Za-z][_0-9A-Za-z]*/,a.lookahead(/\s*:/)),
relevance:0}],illegal:[/[;<']/,/BEGIN/]}}})();export default hljsGrammar;

View file

@ -1,14 +0,0 @@
/*! `http` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict";return e=>{const a="HTTP/([32]|1\\.[01])",n={
className:"attribute",
begin:e.regex.concat("^",/[A-Za-z][A-Za-z0-9-]*/,"(?=\\:\\s)"),starts:{
contains:[{className:"punctuation",begin:/: /,relevance:0,starts:{end:"$",
relevance:0}}]}},s=[n,{begin:"\\n\\n",starts:{subLanguage:[],endsWithParent:!0}
}];return{name:"HTTP",aliases:["https"],illegal:/\S/,contains:[{
begin:"^(?="+a+" \\d{3})",end:/$/,contains:[{className:"meta",begin:a},{
className:"number",begin:"\\b\\d{3}\\b"}],starts:{end:/\b\B/,illegal:/\S/,
contains:s}},{begin:"(?=^[A-Z]+ (.*?) "+a+"$)",end:/$/,contains:[{
className:"string",begin:" ",end:" ",excludeBegin:!0,excludeEnd:!0},{
className:"meta",begin:a},{className:"keyword",begin:"[A-Z]+"}],starts:{
end:/\b\B/,illegal:/\S/,contains:s}},e.inherit(n,{relevance:0})]}}})()
;export default hljsGrammar;

View file

@ -1,16 +0,0 @@
/*! `ini` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict";return e=>{const n=e.regex,a={
className:"number",relevance:0,variants:[{begin:/([+-]+)?[\d]+_[\d_]+/},{
begin:e.NUMBER_RE}]},s=e.COMMENT();s.variants=[{begin:/;/,end:/$/},{begin:/#/,
end:/$/}];const i={className:"variable",variants:[{begin:/\$[\w\d"][\w\d_]*/},{
begin:/\$\{(.*?)\}/}]},r={className:"literal",
begin:/\bon|off|true|false|yes|no\b/},t={className:"string",
contains:[e.BACKSLASH_ESCAPE],variants:[{begin:"'''",end:"'''",relevance:10},{
begin:'"""',end:'"""',relevance:10},{begin:'"',end:'"'},{begin:"'",end:"'"}]
},l={begin:/\[/,end:/\]/,contains:[s,r,i,t,a,"self"],relevance:0
},c=n.either(/[A-Za-z0-9_-]+/,/"(\\"|[^"])*"/,/'[^']*'/);return{
name:"TOML, also INI",aliases:["toml"],case_insensitive:!0,illegal:/\S/,
contains:[s,{className:"section",begin:/\[+/,end:/\]+/},{
begin:n.concat(c,"(\\s*\\.\\s*",c,")*",n.lookahead(/\s*=\s*[^#\s]/)),
className:"attr",starts:{end:/$/,contains:[s,l,r,i,t,a]}}]}}})()
;export default hljsGrammar;

View file

@ -1,38 +0,0 @@
/*! `java` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict"
;var e="[0-9](_*[0-9])*",a=`\\.(${e})`,n="[0-9a-fA-F](_*[0-9a-fA-F])*",s={
className:"number",variants:[{
begin:`(\\b(${e})((${a})|\\.)?|(${a}))[eE][+-]?(${e})[fFdD]?\\b`},{
begin:`\\b(${e})((${a})[fFdD]?\\b|\\.([fFdD]\\b)?)`},{begin:`(${a})[fFdD]?\\b`
},{begin:`\\b(${e})[fFdD]\\b`},{
begin:`\\b0[xX]((${n})\\.?|(${n})?\\.(${n}))[pP][+-]?(${e})[fFdD]?\\b`},{
begin:"\\b(0|[1-9](_*[0-9])*)[lL]?\\b"},{begin:`\\b0[xX](${n})[lL]?\\b`},{
begin:"\\b0(_*[0-7])*[lL]?\\b"},{begin:"\\b0[bB][01](_*[01])*[lL]?\\b"}],
relevance:0};function t(e,a,n){return-1===n?"":e.replace(a,(s=>t(e,a,n-1)))}
return e=>{
const a=e.regex,n="[\xc0-\u02b8a-zA-Z_$][\xc0-\u02b8a-zA-Z_$0-9]*",r=n+t("(?:<"+n+"~~~(?:\\s*,\\s*"+n+"~~~)*>)?",/~~~/g,2),i={
keyword:["synchronized","abstract","private","var","static","if","const ","for","while","strictfp","finally","protected","import","native","final","void","enum","else","break","transient","catch","instanceof","volatile","case","assert","package","default","public","try","switch","continue","throws","protected","public","private","module","requires","exports","do","sealed","yield","permits"],
literal:["false","true","null"],
type:["char","boolean","long","float","int","byte","short","double"],
built_in:["super","this"]},l={className:"meta",begin:"@"+n,contains:[{
begin:/\(/,end:/\)/,contains:["self"]}]},c={className:"params",begin:/\(/,
end:/\)/,keywords:i,relevance:0,contains:[e.C_BLOCK_COMMENT_MODE],endsParent:!0}
;return{name:"Java",aliases:["jsp"],keywords:i,illegal:/<\/|#/,
contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/,
relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]}),{
begin:/import java\.[a-z]+\./,keywords:"import",relevance:2
},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{begin:/"""/,end:/"""/,
className:"string",contains:[e.BACKSLASH_ESCAPE]
},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{
match:[/\b(?:class|interface|enum|extends|implements|new)/,/\s+/,n],className:{
1:"keyword",3:"title.class"}},{match:/non-sealed/,scope:"keyword"},{
begin:[a.concat(/(?!else)/,n),/\s+/,n,/\s+/,/=(?!=)/],className:{1:"type",
3:"variable",5:"operator"}},{begin:[/record/,/\s+/,n],className:{1:"keyword",
3:"title.class"},contains:[c,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{
beginKeywords:"new throw return else",relevance:0},{
begin:["(?:"+r+"\\s+)",e.UNDERSCORE_IDENT_RE,/\s*(?=\()/],className:{
2:"title.function"},keywords:i,contains:[{className:"params",begin:/\(/,
end:/\)/,keywords:i,relevance:0,
contains:[l,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,s,e.C_BLOCK_COMMENT_MODE]
},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},s,l]}}})()
;export default hljsGrammar;

View file

@ -1,80 +0,0 @@
/*! `javascript` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict"
;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],t=["Object","Function","Boolean","Symbol","Math","Date","Number","BigInt","String","RegExp","Array","Float32Array","Float64Array","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Int32Array","Uint16Array","Uint32Array","BigInt64Array","BigUint64Array","Set","Map","WeakSet","WeakMap","ArrayBuffer","SharedArrayBuffer","Atomics","DataView","JSON","Promise","Generator","GeneratorFunction","AsyncFunction","Reflect","Proxy","Intl","WebAssembly"],s=["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],r=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],c=["arguments","this","super","console","window","document","localStorage","sessionStorage","module","global"],i=[].concat(r,t,s)
;return o=>{const l=o.regex,d=e,b={begin:/<[A-Za-z0-9\\._:-]+/,
end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{
const a=e[0].length+e.index,t=e.input[a]
;if("<"===t||","===t)return void n.ignoreMatch();let s
;">"===t&&(((e,{after:n})=>{const a="</"+e[0].slice(1)
;return-1!==e.input.indexOf(a,n)})(e,{after:a})||n.ignoreMatch())
;const r=e.input.substring(a)
;((s=r.match(/^\s*=/))||(s=r.match(/^\s+extends\s+/))&&0===s.index)&&n.ignoreMatch()
}},g={$pattern:e,keyword:n,literal:a,built_in:i,"variable.language":c
},u="[0-9](_?[0-9])*",m=`\\.(${u})`,E="0|[1-9](_?[0-9])*|0[0-7]*[89][0-9]*",A={
className:"number",variants:[{
begin:`(\\b(${E})((${m})|\\.)?|(${m}))[eE][+-]?(${u})\\b`},{
begin:`\\b(${E})\\b((${m})\\b|\\.)?|(${m})\\b`},{
begin:"\\b(0|[1-9](_?[0-9])*)n\\b"},{
begin:"\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*n?\\b"},{
begin:"\\b0[bB][0-1](_?[0-1])*n?\\b"},{begin:"\\b0[oO][0-7](_?[0-7])*n?\\b"},{
begin:"\\b0[0-7]+n?\\b"}],relevance:0},y={className:"subst",begin:"\\$\\{",
end:"\\}",keywords:g,contains:[]},h={begin:"html`",end:"",starts:{end:"`",
returnEnd:!1,contains:[o.BACKSLASH_ESCAPE,y],subLanguage:"xml"}},N={
begin:"css`",end:"",starts:{end:"`",returnEnd:!1,
contains:[o.BACKSLASH_ESCAPE,y],subLanguage:"css"}},_={begin:"gql`",end:"",
starts:{end:"`",returnEnd:!1,contains:[o.BACKSLASH_ESCAPE,y],
subLanguage:"graphql"}},f={className:"string",begin:"`",end:"`",
contains:[o.BACKSLASH_ESCAPE,y]},p={className:"comment",
variants:[o.COMMENT(/\/\*\*(?!\/)/,"\\*/",{relevance:0,contains:[{
begin:"(?=@[A-Za-z]+)",relevance:0,contains:[{className:"doctag",
begin:"@[A-Za-z]+"},{className:"type",begin:"\\{",end:"\\}",excludeEnd:!0,
excludeBegin:!0,relevance:0},{className:"variable",begin:d+"(?=\\s*(-)|$)",
endsParent:!0,relevance:0},{begin:/(?=[^\n])\s/,relevance:0}]}]
}),o.C_BLOCK_COMMENT_MODE,o.C_LINE_COMMENT_MODE]
},v=[o.APOS_STRING_MODE,o.QUOTE_STRING_MODE,h,N,_,f,{match:/\$\d+/},A]
;y.contains=v.concat({begin:/\{/,end:/\}/,keywords:g,contains:["self"].concat(v)
});const S=[].concat(p,y.contains),w=S.concat([{begin:/\(/,end:/\)/,keywords:g,
contains:["self"].concat(S)}]),R={className:"params",begin:/\(/,end:/\)/,
excludeBegin:!0,excludeEnd:!0,keywords:g,contains:w},O={variants:[{
match:[/class/,/\s+/,d,/\s+/,/extends/,/\s+/,l.concat(d,"(",l.concat(/\./,d),")*")],
scope:{1:"keyword",3:"title.class",5:"keyword",7:"title.class.inherited"}},{
match:[/class/,/\s+/,d],scope:{1:"keyword",3:"title.class"}}]},k={relevance:0,
match:l.either(/\bJSON/,/\b[A-Z][a-z]+([A-Z][a-z]*|\d)*/,/\b[A-Z]{2,}([A-Z][a-z]+|\d)+([A-Z][a-z]*)*/,/\b[A-Z]{2,}[a-z]+([A-Z][a-z]+|\d)*([A-Z][a-z]*)*/),
className:"title.class",keywords:{_:[...t,...s]}},I={variants:[{
match:[/function/,/\s+/,d,/(?=\s*\()/]},{match:[/function/,/\s*(?=\()/]}],
className:{1:"keyword",3:"title.function"},label:"func.def",contains:[R],
illegal:/%/},x={
match:l.concat(/\b/,(T=[...r,"super","import"],l.concat("(?!",T.join("|"),")")),d,l.lookahead(/\(/)),
className:"title.function",relevance:0};var T;const C={
begin:l.concat(/\./,l.lookahead(l.concat(d,/(?![0-9A-Za-z$_(])/))),end:d,
excludeBegin:!0,keywords:"prototype",className:"property",relevance:0},M={
match:[/get|set/,/\s+/,d,/(?=\()/],className:{1:"keyword",3:"title.function"},
contains:[{begin:/\(\)/},R]
},B="(\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)|"+o.UNDERSCORE_IDENT_RE+")\\s*=>",$={
match:[/const|var|let/,/\s+/,d,/\s*/,/=\s*/,/(async\s*)?/,l.lookahead(B)],
keywords:"async",className:{1:"keyword",3:"title.function"},contains:[R]}
;return{name:"JavaScript",aliases:["js","jsx","mjs","cjs"],keywords:g,exports:{
PARAMS_CONTAINS:w,CLASS_REFERENCE:k},illegal:/#(?![$_A-z])/,
contains:[o.SHEBANG({label:"shebang",binary:"node",relevance:5}),{
label:"use_strict",className:"meta",relevance:10,
begin:/^\s*['"]use (strict|asm)['"]/
},o.APOS_STRING_MODE,o.QUOTE_STRING_MODE,h,N,_,f,p,{match:/\$\d+/},A,k,{
className:"attr",begin:d+l.lookahead(":"),relevance:0},$,{
begin:"("+o.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",
keywords:"return throw case",relevance:0,contains:[p,o.REGEXP_MODE,{
className:"function",begin:B,returnBegin:!0,end:"\\s*=>",contains:[{
className:"params",variants:[{begin:o.UNDERSCORE_IDENT_RE,relevance:0},{
className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0,
excludeEnd:!0,keywords:g,contains:w}]}]},{begin:/,/,relevance:0},{match:/\s+/,
relevance:0},{variants:[{begin:"<>",end:"</>"},{
match:/<[A-Za-z0-9\\._:-]+\s*\/>/},{begin:b.begin,
"on:begin":b.isTrulyOpeningTag,end:b.end}],subLanguage:"xml",contains:[{
begin:b.begin,end:b.end,skip:!0,contains:["self"]}]}]},I,{
beginKeywords:"while if switch catch for"},{
begin:"\\b(?!function)"+o.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{",
returnBegin:!0,label:"func.def",contains:[R,o.inherit(o.TITLE_MODE,{begin:d,
className:"title.function"})]},{match:/\.\.\./,relevance:0},C,{match:"\\$"+d,
relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"},
contains:[R]},x,{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/,
className:"variable.constant"},O,M,{match:/\$[(.]/}]}}})()
;export default hljsGrammar;

View file

@ -1,8 +0,0 @@
/*! `json` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict";return e=>{
const a=["true","false","null"],r={scope:"literal",beginKeywords:a.join(" ")}
;return{name:"JSON",keywords:{literal:a},contains:[{className:"attr",
begin:/"(\\.|[^\\"\r\n])*"(?=\s*:)/,relevance:1.01},{match:/[{}[\],:]/,
className:"punctuation",relevance:0
},e.QUOTE_STRING_MODE,r,e.C_NUMBER_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],
illegal:"\\S"}}})();export default hljsGrammar;

View file

@ -1,31 +0,0 @@
/*! `markdown` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict";return e=>{const n={begin:/<\/?[A-Za-z_]/,
end:">",subLanguage:"xml",relevance:0},a={variants:[{begin:/\[.+?\]\[.*?\]/,
relevance:0},{
begin:/\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/,
relevance:2},{
begin:e.regex.concat(/\[.+?\]\(/,/[A-Za-z][A-Za-z0-9+.-]*/,/:\/\/.*?\)/),
relevance:2},{begin:/\[.+?\]\([./?&#].*?\)/,relevance:1},{
begin:/\[.*?\]\(.*?\)/,relevance:0}],returnBegin:!0,contains:[{match:/\[(?=\])/
},{className:"string",relevance:0,begin:"\\[",end:"\\]",excludeBegin:!0,
returnEnd:!0},{className:"link",relevance:0,begin:"\\]\\(",end:"\\)",
excludeBegin:!0,excludeEnd:!0},{className:"symbol",relevance:0,begin:"\\]\\[",
end:"\\]",excludeBegin:!0,excludeEnd:!0}]},i={className:"strong",contains:[],
variants:[{begin:/_{2}(?!\s)/,end:/_{2}/},{begin:/\*{2}(?!\s)/,end:/\*{2}/}]
},s={className:"emphasis",contains:[],variants:[{begin:/\*(?![*\s])/,end:/\*/},{
begin:/_(?![_\s])/,end:/_/,relevance:0}]},c=e.inherit(i,{contains:[]
}),t=e.inherit(s,{contains:[]});i.contains.push(t),s.contains.push(c)
;let l=[n,a];return[i,s,c,t].forEach((e=>{e.contains=e.contains.concat(l)
})),l=l.concat(i,s),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{
className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:l},{
begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n",
contains:l}]}]},n,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)",
end:"\\s+",excludeEnd:!0},i,s,{className:"quote",begin:"^>\\s+",contains:l,
end:"$"},{className:"code",variants:[{begin:"(`{3,})[^`](.|\\n)*?\\1`*[ ]*"},{
begin:"(~{3,})[^~](.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{
begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))",
contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{
begin:"^[-\\*]{3,}",end:"$"},a,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{
className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{
className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}}})()
;export default hljsGrammar;

View file

@ -1,21 +0,0 @@
/*! `nginx` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict";return e=>{const n=e.regex,a={
className:"variable",variants:[{begin:/\$\d+/},{begin:/\$\{\w+\}/},{
begin:n.concat(/[$@]/,e.UNDERSCORE_IDENT_RE)}]},s={endsWithParent:!0,keywords:{
$pattern:/[a-z_]{2,}|\/dev\/poll/,
literal:["on","off","yes","no","true","false","none","blocked","debug","info","notice","warn","error","crit","select","break","last","permanent","redirect","kqueue","rtsig","epoll","poll","/dev/poll"]
},relevance:0,illegal:"=>",contains:[e.HASH_COMMENT_MODE,{className:"string",
contains:[e.BACKSLASH_ESCAPE,a],variants:[{begin:/"/,end:/"/},{begin:/'/,end:/'/
}]},{begin:"([a-z]+):/",end:"\\s",endsWithParent:!0,excludeEnd:!0,contains:[a]
},{className:"regexp",contains:[e.BACKSLASH_ESCAPE,a],variants:[{begin:"\\s\\^",
end:"\\s|\\{|;",returnEnd:!0},{begin:"~\\*?\\s+",end:"\\s|\\{|;",returnEnd:!0},{
begin:"\\*(\\.[a-z\\-]+)+"},{begin:"([a-z\\-]+\\.)+\\*"}]},{className:"number",
begin:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{
className:"number",begin:"\\b\\d+[kKmMgGdshdwy]?\\b",relevance:0},a]};return{
name:"Nginx config",aliases:["nginxconf"],contains:[e.HASH_COMMENT_MODE,{
beginKeywords:"upstream location",end:/;|\{/,contains:s.contains,keywords:{
section:"upstream location"}},{className:"section",
begin:n.concat(e.UNDERSCORE_IDENT_RE+n.lookahead(/\s+\{/)),relevance:0},{
begin:n.lookahead(e.UNDERSCORE_IDENT_RE+"\\s"),end:";|\\{",contains:[{
className:"attribute",begin:e.UNDERSCORE_IDENT_RE,starts:s}],relevance:0}],
illegal:"[^\\s\\}\\{]"}}})();export default hljsGrammar;

View file

@ -1,58 +0,0 @@
/*! `php` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict";return e=>{
const t=e.regex,a=/(?![A-Za-z0-9])(?![$])/,r=t.concat(/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/,a),n=t.concat(/(\\?[A-Z][a-z0-9_\x7f-\xff]+|\\?[A-Z]+(?=[A-Z][a-z0-9_\x7f-\xff])){1,}/,a),o={
scope:"variable",match:"\\$+"+r},c={scope:"subst",variants:[{begin:/\$\w+/},{
begin:/\{\$/,end:/\}/}]},i=e.inherit(e.APOS_STRING_MODE,{illegal:null
}),s="[ \t\n]",l={scope:"string",variants:[e.inherit(e.QUOTE_STRING_MODE,{
illegal:null,contains:e.QUOTE_STRING_MODE.contains.concat(c)}),i,{
begin:/<<<[ \t]*(?:(\w+)|"(\w+)")\n/,end:/[ \t]*(\w+)\b/,
contains:e.QUOTE_STRING_MODE.contains.concat(c),"on:begin":(e,t)=>{
t.data._beginMatch=e[1]||e[2]},"on:end":(e,t)=>{
t.data._beginMatch!==e[1]&&t.ignoreMatch()}},e.END_SAME_AS_BEGIN({
begin:/<<<[ \t]*'(\w+)'\n/,end:/[ \t]*(\w+)\b/})]},d={scope:"number",variants:[{
begin:"\\b0[bB][01]+(?:_[01]+)*\\b"},{begin:"\\b0[oO][0-7]+(?:_[0-7]+)*\\b"},{
begin:"\\b0[xX][\\da-fA-F]+(?:_[\\da-fA-F]+)*\\b"},{
begin:"(?:\\b\\d+(?:_\\d+)*(\\.(?:\\d+(?:_\\d+)*))?|\\B\\.\\d+)(?:[eE][+-]?\\d+)?"
}],relevance:0
},_=["false","null","true"],p=["__CLASS__","__DIR__","__FILE__","__FUNCTION__","__COMPILER_HALT_OFFSET__","__LINE__","__METHOD__","__NAMESPACE__","__TRAIT__","die","echo","exit","include","include_once","print","require","require_once","array","abstract","and","as","binary","bool","boolean","break","callable","case","catch","class","clone","const","continue","declare","default","do","double","else","elseif","empty","enddeclare","endfor","endforeach","endif","endswitch","endwhile","enum","eval","extends","final","finally","float","for","foreach","from","global","goto","if","implements","instanceof","insteadof","int","integer","interface","isset","iterable","list","match|0","mixed","new","never","object","or","private","protected","public","readonly","real","return","string","switch","throw","trait","try","unset","use","var","void","while","xor","yield"],b=["Error|0","AppendIterator","ArgumentCountError","ArithmeticError","ArrayIterator","ArrayObject","AssertionError","BadFunctionCallException","BadMethodCallException","CachingIterator","CallbackFilterIterator","CompileError","Countable","DirectoryIterator","DivisionByZeroError","DomainException","EmptyIterator","ErrorException","Exception","FilesystemIterator","FilterIterator","GlobIterator","InfiniteIterator","InvalidArgumentException","IteratorIterator","LengthException","LimitIterator","LogicException","MultipleIterator","NoRewindIterator","OutOfBoundsException","OutOfRangeException","OuterIterator","OverflowException","ParentIterator","ParseError","RangeException","RecursiveArrayIterator","RecursiveCachingIterator","RecursiveCallbackFilterIterator","RecursiveDirectoryIterator","RecursiveFilterIterator","RecursiveIterator","RecursiveIteratorIterator","RecursiveRegexIterator","RecursiveTreeIterator","RegexIterator","RuntimeException","SeekableIterator","SplDoublyLinkedList","SplFileInfo","SplFileObject","SplFixedArray","SplHeap","SplMaxHeap","SplMinHeap","SplObjectStorage","SplObserver","SplPriorityQueue","SplQueue","SplStack","SplSubject","SplTempFileObject","TypeError","UnderflowException","UnexpectedValueException","UnhandledMatchError","ArrayAccess","BackedEnum","Closure","Fiber","Generator","Iterator","IteratorAggregate","Serializable","Stringable","Throwable","Traversable","UnitEnum","WeakReference","WeakMap","Directory","__PHP_Incomplete_Class","parent","php_user_filter","self","static","stdClass"],E={
keyword:p,literal:(e=>{const t=[];return e.forEach((e=>{
t.push(e),e.toLowerCase()===e?t.push(e.toUpperCase()):t.push(e.toLowerCase())
})),t})(_),built_in:b},u=e=>e.map((e=>e.replace(/\|\d+$/,""))),g={variants:[{
match:[/new/,t.concat(s,"+"),t.concat("(?!",u(b).join("\\b|"),"\\b)"),n],scope:{
1:"keyword",4:"title.class"}}]},h=t.concat(r,"\\b(?!\\()"),m={variants:[{
match:[t.concat(/::/,t.lookahead(/(?!class\b)/)),h],scope:{2:"variable.constant"
}},{match:[/::/,/class/],scope:{2:"variable.language"}},{
match:[n,t.concat(/::/,t.lookahead(/(?!class\b)/)),h],scope:{1:"title.class",
3:"variable.constant"}},{match:[n,t.concat("::",t.lookahead(/(?!class\b)/))],
scope:{1:"title.class"}},{match:[n,/::/,/class/],scope:{1:"title.class",
3:"variable.language"}}]},f={scope:"attr",
match:t.concat(r,t.lookahead(":"),t.lookahead(/(?!::)/))},I={relevance:0,
begin:/\(/,end:/\)/,keywords:E,contains:[f,o,m,e.C_BLOCK_COMMENT_MODE,l,d,g]
},O={relevance:0,
match:[/\b/,t.concat("(?!fn\\b|function\\b|",u(p).join("\\b|"),"|",u(b).join("\\b|"),"\\b)"),r,t.concat(s,"*"),t.lookahead(/(?=\()/)],
scope:{3:"title.function.invoke"},contains:[I]};I.contains.push(O)
;const v=[f,m,e.C_BLOCK_COMMENT_MODE,l,d,g];return{case_insensitive:!1,
keywords:E,contains:[{begin:t.concat(/#\[\s*/,n),beginScope:"meta",end:/]/,
endScope:"meta",keywords:{literal:_,keyword:["new","array"]},contains:[{
begin:/\[/,end:/]/,keywords:{literal:_,keyword:["new","array"]},
contains:["self",...v]},...v,{scope:"meta",match:n}]
},e.HASH_COMMENT_MODE,e.COMMENT("//","$"),e.COMMENT("/\\*","\\*/",{contains:[{
scope:"doctag",match:"@[A-Za-z]+"}]}),{match:/__halt_compiler\(\);/,
keywords:"__halt_compiler",starts:{scope:"comment",end:e.MATCH_NOTHING_RE,
contains:[{match:/\?>/,scope:"meta",endsParent:!0}]}},{scope:"meta",variants:[{
begin:/<\?php/,relevance:10},{begin:/<\?=/},{begin:/<\?/,relevance:.1},{
begin:/\?>/}]},{scope:"variable.language",match:/\$this\b/},o,O,m,{
match:[/const/,/\s/,r],scope:{1:"keyword",3:"variable.constant"}},g,{
scope:"function",relevance:0,beginKeywords:"fn function",end:/[;{]/,
excludeEnd:!0,illegal:"[$%\\[]",contains:[{beginKeywords:"use"
},e.UNDERSCORE_TITLE_MODE,{begin:"=>",endsParent:!0},{scope:"params",
begin:"\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0,keywords:E,
contains:["self",o,m,e.C_BLOCK_COMMENT_MODE,l,d]}]},{scope:"class",variants:[{
beginKeywords:"enum",illegal:/[($"]/},{beginKeywords:"class interface trait",
illegal:/[:($"]/}],relevance:0,end:/\{/,excludeEnd:!0,contains:[{
beginKeywords:"extends implements"},e.UNDERSCORE_TITLE_MODE]},{
beginKeywords:"namespace",relevance:0,end:";",illegal:/[.']/,
contains:[e.inherit(e.UNDERSCORE_TITLE_MODE,{scope:"title.class"})]},{
beginKeywords:"use",relevance:0,end:";",contains:[{
match:/\b(as|const|function)\b/,scope:"keyword"},e.UNDERSCORE_TITLE_MODE]},l,d]}
}})();export default hljsGrammar;

View file

@ -1,40 +0,0 @@
/*! `powershell` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict";return e=>{const n={
$pattern:/-?[A-z\.\-]+\b/,
keyword:"if else foreach return do while until elseif begin for trap data dynamicparam end break throw param continue finally in switch exit filter try process catch hidden static parameter",
built_in:"ac asnp cat cd CFS chdir clc clear clhy cli clp cls clv cnsn compare copy cp cpi cpp curl cvpa dbp del diff dir dnsn ebp echo|0 epal epcsv epsn erase etsn exsn fc fhx fl ft fw gal gbp gc gcb gci gcm gcs gdr gerr ghy gi gin gjb gl gm gmo gp gps gpv group gsn gsnp gsv gtz gu gv gwmi h history icm iex ihy ii ipal ipcsv ipmo ipsn irm ise iwmi iwr kill lp ls man md measure mi mount move mp mv nal ndr ni nmo npssc nsn nv ogv oh popd ps pushd pwd r rbp rcjb rcsn rd rdr ren ri rjb rm rmdir rmo rni rnp rp rsn rsnp rujb rv rvpa rwmi sajb sal saps sasv sbp sc scb select set shcm si sl sleep sls sort sp spjb spps spsv start stz sujb sv swmi tee trcm type wget where wjb write"
},s={begin:"`[\\s\\S]",relevance:0},i={className:"variable",variants:[{
begin:/\$\B/},{className:"keyword",begin:/\$this/},{begin:/\$[\w\d][\w\d_:]*/}]
},a={className:"string",variants:[{begin:/"/,end:/"/},{begin:/@"/,end:/^"@/}],
contains:[s,i,{className:"variable",begin:/\$[A-z]/,end:/[^A-z]/}]},t={
className:"string",variants:[{begin:/'/,end:/'/},{begin:/@'/,end:/^'@/}]
},r=e.inherit(e.COMMENT(null,null),{variants:[{begin:/#/,end:/$/},{begin:/<#/,
end:/#>/}],contains:[{className:"doctag",variants:[{
begin:/\.(synopsis|description|example|inputs|outputs|notes|link|component|role|functionality)/
},{
begin:/\.(parameter|forwardhelptargetname|forwardhelpcategory|remotehelprunspace|externalhelp)\s+\S+/
}]}]}),c={className:"class",beginKeywords:"class enum",end:/\s*[{]/,
excludeEnd:!0,relevance:0,contains:[e.TITLE_MODE]},l={className:"function",
begin:/function\s+/,end:/\s*\{|$/,excludeEnd:!0,returnBegin:!0,relevance:0,
contains:[{begin:"function",relevance:0,className:"keyword"},{className:"title",
begin:/\w[\w\d]*((-)[\w\d]+)*/,relevance:0},{begin:/\(/,end:/\)/,
className:"params",relevance:0,contains:[i]}]},o={begin:/using\s/,end:/$/,
returnBegin:!0,contains:[a,t,{className:"keyword",
begin:/(using|assembly|command|module|namespace|type)/}]},p={
className:"function",begin:/\[.*\]\s*[\w]+[ ]??\(/,end:/$/,returnBegin:!0,
relevance:0,contains:[{className:"keyword",
begin:"(".concat(n.keyword.toString().replace(/\s/g,"|"),")\\b"),endsParent:!0,
relevance:0},e.inherit(e.TITLE_MODE,{endsParent:!0})]
},m=[p,r,s,e.NUMBER_MODE,a,t,{className:"built_in",variants:[{
begin:"(Add|Clear|Close|Copy|Enter|Exit|Find|Format|Get|Hide|Join|Lock|Move|New|Open|Optimize|Pop|Push|Redo|Remove|Rename|Reset|Resize|Search|Select|Set|Show|Skip|Split|Step|Switch|Undo|Unlock|Watch|Backup|Checkpoint|Compare|Compress|Convert|ConvertFrom|ConvertTo|Dismount|Edit|Expand|Export|Group|Import|Initialize|Limit|Merge|Mount|Out|Publish|Restore|Save|Sync|Unpublish|Update|Approve|Assert|Build|Complete|Confirm|Deny|Deploy|Disable|Enable|Install|Invoke|Register|Request|Restart|Resume|Start|Stop|Submit|Suspend|Uninstall|Unregister|Wait|Debug|Measure|Ping|Repair|Resolve|Test|Trace|Connect|Disconnect|Read|Receive|Send|Write|Block|Grant|Protect|Revoke|Unblock|Unprotect|Use|ForEach|Sort|Tee|Where)+(-)[\\w\\d]+"
}]},i,{className:"literal",begin:/\$(null|true|false)\b/},{
className:"selector-tag",begin:/@\B/,relevance:0}],g={begin:/\[/,end:/\]/,
excludeBegin:!0,excludeEnd:!0,relevance:0,contains:[].concat("self",m,{
begin:"(string|char|byte|int|long|bool|decimal|single|double|DateTime|xml|array|hashtable|void)",
className:"built_in",relevance:0},{className:"type",begin:/[\.\w\d]+/,
relevance:0})};return p.contains.unshift(g),{name:"PowerShell",
aliases:["pwsh","ps","ps1"],case_insensitive:!0,keywords:n,
contains:m.concat(c,l,o,{variants:[{className:"operator",
begin:"(-and|-as|-band|-bnot|-bor|-bxor|-casesensitive|-ccontains|-ceq|-cge|-cgt|-cle|-clike|-clt|-cmatch|-cne|-cnotcontains|-cnotlike|-cnotmatch|-contains|-creplace|-csplit|-eq|-exact|-f|-file|-ge|-gt|-icontains|-ieq|-ige|-igt|-ile|-ilike|-ilt|-imatch|-in|-ine|-inotcontains|-inotlike|-inotmatch|-ireplace|-is|-isnot|-isplit|-join|-le|-like|-lt|-match|-ne|-not|-notcontains|-notin|-notlike|-notmatch|-or|-regex|-replace|-shl|-shr|-split|-wildcard|-xor)\\b"
},{className:"literal",begin:/(-){1,2}[\w\d-]+/,relevance:0}]},g)}}})()
;export default hljsGrammar;

View file

@ -1,41 +0,0 @@
/*! `python` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict";return e=>{
const n=e.regex,a=/[\p{XID_Start}_]\p{XID_Continue}*/u,s=["and","as","assert","async","await","break","case","class","continue","def","del","elif","else","except","finally","for","from","global","if","import","in","is","lambda","match","nonlocal|10","not","or","pass","raise","return","try","while","with","yield"],i={
$pattern:/[A-Za-z]\w+|__\w+__/,keyword:s,
built_in:["__import__","abs","all","any","ascii","bin","bool","breakpoint","bytearray","bytes","callable","chr","classmethod","compile","complex","delattr","dict","dir","divmod","enumerate","eval","exec","filter","float","format","frozenset","getattr","globals","hasattr","hash","help","hex","id","input","int","isinstance","issubclass","iter","len","list","locals","map","max","memoryview","min","next","object","oct","open","ord","pow","print","property","range","repr","reversed","round","set","setattr","slice","sorted","staticmethod","str","sum","super","tuple","type","vars","zip"],
literal:["__debug__","Ellipsis","False","None","NotImplemented","True"],
type:["Any","Callable","Coroutine","Dict","List","Literal","Generic","Optional","Sequence","Set","Tuple","Type","Union"]
},t={className:"meta",begin:/^(>>>|\.\.\.) /},r={className:"subst",begin:/\{/,
end:/\}/,keywords:i,illegal:/#/},l={begin:/\{\{/,relevance:0},b={
className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{
begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/,end:/'''/,
contains:[e.BACKSLASH_ESCAPE,t],relevance:10},{
begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/,end:/"""/,
contains:[e.BACKSLASH_ESCAPE,t],relevance:10},{
begin:/([fF][rR]|[rR][fF]|[fF])'''/,end:/'''/,
contains:[e.BACKSLASH_ESCAPE,t,l,r]},{begin:/([fF][rR]|[rR][fF]|[fF])"""/,
end:/"""/,contains:[e.BACKSLASH_ESCAPE,t,l,r]},{begin:/([uU]|[rR])'/,end:/'/,
relevance:10},{begin:/([uU]|[rR])"/,end:/"/,relevance:10},{
begin:/([bB]|[bB][rR]|[rR][bB])'/,end:/'/},{begin:/([bB]|[bB][rR]|[rR][bB])"/,
end:/"/},{begin:/([fF][rR]|[rR][fF]|[fF])'/,end:/'/,
contains:[e.BACKSLASH_ESCAPE,l,r]},{begin:/([fF][rR]|[rR][fF]|[fF])"/,end:/"/,
contains:[e.BACKSLASH_ESCAPE,l,r]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]
},o="[0-9](_?[0-9])*",c=`(\\b(${o}))?\\.(${o})|\\b(${o})\\.`,d="\\b|"+s.join("|"),m={
className:"number",relevance:0,variants:[{
begin:`(\\b(${o})|(${c}))[eE][+-]?(${o})[jJ]?(?=${d})`},{begin:`(${c})[jJ]?`},{
begin:`\\b([1-9](_?[0-9])*|0+(_?0)*)[lLjJ]?(?=${d})`},{
begin:`\\b0[bB](_?[01])+[lL]?(?=${d})`},{begin:`\\b0[oO](_?[0-7])+[lL]?(?=${d})`
},{begin:`\\b0[xX](_?[0-9a-fA-F])+[lL]?(?=${d})`},{begin:`\\b(${o})[jJ](?=${d})`
}]},g={className:"comment",begin:n.lookahead(/# type:/),end:/$/,keywords:i,
contains:[{begin:/# type:/},{begin:/#/,end:/\b\B/,endsWithParent:!0}]},p={
className:"params",variants:[{className:"",begin:/\(\s*\)/,skip:!0},{begin:/\(/,
end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:i,
contains:["self",t,m,b,e.HASH_COMMENT_MODE]}]};return r.contains=[b,m,t],{
name:"Python",aliases:["py","gyp","ipython"],unicodeRegex:!0,keywords:i,
illegal:/(<\/|\?)|=>/,contains:[t,m,{begin:/\bself\b/},{beginKeywords:"if",
relevance:0},b,g,e.HASH_COMMENT_MODE,{match:[/\bdef/,/\s+/,a],scope:{
1:"keyword",3:"title.function"},contains:[p]},{variants:[{
match:[/\bclass/,/\s+/,a,/\s*/,/\(\s*/,a,/\s*\)/]},{match:[/\bclass/,/\s+/,a]}],
scope:{1:"keyword",3:"title.class",6:"title.class.inherited"}},{
className:"meta",begin:/^[\t ]*@/,end:/(?=#)|$/,contains:[m,p,b]}]}}})()
;export default hljsGrammar;

View file

@ -1,28 +0,0 @@
/*! `rust` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict";return e=>{const t=e.regex,a={
className:"title.function.invoke",relevance:0,
begin:t.concat(/\b/,/(?!let|for|while|if|else|match\b)/,e.IDENT_RE,t.lookahead(/\s*\(/))
},n="([ui](8|16|32|64|128|size)|f(32|64))?",r=["drop ","Copy","Send","Sized","Sync","Drop","Fn","FnMut","FnOnce","ToOwned","Clone","Debug","PartialEq","PartialOrd","Eq","Ord","AsRef","AsMut","Into","From","Default","Iterator","Extend","IntoIterator","DoubleEndedIterator","ExactSizeIterator","SliceConcatExt","ToString","assert!","assert_eq!","bitflags!","bytes!","cfg!","col!","concat!","concat_idents!","debug_assert!","debug_assert_eq!","env!","eprintln!","panic!","file!","format!","format_args!","include_bytes!","include_str!","line!","local_data_key!","module_path!","option_env!","print!","println!","select!","stringify!","try!","unimplemented!","unreachable!","vec!","write!","writeln!","macro_rules!","assert_ne!","debug_assert_ne!"],i=["i8","i16","i32","i64","i128","isize","u8","u16","u32","u64","u128","usize","f32","f64","str","char","bool","Box","Option","Result","String","Vec"]
;return{name:"Rust",aliases:["rs"],keywords:{$pattern:e.IDENT_RE+"!?",type:i,
keyword:["abstract","as","async","await","become","box","break","const","continue","crate","do","dyn","else","enum","extern","false","final","fn","for","if","impl","in","let","loop","macro","match","mod","move","mut","override","priv","pub","ref","return","self","Self","static","struct","super","trait","true","try","type","typeof","unsafe","unsized","use","virtual","where","while","yield"],
literal:["true","false","Some","None","Ok","Err"],built_in:r},illegal:"</",
contains:[e.C_LINE_COMMENT_MODE,e.COMMENT("/\\*","\\*/",{contains:["self"]
}),e.inherit(e.QUOTE_STRING_MODE,{begin:/b?"/,illegal:null}),{
className:"string",variants:[{begin:/b?r(#*)"(.|\n)*?"\1(?!#)/},{
begin:/b?'\\?(x\w{2}|u\w{4}|U\w{8}|.)'/}]},{className:"symbol",
begin:/'[a-zA-Z_][a-zA-Z0-9_]*/},{className:"number",variants:[{
begin:"\\b0b([01_]+)"+n},{begin:"\\b0o([0-7_]+)"+n},{
begin:"\\b0x([A-Fa-f0-9_]+)"+n},{
begin:"\\b(\\d[\\d_]*(\\.[0-9_]+)?([eE][+-]?[0-9_]+)?)"+n}],relevance:0},{
begin:[/fn/,/\s+/,e.UNDERSCORE_IDENT_RE],className:{1:"keyword",
3:"title.function"}},{className:"meta",begin:"#!?\\[",end:"\\]",contains:[{
className:"string",begin:/"/,end:/"/}]},{
begin:[/let/,/\s+/,/(?:mut\s+)?/,e.UNDERSCORE_IDENT_RE],className:{1:"keyword",
3:"keyword",4:"variable"}},{
begin:[/for/,/\s+/,e.UNDERSCORE_IDENT_RE,/\s+/,/in/],className:{1:"keyword",
3:"variable",5:"keyword"}},{begin:[/type/,/\s+/,e.UNDERSCORE_IDENT_RE],
className:{1:"keyword",3:"title.class"}},{
begin:[/(?:trait|enum|struct|union|impl|for)/,/\s+/,e.UNDERSCORE_IDENT_RE],
className:{1:"keyword",3:"title.class"}},{begin:e.IDENT_RE+"::",keywords:{
keyword:"Self",built_in:r,type:i}},{className:"punctuation",begin:"->"},a]}}})()
;export default hljsGrammar;

File diff suppressed because one or more lines are too long

View file

@ -1,95 +0,0 @@
/*! `typescript` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict"
;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],t=["Object","Function","Boolean","Symbol","Math","Date","Number","BigInt","String","RegExp","Array","Float32Array","Float64Array","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Int32Array","Uint16Array","Uint32Array","BigInt64Array","BigUint64Array","Set","Map","WeakSet","WeakMap","ArrayBuffer","SharedArrayBuffer","Atomics","DataView","JSON","Promise","Generator","GeneratorFunction","AsyncFunction","Reflect","Proxy","Intl","WebAssembly"],s=["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],r=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],c=["arguments","this","super","console","window","document","localStorage","sessionStorage","module","global"],i=[].concat(r,t,s)
;function o(o){const l=o.regex,d=e,b={begin:/<[A-Za-z0-9\\._:-]+/,
end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{
const a=e[0].length+e.index,t=e.input[a]
;if("<"===t||","===t)return void n.ignoreMatch();let s
;">"===t&&(((e,{after:n})=>{const a="</"+e[0].slice(1)
;return-1!==e.input.indexOf(a,n)})(e,{after:a})||n.ignoreMatch())
;const r=e.input.substring(a)
;((s=r.match(/^\s*=/))||(s=r.match(/^\s+extends\s+/))&&0===s.index)&&n.ignoreMatch()
}},g={$pattern:e,keyword:n,literal:a,built_in:i,"variable.language":c
},u="[0-9](_?[0-9])*",m=`\\.(${u})`,E="0|[1-9](_?[0-9])*|0[0-7]*[89][0-9]*",A={
className:"number",variants:[{
begin:`(\\b(${E})((${m})|\\.)?|(${m}))[eE][+-]?(${u})\\b`},{
begin:`\\b(${E})\\b((${m})\\b|\\.)?|(${m})\\b`},{
begin:"\\b(0|[1-9](_?[0-9])*)n\\b"},{
begin:"\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*n?\\b"},{
begin:"\\b0[bB][0-1](_?[0-1])*n?\\b"},{begin:"\\b0[oO][0-7](_?[0-7])*n?\\b"},{
begin:"\\b0[0-7]+n?\\b"}],relevance:0},y={className:"subst",begin:"\\$\\{",
end:"\\}",keywords:g,contains:[]},p={begin:"html`",end:"",starts:{end:"`",
returnEnd:!1,contains:[o.BACKSLASH_ESCAPE,y],subLanguage:"xml"}},f={
begin:"css`",end:"",starts:{end:"`",returnEnd:!1,
contains:[o.BACKSLASH_ESCAPE,y],subLanguage:"css"}},N={begin:"gql`",end:"",
starts:{end:"`",returnEnd:!1,contains:[o.BACKSLASH_ESCAPE,y],
subLanguage:"graphql"}},_={className:"string",begin:"`",end:"`",
contains:[o.BACKSLASH_ESCAPE,y]},h={className:"comment",
variants:[o.COMMENT(/\/\*\*(?!\/)/,"\\*/",{relevance:0,contains:[{
begin:"(?=@[A-Za-z]+)",relevance:0,contains:[{className:"doctag",
begin:"@[A-Za-z]+"},{className:"type",begin:"\\{",end:"\\}",excludeEnd:!0,
excludeBegin:!0,relevance:0},{className:"variable",begin:d+"(?=\\s*(-)|$)",
endsParent:!0,relevance:0},{begin:/(?=[^\n])\s/,relevance:0}]}]
}),o.C_BLOCK_COMMENT_MODE,o.C_LINE_COMMENT_MODE]
},S=[o.APOS_STRING_MODE,o.QUOTE_STRING_MODE,p,f,N,_,{match:/\$\d+/},A]
;y.contains=S.concat({begin:/\{/,end:/\}/,keywords:g,contains:["self"].concat(S)
});const v=[].concat(h,y.contains),w=v.concat([{begin:/\(/,end:/\)/,keywords:g,
contains:["self"].concat(v)}]),R={className:"params",begin:/\(/,end:/\)/,
excludeBegin:!0,excludeEnd:!0,keywords:g,contains:w},x={variants:[{
match:[/class/,/\s+/,d,/\s+/,/extends/,/\s+/,l.concat(d,"(",l.concat(/\./,d),")*")],
scope:{1:"keyword",3:"title.class",5:"keyword",7:"title.class.inherited"}},{
match:[/class/,/\s+/,d],scope:{1:"keyword",3:"title.class"}}]},k={relevance:0,
match:l.either(/\bJSON/,/\b[A-Z][a-z]+([A-Z][a-z]*|\d)*/,/\b[A-Z]{2,}([A-Z][a-z]+|\d)+([A-Z][a-z]*)*/,/\b[A-Z]{2,}[a-z]+([A-Z][a-z]+|\d)*([A-Z][a-z]*)*/),
className:"title.class",keywords:{_:[...t,...s]}},O={variants:[{
match:[/function/,/\s+/,d,/(?=\s*\()/]},{match:[/function/,/\s*(?=\()/]}],
className:{1:"keyword",3:"title.function"},label:"func.def",contains:[R],
illegal:/%/},C={
match:l.concat(/\b/,(I=[...r,"super","import"],l.concat("(?!",I.join("|"),")")),d,l.lookahead(/\(/)),
className:"title.function",relevance:0};var I;const T={
begin:l.concat(/\./,l.lookahead(l.concat(d,/(?![0-9A-Za-z$_(])/))),end:d,
excludeBegin:!0,keywords:"prototype",className:"property",relevance:0},M={
match:[/get|set/,/\s+/,d,/(?=\()/],className:{1:"keyword",3:"title.function"},
contains:[{begin:/\(\)/},R]
},B="(\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)|"+o.UNDERSCORE_IDENT_RE+")\\s*=>",$={
match:[/const|var|let/,/\s+/,d,/\s*/,/=\s*/,/(async\s*)?/,l.lookahead(B)],
keywords:"async",className:{1:"keyword",3:"title.function"},contains:[R]}
;return{name:"JavaScript",aliases:["js","jsx","mjs","cjs"],keywords:g,exports:{
PARAMS_CONTAINS:w,CLASS_REFERENCE:k},illegal:/#(?![$_A-z])/,
contains:[o.SHEBANG({label:"shebang",binary:"node",relevance:5}),{
label:"use_strict",className:"meta",relevance:10,
begin:/^\s*['"]use (strict|asm)['"]/
},o.APOS_STRING_MODE,o.QUOTE_STRING_MODE,p,f,N,_,h,{match:/\$\d+/},A,k,{
className:"attr",begin:d+l.lookahead(":"),relevance:0},$,{
begin:"("+o.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",
keywords:"return throw case",relevance:0,contains:[h,o.REGEXP_MODE,{
className:"function",begin:B,returnBegin:!0,end:"\\s*=>",contains:[{
className:"params",variants:[{begin:o.UNDERSCORE_IDENT_RE,relevance:0},{
className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0,
excludeEnd:!0,keywords:g,contains:w}]}]},{begin:/,/,relevance:0},{match:/\s+/,
relevance:0},{variants:[{begin:"<>",end:"</>"},{
match:/<[A-Za-z0-9\\._:-]+\s*\/>/},{begin:b.begin,
"on:begin":b.isTrulyOpeningTag,end:b.end}],subLanguage:"xml",contains:[{
begin:b.begin,end:b.end,skip:!0,contains:["self"]}]}]},O,{
beginKeywords:"while if switch catch for"},{
begin:"\\b(?!function)"+o.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{",
returnBegin:!0,label:"func.def",contains:[R,o.inherit(o.TITLE_MODE,{begin:d,
className:"title.function"})]},{match:/\.\.\./,relevance:0},T,{match:"\\$"+d,
relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"},
contains:[R]},C,{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/,
className:"variable.constant"},x,M,{match:/\$[(.]/}]}}return t=>{
const s=o(t),r=e,l=["any","void","number","boolean","string","object","never","symbol","bigint","unknown"],d={
beginKeywords:"namespace",end:/\{/,excludeEnd:!0,
contains:[s.exports.CLASS_REFERENCE]},b={beginKeywords:"interface",end:/\{/,
excludeEnd:!0,keywords:{keyword:"interface extends",built_in:l},
contains:[s.exports.CLASS_REFERENCE]},g={$pattern:e,
keyword:n.concat(["type","namespace","interface","public","private","protected","implements","declare","abstract","readonly","enum","override"]),
literal:a,built_in:i.concat(l),"variable.language":c},u={className:"meta",
begin:"@"+r},m=(e,n,a)=>{const t=e.contains.findIndex((e=>e.label===n))
;if(-1===t)throw Error("can not find mode to replace");e.contains.splice(t,1,a)}
;return Object.assign(s.keywords,g),
s.exports.PARAMS_CONTAINS.push(u),s.contains=s.contains.concat([u,d,b]),
m(s,"shebang",t.SHEBANG()),m(s,"use_strict",{className:"meta",relevance:10,
begin:/^\s*['"]use strict['"]/
}),s.contains.find((e=>"func.def"===e.label)).relevance=0,Object.assign(s,{
name:"TypeScript",aliases:["ts","tsx","mts","cts"]}),s}})()
;export default hljsGrammar;

View file

@ -1,29 +0,0 @@
/*! `xml` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict";return e=>{
const a=e.regex,n=a.concat(/[\p{L}_]/u,a.optional(/[\p{L}0-9_.-]*:/u),/[\p{L}0-9_.-]*/u),s={
className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},t={begin:/\s/,
contains:[{className:"keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}]
},i=e.inherit(t,{begin:/\(/,end:/\)/}),c=e.inherit(e.APOS_STRING_MODE,{
className:"string"}),l=e.inherit(e.QUOTE_STRING_MODE,{className:"string"}),r={
endsWithParent:!0,illegal:/</,relevance:0,contains:[{className:"attr",
begin:/[\p{L}0-9._:-]+/u,relevance:0},{begin:/=\s*/,relevance:0,contains:[{
className:"string",endsParent:!0,variants:[{begin:/"/,end:/"/,contains:[s]},{
begin:/'/,end:/'/,contains:[s]},{begin:/[^\s"'=<>`]+/}]}]}]};return{
name:"HTML, XML",
aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"],
case_insensitive:!0,unicodeRegex:!0,contains:[{className:"meta",begin:/<![a-z]/,
end:/>/,relevance:10,contains:[t,l,c,i,{begin:/\[/,end:/\]/,contains:[{
className:"meta",begin:/<![a-z]/,end:/>/,contains:[t,i,l,c]}]}]
},e.COMMENT(/<!--/,/-->/,{relevance:10}),{begin:/<!\[CDATA\[/,end:/\]\]>/,
relevance:10},s,{className:"meta",end:/\?>/,variants:[{begin:/<\?xml/,
relevance:10,contains:[l]},{begin:/<\?[a-z][a-z0-9]+/}]},{className:"tag",
begin:/<style(?=\s|>)/,end:/>/,keywords:{name:"style"},contains:[r],starts:{
end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",
begin:/<script(?=\s|>)/,end:/>/,keywords:{name:"script"},contains:[r],starts:{
end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{
className:"tag",begin:/<>|<\/>/},{className:"tag",
begin:a.concat(/</,a.lookahead(a.concat(n,a.either(/\/>/,/>/,/\s/)))),
end:/\/?>/,contains:[{className:"name",begin:n,relevance:0,starts:r}]},{
className:"tag",begin:a.concat(/<\//,a.lookahead(a.concat(n,/>/))),contains:[{
className:"name",begin:n,relevance:0},{begin:/>/,relevance:0,endsParent:!0}]}]}}
})();export default hljsGrammar;

View file

@ -1,25 +0,0 @@
/*! `yaml` grammar compiled for Highlight.js 11.9.0 */
var hljsGrammar=(()=>{"use strict";return e=>{
const n="true false yes no null",a="[\\w#;/?:@&=+$,.~*'()[\\]]+",s={
className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/
},{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,{className:"template-variable",
variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]}]},i=e.inherit(s,{
variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),l={
end:",",endsWithParent:!0,excludeEnd:!0,keywords:n,relevance:0},t={begin:/\{/,
end:/\}/,contains:[l],illegal:"\\n",relevance:0},r={begin:"\\[",end:"\\]",
contains:[l],illegal:"\\n",relevance:0},b=[{className:"attr",variants:[{
begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{
begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)"}]},{className:"meta",begin:"^---\\s*$",
relevance:10},{className:"string",
begin:"[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"},{
begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,
relevance:0},{className:"type",begin:"!\\w+!"+a},{className:"type",
begin:"!<"+a+">"},{className:"type",begin:"!"+a},{className:"type",begin:"!!"+a
},{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta",
begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"-(?=[ ]|$)",
relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:n,keywords:{literal:n}},{
className:"number",
begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b"
},{className:"number",begin:e.C_NUMBER_RE+"\\b",relevance:0},t,r,s],c=[...b]
;return c.pop(),c.push(i),l.contains=c,{name:"YAML",case_insensitive:!0,
aliases:["yml"],contains:b}}})();export default hljsGrammar;