Spaces:
Running on Zero
Running on Zero
Self-hosted UI assets, polished markdown, load public DibaAi/Diba-Base
Browse files- .gitattributes +1 -0
- app.py +4 -2
- diba-ui.css +94 -44
- diba-ui.js +124 -103
- vendor/fonts/JetBrainsMono-Regular.woff2 +0 -0
- vendor/fonts/JetBrainsMono-SemiBold.woff2 +0 -0
- vendor/fonts/Vazirmatn-Variable.woff2 +3 -0
- vendor/highlight.min.js +0 -0
- vendor/marked.min.js +6 -0
- vendor/purify.min.js +3 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
vendor/fonts/Vazirmatn-Variable.woff2 filter=lfs diff=lfs merge=lfs -text
|
app.py
CHANGED
|
@@ -14,7 +14,7 @@ import spaces
|
|
| 14 |
import torch
|
| 15 |
from transformers import AutoModelForCausalLM, AutoTokenizer, StoppingCriteria, StoppingCriteriaList, TextIteratorStreamer
|
| 16 |
|
| 17 |
-
MODEL_ID = os.environ.get("DIBA_MODEL", "DibaAi/Diba-Base
|
| 18 |
TOKEN = os.environ.get("HF_TOKEN")
|
| 19 |
HERE = Path(__file__).parent
|
| 20 |
|
|
@@ -103,8 +103,10 @@ def ask(message, temperature=0.0, max_new_tokens=768):
|
|
| 103 |
|
| 104 |
UI_CSS = (HERE / "diba-ui.css").read_text(encoding="utf-8")
|
| 105 |
UI_JS = (HERE / "diba-ui.js").read_text(encoding="utf-8")
|
|
|
|
|
|
|
| 106 |
HEAD = ('<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">'
|
| 107 |
-
f"<style>{UI_CSS}</style><script>window.DIBA_BACKEND = 'gradio';</script><script>{UI_JS}</script>")
|
| 108 |
|
| 109 |
with gr.Blocks(title="Diba · دیبا", head=HEAD, css="footer{display:none!important}") as demo:
|
| 110 |
gr.HTML('<div style="padding:40px;text-align:center;font-family:Tahoma">در حال بارگذاری دیبا… · Loading Diba…</div>')
|
|
|
|
| 14 |
import torch
|
| 15 |
from transformers import AutoModelForCausalLM, AutoTokenizer, StoppingCriteria, StoppingCriteriaList, TextIteratorStreamer
|
| 16 |
|
| 17 |
+
MODEL_ID = os.environ.get("DIBA_MODEL", "DibaAi/Diba-Base")
|
| 18 |
TOKEN = os.environ.get("HF_TOKEN")
|
| 19 |
HERE = Path(__file__).parent
|
| 20 |
|
|
|
|
| 103 |
|
| 104 |
UI_CSS = (HERE / "diba-ui.css").read_text(encoding="utf-8")
|
| 105 |
UI_JS = (HERE / "diba-ui.js").read_text(encoding="utf-8")
|
| 106 |
+
gr.set_static_paths(paths=[str(HERE / "vendor")]) # self-hosted fonts and libraries, served at /gradio_api/file=...
|
| 107 |
+
ASSET_BASE = "/gradio_api/file=" + str(HERE).replace("\\", "/").rstrip("/") + "/"
|
| 108 |
HEAD = ('<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">'
|
| 109 |
+
f"<style>{UI_CSS}</style><script>window.DIBA_BACKEND = 'gradio'; window.DIBA_ASSET_BASE = '{ASSET_BASE}';</script><script>{UI_JS}</script>")
|
| 110 |
|
| 111 |
with gr.Blocks(title="Diba · دیبا", head=HEAD, css="footer{display:none!important}") as demo:
|
| 112 |
gr.HTML('<div style="padding:40px;text-align:center;font-family:Tahoma">در حال بارگذاری دیبا… · Loading Diba…</div>')
|
diba-ui.css
CHANGED
|
@@ -1,13 +1,15 @@
|
|
| 1 |
-
/* Diba chat UI — shared by the CPU (llama.cpp) and ZeroGPU (Gradio) Spaces */
|
| 2 |
:root, [data-theme="light"] {
|
| 3 |
-
--bg: #FFFFFF; --side: #F6F6F3; --side-hover: #ECECE7; --panel: #FFFFFF; --line: #E6E4DD;
|
| 4 |
-
--ink: #1B1F1D; --ink-2: #4C5552; --muted: #8A928E; --bubble: #F1F1EC; --
|
| 5 |
-
--
|
|
|
|
| 6 |
}
|
| 7 |
[data-theme="dark"] {
|
| 8 |
-
--bg: #1B1D1C; --side: #131514; --side-hover: #232625; --panel: #242726; --line: #
|
| 9 |
-
--ink: #ECEEEA; --ink-2: #B7BEBA; --muted: #7F8783; --bubble: #2A2E2C; --
|
| 10 |
-
--
|
|
|
|
| 11 |
}
|
| 12 |
|
| 13 |
html, body { height: 100%; margin: 0; }
|
|
@@ -15,28 +17,30 @@ body.diba-lock { overflow: hidden !important; }
|
|
| 15 |
#diba-root, #diba-root * { box-sizing: border-box; }
|
| 16 |
#diba-root {
|
| 17 |
position: fixed; inset: 0; z-index: 2147483000; display: flex; background: var(--bg); color: var(--ink);
|
| 18 |
-
font-family: "Vazirmatn", Tahoma, system-ui, sans-serif; font-size: 15px; line-height: 1.7;
|
|
|
|
| 19 |
}
|
| 20 |
#diba-root button { font-family: inherit; cursor: pointer; }
|
| 21 |
#diba-root :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 8px; }
|
|
|
|
| 22 |
|
| 23 |
/* ---------- sidebar ---------- */
|
| 24 |
.d-side { width: 268px; flex: 0 0 268px; background: var(--side); display: flex; flex-direction: column; border-inline-end: 1px solid var(--line); transition: margin .2s ease; }
|
| 25 |
.d-side.closed { margin-inline-start: -268px; }
|
| 26 |
.d-brand { display: flex; align-items: center; gap: 10px; padding: 16px 16px 10px; }
|
| 27 |
.d-mark { width: 32px; height: 32px; border-radius: 9px; display: grid; place-items: center; color: #fff; font-weight: 800; font-size: 17px; background: linear-gradient(135deg, #1F7A5A, #C8912E); }
|
| 28 |
-
.d-brand-name { font-weight: 800; font-size: 17px; line-height: 1.
|
| 29 |
.d-brand-sub { font-size: 12px; color: var(--muted); }
|
| 30 |
.d-new { margin: 6px 12px 10px; display: flex; align-items: center; gap: 8px; padding: 9px 12px; border-radius: 10px; border: 1px solid var(--line); background: var(--panel); color: var(--ink); font-size: 14px; font-weight: 600; }
|
| 31 |
.d-new:hover { background: var(--side-hover); }
|
| 32 |
.d-list-title { padding: 8px 18px 4px; font-size: 12px; color: var(--muted); font-weight: 600; }
|
| 33 |
.d-list { flex: 1; overflow-y: auto; padding: 0 8px 8px; }
|
| 34 |
-
.d-conv { display: flex; align-items: center; gap: 6px; padding: 8px 10px; border-radius: 9px; color: var(--ink-2); font-size: 14px; }
|
| 35 |
.d-conv:hover, .d-conv.active { background: var(--side-hover); color: var(--ink); }
|
| 36 |
.d-conv-title { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; unicode-bidi: plaintext; text-align: start; }
|
| 37 |
-
.d-conv-del { opacity: 0; border: 0; background: transparent; color: var(--muted); padding: 2px 4px; border-radius: 6px;
|
| 38 |
-
.d-conv:hover .d-conv-del { opacity: 1; }
|
| 39 |
-
.d-conv-del:hover { color: var(--danger); }
|
| 40 |
.d-empty-list { padding: 10px 18px; color: var(--muted); font-size: 13px; }
|
| 41 |
.d-side-foot { border-top: 1px solid var(--line); padding: 10px 12px 12px; display: flex; flex-direction: column; gap: 8px; }
|
| 42 |
.d-seg { display: flex; background: var(--side-hover); border-radius: 10px; padding: 3px; }
|
|
@@ -55,42 +59,87 @@ body.diba-lock { overflow: hidden !important; }
|
|
| 55 |
.d-badge { font-size: 11px; font-weight: 600; color: var(--accent); background: var(--accent-soft); border-radius: 999px; padding: 2px 8px; }
|
| 56 |
.d-top-spacer { flex: 1; }
|
| 57 |
|
| 58 |
-
.d-scroll { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
|
| 59 |
-
.d-thread { max-width: 780px; margin: 0 auto; padding: 18px 20px 28px; display: flex; flex-direction: column; gap:
|
| 60 |
|
| 61 |
.d-msg { display: flex; gap: 12px; }
|
| 62 |
.d-msg.user { justify-content: flex-end; }
|
| 63 |
-
.d-msg.user .d-bubble { background: var(--bubble); border-radius: 18px; padding: 10px 16px; max-width: 78%; white-space: pre-wrap;
|
| 64 |
-
.d-avatar { width: 30px; height: 30px; flex: 0 0 30px; border-radius: 50%; display: grid; place-items: center; font-weight: 800; font-size: 14px; color: #fff; background: linear-gradient(135deg, #1F7A5A, #C8912E); margin-top:
|
| 65 |
.d-body { flex: 1; min-width: 0; }
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
.d-content
|
| 69 |
-
.d-content
|
| 70 |
-
.d-content
|
| 71 |
-
.d-content
|
| 72 |
-
.d-content h1, .d-content h2, .d-content h3 {
|
| 73 |
-
.d-content
|
| 74 |
-
.d-content
|
| 75 |
-
.d-content
|
| 76 |
-
.d-content
|
| 77 |
-
.d-content
|
| 78 |
-
.d-
|
| 79 |
-
.d-
|
| 80 |
-
.d-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
.d-code-head button:hover { color: #fff; background: rgba(255,255,255,.08); }
|
| 82 |
-
.d-code pre { margin: 0; padding: 14px 16px; overflow-x: auto; }
|
| 83 |
-
.d-code pre code { font-family: "JetBrains Mono", Consolas, monospace; font-size: 13px; line-height: 1.
|
| 84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
@keyframes d-blink { 50% { opacity: 0; } }
|
| 86 |
-
.d-actions { display: flex; gap: 2px; margin-top:
|
| 87 |
-
.d-actions button { border: 0; background: transparent; color: var(--muted); font-size: 12.5px; padding: 4px 8px; border-radius: 7px; }
|
| 88 |
.d-actions button:hover { background: var(--side-hover); color: var(--ink); }
|
| 89 |
.d-error { color: var(--danger); font-size: 14px; }
|
| 90 |
-
.d-typing { display: inline-flex; gap: 4px; padding:
|
| 91 |
.d-typing span { width: 7px; height: 7px; border-radius: 50%; background: var(--muted); animation: d-dot 1.2s infinite ease-in-out; }
|
| 92 |
.d-typing span:nth-child(2) { animation-delay: .15s; } .d-typing span:nth-child(3) { animation-delay: .3s; }
|
| 93 |
@keyframes d-dot { 0%, 80%, 100% { transform: scale(.6); opacity: .4; } 40% { transform: scale(1); opacity: 1; } }
|
|
|
|
| 94 |
|
| 95 |
/* ---------- welcome ---------- */
|
| 96 |
.d-welcome { max-width: 780px; margin: 0 auto; padding: 12vh 20px 20px; text-align: center; }
|
|
@@ -105,13 +154,11 @@ body.diba-lock { overflow: hidden !important; }
|
|
| 105 |
|
| 106 |
/* ---------- composer ---------- */
|
| 107 |
.d-compose-wrap { flex: 0 0 auto; padding: 8px 20px 12px; background: linear-gradient(to top, var(--bg) 70%, transparent); }
|
| 108 |
-
.d-compose { max-width: 780px; margin: 0 auto; display: flex; align-items: flex-end; gap: 8px; background: var(--panel); border: 1px solid var(--line); border-radius: 22px; padding: 8px 8px 8px 16px; box-shadow: var(--shadow); }
|
| 109 |
[dir="rtl"] .d-compose { padding: 8px 16px 8px 8px; }
|
| 110 |
-
#diba-root .d-compose textarea:focus, #diba-root .d-compose textarea:focus-visible { outline: none !important; box-shadow: none !important; }
|
| 111 |
.d-compose:focus-within { border-color: var(--accent); }
|
| 112 |
-
.d-
|
| 113 |
-
.d-
|
| 114 |
-
.d-compose textarea { flex: 1; border: 0; outline: none; resize: none; background: transparent; color: var(--ink); font: inherit; font-size: 15px; line-height: 1.6; max-height: 200px; padding: 6px 0; unicode-bidi: plaintext; text-align: start; }
|
| 115 |
.d-compose textarea::placeholder { color: var(--muted); }
|
| 116 |
.d-send { width: 38px; height: 38px; flex: 0 0 38px; border-radius: 50%; border: 0; display: grid; place-items: center; background: var(--accent); color: var(--accent-ink); }
|
| 117 |
.d-send:disabled { opacity: .35; cursor: default; }
|
|
@@ -124,6 +171,7 @@ body.diba-lock { overflow: hidden !important; }
|
|
| 124 |
.d-pop { position: absolute; top: 52px; inset-inline-end: 12px; width: 280px; background: var(--panel); border: 1px solid var(--line); border-radius: 14px; box-shadow: var(--shadow); padding: 14px; display: none; z-index: 5; }
|
| 125 |
.d-pop.show { display: block; }
|
| 126 |
.d-pop label { display: flex; justify-content: space-between; font-size: 13px; color: var(--ink-2); margin: 6px 0 2px; }
|
|
|
|
| 127 |
.d-pop input[type=range] { width: 100%; accent-color: var(--accent); }
|
| 128 |
.d-pop .d-hint { font-size: 11.5px; color: var(--muted); margin-top: 8px; }
|
| 129 |
|
|
@@ -134,5 +182,7 @@ body.diba-lock { overflow: hidden !important; }
|
|
| 134 |
.d-sugg { grid-template-columns: 1fr; }
|
| 135 |
.d-welcome { padding-top: 7vh; }
|
| 136 |
.d-msg.user .d-bubble { max-width: 88%; }
|
|
|
|
|
|
|
| 137 |
}
|
| 138 |
-
@media (prefers-reduced-motion: reduce) { .d-side { transition: none; } .d-cursor::after, .d-typing span { animation: none; } }
|
|
|
|
| 1 |
+
/* Diba chat UI — shared by the CPU (llama.cpp) and ZeroGPU (Gradio) Spaces. All assets self-hosted. */
|
| 2 |
:root, [data-theme="light"] {
|
| 3 |
+
--bg: #FFFFFF; --side: #F6F6F3; --side-hover: #ECECE7; --panel: #FFFFFF; --line: #E6E4DD; --line-soft: #EFEDE7;
|
| 4 |
+
--ink: #1B1F1D; --ink-2: #4C5552; --muted: #8A928E; --bubble: #F1F1EC; --zebra: #FAFAF7;
|
| 5 |
+
--code-bg: #0F1513; --code-head: #1A2320; --code-ink: #DCE6E1; --code-muted: #8FA39B; --inline-code: #EEEDE6;
|
| 6 |
+
--accent: #1F7A5A; --accent-ink: #FFFFFF; --accent-soft: #E7F3ED; --danger: #B3261E; --shadow: 0 6px 24px rgba(20, 30, 25, .08);
|
| 7 |
}
|
| 8 |
[data-theme="dark"] {
|
| 9 |
+
--bg: #1B1D1C; --side: #131514; --side-hover: #232625; --panel: #242726; --line: #313533; --line-soft: #2A2D2C;
|
| 10 |
+
--ink: #ECEEEA; --ink-2: #B7BEBA; --muted: #7F8783; --bubble: #2A2E2C; --zebra: #202322;
|
| 11 |
+
--code-bg: #0B0F0D; --code-head: #151B18; --code-ink: #DCE6E1; --code-muted: #8FA39B; --inline-code: #2C302E;
|
| 12 |
+
--accent: #4CB58C; --accent-ink: #0B1511; --accent-soft: #1C3229; --danger: #F2B8B5; --shadow: 0 6px 24px rgba(0, 0, 0, .35);
|
| 13 |
}
|
| 14 |
|
| 15 |
html, body { height: 100%; margin: 0; }
|
|
|
|
| 17 |
#diba-root, #diba-root * { box-sizing: border-box; }
|
| 18 |
#diba-root {
|
| 19 |
position: fixed; inset: 0; z-index: 2147483000; display: flex; background: var(--bg); color: var(--ink);
|
| 20 |
+
font-family: "Vazirmatn", Tahoma, "Segoe UI", system-ui, sans-serif; font-size: 15px; line-height: 1.7;
|
| 21 |
+
-webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
|
| 22 |
}
|
| 23 |
#diba-root button { font-family: inherit; cursor: pointer; }
|
| 24 |
#diba-root :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 8px; }
|
| 25 |
+
#diba-root svg { flex: none; }
|
| 26 |
|
| 27 |
/* ---------- sidebar ---------- */
|
| 28 |
.d-side { width: 268px; flex: 0 0 268px; background: var(--side); display: flex; flex-direction: column; border-inline-end: 1px solid var(--line); transition: margin .2s ease; }
|
| 29 |
.d-side.closed { margin-inline-start: -268px; }
|
| 30 |
.d-brand { display: flex; align-items: center; gap: 10px; padding: 16px 16px 10px; }
|
| 31 |
.d-mark { width: 32px; height: 32px; border-radius: 9px; display: grid; place-items: center; color: #fff; font-weight: 800; font-size: 17px; background: linear-gradient(135deg, #1F7A5A, #C8912E); }
|
| 32 |
+
.d-brand-name { font-weight: 800; font-size: 17px; line-height: 1.15; }
|
| 33 |
.d-brand-sub { font-size: 12px; color: var(--muted); }
|
| 34 |
.d-new { margin: 6px 12px 10px; display: flex; align-items: center; gap: 8px; padding: 9px 12px; border-radius: 10px; border: 1px solid var(--line); background: var(--panel); color: var(--ink); font-size: 14px; font-weight: 600; }
|
| 35 |
.d-new:hover { background: var(--side-hover); }
|
| 36 |
.d-list-title { padding: 8px 18px 4px; font-size: 12px; color: var(--muted); font-weight: 600; }
|
| 37 |
.d-list { flex: 1; overflow-y: auto; padding: 0 8px 8px; }
|
| 38 |
+
.d-conv { display: flex; align-items: center; gap: 6px; padding: 8px 10px; border-radius: 9px; color: var(--ink-2); font-size: 14px; cursor: pointer; }
|
| 39 |
.d-conv:hover, .d-conv.active { background: var(--side-hover); color: var(--ink); }
|
| 40 |
.d-conv-title { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; unicode-bidi: plaintext; text-align: start; }
|
| 41 |
+
.d-conv-del { opacity: 0; border: 0; background: transparent; color: var(--muted); padding: 2px 4px; border-radius: 6px; display: grid; place-items: center; }
|
| 42 |
+
.d-conv:hover .d-conv-del, .d-conv.active .d-conv-del { opacity: 1; }
|
| 43 |
+
.d-conv-del:hover { color: var(--danger); background: var(--panel); }
|
| 44 |
.d-empty-list { padding: 10px 18px; color: var(--muted); font-size: 13px; }
|
| 45 |
.d-side-foot { border-top: 1px solid var(--line); padding: 10px 12px 12px; display: flex; flex-direction: column; gap: 8px; }
|
| 46 |
.d-seg { display: flex; background: var(--side-hover); border-radius: 10px; padding: 3px; }
|
|
|
|
| 59 |
.d-badge { font-size: 11px; font-weight: 600; color: var(--accent); background: var(--accent-soft); border-radius: 999px; padding: 2px 8px; }
|
| 60 |
.d-top-spacer { flex: 1; }
|
| 61 |
|
| 62 |
+
.d-scroll { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scroll-behavior: auto; }
|
| 63 |
+
.d-thread { max-width: 780px; margin: 0 auto; padding: 18px 20px 28px; display: flex; flex-direction: column; gap: 26px; }
|
| 64 |
|
| 65 |
.d-msg { display: flex; gap: 12px; }
|
| 66 |
.d-msg.user { justify-content: flex-end; }
|
| 67 |
+
.d-msg.user .d-bubble { background: var(--bubble); border-radius: 18px; padding: 10px 16px; max-width: 78%; white-space: pre-wrap; overflow-wrap: anywhere; unicode-bidi: plaintext; text-align: start; }
|
| 68 |
+
.d-avatar { width: 30px; height: 30px; flex: 0 0 30px; border-radius: 50%; display: grid; place-items: center; font-weight: 800; font-size: 14px; color: #fff; background: linear-gradient(135deg, #1F7A5A, #C8912E); margin-top: 3px; }
|
| 69 |
.d-body { flex: 1; min-width: 0; }
|
| 70 |
+
|
| 71 |
+
/* ---------- markdown ---------- */
|
| 72 |
+
.d-content { font-size: 15.5px; line-height: 1.85; color: var(--ink); overflow-wrap: anywhere; }
|
| 73 |
+
.d-content > *:first-child { margin-top: 0 !important; }
|
| 74 |
+
.d-content > *:last-child { margin-bottom: 0 !important; }
|
| 75 |
+
.d-content p { margin: 0 0 .9em; }
|
| 76 |
+
.d-content h1, .d-content h2, .d-content h3, .d-content h4, .d-content h5, .d-content h6 { color: var(--ink); line-height: 1.4; text-wrap: balance; }
|
| 77 |
+
.d-content h1 { font-size: 1.5em; font-weight: 800; margin: 1.3em 0 .55em; }
|
| 78 |
+
.d-content h2 { font-size: 1.28em; font-weight: 750; margin: 1.25em 0 .5em; padding-bottom: .3em; border-bottom: 1px solid var(--line-soft); }
|
| 79 |
+
.d-content h3 { font-size: 1.12em; font-weight: 700; margin: 1.1em 0 .45em; }
|
| 80 |
+
.d-content h4, .d-content h5, .d-content h6 { font-size: 1em; font-weight: 700; margin: 1em 0 .4em; }
|
| 81 |
+
.d-content strong, .d-content b { font-weight: 700; color: var(--ink); }
|
| 82 |
+
.d-content em { font-style: italic; }
|
| 83 |
+
.d-content del { color: var(--muted); }
|
| 84 |
+
.d-content hr { border: 0; border-top: 1px solid var(--line); margin: 1.5em 0; }
|
| 85 |
+
.d-content a { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
|
| 86 |
+
.d-content a:hover { text-decoration-thickness: 2px; }
|
| 87 |
+
.d-content ul, .d-content ol { margin: .3em 0 1em; padding: 0; }
|
| 88 |
+
.d-content ul[dir="rtl"], .d-content ol[dir="rtl"] { padding-right: 1.5em; }
|
| 89 |
+
.d-content ul[dir="ltr"], .d-content ol[dir="ltr"], .d-content ul:not([dir]), .d-content ol:not([dir]) { padding-left: 1.5em; }
|
| 90 |
+
.d-content li { margin: .3em 0; padding-inline-start: .15em; }
|
| 91 |
+
.d-content li > p { margin: 0 0 .4em; }
|
| 92 |
+
.d-content li > ul, .d-content li > ol { margin: .25em 0 .35em; }
|
| 93 |
+
.d-content ul > li::marker { color: var(--muted); }
|
| 94 |
+
.d-content ol > li::marker { color: var(--ink-2); font-weight: 600; }
|
| 95 |
+
.d-content li input[type="checkbox"] { margin-inline-end: .5em; accent-color: var(--accent); vertical-align: middle; }
|
| 96 |
+
.d-content blockquote { margin: 1em 0; padding: .6em 1em; border-inline-start: 3px solid var(--accent); background: var(--accent-soft); border-radius: 0 10px 10px 0; color: var(--ink-2); }
|
| 97 |
+
[dir="rtl"] .d-content blockquote, .d-content blockquote[dir="rtl"] { border-radius: 10px 0 0 10px; }
|
| 98 |
+
.d-content blockquote > p:last-child { margin-bottom: 0; }
|
| 99 |
+
.d-content img { max-width: 100%; border-radius: 10px; }
|
| 100 |
+
.d-content kbd { font-family: "JetBrains Mono", Consolas, monospace; font-size: .82em; padding: 1px 6px; border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 6px; background: var(--panel); }
|
| 101 |
+
.d-content :not(pre) > code { font-family: "JetBrains Mono", Consolas, monospace; font-size: .86em; background: var(--inline-code); color: var(--ink); padding: .12em .42em; border-radius: 6px; direction: ltr; unicode-bidi: isolate; white-space: break-spaces; }
|
| 102 |
+
|
| 103 |
+
.d-table { margin: .9em 0 1.2em; border: 1px solid var(--line); border-radius: 12px; overflow-x: auto; }
|
| 104 |
+
.d-table table { border-collapse: collapse; width: 100%; font-size: 14px; line-height: 1.6; }
|
| 105 |
+
.d-table th, .d-table td { padding: 9px 13px; text-align: start; vertical-align: top; border-bottom: 1px solid var(--line-soft); }
|
| 106 |
+
.d-table th { background: var(--side); font-weight: 700; color: var(--ink); white-space: nowrap; }
|
| 107 |
+
.d-table tbody tr:nth-child(even) td { background: var(--zebra); }
|
| 108 |
+
.d-table tbody tr:last-child td { border-bottom: 0; }
|
| 109 |
+
.d-table th + th, .d-table td + td { border-inline-start: 1px solid var(--line-soft); }
|
| 110 |
+
|
| 111 |
+
.d-code { direction: ltr; text-align: left; margin: .9em 0 1.1em; border-radius: 12px; overflow: hidden; background: var(--code-bg); border: 1px solid rgba(255,255,255,.04); }
|
| 112 |
+
.d-code-head { display: flex; align-items: center; justify-content: space-between; padding: 7px 10px 7px 14px; background: var(--code-head); color: var(--code-muted); font-size: 12px; font-family: "JetBrains Mono", Consolas, monospace; }
|
| 113 |
+
.d-code-head button { display: inline-flex; align-items: center; gap: 6px; border: 0; background: transparent; color: var(--code-muted); font-size: 12px; font-family: "Vazirmatn", Tahoma, sans-serif; padding: 3px 8px; border-radius: 6px; }
|
| 114 |
+
#diba-root .d-code-head button, #diba-root .d-code-head button span { font-family: "Vazirmatn", Tahoma, "Segoe UI", sans-serif; letter-spacing: 0; }
|
| 115 |
.d-code-head button:hover { color: #fff; background: rgba(255,255,255,.08); }
|
| 116 |
+
.d-code pre { margin: 0; padding: 14px 16px; overflow-x: auto; tab-size: 2; }
|
| 117 |
+
.d-code pre code { font-family: "JetBrains Mono", Consolas, monospace; font-size: 13px; line-height: 1.65; color: var(--code-ink); background: transparent !important; padding: 0 !important; white-space: pre; }
|
| 118 |
+
|
| 119 |
+
/* syntax theme (dark code surface in both UI themes) */
|
| 120 |
+
.d-code .hljs-comment, .d-code .hljs-quote { color: #6F8580; font-style: italic; }
|
| 121 |
+
.d-code .hljs-keyword, .d-code .hljs-selector-tag, .d-code .hljs-built_in, .d-code .hljs-doctag { color: #C792EA; }
|
| 122 |
+
.d-code .hljs-string, .d-code .hljs-template-tag, .d-code .hljs-addition { color: #C3E88D; }
|
| 123 |
+
.d-code .hljs-number, .d-code .hljs-literal, .d-code .hljs-symbol { color: #F78C6C; }
|
| 124 |
+
.d-code .hljs-title, .d-code .hljs-title.function_, .d-code .hljs-section { color: #82AAFF; }
|
| 125 |
+
.d-code .hljs-title.class_, .d-code .hljs-type, .d-code .hljs-attr, .d-code .hljs-attribute, .d-code .hljs-property { color: #FFCB6B; }
|
| 126 |
+
.d-code .hljs-variable, .d-code .hljs-template-variable, .d-code .hljs-tag, .d-code .hljs-name, .d-code .hljs-deletion { color: #F07178; }
|
| 127 |
+
.d-code .hljs-meta, .d-code .hljs-regexp, .d-code .hljs-bullet, .d-code .hljs-link, .d-code .hljs-selector-class, .d-code .hljs-selector-id { color: #89DDFF; }
|
| 128 |
+
.d-code .hljs-params { color: var(--code-ink); }
|
| 129 |
+
.d-code .hljs-emphasis { font-style: italic; } .d-code .hljs-strong { font-weight: 700; }
|
| 130 |
+
.d-code .hljs-addition { background: rgba(195,232,141,.08); } .d-code .hljs-deletion { background: rgba(240,113,120,.08); }
|
| 131 |
+
|
| 132 |
+
.d-cursor > *:last-child::after, .d-cursor:empty::after { content: ""; display: inline-block; width: 8px; height: 1.05em; margin-inline-start: 3px; vertical-align: text-bottom; background: var(--accent); border-radius: 2px; animation: d-blink 1s steps(2) infinite; }
|
| 133 |
@keyframes d-blink { 50% { opacity: 0; } }
|
| 134 |
+
.d-actions { display: flex; gap: 2px; margin-top: 8px; }
|
| 135 |
+
.d-actions button { display: inline-flex; align-items: center; gap: 5px; border: 0; background: transparent; color: var(--muted); font-size: 12.5px; padding: 4px 8px; border-radius: 7px; }
|
| 136 |
.d-actions button:hover { background: var(--side-hover); color: var(--ink); }
|
| 137 |
.d-error { color: var(--danger); font-size: 14px; }
|
| 138 |
+
.d-typing { display: inline-flex; gap: 4px; padding: 10px 0; }
|
| 139 |
.d-typing span { width: 7px; height: 7px; border-radius: 50%; background: var(--muted); animation: d-dot 1.2s infinite ease-in-out; }
|
| 140 |
.d-typing span:nth-child(2) { animation-delay: .15s; } .d-typing span:nth-child(3) { animation-delay: .3s; }
|
| 141 |
@keyframes d-dot { 0%, 80%, 100% { transform: scale(.6); opacity: .4; } 40% { transform: scale(1); opacity: 1; } }
|
| 142 |
+
.d-cold { color: var(--muted); font-size: 13px; }
|
| 143 |
|
| 144 |
/* ---------- welcome ---------- */
|
| 145 |
.d-welcome { max-width: 780px; margin: 0 auto; padding: 12vh 20px 20px; text-align: center; }
|
|
|
|
| 154 |
|
| 155 |
/* ---------- composer ---------- */
|
| 156 |
.d-compose-wrap { flex: 0 0 auto; padding: 8px 20px 12px; background: linear-gradient(to top, var(--bg) 70%, transparent); }
|
| 157 |
+
.d-compose { max-width: 780px; margin: 0 auto; display: flex; align-items: flex-end; gap: 8px; background: var(--panel); border: 1px solid var(--line); border-radius: 22px; padding: 8px 8px 8px 16px; box-shadow: var(--shadow); transition: border-color .15s; }
|
| 158 |
[dir="rtl"] .d-compose { padding: 8px 16px 8px 8px; }
|
|
|
|
| 159 |
.d-compose:focus-within { border-color: var(--accent); }
|
| 160 |
+
#diba-root .d-compose textarea, #diba-root .d-compose textarea:focus, #diba-root .d-compose textarea:focus-visible { outline: none !important; box-shadow: none !important; }
|
| 161 |
+
.d-compose textarea { flex: 1; border: 0; resize: none; background: transparent; color: var(--ink); font: inherit; font-size: 15px; line-height: 1.6; max-height: 200px; padding: 6px 0; unicode-bidi: plaintext; text-align: start; }
|
|
|
|
| 162 |
.d-compose textarea::placeholder { color: var(--muted); }
|
| 163 |
.d-send { width: 38px; height: 38px; flex: 0 0 38px; border-radius: 50%; border: 0; display: grid; place-items: center; background: var(--accent); color: var(--accent-ink); }
|
| 164 |
.d-send:disabled { opacity: .35; cursor: default; }
|
|
|
|
| 171 |
.d-pop { position: absolute; top: 52px; inset-inline-end: 12px; width: 280px; background: var(--panel); border: 1px solid var(--line); border-radius: 14px; box-shadow: var(--shadow); padding: 14px; display: none; z-index: 5; }
|
| 172 |
.d-pop.show { display: block; }
|
| 173 |
.d-pop label { display: flex; justify-content: space-between; font-size: 13px; color: var(--ink-2); margin: 6px 0 2px; }
|
| 174 |
+
.d-pop b { font-variant-numeric: tabular-nums; }
|
| 175 |
.d-pop input[type=range] { width: 100%; accent-color: var(--accent); }
|
| 176 |
.d-pop .d-hint { font-size: 11.5px; color: var(--muted); margin-top: 8px; }
|
| 177 |
|
|
|
|
| 182 |
.d-sugg { grid-template-columns: 1fr; }
|
| 183 |
.d-welcome { padding-top: 7vh; }
|
| 184 |
.d-msg.user .d-bubble { max-width: 88%; }
|
| 185 |
+
.d-thread { padding: 14px 14px 24px; }
|
| 186 |
+
.d-compose-wrap { padding: 6px 12px 10px; }
|
| 187 |
}
|
| 188 |
+
@media (prefers-reduced-motion: reduce) { .d-side, .d-compose { transition: none; } .d-cursor > *:last-child::after, .d-typing span { animation: none; } }
|
diba-ui.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
| 1 |
-
/* Diba chat UI — shared front-end
|
|
|
|
|
|
|
| 2 |
(function () {
|
| 3 |
"use strict";
|
| 4 |
if (window.__dibaUI) return; window.__dibaUI = true;
|
| 5 |
|
| 6 |
-
const
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
|
|
|
| 13 |
};
|
| 14 |
|
| 15 |
const T = {
|
|
@@ -17,9 +20,9 @@
|
|
| 17 |
dir: "rtl", brandSub: "دستیار هوش مصنوعی دیباچین", newChat: "گفتوگوی جدید", history: "گفتوگوها", noChats: "هنوز گفتوگویی ندارید.",
|
| 18 |
welcome: "امروز چطور میتوانم کمکتان کنم؟", welcomeSub: "به هر زبانی بنویسید، به همان زبان پاسخ میدهم.",
|
| 19 |
placeholder: "پیام به دیبا…", disclaimer: "دیبا ممکن است اشتباه کند. اطلاعات مهم را بررسی کنید.", preview: "پیشنمایش",
|
| 20 |
-
copy: "کپی", copied: "کپی شد", regenerate: "پاسخ دوباره", delete: "حذف", stop: "توقف", send: "ارسال", menu: "منو",
|
| 21 |
-
settings: "تنظیمات", temperature: "خلاقیت", maxTokens: "حداکثر طول پاسخ", tempHint: "برای کدنویسی و پاسخ دقیق، خلاقیت را صفر نگ
|
| 22 |
-
|
| 23 |
footer: 'ساختهی <a href="https://dibachain.ir" target="_blank" rel="noopener">دیباچین</a>', untitled: "گفتوگوی بدون عنوان",
|
| 24 |
coldStart: "در حال آمادهسازی مدل… اولین پاسخ ممکن است چند ثانیه طول بکشد.",
|
| 25 |
},
|
|
@@ -27,14 +30,13 @@
|
|
| 27 |
dir: "ltr", brandSub: "AI assistant by Dibachain", newChat: "New chat", history: "Chats", noChats: "No chats yet.",
|
| 28 |
welcome: "How can I help you today?", welcomeSub: "Write in any language and I will reply in the same one.",
|
| 29 |
placeholder: "Message Diba…", disclaimer: "Diba can make mistakes. Check important information.", preview: "Preview",
|
| 30 |
-
copy: "Copy", copied: "Copied", regenerate: "Regenerate", delete: "Delete", stop: "Stop", send: "Send", menu: "Menu",
|
| 31 |
settings: "Settings", temperature: "Creativity", maxTokens: "Max response length", tempHint: "Keep creativity at 0 for code and precise answers.",
|
| 32 |
-
|
| 33 |
footer: 'Built by <a href="https://dibachain.ir" target="_blank" rel="noopener">Dibachain</a>', untitled: "Untitled chat",
|
| 34 |
coldStart: "Warming up the model… the first reply may take a few seconds.",
|
| 35 |
},
|
| 36 |
};
|
| 37 |
-
T.fa.tempHint = "برای کدنویسی و پاسخ دقیق، خلاقیت را روی صفر نگه دارید.";
|
| 38 |
|
| 39 |
const SUGG = {
|
| 40 |
fa: [
|
|
@@ -52,9 +54,9 @@
|
|
| 52 |
};
|
| 53 |
|
| 54 |
const SYSTEM = {
|
| 55 |
-
fa: "تو «دیبا» هستی، دستیار هوش مصنوعی ساختهی شرکت دیباچین. کاربر به فارسی نوشته؛ فقط به فارسی جواب بده، به زبان نوشتاری و مؤدبانه. دقیقاً به همان چیزی که کاربر خواسته جواب بده، روشن و بدون مقدمهی اضافه. اگر کد لازم است، کد تمیز و کامل در بلوک کد بده. هرگز نام مدل پایه یا سازندهی آن را نگو؛ اگر پرسیدند فقط بگو روی یک مدل زبانی متنباز ساخته شدهای و دیباچین تو را آموزش داده است.",
|
| 56 |
-
en: "You are Diba, an AI assistant built by the company Dibachain. The user wrote in English, so reply ONLY in English. Be clear, accurate and professional. Answer exactly what was asked, without unnecessary preamble. When code is needed, give clean, complete code in a fenced code block. Never name or hint at any base model or its maker; if asked, say only that you were built on an open-source language model and trained by Dibachain.",
|
| 57 |
-
other: "You are Diba, an AI assistant built by the company Dibachain. Reply in the same language the user wrote in. Be clear, accurate and professional. Never name any base model or its maker.",
|
| 58 |
};
|
| 59 |
|
| 60 |
const ICON = {
|
|
@@ -62,8 +64,12 @@
|
|
| 62 |
menu: '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M4 6h16M4 12h16M4 18h16"/></svg>',
|
| 63 |
send: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19V5M5 12l7-7 7 7"/></svg>',
|
| 64 |
stop: '<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><rect x="5" y="5" width="14" height="14" rx="2"/></svg>',
|
| 65 |
-
gear: '<svg width="19" height="19" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><
|
| 66 |
down: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M19 12l-7 7-7-7"/></svg>',
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
};
|
| 68 |
|
| 69 |
// ---------------------------------------------------------------- utils
|
|
@@ -73,10 +79,14 @@
|
|
| 73 |
set(k, v) { try { localStorage.setItem("diba." + k, JSON.stringify(v)); } catch (e) { /* storage unavailable */ } },
|
| 74 |
};
|
| 75 |
const uid = () => Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
|
| 76 |
-
const esc = (s) => s.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c]));
|
| 77 |
-
const loadScript = (src) => new Promise((res, rej) => { const s = document.createElement("script"); s.src = src; s.onload = res; s.onerror = rej; document.head.appendChild(s); });
|
| 78 |
-
|
| 79 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
function detectLang(text) {
|
| 81 |
const noCode = text.replace(/```[\s\S]*?```|`[^`]*`/g, " ");
|
| 82 |
const fa = (noCode.match(/[-ۿ]/g) || []).length;
|
|
@@ -84,17 +94,16 @@
|
|
| 84 |
if (!fa && !en) return "other";
|
| 85 |
return fa >= en ? "fa" : "en";
|
| 86 |
}
|
|
|
|
| 87 |
|
| 88 |
// ---------------------------------------------------------------- state
|
| 89 |
const BACKEND = window.DIBA_BACKEND || (document.querySelector("gradio-app") || window.gradio_config ? "gradio" : "openai");
|
| 90 |
const S = {
|
| 91 |
-
lang: store.get("lang",
|
| 92 |
theme: store.get("theme", window.matchMedia && matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"),
|
| 93 |
settings: Object.assign({ temperature: 0, max_tokens: 1024 }, store.get("settings", {})),
|
| 94 |
convs: store.get("convs", []),
|
| 95 |
-
currentId: null,
|
| 96 |
-
streaming: false,
|
| 97 |
-
controller: null,
|
| 98 |
sideOpen: window.innerWidth > 820,
|
| 99 |
};
|
| 100 |
const qp = new URLSearchParams(location.search);
|
|
@@ -106,86 +115,92 @@
|
|
| 106 |
|
| 107 |
// ---------------------------------------------------------------- markdown
|
| 108 |
function renderMarkdown(md) {
|
| 109 |
-
if (!window.marked || !window.DOMPurify)
|
| 110 |
-
|
|
|
|
|
|
|
| 111 |
const box = document.createElement("div");
|
| 112 |
box.innerHTML = html;
|
| 113 |
box.querySelectorAll("pre > code").forEach((code) => {
|
| 114 |
const pre = code.parentElement;
|
| 115 |
-
const lang = (
|
| 116 |
const wrap = document.createElement("div"); wrap.className = "d-code";
|
| 117 |
-
wrap.innerHTML =
|
| 118 |
pre.replaceWith(wrap); wrap.appendChild(pre);
|
| 119 |
-
if (window.hljs) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 120 |
});
|
| 121 |
-
box.querySelectorAll("
|
| 122 |
-
|
| 123 |
-
box.querySelectorAll("p, ul, ol, li, h1, h2, h3, h4, blockquote, table").forEach((n) => {
|
| 124 |
if (n.closest(".d-code")) return;
|
| 125 |
-
|
| 126 |
-
const first = txt.match(/[-ۿA-Za-z]/);
|
| 127 |
-
n.setAttribute("dir", first && /[-ۿ]/.test(first[0]) ? "rtl" : "ltr");
|
| 128 |
});
|
| 129 |
return box.innerHTML;
|
| 130 |
}
|
| 131 |
|
| 132 |
// ---------------------------------------------------------------- backends (each yields the full text so far)
|
| 133 |
-
async function*
|
| 134 |
-
const
|
| 135 |
-
const body = {
|
| 136 |
-
model: "diba", stream: true, temperature: S.settings.temperature, max_tokens: S.settings.max_tokens,
|
| 137 |
-
messages: [{ role: "system", content: SYSTEM[lang] }, ...messages.slice(-16)],
|
| 138 |
-
chat_template_kwargs: { enable_thinking: false },
|
| 139 |
-
};
|
| 140 |
-
const res = await fetch((window.DIBA_API_BASE || "") + "/v1/chat/completions", {
|
| 141 |
-
method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), signal: S.controller.signal,
|
| 142 |
-
});
|
| 143 |
-
if (!res.ok || !res.body) throw new Error("HTTP " + res.status);
|
| 144 |
-
const reader = res.body.getReader(); const dec = new TextDecoder(); let buf = ""; let text = "";
|
| 145 |
for (;;) {
|
| 146 |
-
const { value, done } = await reader.read(); if (done)
|
| 147 |
buf += dec.decode(value, { stream: true });
|
| 148 |
let i;
|
| 149 |
while ((i = buf.indexOf("\n")) >= 0) {
|
| 150 |
-
const line = buf.slice(0, i).
|
| 151 |
-
if (
|
| 152 |
-
|
| 153 |
-
|
| 154 |
}
|
| 155 |
}
|
| 156 |
}
|
| 157 |
|
| 158 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 159 |
let gradioWarm = false;
|
| 160 |
async function* streamGradio(messages) {
|
| 161 |
const base = window.location.origin + window.location.pathname.replace(/\/+$/, "");
|
| 162 |
-
const signal = S.controller.signal;
|
| 163 |
const start = await fetch(base + "/gradio_api/call/chat_stream", {
|
| 164 |
-
method: "POST", headers: { "Content-Type": "application/json" }, signal,
|
| 165 |
body: JSON.stringify({ data: [JSON.stringify(messages.slice(-16)), S.settings.temperature, S.settings.max_tokens] }),
|
| 166 |
});
|
| 167 |
if (!start.ok) throw new Error("HTTP " + start.status);
|
| 168 |
const { event_id } = await start.json();
|
| 169 |
-
const res = await fetch(base + "/gradio_api/call/chat_stream/" + event_id, { signal });
|
| 170 |
if (!res.ok || !res.body) throw new Error("HTTP " + res.status);
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
if (line.startsWith("event:")) { event = line.slice(6).trim(); continue; }
|
| 179 |
-
if (!line.startsWith("data:")) continue;
|
| 180 |
-
const raw = line.slice(5).trim();
|
| 181 |
-
if (event === "error") throw new Error(raw || "gradio error");
|
| 182 |
-
if (event === "generating" || event === "complete") {
|
| 183 |
-
try { const arr = JSON.parse(raw); if (Array.isArray(arr) && typeof arr[0] === "string") { gradioWarm = true; yield arr[0]; } } catch (e) { /* heartbeat */ }
|
| 184 |
-
if (event === "complete") return;
|
| 185 |
-
}
|
| 186 |
}
|
| 187 |
-
|
|
|
|
|
|
|
| 188 |
}
|
|
|
|
| 189 |
|
| 190 |
// ---------------------------------------------------------------- DOM
|
| 191 |
const root = document.createElement("div");
|
|
@@ -241,15 +256,15 @@
|
|
| 241 |
$(".d-max", root).value = S.settings.max_tokens; $(".d-max-v", root).textContent = S.settings.max_tokens;
|
| 242 |
el.side.classList.toggle("closed", !S.sideOpen);
|
| 243 |
el.backdrop.classList.toggle("show", S.sideOpen && window.innerWidth <= 820);
|
| 244 |
-
renderList(); renderThread();
|
| 245 |
}
|
| 246 |
|
| 247 |
function renderList() {
|
| 248 |
-
if (!S.convs.length) { el.list.innerHTML =
|
| 249 |
el.list.innerHTML = S.convs.map((c) =>
|
| 250 |
`<div class="d-conv${c.id === S.currentId ? " active" : ""}" data-id="${c.id}" role="button" tabindex="0">` +
|
| 251 |
`<span class="d-conv-title">${esc(c.title || t("untitled"))}</span>` +
|
| 252 |
-
`<button class="d-conv-del" type="button" data-del="${c.id}" title="${esc(t("delete"))}">
|
| 253 |
}
|
| 254 |
|
| 255 |
function renderWelcome() {
|
|
@@ -259,11 +274,12 @@
|
|
| 259 |
|
| 260 |
function msgHTML(m, idx, isLast) {
|
| 261 |
if (m.role === "user") return `<div class="d-msg user" data-idx="${idx}"><div class="d-bubble" dir="auto">${esc(m.content)}</div></div>`;
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
|
|
|
| 267 |
return `<div class="d-msg bot" data-idx="${idx}"><div class="d-avatar">د</div><div class="d-body">${body}${actions}</div></div>`;
|
| 268 |
}
|
| 269 |
|
|
@@ -280,7 +296,7 @@
|
|
| 280 |
const c = current(); if (!c) return;
|
| 281 |
const idx = c.messages.length - 1; const node = el.thread.querySelector(`.d-msg[data-idx="${idx}"]`);
|
| 282 |
const html = msgHTML(c.messages[idx], idx, true);
|
| 283 |
-
if (node)
|
| 284 |
}
|
| 285 |
|
| 286 |
// ---------------------------------------------------------------- scrolling: follow only when the reader is at the bottom
|
|
@@ -312,11 +328,10 @@
|
|
| 312 |
const gen = BACKEND === "gradio" ? streamGradio(history) : streamOpenAI(history);
|
| 313 |
for await (const text of gen) { latest = text; if (!frame) frame = requestAnimationFrame(paint); }
|
| 314 |
} catch (e) {
|
| 315 |
-
if (!(S.controller && S.controller.signal.aborted)) { bot.error =
|
| 316 |
} finally {
|
| 317 |
if (frame) cancelAnimationFrame(frame);
|
| 318 |
bot.content = latest; bot.pending = false; bot.cold = false;
|
| 319 |
-
if (!bot.content && !bot.error) bot.error = !(S.controller && S.controller.signal.aborted);
|
| 320 |
if (!bot.content && !bot.error) c.messages.pop();
|
| 321 |
S.streaming = false; S.controller = null; c.updated = Date.now();
|
| 322 |
saveConvs(); renderThread(); toBottom(false); setSendState();
|
|
@@ -338,16 +353,26 @@
|
|
| 338 |
el.send.classList.toggle("stop", S.streaming);
|
| 339 |
el.send.innerHTML = S.streaming ? ICON.stop : ICON.send;
|
| 340 |
el.send.title = S.streaming ? t("stop") : t("send");
|
|
|
|
| 341 |
el.send.disabled = !S.streaming && !el.input.value.trim();
|
| 342 |
}
|
| 343 |
function autoGrow() { el.input.style.height = "auto"; el.input.style.height = Math.min(el.input.scrollHeight, 200) + "px"; setSendState(); }
|
| 344 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 345 |
// ---------------------------------------------------------------- events
|
| 346 |
el.form.addEventListener("submit", (e) => { e.preventDefault(); if (S.streaming) stopStream(); else sendMessage(el.input.value); });
|
| 347 |
el.input.addEventListener("input", autoGrow);
|
| 348 |
-
el.input.addEventListener("keydown", (e) => {
|
| 349 |
-
if (e.key === "Enter" && !e.shiftKey && !e.isComposing) { e.preventDefault(); if (!S.streaming) sendMessage(el.input.value); }
|
| 350 |
-
});
|
| 351 |
$(".d-new", root).addEventListener("click", newChat);
|
| 352 |
$(".d-menu", root).addEventListener("click", () => { S.sideOpen = !S.sideOpen; applyChrome(); });
|
| 353 |
el.backdrop.addEventListener("click", () => { S.sideOpen = false; applyChrome(); });
|
|
@@ -365,35 +390,31 @@
|
|
| 365 |
if (b.dataset.del) { e.stopPropagation(); S.convs = S.convs.filter((c) => c.id !== b.dataset.del); if (S.currentId === b.dataset.del) S.currentId = null; saveConvs(); renderList(); renderThread(); return; }
|
| 366 |
if (b.classList.contains("d-conv")) { if (S.streaming) stopStream(); S.currentId = b.dataset.id; renderList(); renderThread(); toBottom(true); if (window.innerWidth <= 820) { S.sideOpen = false; applyChrome(); } return; }
|
| 367 |
if (b.dataset.copyMsg !== undefined) { const m = current().messages[+b.dataset.copyMsg]; copyText(m.content, b); return; }
|
| 368 |
-
if (b.hasAttribute("data-copy-code")) { copyText(b.closest(".d-code").querySelector("code").
|
| 369 |
if (b.hasAttribute("data-regen")) { const c = current(); if (!c || S.streaming) return; if (c.messages[c.messages.length - 1].role === "assistant") c.messages.pop(); runAssistant(); }
|
| 370 |
});
|
| 371 |
root.addEventListener("keydown", (e) => { const conv = e.target.closest && e.target.closest(".d-conv"); if (conv && (e.key === "Enter" || e.key === " ")) { e.preventDefault(); conv.click(); } });
|
| 372 |
-
|
| 373 |
-
function copyText(text, btn) {
|
| 374 |
-
const done = () => { const old = btn.textContent; btn.textContent = t("copied"); setTimeout(() => { btn.textContent = old; }, 1400); };
|
| 375 |
-
if (navigator.clipboard && navigator.clipboard.writeText) navigator.clipboard.writeText(text).then(done, done);
|
| 376 |
-
else { const ta = document.createElement("textarea"); ta.value = text; document.body.appendChild(ta); ta.select(); try { document.execCommand("copy"); } catch (err) { /* ignore */ } ta.remove(); done(); }
|
| 377 |
-
}
|
| 378 |
window.addEventListener("resize", () => { if (window.innerWidth > 820 && !S.sideOpen) { S.sideOpen = true; applyChrome(); } });
|
| 379 |
|
| 380 |
// ---------------------------------------------------------------- demo seed for screenshots (#demo)
|
| 381 |
if (location.hash === "#demo") {
|
| 382 |
-
S.convs = [{ id: "demo", title: "
|
| 383 |
-
{ role: "user", content: "یک
|
| 384 |
-
{ role: "assistant", content: "
|
| 385 |
-
{ role: "user", content: "
|
| 386 |
-
{ role: "assistant", content: "
|
| 387 |
] }, { id: "demo2", title: "Who was Cyrus the Great?", updated: Date.now(), messages: [] }];
|
| 388 |
S.currentId = "demo";
|
| 389 |
}
|
| 390 |
|
| 391 |
// ---------------------------------------------------------------- boot
|
| 392 |
function boot() {
|
| 393 |
-
|
| 394 |
document.body.appendChild(root); document.body.classList.add("diba-lock");
|
| 395 |
-
applyChrome(); toBottom(true);
|
| 396 |
-
Promise.all([loadScript(
|
|
|
|
|
|
|
| 397 |
if (window.innerWidth > 820) el.input.focus();
|
| 398 |
const autoQ = qp.get("q"); // test hook: ?q=... sends one message on load
|
| 399 |
if (autoQ && location.hash !== "#demo") setTimeout(() => { newChat(); sendMessage(autoQ); }, 1200);
|
|
|
|
| 1 |
+
/* Diba chat UI — shared front-end, fully self-hosted (no external CDN).
|
| 2 |
+
Backends: "openai" (llama.cpp server, same origin) and "gradio" (ZeroGPU Space, Gradio REST SSE).
|
| 3 |
+
Config globals: DIBA_BACKEND, DIBA_ASSET_BASE (prefix for vendor/ assets), DIBA_API_BASE. */
|
| 4 |
(function () {
|
| 5 |
"use strict";
|
| 6 |
if (window.__dibaUI) return; window.__dibaUI = true;
|
| 7 |
|
| 8 |
+
const ASSET = window.DIBA_ASSET_BASE || "";
|
| 9 |
+
const VENDOR = {
|
| 10 |
+
marked: ASSET + "vendor/marked.min.js",
|
| 11 |
+
purify: ASSET + "vendor/purify.min.js",
|
| 12 |
+
hljs: ASSET + "vendor/highlight.min.js",
|
| 13 |
+
vazir: ASSET + "vendor/fonts/Vazirmatn-Variable.woff2",
|
| 14 |
+
monoRegular: ASSET + "vendor/fonts/JetBrainsMono-Regular.woff2",
|
| 15 |
+
monoSemi: ASSET + "vendor/fonts/JetBrainsMono-SemiBold.woff2",
|
| 16 |
};
|
| 17 |
|
| 18 |
const T = {
|
|
|
|
| 20 |
dir: "rtl", brandSub: "دستیار هوش مصنوعی دیباچین", newChat: "گفتوگوی جدید", history: "گفتوگوها", noChats: "هنوز گفتوگویی ندارید.",
|
| 21 |
welcome: "امروز چطور میتوانم کمکتان کنم؟", welcomeSub: "به هر زبانی بنویسید، به همان زبان پاسخ میدهم.",
|
| 22 |
placeholder: "پیام به دیبا…", disclaimer: "دیبا ممکن است اشتباه کند. اطلاعات مهم را بررسی کنید.", preview: "پیشنمایش",
|
| 23 |
+
copy: "کپی", copied: "کپی شد", copyCode: "کپی کد", regenerate: "پاسخ دوباره", delete: "حذف", stop: "توقف", send: "ارسال", menu: "منو",
|
| 24 |
+
settings: "تنظیمات", temperature: "خلاقیت", maxTokens: "حداکثر طول پاسخ", tempHint: "برای کدنویسی و پاسخ دقیق، خلاقیت را روی صفر نگه دارید.",
|
| 25 |
+
light: "روشن", dark: "تیره", error: "ارتباط با مدل برقرار نشد. لطفاً دوباره تلاش کنید.", jump: "رفتن به آخرین پیام",
|
| 26 |
footer: 'ساختهی <a href="https://dibachain.ir" target="_blank" rel="noopener">دیباچین</a>', untitled: "گفتوگوی بدون عنوان",
|
| 27 |
coldStart: "در حال آمادهسازی مدل… اولین پاسخ ممکن است چند ثانیه طول بکشد.",
|
| 28 |
},
|
|
|
|
| 30 |
dir: "ltr", brandSub: "AI assistant by Dibachain", newChat: "New chat", history: "Chats", noChats: "No chats yet.",
|
| 31 |
welcome: "How can I help you today?", welcomeSub: "Write in any language and I will reply in the same one.",
|
| 32 |
placeholder: "Message Diba…", disclaimer: "Diba can make mistakes. Check important information.", preview: "Preview",
|
| 33 |
+
copy: "Copy", copied: "Copied", copyCode: "Copy code", regenerate: "Regenerate", delete: "Delete", stop: "Stop", send: "Send", menu: "Menu",
|
| 34 |
settings: "Settings", temperature: "Creativity", maxTokens: "Max response length", tempHint: "Keep creativity at 0 for code and precise answers.",
|
| 35 |
+
light: "Light", dark: "Dark", error: "Could not reach the model. Please try again.", jump: "Jump to latest",
|
| 36 |
footer: 'Built by <a href="https://dibachain.ir" target="_blank" rel="noopener">Dibachain</a>', untitled: "Untitled chat",
|
| 37 |
coldStart: "Warming up the model… the first reply may take a few seconds.",
|
| 38 |
},
|
| 39 |
};
|
|
|
|
| 40 |
|
| 41 |
const SUGG = {
|
| 42 |
fa: [
|
|
|
|
| 54 |
};
|
| 55 |
|
| 56 |
const SYSTEM = {
|
| 57 |
+
fa: "تو «دیبا» هستی، دستیار هوش مصنوعی ساختهی شرکت دیباچین. کاربر به فارسی نوشته؛ فقط به فارسی جواب بده، به زبان نوشتاری و مؤدبانه. دقیقاً به همان چیزی که کاربر خواسته جواب بده، روشن و بدون مقدمهی اضافه. از قالببندی Markdown (عنوان، فهرست، جدول، بلوک کد) هر جا به خوانایی کمک میکند استفاده کن. اگر کد لازم است، کد تمیز و کامل در بلوک کد بده. هرگز نام مدل پایه یا سازندهی آن را نگو؛ اگر پرسیدند فقط بگو روی یک مدل زبانی متنباز ساخته شدهای و دیباچین تو را آموزش داده است.",
|
| 58 |
+
en: "You are Diba, an AI assistant built by the company Dibachain. The user wrote in English, so reply ONLY in English. Be clear, accurate and professional. Answer exactly what was asked, without unnecessary preamble. Use Markdown formatting (headings, lists, tables, code blocks) where it improves readability. When code is needed, give clean, complete code in a fenced code block. Never name or hint at any base model or its maker; if asked, say only that you were built on an open-source language model and trained by Dibachain.",
|
| 59 |
+
other: "You are Diba, an AI assistant built by the company Dibachain. Reply in the same language the user wrote in. Be clear, accurate and professional, and use Markdown where helpful. Never name any base model or its maker.",
|
| 60 |
};
|
| 61 |
|
| 62 |
const ICON = {
|
|
|
|
| 64 |
menu: '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M4 6h16M4 12h16M4 18h16"/></svg>',
|
| 65 |
send: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19V5M5 12l7-7 7 7"/></svg>',
|
| 66 |
stop: '<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><rect x="5" y="5" width="14" height="14" rx="2"/></svg>',
|
| 67 |
+
gear: '<svg width="19" height="19" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z"/></svg>',
|
| 68 |
down: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M19 12l-7 7-7-7"/></svg>',
|
| 69 |
+
copy: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="12" height="12" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>',
|
| 70 |
+
check: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>',
|
| 71 |
+
regen: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-2.64-6.36L21 8"/><path d="M21 3v5h-5"/></svg>',
|
| 72 |
+
trash: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18M8 6V4h8v2M19 6l-1 14H6L5 6"/></svg>',
|
| 73 |
};
|
| 74 |
|
| 75 |
// ---------------------------------------------------------------- utils
|
|
|
|
| 79 |
set(k, v) { try { localStorage.setItem("diba." + k, JSON.stringify(v)); } catch (e) { /* storage unavailable */ } },
|
| 80 |
};
|
| 81 |
const uid = () => Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
|
| 82 |
+
const esc = (s) => String(s).replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c]));
|
| 83 |
+
const loadScript = (src) => new Promise((res, rej) => { const s = document.createElement("script"); s.src = src; s.onload = res; s.onerror = () => rej(new Error("load " + src)); document.head.appendChild(s); });
|
| 84 |
+
function injectFonts() {
|
| 85 |
+
const css = `@font-face{font-family:"Vazirmatn";src:url("${VENDOR.vazir}") format("woff2");font-weight:100 900;font-style:normal;font-display:swap}` +
|
| 86 |
+
`@font-face{font-family:"JetBrains Mono";src:url("${VENDOR.monoRegular}") format("woff2");font-weight:400;font-display:swap}` +
|
| 87 |
+
`@font-face{font-family:"JetBrains Mono";src:url("${VENDOR.monoSemi}") format("woff2");font-weight:600;font-display:swap}`;
|
| 88 |
+
const st = document.createElement("style"); st.textContent = css; document.head.appendChild(st);
|
| 89 |
+
}
|
| 90 |
function detectLang(text) {
|
| 91 |
const noCode = text.replace(/```[\s\S]*?```|`[^`]*`/g, " ");
|
| 92 |
const fa = (noCode.match(/[-ۿ]/g) || []).length;
|
|
|
|
| 94 |
if (!fa && !en) return "other";
|
| 95 |
return fa >= en ? "fa" : "en";
|
| 96 |
}
|
| 97 |
+
const strongDir = (text) => { const m = (text || "").match(/[-ۿA-Za-z]/); return m && /[-ۿ]/.test(m[0]) ? "rtl" : "ltr"; };
|
| 98 |
|
| 99 |
// ---------------------------------------------------------------- state
|
| 100 |
const BACKEND = window.DIBA_BACKEND || (document.querySelector("gradio-app") || window.gradio_config ? "gradio" : "openai");
|
| 101 |
const S = {
|
| 102 |
+
lang: store.get("lang", "fa"),
|
| 103 |
theme: store.get("theme", window.matchMedia && matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"),
|
| 104 |
settings: Object.assign({ temperature: 0, max_tokens: 1024 }, store.get("settings", {})),
|
| 105 |
convs: store.get("convs", []),
|
| 106 |
+
currentId: null, streaming: false, controller: null,
|
|
|
|
|
|
|
| 107 |
sideOpen: window.innerWidth > 820,
|
| 108 |
};
|
| 109 |
const qp = new URLSearchParams(location.search);
|
|
|
|
| 115 |
|
| 116 |
// ---------------------------------------------------------------- markdown
|
| 117 |
function renderMarkdown(md) {
|
| 118 |
+
if (!window.marked || !window.DOMPurify) {
|
| 119 |
+
return md.split(/\n{2,}/).map((p) => `<p dir="${strongDir(p)}">${esc(p).replace(/\n/g, "<br>")}</p>`).join("");
|
| 120 |
+
}
|
| 121 |
+
const html = window.DOMPurify.sanitize(window.marked.parse(md, { gfm: true, breaks: false }), { ADD_ATTR: ["target"] });
|
| 122 |
const box = document.createElement("div");
|
| 123 |
box.innerHTML = html;
|
| 124 |
box.querySelectorAll("pre > code").forEach((code) => {
|
| 125 |
const pre = code.parentElement;
|
| 126 |
+
const lang = (code.className.match(/language-([\w+#.-]+)/) || [])[1] || "";
|
| 127 |
const wrap = document.createElement("div"); wrap.className = "d-code";
|
| 128 |
+
wrap.innerHTML = `<div class="d-code-head"><span>${esc(lang || "code")}</span><button type="button" data-copy-code>${ICON.copy}<span>${esc(t("copyCode"))}</span></button></div>`;
|
| 129 |
pre.replaceWith(wrap); wrap.appendChild(pre);
|
| 130 |
+
if (window.hljs) {
|
| 131 |
+
try {
|
| 132 |
+
if (lang && window.hljs.getLanguage(lang)) { code.innerHTML = window.hljs.highlight(code.textContent, { language: lang, ignoreIllegals: true }).value; }
|
| 133 |
+
else { code.innerHTML = window.hljs.highlightAuto(code.textContent).value; }
|
| 134 |
+
} catch (e) { /* leave plain */ }
|
| 135 |
+
}
|
| 136 |
});
|
| 137 |
+
box.querySelectorAll("table").forEach((tb) => { const w = document.createElement("div"); w.className = "d-table"; tb.replaceWith(w); w.appendChild(tb); });
|
| 138 |
+
box.querySelectorAll("a").forEach((a) => { a.target = "_blank"; a.rel = "noopener noreferrer"; });
|
| 139 |
+
box.querySelectorAll("p, ul, ol, li, h1, h2, h3, h4, h5, h6, blockquote, .d-table").forEach((n) => {
|
| 140 |
if (n.closest(".d-code")) return;
|
| 141 |
+
n.setAttribute("dir", strongDir((n.textContent || "").replace(/[`*_\d\s.,:;!?()\-–—"'«»|#]/g, "")));
|
|
|
|
|
|
|
| 142 |
});
|
| 143 |
return box.innerHTML;
|
| 144 |
}
|
| 145 |
|
| 146 |
// ---------------------------------------------------------------- backends (each yields the full text so far)
|
| 147 |
+
async function* readSSE(res, onEvent) {
|
| 148 |
+
const reader = res.body.getReader(); const dec = new TextDecoder(); let buf = ""; let event = "message";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
for (;;) {
|
| 150 |
+
const { value, done } = await reader.read(); if (done) return;
|
| 151 |
buf += dec.decode(value, { stream: true });
|
| 152 |
let i;
|
| 153 |
while ((i = buf.indexOf("\n")) >= 0) {
|
| 154 |
+
const line = buf.slice(0, i).replace(/\r$/, ""); buf = buf.slice(i + 1);
|
| 155 |
+
if (line.startsWith("event:")) { event = line.slice(6).trim(); continue; }
|
| 156 |
+
if (line.startsWith("data:")) { const r = onEvent(event, line.slice(5).trim()); if (r === null) return; if (r !== undefined) yield r; }
|
| 157 |
+
if (line === "") event = "message";
|
| 158 |
}
|
| 159 |
}
|
| 160 |
}
|
| 161 |
|
| 162 |
+
async function* streamOpenAI(messages) {
|
| 163 |
+
const lang = detectLang([...messages].reverse().find((m) => m.role === "user")?.content || "");
|
| 164 |
+
const res = await fetch((window.DIBA_API_BASE || "") + "/v1/chat/completions", {
|
| 165 |
+
method: "POST", headers: { "Content-Type": "application/json" }, signal: S.controller.signal,
|
| 166 |
+
body: JSON.stringify({
|
| 167 |
+
model: "diba", stream: true, temperature: S.settings.temperature, max_tokens: S.settings.max_tokens,
|
| 168 |
+
messages: [{ role: "system", content: SYSTEM[lang] }, ...messages.slice(-16)], chat_template_kwargs: { enable_thinking: false },
|
| 169 |
+
}),
|
| 170 |
+
});
|
| 171 |
+
if (!res.ok || !res.body) throw new Error("HTTP " + res.status);
|
| 172 |
+
let text = "";
|
| 173 |
+
yield* readSSE(res, (ev, data) => {
|
| 174 |
+
if (data === "[DONE]") return null;
|
| 175 |
+
try { const d = JSON.parse(data).choices?.[0]?.delta?.content; if (d) { text += d; return text; } } catch (e) { /* keep-alive */ }
|
| 176 |
+
return undefined;
|
| 177 |
+
});
|
| 178 |
+
}
|
| 179 |
+
|
| 180 |
let gradioWarm = false;
|
| 181 |
async function* streamGradio(messages) {
|
| 182 |
const base = window.location.origin + window.location.pathname.replace(/\/+$/, "");
|
|
|
|
| 183 |
const start = await fetch(base + "/gradio_api/call/chat_stream", {
|
| 184 |
+
method: "POST", headers: { "Content-Type": "application/json" }, signal: S.controller.signal,
|
| 185 |
body: JSON.stringify({ data: [JSON.stringify(messages.slice(-16)), S.settings.temperature, S.settings.max_tokens] }),
|
| 186 |
});
|
| 187 |
if (!start.ok) throw new Error("HTTP " + start.status);
|
| 188 |
const { event_id } = await start.json();
|
| 189 |
+
const res = await fetch(base + "/gradio_api/call/chat_stream/" + event_id, { signal: S.controller.signal });
|
| 190 |
if (!res.ok || !res.body) throw new Error("HTTP " + res.status);
|
| 191 |
+
yield* readSSE(res, (ev, data) => {
|
| 192 |
+
if (ev === "error") throw new Error(data || "gradio error");
|
| 193 |
+
if (ev === "generating" || ev === "complete") {
|
| 194 |
+
let out;
|
| 195 |
+
try { const arr = JSON.parse(data); if (Array.isArray(arr) && typeof arr[0] === "string") { gradioWarm = true; out = arr[0]; } } catch (e) { /* heartbeat */ }
|
| 196 |
+
if (ev === "complete") { if (out !== undefined) latestFinal = out; return null; }
|
| 197 |
+
return out;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
}
|
| 199 |
+
return undefined;
|
| 200 |
+
});
|
| 201 |
+
if (latestFinal !== null) { const f = latestFinal; latestFinal = null; yield f; }
|
| 202 |
}
|
| 203 |
+
let latestFinal = null;
|
| 204 |
|
| 205 |
// ---------------------------------------------------------------- DOM
|
| 206 |
const root = document.createElement("div");
|
|
|
|
| 256 |
$(".d-max", root).value = S.settings.max_tokens; $(".d-max-v", root).textContent = S.settings.max_tokens;
|
| 257 |
el.side.classList.toggle("closed", !S.sideOpen);
|
| 258 |
el.backdrop.classList.toggle("show", S.sideOpen && window.innerWidth <= 820);
|
| 259 |
+
setSendState(); renderList(); renderThread();
|
| 260 |
}
|
| 261 |
|
| 262 |
function renderList() {
|
| 263 |
+
if (!S.convs.length) { el.list.innerHTML = `<div class="d-empty-list">${esc(t("noChats"))}</div>`; return; }
|
| 264 |
el.list.innerHTML = S.convs.map((c) =>
|
| 265 |
`<div class="d-conv${c.id === S.currentId ? " active" : ""}" data-id="${c.id}" role="button" tabindex="0">` +
|
| 266 |
`<span class="d-conv-title">${esc(c.title || t("untitled"))}</span>` +
|
| 267 |
+
`<button class="d-conv-del" type="button" data-del="${c.id}" title="${esc(t("delete"))}" aria-label="${esc(t("delete"))}">${ICON.trash}</button></div>`).join("");
|
| 268 |
}
|
| 269 |
|
| 270 |
function renderWelcome() {
|
|
|
|
| 274 |
|
| 275 |
function msgHTML(m, idx, isLast) {
|
| 276 |
if (m.role === "user") return `<div class="d-msg user" data-idx="${idx}"><div class="d-bubble" dir="auto">${esc(m.content)}</div></div>`;
|
| 277 |
+
let body;
|
| 278 |
+
if (m.error) body = `<div class="d-error">${esc(t("error"))}</div>`;
|
| 279 |
+
else if (m.content) body = `<div class="d-content${m.pending ? " d-cursor" : ""}">${renderMarkdown(m.content)}</div>`;
|
| 280 |
+
else body = `<div class="d-typing"><span></span><span></span><span></span></div>` + (m.cold ? `<div class="d-cold">${esc(t("coldStart"))}</div>` : "");
|
| 281 |
+
const actions = m.pending ? "" : `<div class="d-actions"><button type="button" data-copy-msg="${idx}">${ICON.copy}<span>${esc(t("copy"))}</span></button>` +
|
| 282 |
+
(isLast ? `<button type="button" data-regen>${ICON.regen}<span>${esc(t("regenerate"))}</span></button>` : "") + "</div>";
|
| 283 |
return `<div class="d-msg bot" data-idx="${idx}"><div class="d-avatar">د</div><div class="d-body">${body}${actions}</div></div>`;
|
| 284 |
}
|
| 285 |
|
|
|
|
| 296 |
const c = current(); if (!c) return;
|
| 297 |
const idx = c.messages.length - 1; const node = el.thread.querySelector(`.d-msg[data-idx="${idx}"]`);
|
| 298 |
const html = msgHTML(c.messages[idx], idx, true);
|
| 299 |
+
if (node) node.outerHTML = html; else el.thread.insertAdjacentHTML("beforeend", html);
|
| 300 |
}
|
| 301 |
|
| 302 |
// ---------------------------------------------------------------- scrolling: follow only when the reader is at the bottom
|
|
|
|
| 328 |
const gen = BACKEND === "gradio" ? streamGradio(history) : streamOpenAI(history);
|
| 329 |
for await (const text of gen) { latest = text; if (!frame) frame = requestAnimationFrame(paint); }
|
| 330 |
} catch (e) {
|
| 331 |
+
if (!(S.controller && S.controller.signal.aborted)) { bot.error = !latest; console.error("[diba]", e); }
|
| 332 |
} finally {
|
| 333 |
if (frame) cancelAnimationFrame(frame);
|
| 334 |
bot.content = latest; bot.pending = false; bot.cold = false;
|
|
|
|
| 335 |
if (!bot.content && !bot.error) c.messages.pop();
|
| 336 |
S.streaming = false; S.controller = null; c.updated = Date.now();
|
| 337 |
saveConvs(); renderThread(); toBottom(false); setSendState();
|
|
|
|
| 353 |
el.send.classList.toggle("stop", S.streaming);
|
| 354 |
el.send.innerHTML = S.streaming ? ICON.stop : ICON.send;
|
| 355 |
el.send.title = S.streaming ? t("stop") : t("send");
|
| 356 |
+
el.send.setAttribute("aria-label", el.send.title);
|
| 357 |
el.send.disabled = !S.streaming && !el.input.value.trim();
|
| 358 |
}
|
| 359 |
function autoGrow() { el.input.style.height = "auto"; el.input.style.height = Math.min(el.input.scrollHeight, 200) + "px"; setSendState(); }
|
| 360 |
|
| 361 |
+
function copyText(text, btn) {
|
| 362 |
+
const label = btn.querySelector("span"); const icon = btn.querySelector("svg");
|
| 363 |
+
const done = () => {
|
| 364 |
+
const oldLabel = label ? label.textContent : ""; const oldIcon = icon ? icon.outerHTML : "";
|
| 365 |
+
if (label) label.textContent = t("copied"); if (icon) icon.outerHTML = ICON.check;
|
| 366 |
+
setTimeout(() => { if (label) label.textContent = oldLabel; const s = btn.querySelector("svg"); if (s && oldIcon) s.outerHTML = oldIcon; }, 1400);
|
| 367 |
+
};
|
| 368 |
+
if (navigator.clipboard && navigator.clipboard.writeText) navigator.clipboard.writeText(text).then(done, done);
|
| 369 |
+
else { const ta = document.createElement("textarea"); ta.value = text; document.body.appendChild(ta); ta.select(); try { document.execCommand("copy"); } catch (err) { /* ignore */ } ta.remove(); done(); }
|
| 370 |
+
}
|
| 371 |
+
|
| 372 |
// ---------------------------------------------------------------- events
|
| 373 |
el.form.addEventListener("submit", (e) => { e.preventDefault(); if (S.streaming) stopStream(); else sendMessage(el.input.value); });
|
| 374 |
el.input.addEventListener("input", autoGrow);
|
| 375 |
+
el.input.addEventListener("keydown", (e) => { if (e.key === "Enter" && !e.shiftKey && !e.isComposing) { e.preventDefault(); if (!S.streaming) sendMessage(el.input.value); } });
|
|
|
|
|
|
|
| 376 |
$(".d-new", root).addEventListener("click", newChat);
|
| 377 |
$(".d-menu", root).addEventListener("click", () => { S.sideOpen = !S.sideOpen; applyChrome(); });
|
| 378 |
el.backdrop.addEventListener("click", () => { S.sideOpen = false; applyChrome(); });
|
|
|
|
| 390 |
if (b.dataset.del) { e.stopPropagation(); S.convs = S.convs.filter((c) => c.id !== b.dataset.del); if (S.currentId === b.dataset.del) S.currentId = null; saveConvs(); renderList(); renderThread(); return; }
|
| 391 |
if (b.classList.contains("d-conv")) { if (S.streaming) stopStream(); S.currentId = b.dataset.id; renderList(); renderThread(); toBottom(true); if (window.innerWidth <= 820) { S.sideOpen = false; applyChrome(); } return; }
|
| 392 |
if (b.dataset.copyMsg !== undefined) { const m = current().messages[+b.dataset.copyMsg]; copyText(m.content, b); return; }
|
| 393 |
+
if (b.hasAttribute("data-copy-code")) { copyText(b.closest(".d-code").querySelector("code").textContent, b); return; }
|
| 394 |
if (b.hasAttribute("data-regen")) { const c = current(); if (!c || S.streaming) return; if (c.messages[c.messages.length - 1].role === "assistant") c.messages.pop(); runAssistant(); }
|
| 395 |
});
|
| 396 |
root.addEventListener("keydown", (e) => { const conv = e.target.closest && e.target.closest(".d-conv"); if (conv && (e.key === "Enter" || e.key === " ")) { e.preventDefault(); conv.click(); } });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 397 |
window.addEventListener("resize", () => { if (window.innerWidth > 820 && !S.sideOpen) { S.sideOpen = true; applyChrome(); } });
|
| 398 |
|
| 399 |
// ---------------------------------------------------------------- demo seed for screenshots (#demo)
|
| 400 |
if (location.hash === "#demo") {
|
| 401 |
+
S.convs = [{ id: "demo", title: "مقایسهی روشهای کپی آرایه", updated: Date.now(), messages: [
|
| 402 |
+
{ role: "user", content: "روشهای کپی آرایه در جاوااسکریپت را مقایسه کن." },
|
| 403 |
+
{ role: "assistant", content: "## کپی سطحی در برابر کپی عمیق\n\nدر جاوااسکریپت **کپی سطحی** فقط لایهی اول را کپی میکند، اما **کپی عمیق** همهی لایهها را.\n\n| روش | نوع کپی | اشیای تو در تو |\n|---|---|---|\n| `[...arr]` | سطحی | مشترک میمانند |\n| `arr.slice()` | سطحی | مشترک میمانند |\n| `structuredClone(arr)` | عمیق | مستقل میشوند |\n\n### نمونه\n\n```javascript\nconst original = [{ id: 1 }, { id: 2 }];\nconst shallow = [...original];\nconst deep = structuredClone(original);\n\nshallow[0].id = 99; // original هم تغییر میکند\nconsole.log(original[0].id); // 99\n```\n\n> برای دادههایی که تابع یا DOM ندارند، `structuredClone` سادهترین انتخاب است.\n\n1. اگر فقط ترتیب را عوض میکنید، کپی سطحی کافی است.\n2. اگر اشیای داخلی را تغییر میدهید، کپی عمیق بگیرید." },
|
| 404 |
+
{ role: "user", content: "Show the same idea in Python." },
|
| 405 |
+
{ role: "assistant", content: "Python has the same distinction:\n\n- **Shallow copy** with `list.copy()` or `copy.copy()`\n- **Deep copy** with `copy.deepcopy()`\n\n```python\nimport copy\n\noriginal = [{\"id\": 1}, {\"id\": 2}]\nshallow = original.copy()\ndeep = copy.deepcopy(original)\n\nshallow[0][\"id\"] = 99\nprint(original[0][\"id\"]) # 99\n```" },
|
| 406 |
] }, { id: "demo2", title: "Who was Cyrus the Great?", updated: Date.now(), messages: [] }];
|
| 407 |
S.currentId = "demo";
|
| 408 |
}
|
| 409 |
|
| 410 |
// ---------------------------------------------------------------- boot
|
| 411 |
function boot() {
|
| 412 |
+
injectFonts();
|
| 413 |
document.body.appendChild(root); document.body.classList.add("diba-lock");
|
| 414 |
+
applyChrome(); toBottom(true);
|
| 415 |
+
Promise.all([loadScript(VENDOR.marked), loadScript(VENDOR.purify), loadScript(VENDOR.hljs)])
|
| 416 |
+
.then(() => { renderThread(); toBottom(true); })
|
| 417 |
+
.catch((e) => console.error("[diba] vendor load failed", e));
|
| 418 |
if (window.innerWidth > 820) el.input.focus();
|
| 419 |
const autoQ = qp.get("q"); // test hook: ?q=... sends one message on load
|
| 420 |
if (autoQ && location.hash !== "#demo") setTimeout(() => { newChat(); sendMessage(autoQ); }, 1200);
|
vendor/fonts/JetBrainsMono-Regular.woff2
ADDED
|
Binary file (92.2 kB). View file
|
|
|
vendor/fonts/JetBrainsMono-SemiBold.woff2
ADDED
|
Binary file (94.5 kB). View file
|
|
|
vendor/fonts/Vazirmatn-Variable.woff2
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:4e3fa217d38fdafc1fea4414ceb58ca5e662cf0ab5fa735a8c8c20e8b42cad92
|
| 3 |
+
size 111152
|
vendor/highlight.min.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
vendor/marked.min.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* marked v12.0.2 - a markdown parser
|
| 3 |
+
* Copyright (c) 2011-2024, Christopher Jeffrey. (MIT Licensed)
|
| 4 |
+
* https://github.com/markedjs/marked
|
| 5 |
+
*/
|
| 6 |
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).marked={})}(this,(function(e){"use strict";function t(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}function n(t){e.defaults=t}e.defaults={async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null};const s=/[&<>"']/,r=new RegExp(s.source,"g"),i=/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,l=new RegExp(i.source,"g"),o={"&":"&","<":"<",">":">",'"':""","'":"'"},a=e=>o[e];function c(e,t){if(t){if(s.test(e))return e.replace(r,a)}else if(i.test(e))return e.replace(l,a);return e}const h=/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/gi;function p(e){return e.replace(h,((e,t)=>"colon"===(t=t.toLowerCase())?":":"#"===t.charAt(0)?"x"===t.charAt(1)?String.fromCharCode(parseInt(t.substring(2),16)):String.fromCharCode(+t.substring(1)):""))}const u=/(^|[^\[])\^/g;function k(e,t){let n="string"==typeof e?e:e.source;t=t||"";const s={replace:(e,t)=>{let r="string"==typeof t?t:t.source;return r=r.replace(u,"$1"),n=n.replace(e,r),s},getRegex:()=>new RegExp(n,t)};return s}function g(e){try{e=encodeURI(e).replace(/%25/g,"%")}catch(e){return null}return e}const f={exec:()=>null};function d(e,t){const n=e.replace(/\|/g,((e,t,n)=>{let s=!1,r=t;for(;--r>=0&&"\\"===n[r];)s=!s;return s?"|":" |"})).split(/ \|/);let s=0;if(n[0].trim()||n.shift(),n.length>0&&!n[n.length-1].trim()&&n.pop(),t)if(n.length>t)n.splice(t);else for(;n.length<t;)n.push("");for(;s<n.length;s++)n[s]=n[s].trim().replace(/\\\|/g,"|");return n}function x(e,t,n){const s=e.length;if(0===s)return"";let r=0;for(;r<s;){const i=e.charAt(s-r-1);if(i!==t||n){if(i===t||!n)break;r++}else r++}return e.slice(0,s-r)}function b(e,t,n,s){const r=t.href,i=t.title?c(t.title):null,l=e[1].replace(/\\([\[\]])/g,"$1");if("!"!==e[0].charAt(0)){s.state.inLink=!0;const e={type:"link",raw:n,href:r,title:i,text:l,tokens:s.inlineTokens(l)};return s.state.inLink=!1,e}return{type:"image",raw:n,href:r,title:i,text:c(l)}}class w{options;rules;lexer;constructor(t){this.options=t||e.defaults}space(e){const t=this.rules.block.newline.exec(e);if(t&&t[0].length>0)return{type:"space",raw:t[0]}}code(e){const t=this.rules.block.code.exec(e);if(t){const e=t[0].replace(/^ {1,4}/gm,"");return{type:"code",raw:t[0],codeBlockStyle:"indented",text:this.options.pedantic?e:x(e,"\n")}}}fences(e){const t=this.rules.block.fences.exec(e);if(t){const e=t[0],n=function(e,t){const n=e.match(/^(\s+)(?:```)/);if(null===n)return t;const s=n[1];return t.split("\n").map((e=>{const t=e.match(/^\s+/);if(null===t)return e;const[n]=t;return n.length>=s.length?e.slice(s.length):e})).join("\n")}(e,t[3]||"");return{type:"code",raw:e,lang:t[2]?t[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):t[2],text:n}}}heading(e){const t=this.rules.block.heading.exec(e);if(t){let e=t[2].trim();if(/#$/.test(e)){const t=x(e,"#");this.options.pedantic?e=t.trim():t&&!/ $/.test(t)||(e=t.trim())}return{type:"heading",raw:t[0],depth:t[1].length,text:e,tokens:this.lexer.inline(e)}}}hr(e){const t=this.rules.block.hr.exec(e);if(t)return{type:"hr",raw:t[0]}}blockquote(e){const t=this.rules.block.blockquote.exec(e);if(t){let e=t[0].replace(/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,"\n $1");e=x(e.replace(/^ *>[ \t]?/gm,""),"\n");const n=this.lexer.state.top;this.lexer.state.top=!0;const s=this.lexer.blockTokens(e);return this.lexer.state.top=n,{type:"blockquote",raw:t[0],tokens:s,text:e}}}list(e){let t=this.rules.block.list.exec(e);if(t){let n=t[1].trim();const s=n.length>1,r={type:"list",raw:"",ordered:s,start:s?+n.slice(0,-1):"",loose:!1,items:[]};n=s?`\\d{1,9}\\${n.slice(-1)}`:`\\${n}`,this.options.pedantic&&(n=s?n:"[*+-]");const i=new RegExp(`^( {0,3}${n})((?:[\t ][^\\n]*)?(?:\\n|$))`);let l="",o="",a=!1;for(;e;){let n=!1;if(!(t=i.exec(e)))break;if(this.rules.block.hr.test(e))break;l=t[0],e=e.substring(l.length);let s=t[2].split("\n",1)[0].replace(/^\t+/,(e=>" ".repeat(3*e.length))),c=e.split("\n",1)[0],h=0;this.options.pedantic?(h=2,o=s.trimStart()):(h=t[2].search(/[^ ]/),h=h>4?1:h,o=s.slice(h),h+=t[1].length);let p=!1;if(!s&&/^ *$/.test(c)&&(l+=c+"\n",e=e.substring(c.length+1),n=!0),!n){const t=new RegExp(`^ {0,${Math.min(3,h-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ \t][^\\n]*)?(?:\\n|$))`),n=new RegExp(`^ {0,${Math.min(3,h-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),r=new RegExp(`^ {0,${Math.min(3,h-1)}}(?:\`\`\`|~~~)`),i=new RegExp(`^ {0,${Math.min(3,h-1)}}#`);for(;e;){const a=e.split("\n",1)[0];if(c=a,this.options.pedantic&&(c=c.replace(/^ {1,4}(?=( {4})*[^ ])/g," ")),r.test(c))break;if(i.test(c))break;if(t.test(c))break;if(n.test(e))break;if(c.search(/[^ ]/)>=h||!c.trim())o+="\n"+c.slice(h);else{if(p)break;if(s.search(/[^ ]/)>=4)break;if(r.test(s))break;if(i.test(s))break;if(n.test(s))break;o+="\n"+c}p||c.trim()||(p=!0),l+=a+"\n",e=e.substring(a.length+1),s=c.slice(h)}}r.loose||(a?r.loose=!0:/\n *\n *$/.test(l)&&(a=!0));let u,k=null;this.options.gfm&&(k=/^\[[ xX]\] /.exec(o),k&&(u="[ ] "!==k[0],o=o.replace(/^\[[ xX]\] +/,""))),r.items.push({type:"list_item",raw:l,task:!!k,checked:u,loose:!1,text:o,tokens:[]}),r.raw+=l}r.items[r.items.length-1].raw=l.trimEnd(),r.items[r.items.length-1].text=o.trimEnd(),r.raw=r.raw.trimEnd();for(let e=0;e<r.items.length;e++)if(this.lexer.state.top=!1,r.items[e].tokens=this.lexer.blockTokens(r.items[e].text,[]),!r.loose){const t=r.items[e].tokens.filter((e=>"space"===e.type)),n=t.length>0&&t.some((e=>/\n.*\n/.test(e.raw)));r.loose=n}if(r.loose)for(let e=0;e<r.items.length;e++)r.items[e].loose=!0;return r}}html(e){const t=this.rules.block.html.exec(e);if(t){return{type:"html",block:!0,raw:t[0],pre:"pre"===t[1]||"script"===t[1]||"style"===t[1],text:t[0]}}}def(e){const t=this.rules.block.def.exec(e);if(t){const e=t[1].toLowerCase().replace(/\s+/g," "),n=t[2]?t[2].replace(/^<(.*)>$/,"$1").replace(this.rules.inline.anyPunctuation,"$1"):"",s=t[3]?t[3].substring(1,t[3].length-1).replace(this.rules.inline.anyPunctuation,"$1"):t[3];return{type:"def",tag:e,raw:t[0],href:n,title:s}}}table(e){const t=this.rules.block.table.exec(e);if(!t)return;if(!/[:|]/.test(t[2]))return;const n=d(t[1]),s=t[2].replace(/^\||\| *$/g,"").split("|"),r=t[3]&&t[3].trim()?t[3].replace(/\n[ \t]*$/,"").split("\n"):[],i={type:"table",raw:t[0],header:[],align:[],rows:[]};if(n.length===s.length){for(const e of s)/^ *-+: *$/.test(e)?i.align.push("right"):/^ *:-+: *$/.test(e)?i.align.push("center"):/^ *:-+ *$/.test(e)?i.align.push("left"):i.align.push(null);for(const e of n)i.header.push({text:e,tokens:this.lexer.inline(e)});for(const e of r)i.rows.push(d(e,i.header.length).map((e=>({text:e,tokens:this.lexer.inline(e)}))));return i}}lheading(e){const t=this.rules.block.lheading.exec(e);if(t)return{type:"heading",raw:t[0],depth:"="===t[2].charAt(0)?1:2,text:t[1],tokens:this.lexer.inline(t[1])}}paragraph(e){const t=this.rules.block.paragraph.exec(e);if(t){const e="\n"===t[1].charAt(t[1].length-1)?t[1].slice(0,-1):t[1];return{type:"paragraph",raw:t[0],text:e,tokens:this.lexer.inline(e)}}}text(e){const t=this.rules.block.text.exec(e);if(t)return{type:"text",raw:t[0],text:t[0],tokens:this.lexer.inline(t[0])}}escape(e){const t=this.rules.inline.escape.exec(e);if(t)return{type:"escape",raw:t[0],text:c(t[1])}}tag(e){const t=this.rules.inline.tag.exec(e);if(t)return!this.lexer.state.inLink&&/^<a /i.test(t[0])?this.lexer.state.inLink=!0:this.lexer.state.inLink&&/^<\/a>/i.test(t[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&/^<(pre|code|kbd|script)(\s|>)/i.test(t[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&/^<\/(pre|code|kbd|script)(\s|>)/i.test(t[0])&&(this.lexer.state.inRawBlock=!1),{type:"html",raw:t[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:t[0]}}link(e){const t=this.rules.inline.link.exec(e);if(t){const e=t[2].trim();if(!this.options.pedantic&&/^</.test(e)){if(!/>$/.test(e))return;const t=x(e.slice(0,-1),"\\");if((e.length-t.length)%2==0)return}else{const e=function(e,t){if(-1===e.indexOf(t[1]))return-1;let n=0;for(let s=0;s<e.length;s++)if("\\"===e[s])s++;else if(e[s]===t[0])n++;else if(e[s]===t[1]&&(n--,n<0))return s;return-1}(t[2],"()");if(e>-1){const n=(0===t[0].indexOf("!")?5:4)+t[1].length+e;t[2]=t[2].substring(0,e),t[0]=t[0].substring(0,n).trim(),t[3]=""}}let n=t[2],s="";if(this.options.pedantic){const e=/^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(n);e&&(n=e[1],s=e[3])}else s=t[3]?t[3].slice(1,-1):"";return n=n.trim(),/^</.test(n)&&(n=this.options.pedantic&&!/>$/.test(e)?n.slice(1):n.slice(1,-1)),b(t,{href:n?n.replace(this.rules.inline.anyPunctuation,"$1"):n,title:s?s.replace(this.rules.inline.anyPunctuation,"$1"):s},t[0],this.lexer)}}reflink(e,t){let n;if((n=this.rules.inline.reflink.exec(e))||(n=this.rules.inline.nolink.exec(e))){const e=t[(n[2]||n[1]).replace(/\s+/g," ").toLowerCase()];if(!e){const e=n[0].charAt(0);return{type:"text",raw:e,text:e}}return b(n,e,n[0],this.lexer)}}emStrong(e,t,n=""){let s=this.rules.inline.emStrongLDelim.exec(e);if(!s)return;if(s[3]&&n.match(/[\p{L}\p{N}]/u))return;if(!(s[1]||s[2]||"")||!n||this.rules.inline.punctuation.exec(n)){const n=[...s[0]].length-1;let r,i,l=n,o=0;const a="*"===s[0][0]?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(a.lastIndex=0,t=t.slice(-1*e.length+n);null!=(s=a.exec(t));){if(r=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!r)continue;if(i=[...r].length,s[3]||s[4]){l+=i;continue}if((s[5]||s[6])&&n%3&&!((n+i)%3)){o+=i;continue}if(l-=i,l>0)continue;i=Math.min(i,i+l+o);const t=[...s[0]][0].length,a=e.slice(0,n+s.index+t+i);if(Math.min(n,i)%2){const e=a.slice(1,-1);return{type:"em",raw:a,text:e,tokens:this.lexer.inlineTokens(e)}}const c=a.slice(2,-2);return{type:"strong",raw:a,text:c,tokens:this.lexer.inlineTokens(c)}}}}codespan(e){const t=this.rules.inline.code.exec(e);if(t){let e=t[2].replace(/\n/g," ");const n=/[^ ]/.test(e),s=/^ /.test(e)&&/ $/.test(e);return n&&s&&(e=e.substring(1,e.length-1)),e=c(e,!0),{type:"codespan",raw:t[0],text:e}}}br(e){const t=this.rules.inline.br.exec(e);if(t)return{type:"br",raw:t[0]}}del(e){const t=this.rules.inline.del.exec(e);if(t)return{type:"del",raw:t[0],text:t[2],tokens:this.lexer.inlineTokens(t[2])}}autolink(e){const t=this.rules.inline.autolink.exec(e);if(t){let e,n;return"@"===t[2]?(e=c(t[1]),n="mailto:"+e):(e=c(t[1]),n=e),{type:"link",raw:t[0],text:e,href:n,tokens:[{type:"text",raw:e,text:e}]}}}url(e){let t;if(t=this.rules.inline.url.exec(e)){let e,n;if("@"===t[2])e=c(t[0]),n="mailto:"+e;else{let s;do{s=t[0],t[0]=this.rules.inline._backpedal.exec(t[0])?.[0]??""}while(s!==t[0]);e=c(t[0]),n="www."===t[1]?"http://"+t[0]:t[0]}return{type:"link",raw:t[0],text:e,href:n,tokens:[{type:"text",raw:e,text:e}]}}}inlineText(e){const t=this.rules.inline.text.exec(e);if(t){let e;return e=this.lexer.state.inRawBlock?t[0]:c(t[0]),{type:"text",raw:t[0],text:e}}}}const m=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,y=/(?:[*+-]|\d{1,9}[.)])/,$=k(/^(?!bull |blockCode|fences|blockquote|heading|html)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html))+?)\n {0,3}(=+|-+) *(?:\n+|$)/).replace(/bull/g,y).replace(/blockCode/g,/ {4}/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).getRegex(),z=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,T=/(?!\s*\])(?:\\.|[^\[\]\\])+/,R=k(/^ {0,3}\[(label)\]: *(?:\n *)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n *)?| *\n *)(title))? *(?:\n+|$)/).replace("label",T).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),_=k(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,y).getRegex(),A="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",S=/<!--(?:-?>|[\s\S]*?(?:-->|$))/,I=k("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|<![A-Z][\\s\\S]*?(?:>\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n *)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$))","i").replace("comment",S).replace("tag",A).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),E=k(z).replace("hr",m).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",A).getRegex(),q={blockquote:k(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",E).getRegex(),code:/^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,def:R,fences:/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,heading:/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,hr:m,html:I,lheading:$,list:_,newline:/^(?: *(?:\n|$))+/,paragraph:E,table:f,text:/^[^\n]+/},Z=k("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",m).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code"," {4}[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",A).getRegex(),L={...q,table:Z,paragraph:k(z).replace("hr",m).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",Z).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",A).getRegex()},P={...q,html:k("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:\"[^\"]*\"|'[^']*'|\\s[^'\"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",S).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:f,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:k(z).replace("hr",m).replace("heading"," *#{1,6} *[^\n]").replace("lheading",$).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},Q=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,v=/^( {2,}|\\)\n(?!\s*$)/,B="\\p{P}\\p{S}",C=k(/^((?![*_])[\spunctuation])/,"u").replace(/punctuation/g,B).getRegex(),M=k(/^(?:\*+(?:((?!\*)[punct])|[^\s*]))|^_+(?:((?!_)[punct])|([^\s_]))/,"u").replace(/punct/g,B).getRegex(),O=k("^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)[punct](\\*+)(?=[\\s]|$)|[^punct\\s](\\*+)(?!\\*)(?=[punct\\s]|$)|(?!\\*)[punct\\s](\\*+)(?=[^punct\\s])|[\\s](\\*+)(?!\\*)(?=[punct])|(?!\\*)[punct](\\*+)(?!\\*)(?=[punct])|[^punct\\s](\\*+)(?=[^punct\\s])","gu").replace(/punct/g,B).getRegex(),D=k("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)[punct](_+)(?=[\\s]|$)|[^punct\\s](_+)(?!_)(?=[punct\\s]|$)|(?!_)[punct\\s](_+)(?=[^punct\\s])|[\\s](_+)(?!_)(?=[punct])|(?!_)[punct](_+)(?!_)(?=[punct])","gu").replace(/punct/g,B).getRegex(),j=k(/\\([punct])/,"gu").replace(/punct/g,B).getRegex(),H=k(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),U=k(S).replace("(?:--\x3e|$)","--\x3e").getRegex(),X=k("^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment",U).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),F=/(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,N=k(/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/).replace("label",F).replace("href",/<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),G=k(/^!?\[(label)\]\[(ref)\]/).replace("label",F).replace("ref",T).getRegex(),J=k(/^!?\[(ref)\](?:\[\])?/).replace("ref",T).getRegex(),K={_backpedal:f,anyPunctuation:j,autolink:H,blockSkip:/\[[^[\]]*?\]\([^\(\)]*?\)|`[^`]*?`|<[^<>]*?>/g,br:v,code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,del:f,emStrongLDelim:M,emStrongRDelimAst:O,emStrongRDelimUnd:D,escape:Q,link:N,nolink:J,punctuation:C,reflink:G,reflinkSearch:k("reflink|nolink(?!\\()","g").replace("reflink",G).replace("nolink",J).getRegex(),tag:X,text:/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,url:f},V={...K,link:k(/^!?\[(label)\]\((.*?)\)/).replace("label",F).getRegex(),reflink:k(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",F).getRegex()},W={...K,escape:k(Q).replace("])","~|])").getRegex(),url:k(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,"i").replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,text:/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/},Y={...W,br:k(v).replace("{2,}","*").getRegex(),text:k(W.text).replace("\\b_","\\b_| {2,}\\n").replace(/\{2,\}/g,"*").getRegex()},ee={normal:q,gfm:L,pedantic:P},te={normal:K,gfm:W,breaks:Y,pedantic:V};class ne{tokens;options;state;tokenizer;inlineQueue;constructor(t){this.tokens=[],this.tokens.links=Object.create(null),this.options=t||e.defaults,this.options.tokenizer=this.options.tokenizer||new w,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:!1,inRawBlock:!1,top:!0};const n={block:ee.normal,inline:te.normal};this.options.pedantic?(n.block=ee.pedantic,n.inline=te.pedantic):this.options.gfm&&(n.block=ee.gfm,this.options.breaks?n.inline=te.breaks:n.inline=te.gfm),this.tokenizer.rules=n}static get rules(){return{block:ee,inline:te}}static lex(e,t){return new ne(t).lex(e)}static lexInline(e,t){return new ne(t).inlineTokens(e)}lex(e){e=e.replace(/\r\n|\r/g,"\n"),this.blockTokens(e,this.tokens);for(let e=0;e<this.inlineQueue.length;e++){const t=this.inlineQueue[e];this.inlineTokens(t.src,t.tokens)}return this.inlineQueue=[],this.tokens}blockTokens(e,t=[]){let n,s,r,i;for(e=this.options.pedantic?e.replace(/\t/g," ").replace(/^ +$/gm,""):e.replace(/^( *)(\t+)/gm,((e,t,n)=>t+" ".repeat(n.length)));e;)if(!(this.options.extensions&&this.options.extensions.block&&this.options.extensions.block.some((s=>!!(n=s.call({lexer:this},e,t))&&(e=e.substring(n.raw.length),t.push(n),!0)))))if(n=this.tokenizer.space(e))e=e.substring(n.raw.length),1===n.raw.length&&t.length>0?t[t.length-1].raw+="\n":t.push(n);else if(n=this.tokenizer.code(e))e=e.substring(n.raw.length),s=t[t.length-1],!s||"paragraph"!==s.type&&"text"!==s.type?t.push(n):(s.raw+="\n"+n.raw,s.text+="\n"+n.text,this.inlineQueue[this.inlineQueue.length-1].src=s.text);else if(n=this.tokenizer.fences(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.heading(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.hr(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.blockquote(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.list(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.html(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.def(e))e=e.substring(n.raw.length),s=t[t.length-1],!s||"paragraph"!==s.type&&"text"!==s.type?this.tokens.links[n.tag]||(this.tokens.links[n.tag]={href:n.href,title:n.title}):(s.raw+="\n"+n.raw,s.text+="\n"+n.raw,this.inlineQueue[this.inlineQueue.length-1].src=s.text);else if(n=this.tokenizer.table(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.lheading(e))e=e.substring(n.raw.length),t.push(n);else{if(r=e,this.options.extensions&&this.options.extensions.startBlock){let t=1/0;const n=e.slice(1);let s;this.options.extensions.startBlock.forEach((e=>{s=e.call({lexer:this},n),"number"==typeof s&&s>=0&&(t=Math.min(t,s))})),t<1/0&&t>=0&&(r=e.substring(0,t+1))}if(this.state.top&&(n=this.tokenizer.paragraph(r)))s=t[t.length-1],i&&"paragraph"===s.type?(s.raw+="\n"+n.raw,s.text+="\n"+n.text,this.inlineQueue.pop(),this.inlineQueue[this.inlineQueue.length-1].src=s.text):t.push(n),i=r.length!==e.length,e=e.substring(n.raw.length);else if(n=this.tokenizer.text(e))e=e.substring(n.raw.length),s=t[t.length-1],s&&"text"===s.type?(s.raw+="\n"+n.raw,s.text+="\n"+n.text,this.inlineQueue.pop(),this.inlineQueue[this.inlineQueue.length-1].src=s.text):t.push(n);else if(e){const t="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(t);break}throw new Error(t)}}return this.state.top=!0,t}inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}inlineTokens(e,t=[]){let n,s,r,i,l,o,a=e;if(this.tokens.links){const e=Object.keys(this.tokens.links);if(e.length>0)for(;null!=(i=this.tokenizer.rules.inline.reflinkSearch.exec(a));)e.includes(i[0].slice(i[0].lastIndexOf("[")+1,-1))&&(a=a.slice(0,i.index)+"["+"a".repeat(i[0].length-2)+"]"+a.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;null!=(i=this.tokenizer.rules.inline.blockSkip.exec(a));)a=a.slice(0,i.index)+"["+"a".repeat(i[0].length-2)+"]"+a.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);for(;null!=(i=this.tokenizer.rules.inline.anyPunctuation.exec(a));)a=a.slice(0,i.index)+"++"+a.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);for(;e;)if(l||(o=""),l=!1,!(this.options.extensions&&this.options.extensions.inline&&this.options.extensions.inline.some((s=>!!(n=s.call({lexer:this},e,t))&&(e=e.substring(n.raw.length),t.push(n),!0)))))if(n=this.tokenizer.escape(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.tag(e))e=e.substring(n.raw.length),s=t[t.length-1],s&&"text"===n.type&&"text"===s.type?(s.raw+=n.raw,s.text+=n.text):t.push(n);else if(n=this.tokenizer.link(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.reflink(e,this.tokens.links))e=e.substring(n.raw.length),s=t[t.length-1],s&&"text"===n.type&&"text"===s.type?(s.raw+=n.raw,s.text+=n.text):t.push(n);else if(n=this.tokenizer.emStrong(e,a,o))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.codespan(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.br(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.del(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.autolink(e))e=e.substring(n.raw.length),t.push(n);else if(this.state.inLink||!(n=this.tokenizer.url(e))){if(r=e,this.options.extensions&&this.options.extensions.startInline){let t=1/0;const n=e.slice(1);let s;this.options.extensions.startInline.forEach((e=>{s=e.call({lexer:this},n),"number"==typeof s&&s>=0&&(t=Math.min(t,s))})),t<1/0&&t>=0&&(r=e.substring(0,t+1))}if(n=this.tokenizer.inlineText(r))e=e.substring(n.raw.length),"_"!==n.raw.slice(-1)&&(o=n.raw.slice(-1)),l=!0,s=t[t.length-1],s&&"text"===s.type?(s.raw+=n.raw,s.text+=n.text):t.push(n);else if(e){const t="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(t);break}throw new Error(t)}}else e=e.substring(n.raw.length),t.push(n);return t}}class se{options;constructor(t){this.options=t||e.defaults}code(e,t,n){const s=(t||"").match(/^\S*/)?.[0];return e=e.replace(/\n$/,"")+"\n",s?'<pre><code class="language-'+c(s)+'">'+(n?e:c(e,!0))+"</code></pre>\n":"<pre><code>"+(n?e:c(e,!0))+"</code></pre>\n"}blockquote(e){return`<blockquote>\n${e}</blockquote>\n`}html(e,t){return e}heading(e,t,n){return`<h${t}>${e}</h${t}>\n`}hr(){return"<hr>\n"}list(e,t,n){const s=t?"ol":"ul";return"<"+s+(t&&1!==n?' start="'+n+'"':"")+">\n"+e+"</"+s+">\n"}listitem(e,t,n){return`<li>${e}</li>\n`}checkbox(e){return"<input "+(e?'checked="" ':"")+'disabled="" type="checkbox">'}paragraph(e){return`<p>${e}</p>\n`}table(e,t){return t&&(t=`<tbody>${t}</tbody>`),"<table>\n<thead>\n"+e+"</thead>\n"+t+"</table>\n"}tablerow(e){return`<tr>\n${e}</tr>\n`}tablecell(e,t){const n=t.header?"th":"td";return(t.align?`<${n} align="${t.align}">`:`<${n}>`)+e+`</${n}>\n`}strong(e){return`<strong>${e}</strong>`}em(e){return`<em>${e}</em>`}codespan(e){return`<code>${e}</code>`}br(){return"<br>"}del(e){return`<del>${e}</del>`}link(e,t,n){const s=g(e);if(null===s)return n;let r='<a href="'+(e=s)+'"';return t&&(r+=' title="'+t+'"'),r+=">"+n+"</a>",r}image(e,t,n){const s=g(e);if(null===s)return n;let r=`<img src="${e=s}" alt="${n}"`;return t&&(r+=` title="${t}"`),r+=">",r}text(e){return e}}class re{strong(e){return e}em(e){return e}codespan(e){return e}del(e){return e}html(e){return e}text(e){return e}link(e,t,n){return""+n}image(e,t,n){return""+n}br(){return""}}class ie{options;renderer;textRenderer;constructor(t){this.options=t||e.defaults,this.options.renderer=this.options.renderer||new se,this.renderer=this.options.renderer,this.renderer.options=this.options,this.textRenderer=new re}static parse(e,t){return new ie(t).parse(e)}static parseInline(e,t){return new ie(t).parseInline(e)}parse(e,t=!0){let n="";for(let s=0;s<e.length;s++){const r=e[s];if(this.options.extensions&&this.options.extensions.renderers&&this.options.extensions.renderers[r.type]){const e=r,t=this.options.extensions.renderers[e.type].call({parser:this},e);if(!1!==t||!["space","hr","heading","code","table","blockquote","list","html","paragraph","text"].includes(e.type)){n+=t||"";continue}}switch(r.type){case"space":continue;case"hr":n+=this.renderer.hr();continue;case"heading":{const e=r;n+=this.renderer.heading(this.parseInline(e.tokens),e.depth,p(this.parseInline(e.tokens,this.textRenderer)));continue}case"code":{const e=r;n+=this.renderer.code(e.text,e.lang,!!e.escaped);continue}case"table":{const e=r;let t="",s="";for(let t=0;t<e.header.length;t++)s+=this.renderer.tablecell(this.parseInline(e.header[t].tokens),{header:!0,align:e.align[t]});t+=this.renderer.tablerow(s);let i="";for(let t=0;t<e.rows.length;t++){const n=e.rows[t];s="";for(let t=0;t<n.length;t++)s+=this.renderer.tablecell(this.parseInline(n[t].tokens),{header:!1,align:e.align[t]});i+=this.renderer.tablerow(s)}n+=this.renderer.table(t,i);continue}case"blockquote":{const e=r,t=this.parse(e.tokens);n+=this.renderer.blockquote(t);continue}case"list":{const e=r,t=e.ordered,s=e.start,i=e.loose;let l="";for(let t=0;t<e.items.length;t++){const n=e.items[t],s=n.checked,r=n.task;let o="";if(n.task){const e=this.renderer.checkbox(!!s);i?n.tokens.length>0&&"paragraph"===n.tokens[0].type?(n.tokens[0].text=e+" "+n.tokens[0].text,n.tokens[0].tokens&&n.tokens[0].tokens.length>0&&"text"===n.tokens[0].tokens[0].type&&(n.tokens[0].tokens[0].text=e+" "+n.tokens[0].tokens[0].text)):n.tokens.unshift({type:"text",text:e+" "}):o+=e+" "}o+=this.parse(n.tokens,i),l+=this.renderer.listitem(o,r,!!s)}n+=this.renderer.list(l,t,s);continue}case"html":{const e=r;n+=this.renderer.html(e.text,e.block);continue}case"paragraph":{const e=r;n+=this.renderer.paragraph(this.parseInline(e.tokens));continue}case"text":{let i=r,l=i.tokens?this.parseInline(i.tokens):i.text;for(;s+1<e.length&&"text"===e[s+1].type;)i=e[++s],l+="\n"+(i.tokens?this.parseInline(i.tokens):i.text);n+=t?this.renderer.paragraph(l):l;continue}default:{const e='Token with "'+r.type+'" type was not found.';if(this.options.silent)return console.error(e),"";throw new Error(e)}}}return n}parseInline(e,t){t=t||this.renderer;let n="";for(let s=0;s<e.length;s++){const r=e[s];if(this.options.extensions&&this.options.extensions.renderers&&this.options.extensions.renderers[r.type]){const e=this.options.extensions.renderers[r.type].call({parser:this},r);if(!1!==e||!["escape","html","link","image","strong","em","codespan","br","del","text"].includes(r.type)){n+=e||"";continue}}switch(r.type){case"escape":{const e=r;n+=t.text(e.text);break}case"html":{const e=r;n+=t.html(e.text);break}case"link":{const e=r;n+=t.link(e.href,e.title,this.parseInline(e.tokens,t));break}case"image":{const e=r;n+=t.image(e.href,e.title,e.text);break}case"strong":{const e=r;n+=t.strong(this.parseInline(e.tokens,t));break}case"em":{const e=r;n+=t.em(this.parseInline(e.tokens,t));break}case"codespan":{const e=r;n+=t.codespan(e.text);break}case"br":n+=t.br();break;case"del":{const e=r;n+=t.del(this.parseInline(e.tokens,t));break}case"text":{const e=r;n+=t.text(e.text);break}default:{const e='Token with "'+r.type+'" type was not found.';if(this.options.silent)return console.error(e),"";throw new Error(e)}}}return n}}class le{options;constructor(t){this.options=t||e.defaults}static passThroughHooks=new Set(["preprocess","postprocess","processAllTokens"]);preprocess(e){return e}postprocess(e){return e}processAllTokens(e){return e}}class oe{defaults={async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null};options=this.setOptions;parse=this.#e(ne.lex,ie.parse);parseInline=this.#e(ne.lexInline,ie.parseInline);Parser=ie;Renderer=se;TextRenderer=re;Lexer=ne;Tokenizer=w;Hooks=le;constructor(...e){this.use(...e)}walkTokens(e,t){let n=[];for(const s of e)switch(n=n.concat(t.call(this,s)),s.type){case"table":{const e=s;for(const s of e.header)n=n.concat(this.walkTokens(s.tokens,t));for(const s of e.rows)for(const e of s)n=n.concat(this.walkTokens(e.tokens,t));break}case"list":{const e=s;n=n.concat(this.walkTokens(e.items,t));break}default:{const e=s;this.defaults.extensions?.childTokens?.[e.type]?this.defaults.extensions.childTokens[e.type].forEach((s=>{const r=e[s].flat(1/0);n=n.concat(this.walkTokens(r,t))})):e.tokens&&(n=n.concat(this.walkTokens(e.tokens,t)))}}return n}use(...e){const t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach((e=>{const n={...e};if(n.async=this.defaults.async||n.async||!1,e.extensions&&(e.extensions.forEach((e=>{if(!e.name)throw new Error("extension name required");if("renderer"in e){const n=t.renderers[e.name];t.renderers[e.name]=n?function(...t){let s=e.renderer.apply(this,t);return!1===s&&(s=n.apply(this,t)),s}:e.renderer}if("tokenizer"in e){if(!e.level||"block"!==e.level&&"inline"!==e.level)throw new Error("extension level must be 'block' or 'inline'");const n=t[e.level];n?n.unshift(e.tokenizer):t[e.level]=[e.tokenizer],e.start&&("block"===e.level?t.startBlock?t.startBlock.push(e.start):t.startBlock=[e.start]:"inline"===e.level&&(t.startInline?t.startInline.push(e.start):t.startInline=[e.start]))}"childTokens"in e&&e.childTokens&&(t.childTokens[e.name]=e.childTokens)})),n.extensions=t),e.renderer){const t=this.defaults.renderer||new se(this.defaults);for(const n in e.renderer){if(!(n in t))throw new Error(`renderer '${n}' does not exist`);if("options"===n)continue;const s=n,r=e.renderer[s],i=t[s];t[s]=(...e)=>{let n=r.apply(t,e);return!1===n&&(n=i.apply(t,e)),n||""}}n.renderer=t}if(e.tokenizer){const t=this.defaults.tokenizer||new w(this.defaults);for(const n in e.tokenizer){if(!(n in t))throw new Error(`tokenizer '${n}' does not exist`);if(["options","rules","lexer"].includes(n))continue;const s=n,r=e.tokenizer[s],i=t[s];t[s]=(...e)=>{let n=r.apply(t,e);return!1===n&&(n=i.apply(t,e)),n}}n.tokenizer=t}if(e.hooks){const t=this.defaults.hooks||new le;for(const n in e.hooks){if(!(n in t))throw new Error(`hook '${n}' does not exist`);if("options"===n)continue;const s=n,r=e.hooks[s],i=t[s];le.passThroughHooks.has(n)?t[s]=e=>{if(this.defaults.async)return Promise.resolve(r.call(t,e)).then((e=>i.call(t,e)));const n=r.call(t,e);return i.call(t,n)}:t[s]=(...e)=>{let n=r.apply(t,e);return!1===n&&(n=i.apply(t,e)),n}}n.hooks=t}if(e.walkTokens){const t=this.defaults.walkTokens,s=e.walkTokens;n.walkTokens=function(e){let n=[];return n.push(s.call(this,e)),t&&(n=n.concat(t.call(this,e))),n}}this.defaults={...this.defaults,...n}})),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return ne.lex(e,t??this.defaults)}parser(e,t){return ie.parse(e,t??this.defaults)}#e(e,t){return(n,s)=>{const r={...s},i={...this.defaults,...r};!0===this.defaults.async&&!1===r.async&&(i.silent||console.warn("marked(): The async option was set to true by an extension. The async: false option sent to parse will be ignored."),i.async=!0);const l=this.#t(!!i.silent,!!i.async);if(null==n)return l(new Error("marked(): input parameter is undefined or null"));if("string"!=typeof n)return l(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(n)+", string expected"));if(i.hooks&&(i.hooks.options=i),i.async)return Promise.resolve(i.hooks?i.hooks.preprocess(n):n).then((t=>e(t,i))).then((e=>i.hooks?i.hooks.processAllTokens(e):e)).then((e=>i.walkTokens?Promise.all(this.walkTokens(e,i.walkTokens)).then((()=>e)):e)).then((e=>t(e,i))).then((e=>i.hooks?i.hooks.postprocess(e):e)).catch(l);try{i.hooks&&(n=i.hooks.preprocess(n));let s=e(n,i);i.hooks&&(s=i.hooks.processAllTokens(s)),i.walkTokens&&this.walkTokens(s,i.walkTokens);let r=t(s,i);return i.hooks&&(r=i.hooks.postprocess(r)),r}catch(e){return l(e)}}}#t(e,t){return n=>{if(n.message+="\nPlease report this to https://github.com/markedjs/marked.",e){const e="<p>An error occurred:</p><pre>"+c(n.message+"",!0)+"</pre>";return t?Promise.resolve(e):e}if(t)return Promise.reject(n);throw n}}}const ae=new oe;function ce(e,t){return ae.parse(e,t)}ce.options=ce.setOptions=function(e){return ae.setOptions(e),ce.defaults=ae.defaults,n(ce.defaults),ce},ce.getDefaults=t,ce.defaults=e.defaults,ce.use=function(...e){return ae.use(...e),ce.defaults=ae.defaults,n(ce.defaults),ce},ce.walkTokens=function(e,t){return ae.walkTokens(e,t)},ce.parseInline=ae.parseInline,ce.Parser=ie,ce.parser=ie.parse,ce.Renderer=se,ce.TextRenderer=re,ce.Lexer=ne,ce.lexer=ne.lex,ce.Tokenizer=w,ce.Hooks=le,ce.parse=ce;const he=ce.options,pe=ce.setOptions,ue=ce.use,ke=ce.walkTokens,ge=ce.parseInline,fe=ce,de=ie.parse,xe=ne.lex;e.Hooks=le,e.Lexer=ne,e.Marked=oe,e.Parser=ie,e.Renderer=se,e.TextRenderer=re,e.Tokenizer=w,e.getDefaults=t,e.lexer=xe,e.marked=ce,e.options=he,e.parse=fe,e.parseInline=ge,e.parser=de,e.setOptions=pe,e.use=ue,e.walkTokens=ke}));
|
vendor/purify.min.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*! @license DOMPurify 3.1.6 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.1.6/LICENSE */
|
| 2 |
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).DOMPurify=t()}(this,(function(){"use strict";const{entries:e,setPrototypeOf:t,isFrozen:n,getPrototypeOf:o,getOwnPropertyDescriptor:r}=Object;let{freeze:i,seal:a,create:l}=Object,{apply:c,construct:s}="undefined"!=typeof Reflect&&Reflect;i||(i=function(e){return e}),a||(a=function(e){return e}),c||(c=function(e,t,n){return e.apply(t,n)}),s||(s=function(e,t){return new e(...t)});const u=b(Array.prototype.forEach),m=b(Array.prototype.pop),p=b(Array.prototype.push),f=b(String.prototype.toLowerCase),d=b(String.prototype.toString),h=b(String.prototype.match),g=b(String.prototype.replace),T=b(String.prototype.indexOf),y=b(String.prototype.trim),E=b(Object.prototype.hasOwnProperty),_=b(RegExp.prototype.test),A=(N=TypeError,function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return s(N,t)});var N;function b(e){return function(t){for(var n=arguments.length,o=new Array(n>1?n-1:0),r=1;r<n;r++)o[r-1]=arguments[r];return c(e,t,o)}}function S(e,o){let r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:f;t&&t(e,null);let i=o.length;for(;i--;){let t=o[i];if("string"==typeof t){const e=r(t);e!==t&&(n(o)||(o[i]=e),t=e)}e[t]=!0}return e}function R(e){for(let t=0;t<e.length;t++){E(e,t)||(e[t]=null)}return e}function w(t){const n=l(null);for(const[o,r]of e(t)){E(t,o)&&(Array.isArray(r)?n[o]=R(r):r&&"object"==typeof r&&r.constructor===Object?n[o]=w(r):n[o]=r)}return n}function C(e,t){for(;null!==e;){const n=r(e,t);if(n){if(n.get)return b(n.get);if("function"==typeof n.value)return b(n.value)}e=o(e)}return function(){return null}}const L=i(["a","abbr","acronym","address","area","article","aside","audio","b","bdi","bdo","big","blink","blockquote","body","br","button","canvas","caption","center","cite","code","col","colgroup","content","data","datalist","dd","decorator","del","details","dfn","dialog","dir","div","dl","dt","element","em","fieldset","figcaption","figure","font","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","img","input","ins","kbd","label","legend","li","main","map","mark","marquee","menu","menuitem","meter","nav","nobr","ol","optgroup","option","output","p","picture","pre","progress","q","rp","rt","ruby","s","samp","section","select","shadow","small","source","spacer","span","strike","strong","style","sub","summary","sup","table","tbody","td","template","textarea","tfoot","th","thead","time","tr","track","tt","u","ul","var","video","wbr"]),D=i(["svg","a","altglyph","altglyphdef","altglyphitem","animatecolor","animatemotion","animatetransform","circle","clippath","defs","desc","ellipse","filter","font","g","glyph","glyphref","hkern","image","line","lineargradient","marker","mask","metadata","mpath","path","pattern","polygon","polyline","radialgradient","rect","stop","style","switch","symbol","text","textpath","title","tref","tspan","view","vkern"]),v=i(["feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feDropShadow","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence"]),O=i(["animate","color-profile","cursor","discard","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","foreignobject","hatch","hatchpath","mesh","meshgradient","meshpatch","meshrow","missing-glyph","script","set","solidcolor","unknown","use"]),x=i(["math","menclose","merror","mfenced","mfrac","mglyph","mi","mlabeledtr","mmultiscripts","mn","mo","mover","mpadded","mphantom","mroot","mrow","ms","mspace","msqrt","mstyle","msub","msup","msubsup","mtable","mtd","mtext","mtr","munder","munderover","mprescripts"]),k=i(["maction","maligngroup","malignmark","mlongdiv","mscarries","mscarry","msgroup","mstack","msline","msrow","semantics","annotation","annotation-xml","mprescripts","none"]),M=i(["#text"]),I=i(["accept","action","align","alt","autocapitalize","autocomplete","autopictureinpicture","autoplay","background","bgcolor","border","capture","cellpadding","cellspacing","checked","cite","class","clear","color","cols","colspan","controls","controlslist","coords","crossorigin","datetime","decoding","default","dir","disabled","disablepictureinpicture","disableremoteplayback","download","draggable","enctype","enterkeyhint","face","for","headers","height","hidden","high","href","hreflang","id","inputmode","integrity","ismap","kind","label","lang","list","loading","loop","low","max","maxlength","media","method","min","minlength","multiple","muted","name","nonce","noshade","novalidate","nowrap","open","optimum","pattern","placeholder","playsinline","popover","popovertarget","popovertargetaction","poster","preload","pubdate","radiogroup","readonly","rel","required","rev","reversed","role","rows","rowspan","spellcheck","scope","selected","shape","size","sizes","span","srclang","start","src","srcset","step","style","summary","tabindex","title","translate","type","usemap","valign","value","width","wrap","xmlns","slot"]),U=i(["accent-height","accumulate","additive","alignment-baseline","ascent","attributename","attributetype","azimuth","basefrequency","baseline-shift","begin","bias","by","class","clip","clippathunits","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","cx","cy","d","dx","dy","diffuseconstant","direction","display","divisor","dur","edgemode","elevation","end","fill","fill-opacity","fill-rule","filter","filterunits","flood-color","flood-opacity","font-family","font-size","font-size-adjust","font-stretch","font-style","font-variant","font-weight","fx","fy","g1","g2","glyph-name","glyphref","gradientunits","gradienttransform","height","href","id","image-rendering","in","in2","k","k1","k2","k3","k4","kerning","keypoints","keysplines","keytimes","lang","lengthadjust","letter-spacing","kernelmatrix","kernelunitlength","lighting-color","local","marker-end","marker-mid","marker-start","markerheight","markerunits","markerwidth","maskcontentunits","maskunits","max","mask","media","method","mode","min","name","numoctaves","offset","operator","opacity","order","orient","orientation","origin","overflow","paint-order","path","pathlength","patterncontentunits","patterntransform","patternunits","points","preservealpha","preserveaspectratio","primitiveunits","r","rx","ry","radius","refx","refy","repeatcount","repeatdur","restart","result","rotate","scale","seed","shape-rendering","specularconstant","specularexponent","spreadmethod","startoffset","stddeviation","stitchtiles","stop-color","stop-opacity","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke","stroke-width","style","surfacescale","systemlanguage","tabindex","targetx","targety","transform","transform-origin","text-anchor","text-decoration","text-rendering","textlength","type","u1","u2","unicode","values","viewbox","visibility","version","vert-adv-y","vert-origin-x","vert-origin-y","width","word-spacing","wrap","writing-mode","xchannelselector","ychannelselector","x","x1","x2","xmlns","y","y1","y2","z","zoomandpan"]),P=i(["accent","accentunder","align","bevelled","close","columnsalign","columnlines","columnspan","denomalign","depth","dir","display","displaystyle","encoding","fence","frame","height","href","id","largeop","length","linethickness","lspace","lquote","mathbackground","mathcolor","mathsize","mathvariant","maxsize","minsize","movablelimits","notation","numalign","open","rowalign","rowlines","rowspacing","rowspan","rspace","rquote","scriptlevel","scriptminsize","scriptsizemultiplier","selection","separator","separators","stretchy","subscriptshift","supscriptshift","symmetric","voffset","width","xmlns"]),F=i(["xlink:href","xml:id","xlink:title","xml:space","xmlns:xlink"]),H=a(/\{\{[\w\W]*|[\w\W]*\}\}/gm),z=a(/<%[\w\W]*|[\w\W]*%>/gm),B=a(/\${[\w\W]*}/gm),W=a(/^data-[\-\w.\u00B7-\uFFFF]/),G=a(/^aria-[\-\w]+$/),Y=a(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),j=a(/^(?:\w+script|data):/i),X=a(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),q=a(/^html$/i),$=a(/^[a-z][.\w]*(-[.\w]+)+$/i);var K=Object.freeze({__proto__:null,MUSTACHE_EXPR:H,ERB_EXPR:z,TMPLIT_EXPR:B,DATA_ATTR:W,ARIA_ATTR:G,IS_ALLOWED_URI:Y,IS_SCRIPT_OR_DATA:j,ATTR_WHITESPACE:X,DOCTYPE_NAME:q,CUSTOM_ELEMENT:$});const V=1,Z=3,J=7,Q=8,ee=9,te=function(){return"undefined"==typeof window?null:window};var ne=function t(){let n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:te();const o=e=>t(e);if(o.version="3.1.6",o.removed=[],!n||!n.document||n.document.nodeType!==ee)return o.isSupported=!1,o;let{document:r}=n;const a=r,c=a.currentScript,{DocumentFragment:s,HTMLTemplateElement:N,Node:b,Element:R,NodeFilter:H,NamedNodeMap:z=n.NamedNodeMap||n.MozNamedAttrMap,HTMLFormElement:B,DOMParser:W,trustedTypes:G}=n,j=R.prototype,X=C(j,"cloneNode"),$=C(j,"remove"),ne=C(j,"nextSibling"),oe=C(j,"childNodes"),re=C(j,"parentNode");if("function"==typeof N){const e=r.createElement("template");e.content&&e.content.ownerDocument&&(r=e.content.ownerDocument)}let ie,ae="";const{implementation:le,createNodeIterator:ce,createDocumentFragment:se,getElementsByTagName:ue}=r,{importNode:me}=a;let pe={};o.isSupported="function"==typeof e&&"function"==typeof re&&le&&void 0!==le.createHTMLDocument;const{MUSTACHE_EXPR:fe,ERB_EXPR:de,TMPLIT_EXPR:he,DATA_ATTR:ge,ARIA_ATTR:Te,IS_SCRIPT_OR_DATA:ye,ATTR_WHITESPACE:Ee,CUSTOM_ELEMENT:_e}=K;let{IS_ALLOWED_URI:Ae}=K,Ne=null;const be=S({},[...L,...D,...v,...x,...M]);let Se=null;const Re=S({},[...I,...U,...P,...F]);let we=Object.seal(l(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),Ce=null,Le=null,De=!0,ve=!0,Oe=!1,xe=!0,ke=!1,Me=!0,Ie=!1,Ue=!1,Pe=!1,Fe=!1,He=!1,ze=!1,Be=!0,We=!1,Ge=!0,Ye=!1,je={},Xe=null;const qe=S({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let $e=null;const Ke=S({},["audio","video","img","source","image","track"]);let Ve=null;const Ze=S({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),Je="http://www.w3.org/1998/Math/MathML",Qe="http://www.w3.org/2000/svg",et="http://www.w3.org/1999/xhtml";let tt=et,nt=!1,ot=null;const rt=S({},[Je,Qe,et],d);let it=null;const at=["application/xhtml+xml","text/html"];let lt=null,ct=null;const st=r.createElement("form"),ut=function(e){return e instanceof RegExp||e instanceof Function},mt=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(!ct||ct!==e){if(e&&"object"==typeof e||(e={}),e=w(e),it=-1===at.indexOf(e.PARSER_MEDIA_TYPE)?"text/html":e.PARSER_MEDIA_TYPE,lt="application/xhtml+xml"===it?d:f,Ne=E(e,"ALLOWED_TAGS")?S({},e.ALLOWED_TAGS,lt):be,Se=E(e,"ALLOWED_ATTR")?S({},e.ALLOWED_ATTR,lt):Re,ot=E(e,"ALLOWED_NAMESPACES")?S({},e.ALLOWED_NAMESPACES,d):rt,Ve=E(e,"ADD_URI_SAFE_ATTR")?S(w(Ze),e.ADD_URI_SAFE_ATTR,lt):Ze,$e=E(e,"ADD_DATA_URI_TAGS")?S(w(Ke),e.ADD_DATA_URI_TAGS,lt):Ke,Xe=E(e,"FORBID_CONTENTS")?S({},e.FORBID_CONTENTS,lt):qe,Ce=E(e,"FORBID_TAGS")?S({},e.FORBID_TAGS,lt):{},Le=E(e,"FORBID_ATTR")?S({},e.FORBID_ATTR,lt):{},je=!!E(e,"USE_PROFILES")&&e.USE_PROFILES,De=!1!==e.ALLOW_ARIA_ATTR,ve=!1!==e.ALLOW_DATA_ATTR,Oe=e.ALLOW_UNKNOWN_PROTOCOLS||!1,xe=!1!==e.ALLOW_SELF_CLOSE_IN_ATTR,ke=e.SAFE_FOR_TEMPLATES||!1,Me=!1!==e.SAFE_FOR_XML,Ie=e.WHOLE_DOCUMENT||!1,Fe=e.RETURN_DOM||!1,He=e.RETURN_DOM_FRAGMENT||!1,ze=e.RETURN_TRUSTED_TYPE||!1,Pe=e.FORCE_BODY||!1,Be=!1!==e.SANITIZE_DOM,We=e.SANITIZE_NAMED_PROPS||!1,Ge=!1!==e.KEEP_CONTENT,Ye=e.IN_PLACE||!1,Ae=e.ALLOWED_URI_REGEXP||Y,tt=e.NAMESPACE||et,we=e.CUSTOM_ELEMENT_HANDLING||{},e.CUSTOM_ELEMENT_HANDLING&&ut(e.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(we.tagNameCheck=e.CUSTOM_ELEMENT_HANDLING.tagNameCheck),e.CUSTOM_ELEMENT_HANDLING&&ut(e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(we.attributeNameCheck=e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),e.CUSTOM_ELEMENT_HANDLING&&"boolean"==typeof e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements&&(we.allowCustomizedBuiltInElements=e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),ke&&(ve=!1),He&&(Fe=!0),je&&(Ne=S({},M),Se=[],!0===je.html&&(S(Ne,L),S(Se,I)),!0===je.svg&&(S(Ne,D),S(Se,U),S(Se,F)),!0===je.svgFilters&&(S(Ne,v),S(Se,U),S(Se,F)),!0===je.mathMl&&(S(Ne,x),S(Se,P),S(Se,F))),e.ADD_TAGS&&(Ne===be&&(Ne=w(Ne)),S(Ne,e.ADD_TAGS,lt)),e.ADD_ATTR&&(Se===Re&&(Se=w(Se)),S(Se,e.ADD_ATTR,lt)),e.ADD_URI_SAFE_ATTR&&S(Ve,e.ADD_URI_SAFE_ATTR,lt),e.FORBID_CONTENTS&&(Xe===qe&&(Xe=w(Xe)),S(Xe,e.FORBID_CONTENTS,lt)),Ge&&(Ne["#text"]=!0),Ie&&S(Ne,["html","head","body"]),Ne.table&&(S(Ne,["tbody"]),delete Ce.tbody),e.TRUSTED_TYPES_POLICY){if("function"!=typeof e.TRUSTED_TYPES_POLICY.createHTML)throw A('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if("function"!=typeof e.TRUSTED_TYPES_POLICY.createScriptURL)throw A('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');ie=e.TRUSTED_TYPES_POLICY,ae=ie.createHTML("")}else void 0===ie&&(ie=function(e,t){if("object"!=typeof e||"function"!=typeof e.createPolicy)return null;let n=null;const o="data-tt-policy-suffix";t&&t.hasAttribute(o)&&(n=t.getAttribute(o));const r="dompurify"+(n?"#"+n:"");try{return e.createPolicy(r,{createHTML:e=>e,createScriptURL:e=>e})}catch(e){return console.warn("TrustedTypes policy "+r+" could not be created."),null}}(G,c)),null!==ie&&"string"==typeof ae&&(ae=ie.createHTML(""));i&&i(e),ct=e}},pt=S({},["mi","mo","mn","ms","mtext"]),ft=S({},["foreignobject","annotation-xml"]),dt=S({},["title","style","font","a","script"]),ht=S({},[...D,...v,...O]),gt=S({},[...x,...k]),Tt=function(e){p(o.removed,{element:e});try{re(e).removeChild(e)}catch(t){$(e)}},yt=function(e,t){try{p(o.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){p(o.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e&&!Se[e])if(Fe||He)try{Tt(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},Et=function(e){let t=null,n=null;if(Pe)e="<remove></remove>"+e;else{const t=h(e,/^[\r\n\t ]+/);n=t&&t[0]}"application/xhtml+xml"===it&&tt===et&&(e='<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>'+e+"</body></html>");const o=ie?ie.createHTML(e):e;if(tt===et)try{t=(new W).parseFromString(o,it)}catch(e){}if(!t||!t.documentElement){t=le.createDocument(tt,"template",null);try{t.documentElement.innerHTML=nt?ae:o}catch(e){}}const i=t.body||t.documentElement;return e&&n&&i.insertBefore(r.createTextNode(n),i.childNodes[0]||null),tt===et?ue.call(t,Ie?"html":"body")[0]:Ie?t.documentElement:i},_t=function(e){return ce.call(e.ownerDocument||e,e,H.SHOW_ELEMENT|H.SHOW_COMMENT|H.SHOW_TEXT|H.SHOW_PROCESSING_INSTRUCTION|H.SHOW_CDATA_SECTION,null)},At=function(e){return e instanceof B&&("string"!=typeof e.nodeName||"string"!=typeof e.textContent||"function"!=typeof e.removeChild||!(e.attributes instanceof z)||"function"!=typeof e.removeAttribute||"function"!=typeof e.setAttribute||"string"!=typeof e.namespaceURI||"function"!=typeof e.insertBefore||"function"!=typeof e.hasChildNodes)},Nt=function(e){return"function"==typeof b&&e instanceof b},bt=function(e,t,n){pe[e]&&u(pe[e],(e=>{e.call(o,t,n,ct)}))},St=function(e){let t=null;if(bt("beforeSanitizeElements",e,null),At(e))return Tt(e),!0;const n=lt(e.nodeName);if(bt("uponSanitizeElement",e,{tagName:n,allowedTags:Ne}),e.hasChildNodes()&&!Nt(e.firstElementChild)&&_(/<[/\w]/g,e.innerHTML)&&_(/<[/\w]/g,e.textContent))return Tt(e),!0;if(e.nodeType===J)return Tt(e),!0;if(Me&&e.nodeType===Q&&_(/<[/\w]/g,e.data))return Tt(e),!0;if(!Ne[n]||Ce[n]){if(!Ce[n]&&wt(n)){if(we.tagNameCheck instanceof RegExp&&_(we.tagNameCheck,n))return!1;if(we.tagNameCheck instanceof Function&&we.tagNameCheck(n))return!1}if(Ge&&!Xe[n]){const t=re(e)||e.parentNode,n=oe(e)||e.childNodes;if(n&&t){for(let o=n.length-1;o>=0;--o){const r=X(n[o],!0);r.__removalCount=(e.__removalCount||0)+1,t.insertBefore(r,ne(e))}}}return Tt(e),!0}return e instanceof R&&!function(e){let t=re(e);t&&t.tagName||(t={namespaceURI:tt,tagName:"template"});const n=f(e.tagName),o=f(t.tagName);return!!ot[e.namespaceURI]&&(e.namespaceURI===Qe?t.namespaceURI===et?"svg"===n:t.namespaceURI===Je?"svg"===n&&("annotation-xml"===o||pt[o]):Boolean(ht[n]):e.namespaceURI===Je?t.namespaceURI===et?"math"===n:t.namespaceURI===Qe?"math"===n&&ft[o]:Boolean(gt[n]):e.namespaceURI===et?!(t.namespaceURI===Qe&&!ft[o])&&!(t.namespaceURI===Je&&!pt[o])&&!gt[n]&&(dt[n]||!ht[n]):!("application/xhtml+xml"!==it||!ot[e.namespaceURI]))}(e)?(Tt(e),!0):"noscript"!==n&&"noembed"!==n&&"noframes"!==n||!_(/<\/no(script|embed|frames)/i,e.innerHTML)?(ke&&e.nodeType===Z&&(t=e.textContent,u([fe,de,he],(e=>{t=g(t,e," ")})),e.textContent!==t&&(p(o.removed,{element:e.cloneNode()}),e.textContent=t)),bt("afterSanitizeElements",e,null),!1):(Tt(e),!0)},Rt=function(e,t,n){if(Be&&("id"===t||"name"===t)&&(n in r||n in st))return!1;if(ve&&!Le[t]&&_(ge,t));else if(De&&_(Te,t));else if(!Se[t]||Le[t]){if(!(wt(e)&&(we.tagNameCheck instanceof RegExp&&_(we.tagNameCheck,e)||we.tagNameCheck instanceof Function&&we.tagNameCheck(e))&&(we.attributeNameCheck instanceof RegExp&&_(we.attributeNameCheck,t)||we.attributeNameCheck instanceof Function&&we.attributeNameCheck(t))||"is"===t&&we.allowCustomizedBuiltInElements&&(we.tagNameCheck instanceof RegExp&&_(we.tagNameCheck,n)||we.tagNameCheck instanceof Function&&we.tagNameCheck(n))))return!1}else if(Ve[t]);else if(_(Ae,g(n,Ee,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==T(n,"data:")||!$e[e]){if(Oe&&!_(ye,g(n,Ee,"")));else if(n)return!1}else;return!0},wt=function(e){return"annotation-xml"!==e&&h(e,_e)},Ct=function(e){bt("beforeSanitizeAttributes",e,null);const{attributes:t}=e;if(!t)return;const n={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:Se};let r=t.length;for(;r--;){const i=t[r],{name:a,namespaceURI:l,value:c}=i,s=lt(a);let p="value"===a?c:y(c);if(n.attrName=s,n.attrValue=p,n.keepAttr=!0,n.forceKeepAttr=void 0,bt("uponSanitizeAttribute",e,n),p=n.attrValue,Me&&_(/((--!?|])>)|<\/(style|title)/i,p)){yt(a,e);continue}if(n.forceKeepAttr)continue;if(yt(a,e),!n.keepAttr)continue;if(!xe&&_(/\/>/i,p)){yt(a,e);continue}ke&&u([fe,de,he],(e=>{p=g(p,e," ")}));const f=lt(e.nodeName);if(Rt(f,s,p)){if(!We||"id"!==s&&"name"!==s||(yt(a,e),p="user-content-"+p),ie&&"object"==typeof G&&"function"==typeof G.getAttributeType)if(l);else switch(G.getAttributeType(f,s)){case"TrustedHTML":p=ie.createHTML(p);break;case"TrustedScriptURL":p=ie.createScriptURL(p)}try{l?e.setAttributeNS(l,a,p):e.setAttribute(a,p),At(e)?Tt(e):m(o.removed)}catch(e){}}}bt("afterSanitizeAttributes",e,null)},Lt=function e(t){let n=null;const o=_t(t);for(bt("beforeSanitizeShadowDOM",t,null);n=o.nextNode();)bt("uponSanitizeShadowNode",n,null),St(n)||(n.content instanceof s&&e(n.content),Ct(n));bt("afterSanitizeShadowDOM",t,null)};return o.sanitize=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=null,r=null,i=null,l=null;if(nt=!e,nt&&(e="\x3c!--\x3e"),"string"!=typeof e&&!Nt(e)){if("function"!=typeof e.toString)throw A("toString is not a function");if("string"!=typeof(e=e.toString()))throw A("dirty is not a string, aborting")}if(!o.isSupported)return e;if(Ue||mt(t),o.removed=[],"string"==typeof e&&(Ye=!1),Ye){if(e.nodeName){const t=lt(e.nodeName);if(!Ne[t]||Ce[t])throw A("root node is forbidden and cannot be sanitized in-place")}}else if(e instanceof b)n=Et("\x3c!----\x3e"),r=n.ownerDocument.importNode(e,!0),r.nodeType===V&&"BODY"===r.nodeName||"HTML"===r.nodeName?n=r:n.appendChild(r);else{if(!Fe&&!ke&&!Ie&&-1===e.indexOf("<"))return ie&&ze?ie.createHTML(e):e;if(n=Et(e),!n)return Fe?null:ze?ae:""}n&&Pe&&Tt(n.firstChild);const c=_t(Ye?e:n);for(;i=c.nextNode();)St(i)||(i.content instanceof s&&Lt(i.content),Ct(i));if(Ye)return e;if(Fe){if(He)for(l=se.call(n.ownerDocument);n.firstChild;)l.appendChild(n.firstChild);else l=n;return(Se.shadowroot||Se.shadowrootmode)&&(l=me.call(a,l,!0)),l}let m=Ie?n.outerHTML:n.innerHTML;return Ie&&Ne["!doctype"]&&n.ownerDocument&&n.ownerDocument.doctype&&n.ownerDocument.doctype.name&&_(q,n.ownerDocument.doctype.name)&&(m="<!DOCTYPE "+n.ownerDocument.doctype.name+">\n"+m),ke&&u([fe,de,he],(e=>{m=g(m,e," ")})),ie&&ze?ie.createHTML(m):m},o.setConfig=function(){mt(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}),Ue=!0},o.clearConfig=function(){ct=null,Ue=!1},o.isValidAttribute=function(e,t,n){ct||mt({});const o=lt(e),r=lt(t);return Rt(o,r,n)},o.addHook=function(e,t){"function"==typeof t&&(pe[e]=pe[e]||[],p(pe[e],t))},o.removeHook=function(e){if(pe[e])return m(pe[e])},o.removeHooks=function(e){pe[e]&&(pe[e]=[])},o.removeAllHooks=function(){pe={}},o}();return ne}));
|
| 3 |
+
//# sourceMappingURL=purify.min.js.map
|