@oversk7/pi-web-dsh-style 1.3.1 → 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/THIRD_PARTY_NOTICES.md +32 -3
- package/package.json +4 -1
- package/server.ts +194 -18
- package/web/app.css +9 -1
- package/web/app.js +16 -4
- package/web/assets/fonts/KaTeX_AMS-Regular.ttf +0 -0
- package/web/assets/fonts/KaTeX_AMS-Regular.woff +0 -0
- package/web/assets/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- package/web/assets/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
- package/web/assets/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
- package/web/assets/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/web/assets/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
- package/web/assets/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
- package/web/assets/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/web/assets/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
- package/web/assets/fonts/KaTeX_Fraktur-Bold.woff +0 -0
- package/web/assets/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/web/assets/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
- package/web/assets/fonts/KaTeX_Fraktur-Regular.woff +0 -0
- package/web/assets/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/web/assets/fonts/KaTeX_Main-Bold.ttf +0 -0
- package/web/assets/fonts/KaTeX_Main-Bold.woff +0 -0
- package/web/assets/fonts/KaTeX_Main-Bold.woff2 +0 -0
- package/web/assets/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
- package/web/assets/fonts/KaTeX_Main-BoldItalic.woff +0 -0
- package/web/assets/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/web/assets/fonts/KaTeX_Main-Italic.ttf +0 -0
- package/web/assets/fonts/KaTeX_Main-Italic.woff +0 -0
- package/web/assets/fonts/KaTeX_Main-Italic.woff2 +0 -0
- package/web/assets/fonts/KaTeX_Main-Regular.ttf +0 -0
- package/web/assets/fonts/KaTeX_Main-Regular.woff +0 -0
- package/web/assets/fonts/KaTeX_Main-Regular.woff2 +0 -0
- package/web/assets/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
- package/web/assets/fonts/KaTeX_Math-BoldItalic.woff +0 -0
- package/web/assets/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/web/assets/fonts/KaTeX_Math-Italic.ttf +0 -0
- package/web/assets/fonts/KaTeX_Math-Italic.woff +0 -0
- package/web/assets/fonts/KaTeX_Math-Italic.woff2 +0 -0
- package/web/assets/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
- package/web/assets/fonts/KaTeX_SansSerif-Bold.woff +0 -0
- package/web/assets/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/web/assets/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
- package/web/assets/fonts/KaTeX_SansSerif-Italic.woff +0 -0
- package/web/assets/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/web/assets/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
- package/web/assets/fonts/KaTeX_SansSerif-Regular.woff +0 -0
- package/web/assets/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/web/assets/fonts/KaTeX_Script-Regular.ttf +0 -0
- package/web/assets/fonts/KaTeX_Script-Regular.woff +0 -0
- package/web/assets/fonts/KaTeX_Script-Regular.woff2 +0 -0
- package/web/assets/fonts/KaTeX_Size1-Regular.ttf +0 -0
- package/web/assets/fonts/KaTeX_Size1-Regular.woff +0 -0
- package/web/assets/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- package/web/assets/fonts/KaTeX_Size2-Regular.ttf +0 -0
- package/web/assets/fonts/KaTeX_Size2-Regular.woff +0 -0
- package/web/assets/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- package/web/assets/fonts/KaTeX_Size3-Regular.ttf +0 -0
- package/web/assets/fonts/KaTeX_Size3-Regular.woff +0 -0
- package/web/assets/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- package/web/assets/fonts/KaTeX_Size4-Regular.ttf +0 -0
- package/web/assets/fonts/KaTeX_Size4-Regular.woff +0 -0
- package/web/assets/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- package/web/assets/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
- package/web/assets/fonts/KaTeX_Typewriter-Regular.woff +0 -0
- package/web/assets/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/web/assets/katex.min.css +1 -0
- package/web/assets/markdown.LICENSE.txt +78 -0
- package/web/assets/markdown.js +536 -21
- package/web/assets/mermaid/chunks/abnfDiagram-YUKMZFIV-FZYDJU67.js +1 -0
- package/web/assets/mermaid/chunks/architecture-WOLXFQ4H-BZVX64AA.js +1 -0
- package/web/assets/mermaid/chunks/architectureDiagram-47P4ROYG-2BMC2Z7S.js +36 -0
- package/web/assets/mermaid/chunks/blockDiagram-E7TT5TSB-FH6ZULKF.js +140 -0
- package/web/assets/mermaid/chunks/c4Diagram-CRA5TL53-OG62EAHM.js +38 -0
- package/web/assets/mermaid/chunks/chunk-22D53RF2.js +2 -0
- package/web/assets/mermaid/chunks/chunk-25KVF5ZE.js +1 -0
- package/web/assets/mermaid/chunks/chunk-4HYFSIZT.js +1 -0
- package/web/assets/mermaid/chunks/chunk-4W4OQ3QY.js +1 -0
- package/web/assets/mermaid/chunks/chunk-5TQRX2ND.js +1 -0
- package/web/assets/mermaid/chunks/chunk-64OFLKGX.js +322 -0
- package/web/assets/mermaid/chunks/chunk-64OFLKGX.js.LEGAL.txt +17 -0
- package/web/assets/mermaid/chunks/chunk-6UFWKTSA.js +1 -0
- package/web/assets/mermaid/chunks/chunk-6ZAAIG6Q.js +10 -0
- package/web/assets/mermaid/chunks/chunk-76QEHT4T.js +1 -0
- package/web/assets/mermaid/chunks/chunk-A7665WVC.js +1 -0
- package/web/assets/mermaid/chunks/chunk-AECJS4LP.js +130 -0
- package/web/assets/mermaid/chunks/chunk-AECJS4LP.js.LEGAL.txt +5 -0
- package/web/assets/mermaid/chunks/chunk-ATQQWCXO.js +2 -0
- package/web/assets/mermaid/chunks/chunk-DQVO43GU.js +1 -0
- package/web/assets/mermaid/chunks/chunk-DSKRGV6V.js +1 -0
- package/web/assets/mermaid/chunks/chunk-EIBFAW37.js +1 -0
- package/web/assets/mermaid/chunks/chunk-FBC3PYSO.js +1 -0
- package/web/assets/mermaid/chunks/chunk-FQ5IIL54.js +88 -0
- package/web/assets/mermaid/chunks/chunk-GZYY6JMP.js +1 -0
- package/web/assets/mermaid/chunks/chunk-HIGPS4L2.js +1 -0
- package/web/assets/mermaid/chunks/chunk-HP75Y56I.js +2 -0
- package/web/assets/mermaid/chunks/chunk-JRAHLUQM.js +32 -0
- package/web/assets/mermaid/chunks/chunk-KNYDPLLK.js +1 -0
- package/web/assets/mermaid/chunks/chunk-L465623K.js +136 -0
- package/web/assets/mermaid/chunks/chunk-L7BMR7WL.js +1 -0
- package/web/assets/mermaid/chunks/chunk-LLGPMHB6.js +1 -0
- package/web/assets/mermaid/chunks/chunk-NBH7YOBD.js +15 -0
- package/web/assets/mermaid/chunks/chunk-NCOVM3YF.js +1 -0
- package/web/assets/mermaid/chunks/chunk-PHKIAKHS.js +1 -0
- package/web/assets/mermaid/chunks/chunk-PM2IFX5O.js +1 -0
- package/web/assets/mermaid/chunks/chunk-PN62QGJW.js +72 -0
- package/web/assets/mermaid/chunks/chunk-QHMFFOZZ.js +1 -0
- package/web/assets/mermaid/chunks/chunk-QQZBUVKZ.js +1 -0
- package/web/assets/mermaid/chunks/chunk-RV7WQMNL.js +1 -0
- package/web/assets/mermaid/chunks/chunk-STBOPOHX.js +1 -0
- package/web/assets/mermaid/chunks/chunk-T3FZWEYV.js +1 -0
- package/web/assets/mermaid/chunks/chunk-TMMWB6NQ.js +1 -0
- package/web/assets/mermaid/chunks/chunk-TPW5CADB.js +1 -0
- package/web/assets/mermaid/chunks/chunk-TSOLLCID.js +2 -0
- package/web/assets/mermaid/chunks/chunk-TWGPYWIY.js +1 -0
- package/web/assets/mermaid/chunks/chunk-WGMEMLED.js +1 -0
- package/web/assets/mermaid/chunks/chunk-XC2LKMMW.js +1 -0
- package/web/assets/mermaid/chunks/chunk-XHVVPFJ5.js +1 -0
- package/web/assets/mermaid/chunks/chunk-YIN5CSIF.js +2 -0
- package/web/assets/mermaid/chunks/chunk-YIN5CSIF.js.LEGAL.txt +12 -0
- package/web/assets/mermaid/chunks/chunk-YORIST7Z.js +1 -0
- package/web/assets/mermaid/chunks/chunk-YPXVLPXW.js +3 -0
- package/web/assets/mermaid/chunks/chunk-Z4WODCD2.js +213 -0
- package/web/assets/mermaid/chunks/chunk-ZAERIUBF.js +1 -0
- package/web/assets/mermaid/chunks/chunk-ZDOBOOWG.js +62 -0
- package/web/assets/mermaid/chunks/classDiagram-v2-K4WV4PDN-HXQD675C.js +217 -0
- package/web/assets/mermaid/chunks/cose-bilkent-JH36ORCC-3VHNHM7I.js +1 -0
- package/web/assets/mermaid/chunks/cynefin-EF2NZ3EQ-ZO5PPXJG.js +1 -0
- package/web/assets/mermaid/chunks/cynefinDiagram-3GCD6N5R-LFWDWE4E.js +62 -0
- package/web/assets/mermaid/chunks/dagre-W4DXFKR2-SDBBVBGG.js +4 -0
- package/web/assets/mermaid/chunks/diagram-2UJZ2QOL-YCKW3WNJ.js +200 -0
- package/web/assets/mermaid/chunks/diagram-OVF4WLC6-62NNPE34.js +24 -0
- package/web/assets/mermaid/chunks/diagram-PFPMY2P6-7RR2GTZ5.js +30 -0
- package/web/assets/mermaid/chunks/diagram-UMYRVEAY-Q4I25SMR.js +24 -0
- package/web/assets/mermaid/chunks/diagram-YEKJPTXX-VNUTOPRK.js +41 -0
- package/web/assets/mermaid/chunks/diagram-ZIFT7M5P-KALXX5CE.js +3 -0
- package/web/assets/mermaid/chunks/ebnfDiagram-VR2GEFS7-WIFBISHL.js +1 -0
- package/web/assets/mermaid/chunks/elk-IJKZMXRS-LGG232IL.js +27 -0
- package/web/assets/mermaid/chunks/erDiagram-O2IAPWRE-KWX2J2TX.js +99 -0
- package/web/assets/mermaid/chunks/eventmodeling-K75KTNOO-3JNV4VSP.js +1 -0
- package/web/assets/mermaid/chunks/flowDiagram-OXPTDLAJ-CUMOBDC3.js +1 -0
- package/web/assets/mermaid/chunks/ganttDiagram-R7TSEDQI-GCS3MRFX.js +292 -0
- package/web/assets/mermaid/chunks/gitGraph-VSP46ZUC-HSAXKLAG.js +1 -0
- package/web/assets/mermaid/chunks/gitGraphDiagram-XJZIOB7I-FB763ROZ.js +106 -0
- package/web/assets/mermaid/chunks/info-OHQRW6UA-C4R2B34T.js +1 -0
- package/web/assets/mermaid/chunks/infoDiagram-5W2HQ5XZ-XCQU5T5D.js +2 -0
- package/web/assets/mermaid/chunks/ishikawaDiagram-K3B6WC7H-UWYT66G7.js +70 -0
- package/web/assets/mermaid/chunks/journeyDiagram-COXZFDF6-DOW66RYW.js +139 -0
- package/web/assets/mermaid/chunks/kanban-definition-P3RFRI5V-K55BXDLO.js +89 -0
- package/web/assets/mermaid/chunks/katex-5AUD5AJN.js +257 -0
- package/web/assets/mermaid/chunks/mindmap-definition-LZFPQGKD-WG3FIZ5U.js +96 -0
- package/web/assets/mermaid/chunks/packet-JDAUHWVQ-SFUSDIUN.js +1 -0
- package/web/assets/mermaid/chunks/pegDiagram-BGZESJAR-MQOH3WII.js +1 -0
- package/web/assets/mermaid/chunks/pie-XZMESJXO-M76QC4CD.js +1 -0
- package/web/assets/mermaid/chunks/pieDiagram-CAPJLFHJ-V3WNR4Y2.js +39 -0
- package/web/assets/mermaid/chunks/quadrantDiagram-GDMTTRAM-DJLTATHS.js +7 -0
- package/web/assets/mermaid/chunks/radar-ABXABTNO-HSBJ6SSD.js +1 -0
- package/web/assets/mermaid/chunks/railroad-I3PHUGI6-4QJMJ7LG.js +1 -0
- package/web/assets/mermaid/chunks/railroad-abnf-LNEFI6M7-ZLNZ5ZRH.js +1 -0
- package/web/assets/mermaid/chunks/railroad-ebnf-DWYD2UWJ-EBV6ZOUW.js +1 -0
- package/web/assets/mermaid/chunks/railroad-peg-JR7BVNR7-X3E47TO7.js +1 -0
- package/web/assets/mermaid/chunks/railroadDiagram-SM67HX2B-ZHEERYJS.js +1 -0
- package/web/assets/mermaid/chunks/requirementDiagram-X7JNWC4A-TVHJNPPI.js +84 -0
- package/web/assets/mermaid/chunks/sankeyDiagram-UM26HJRW-FXHWY3MM.js +40 -0
- package/web/assets/mermaid/chunks/sequenceDiagram-ZO4K6R2Y-OP7DCVPK.js +169 -0
- package/web/assets/mermaid/chunks/sizeCapture-INFHLROL-2GUJIKNX.js +1 -0
- package/web/assets/mermaid/chunks/stateDiagram-v2-TBUQTH76-R26D6XHK.js +291 -0
- package/web/assets/mermaid/chunks/swimlanes-N4OXWK64-FPGACWHE.js +1 -0
- package/web/assets/mermaid/chunks/swimlanesDiagram-K3J5GTZL-YMNX34Q2.js +8 -0
- package/web/assets/mermaid/chunks/timeline-definition-YOQAKGHF-R2U2UR4K.js +120 -0
- package/web/assets/mermaid/chunks/treeView-D4JQ5SDB-3BQHZUCI.js +1 -0
- package/web/assets/mermaid/chunks/treemap-SAJKECNS-6NJPJ5NM.js +1 -0
- package/web/assets/mermaid/chunks/usecaseDiagram-VIAY4XPW-BCEIGXDX.js +370 -0
- package/web/assets/mermaid/chunks/vennDiagram-BLWOH2XV-DOV5W2IV.js +34 -0
- package/web/assets/mermaid/chunks/wardley-7MLQ67FV-ITOM4KQ2.js +1 -0
- package/web/assets/mermaid/chunks/wardleyDiagram-YMQ3BMBF-CGJ7AG4L.js +78 -0
- package/web/assets/mermaid/chunks/xychartDiagram-TAQBALBS-2MTP7IBV.js +7 -0
- package/web/assets/mermaid/mermaid.js +11 -0
- package/web/assets/mermaid/mermaid.js.LEGAL.txt +7 -0
- package/web/index.html +1 -0
- package/web/markdown-diagrams.js +147 -0
- package/web/markdown.ts +50 -4
- package/web/slash-commands.js +1 -0
- package/web/themes.css +46 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
let renderer;
|
|
2
|
+
let configuredTheme;
|
|
3
|
+
let sequence = 0;
|
|
4
|
+
const cache = new Map();
|
|
5
|
+
const rendered = new WeakMap();
|
|
6
|
+
|
|
7
|
+
function diagramFragment(template) {
|
|
8
|
+
const content = template.content.cloneNode(true);
|
|
9
|
+
const prefix = `pi-diagram-${++sequence}`;
|
|
10
|
+
const ids = new Map();
|
|
11
|
+
for (const element of content.querySelectorAll("[id]")) {
|
|
12
|
+
const original = element.id;
|
|
13
|
+
const unique = `${prefix}-${ids.size}`;
|
|
14
|
+
ids.set(original, unique);
|
|
15
|
+
element.id = unique;
|
|
16
|
+
}
|
|
17
|
+
const replaceUrls = value => value.replace(/url\(\s*(["']?)#([^\s)"']+)\1\s*\)/g,
|
|
18
|
+
(match, quote, id) => ids.has(id) ? `url(${quote}#${ids.get(id)}${quote})` : match);
|
|
19
|
+
for (const element of content.querySelectorAll("*")) {
|
|
20
|
+
for (const attribute of [...element.attributes]) {
|
|
21
|
+
let value = replaceUrls(attribute.value);
|
|
22
|
+
if (["href", "xlink:href"].includes(attribute.name) && value.startsWith("#") && ids.has(value.slice(1))) {
|
|
23
|
+
value = `#${ids.get(value.slice(1))}`;
|
|
24
|
+
}
|
|
25
|
+
if (["aria-labelledby", "aria-describedby"].includes(attribute.name)) {
|
|
26
|
+
value = value.split(/\s+/).map(id => ids.get(id) || id).join(" ");
|
|
27
|
+
}
|
|
28
|
+
if (value !== attribute.value) element.setAttribute(attribute.name, value);
|
|
29
|
+
}
|
|
30
|
+
if (element.localName === "style") {
|
|
31
|
+
element.textContent = replaceUrls(element.textContent).replace(/#([\w:.-]+)/g,
|
|
32
|
+
(match, id) => ids.has(id) ? `#${ids.get(id)}` : match);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return content;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function observeMarkdownDiagrams(root = document.body) {
|
|
39
|
+
let frame;
|
|
40
|
+
let running = false;
|
|
41
|
+
let stopped = false;
|
|
42
|
+
const pending = new Set();
|
|
43
|
+
const selector = '.md-mermaid[data-mermaid-complete="true"]';
|
|
44
|
+
|
|
45
|
+
function collect(node) {
|
|
46
|
+
if (node.nodeType !== 1) return;
|
|
47
|
+
if (node.matches(selector)) pending.add(node);
|
|
48
|
+
for (const diagram of node.querySelectorAll(selector)) pending.add(diagram);
|
|
49
|
+
if (pending.size) schedule();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function update() {
|
|
53
|
+
frame = undefined;
|
|
54
|
+
if (running || stopped) return;
|
|
55
|
+
running = true;
|
|
56
|
+
try {
|
|
57
|
+
for (const node of [...pending]) {
|
|
58
|
+
pending.delete(node);
|
|
59
|
+
const dark = document.body.hasAttribute("data-ds-dark-theme");
|
|
60
|
+
const source = node.dataset.mermaidSource || "";
|
|
61
|
+
const key = `${dark}:${source}`;
|
|
62
|
+
if (rendered.get(node) === key || !node.isConnected) continue;
|
|
63
|
+
rendered.set(node, key);
|
|
64
|
+
if (source.length > 32 * 1024) continue;
|
|
65
|
+
try {
|
|
66
|
+
let result = cache.get(key);
|
|
67
|
+
if (!result) {
|
|
68
|
+
renderer ||= import("./assets/mermaid/mermaid.js").then(module => module.default).catch(error => {
|
|
69
|
+
renderer = undefined;
|
|
70
|
+
throw error;
|
|
71
|
+
});
|
|
72
|
+
const mermaid = await renderer;
|
|
73
|
+
if (!node.isConnected || stopped) continue;
|
|
74
|
+
if (dark !== document.body.hasAttribute("data-ds-dark-theme")) {
|
|
75
|
+
rendered.delete(node);
|
|
76
|
+
pending.add(node);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (configuredTheme !== dark) mermaid.initialize({
|
|
80
|
+
startOnLoad: false,
|
|
81
|
+
securityLevel: "strict",
|
|
82
|
+
theme: dark ? "dark" : "default",
|
|
83
|
+
layout: "dagre",
|
|
84
|
+
suppressErrorRendering: true,
|
|
85
|
+
maxTextSize: 32 * 1024,
|
|
86
|
+
flowchart: { htmlLabels: false },
|
|
87
|
+
});
|
|
88
|
+
configuredTheme = dark;
|
|
89
|
+
const id = `pi-mermaid-${++sequence}`;
|
|
90
|
+
let svg;
|
|
91
|
+
try {
|
|
92
|
+
({ svg } = await mermaid.render(id, source));
|
|
93
|
+
} catch {
|
|
94
|
+
result = { error: true };
|
|
95
|
+
}
|
|
96
|
+
if (!result) {
|
|
97
|
+
const template = document.createElement("template");
|
|
98
|
+
template.innerHTML = svg;
|
|
99
|
+
result = { template };
|
|
100
|
+
}
|
|
101
|
+
cache.set(key, result);
|
|
102
|
+
if (cache.size > 64) cache.delete(cache.keys().next().value);
|
|
103
|
+
}
|
|
104
|
+
if (!node.isConnected || stopped) continue;
|
|
105
|
+
if (dark !== document.body.hasAttribute("data-ds-dark-theme")) {
|
|
106
|
+
rendered.delete(node);
|
|
107
|
+
pending.add(node);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (result.error) {
|
|
111
|
+
node.dataset.mermaidState = "error";
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
node.replaceChildren(diagramFragment(result.template));
|
|
115
|
+
node.dataset.mermaidState = "rendered";
|
|
116
|
+
node.setAttribute("role", "img");
|
|
117
|
+
node.setAttribute("aria-label", "Mermaid diagram");
|
|
118
|
+
} catch {
|
|
119
|
+
// Keep the readable source when a diagram is invalid or still incomplete.
|
|
120
|
+
node.dataset.mermaidState = "error";
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
} finally {
|
|
124
|
+
running = false;
|
|
125
|
+
if (pending.size) schedule();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function schedule() {
|
|
130
|
+
if (!stopped && frame === undefined) frame = requestAnimationFrame(update);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const observer = new MutationObserver(records => {
|
|
134
|
+
for (const record of records) {
|
|
135
|
+
if (record.type === "attributes") collect(root);
|
|
136
|
+
else for (const node of record.addedNodes) collect(node);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
observer.observe(root, { childList: true, subtree: true, attributes: true, attributeFilter: ["data-ds-dark-theme"] });
|
|
140
|
+
collect(root);
|
|
141
|
+
return () => {
|
|
142
|
+
stopped = true;
|
|
143
|
+
observer.disconnect();
|
|
144
|
+
if (frame !== undefined) cancelAnimationFrame(frame);
|
|
145
|
+
pending.clear();
|
|
146
|
+
};
|
|
147
|
+
}
|
package/web/markdown.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import MarkdownIt from "markdown-it";
|
|
2
|
+
import katex from "katex";
|
|
3
|
+
import texmath from "markdown-it-texmath";
|
|
2
4
|
import hljs from "highlight.js/lib/common";
|
|
3
5
|
import dockerfile from "highlight.js/lib/languages/dockerfile";
|
|
4
6
|
import powershell from "highlight.js/lib/languages/powershell";
|
|
@@ -35,7 +37,38 @@ function localFileLink(target: string, workspace = false) {
|
|
|
35
37
|
return { path: value, line, href };
|
|
36
38
|
}
|
|
37
39
|
|
|
40
|
+
const formulaCache = new Map<string, string>();
|
|
41
|
+
let formulaCacheBytes = 0;
|
|
42
|
+
|
|
43
|
+
function renderFormula(source: string, options: katex.KatexOptions) {
|
|
44
|
+
if (source.length > 16 * 1024) throw new Error("Formula exceeds rendering limit");
|
|
45
|
+
const key = `${options.displayMode ? "display" : "inline"}:${source}`;
|
|
46
|
+
const cached = formulaCache.get(key);
|
|
47
|
+
if (cached !== undefined) {
|
|
48
|
+
formulaCache.delete(key);
|
|
49
|
+
formulaCache.set(key, cached);
|
|
50
|
+
return cached;
|
|
51
|
+
}
|
|
52
|
+
const html = katex.renderToString(source, options);
|
|
53
|
+
const bytes = (key.length + html.length) * 2;
|
|
54
|
+
if (bytes <= 1024 * 1024) {
|
|
55
|
+
formulaCache.set(key, html);
|
|
56
|
+
formulaCacheBytes += bytes;
|
|
57
|
+
while (formulaCache.size > 128 || formulaCacheBytes > 1024 * 1024) {
|
|
58
|
+
const oldest = formulaCache.keys().next().value!;
|
|
59
|
+
formulaCacheBytes -= (oldest.length + formulaCache.get(oldest)!.length) * 2;
|
|
60
|
+
formulaCache.delete(oldest);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return html;
|
|
64
|
+
}
|
|
65
|
+
|
|
38
66
|
const parser = new MarkdownIt({ html: false, breaks: false, linkify: true });
|
|
67
|
+
parser.use(texmath, {
|
|
68
|
+
engine: { renderToString: renderFormula },
|
|
69
|
+
delimiters: ["dollars", "brackets"],
|
|
70
|
+
katexOptions: { trust: false, strict: "ignore", throwOnError: false, maxExpand: 1000, maxSize: 20 },
|
|
71
|
+
});
|
|
39
72
|
const InlineState = parser.inline.State;
|
|
40
73
|
parser.inline.State = class extends InlineState {
|
|
41
74
|
scanDelims(start: number, canSplitWord: boolean) {
|
|
@@ -60,7 +93,14 @@ parser.validateLink = (target) => Boolean(localFileLink(target)) || validateLink
|
|
|
60
93
|
parser.renderer.rules.link_open = (tokens, index, options, env, renderer) => {
|
|
61
94
|
const token = tokens[index];
|
|
62
95
|
const target = String(token.attrGet("href") || "");
|
|
63
|
-
|
|
96
|
+
let local = localFileLink(target, true);
|
|
97
|
+
if (local && typeof env?.cwd === "string" && !/^[A-Za-z]:[\\/]|^\\\\/.test(local.path)) {
|
|
98
|
+
const base = new URL("file:///");
|
|
99
|
+
base.pathname = `${env.cwd.replace(/\\/g, "/").replace(/%/g, "%25").replace(/\/+$/, "")}/`;
|
|
100
|
+
const relative = local.path.replace(/\\/g, "/").split("/").map(encodeURIComponent).join("/");
|
|
101
|
+
const resolved = new URL(relative, base);
|
|
102
|
+
local = localFileLink(`${resolved.href}${local.line ? `#L${local.line}` : ""}`) || local;
|
|
103
|
+
}
|
|
64
104
|
if (local) {
|
|
65
105
|
token.attrSet("href", local.href);
|
|
66
106
|
token.attrJoin("class", "md-local-file");
|
|
@@ -84,9 +124,14 @@ parser.renderer.rules.image = (tokens, index, options, env, renderer) => {
|
|
|
84
124
|
return renderImage(tokens, index, options, env, renderer);
|
|
85
125
|
};
|
|
86
126
|
|
|
87
|
-
parser.renderer.rules.fence = (tokens, index) => {
|
|
127
|
+
parser.renderer.rules.fence = (tokens, index, _options, env) => {
|
|
88
128
|
const token = tokens[index];
|
|
89
129
|
const language = token.info.trim().split(/\s+/)[0];
|
|
130
|
+
if (language.toLowerCase() === "mermaid") {
|
|
131
|
+
const lastLine = (env?.markdownLines as string[] | undefined)?.[token.map![1] - 1] || "";
|
|
132
|
+
const closed = new RegExp(`^\\s*(?:>\\s*)*[${token.markup[0]}]{${token.markup.length},}\\s*$`).test(lastLine);
|
|
133
|
+
return `<div class="md-mermaid" data-mermaid-source="${escape(token.content)}" data-mermaid-complete="${closed}"><pre class="md-code-block"><code>${escape(token.content)}</code></pre></div>\n`;
|
|
134
|
+
}
|
|
90
135
|
let code = escape(token.content);
|
|
91
136
|
// Bound synchronous highlighting work while streaming large tool-generated snippets.
|
|
92
137
|
if (language && hljs.getLanguage(language) && token.content.length <= 32 * 1024) {
|
|
@@ -121,6 +166,7 @@ parser.renderer.rules.task_checkbox = (tokens, index) => {
|
|
|
121
166
|
return `<input type="checkbox" disabled${checked ? " checked" : ""} aria-label="${checked ? "已完成" : "未完成"}"/> `;
|
|
122
167
|
};
|
|
123
168
|
|
|
124
|
-
export function markdown(src: unknown): string {
|
|
125
|
-
|
|
169
|
+
export function markdown(src: unknown, context: { cwd?: string } = {}): string {
|
|
170
|
+
const text = String(src ?? "");
|
|
171
|
+
return parser.render(text, { ...context, markdownLines: text.replace(/\r\n?/g, "\n").split("\n") });
|
|
126
172
|
}
|
package/web/slash-commands.js
CHANGED
|
@@ -24,6 +24,7 @@ export const unsupportedSlashCommands = {
|
|
|
24
24
|
trust: "项目信任设置需要在 Pi 终端中通过 /trust 管理。",
|
|
25
25
|
changelog: "Web 暂不展示 Pi 更新日志,请在 Pi 终端执行 /changelog。",
|
|
26
26
|
hotkeys: "终端快捷键不适用于网页。网页输入框支持 Enter 发送、Shift+Enter 换行,命令菜单支持方向键选择和 Tab 补全。",
|
|
27
|
+
bug: "Web 暂不支持提交问题报告,请在 Pi 终端执行 /bug。",
|
|
27
28
|
debug: "此调试命令仅支持 Pi 终端。",
|
|
28
29
|
arminsayshi: "此彩蛋命令仅支持 Pi 终端。",
|
|
29
30
|
dementedelves: "此彩蛋命令仅支持 Pi 终端。",
|
package/web/themes.css
CHANGED
|
@@ -156,3 +156,49 @@ body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-back
|
|
|
156
156
|
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) [data-chat-flow-kind=assistant-text]{padding:14px;border-radius:16px}
|
|
157
157
|
body:is([data-theme-style=sakura],[data-theme-style=starlight],[data-custom-background]) .pXSMma_headline{padding:10px 12px;margin:0;box-sizing:border-box}
|
|
158
158
|
}
|
|
159
|
+
|
|
160
|
+
/* Claude Code UI + Tokyo Night chat colors apply only in dark mode. */
|
|
161
|
+
body[data-ds-dark-theme]{
|
|
162
|
+
--pi-chat-heading:#ff9e64;--pi-chat-code:#9ece6a;--pi-chat-link:#7dcfff;
|
|
163
|
+
--pi-chat-blue:#7aa2f7;--pi-chat-purple:#bb9af7;--pi-chat-orange:#ff9e64;
|
|
164
|
+
--pi-chat-green:#9ece6a;--pi-chat-red:#f7768e;--pi-chat-yellow:#e0af68;
|
|
165
|
+
--pi-chat-muted:#9aa5ce;--pi-chat-thinking:#a0a4b0;
|
|
166
|
+
--pi-chat-text:var(--dsw-alias-label-primary);
|
|
167
|
+
--pi-chat-strong:color-mix(in srgb,var(--pi-chat-heading) 28%,var(--dsw-alias-label-primary));
|
|
168
|
+
--pi-chat-border:color-mix(in srgb,var(--pi-chat-blue) 22%,var(--dsw-alias-border-l2));
|
|
169
|
+
--pi-chat-inline-bg:color-mix(in srgb,var(--pi-chat-code) 7%,var(--dsw-alias-markdown-inline-code));
|
|
170
|
+
--pi-chat-inline-border:color-mix(in srgb,var(--pi-chat-code) 20%,var(--dsw-alias-border-l2));
|
|
171
|
+
}
|
|
172
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5{color:var(--pi-chat-text)}
|
|
173
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 :is(h1,h2,h3,h4,h5,h6){color:var(--pi-chat-heading)}
|
|
174
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 strong{color:var(--pi-chat-strong);font-weight:650}
|
|
175
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 em{color:var(--pi-chat-muted)}
|
|
176
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 a{color:var(--pi-chat-link);text-decoration-color:color-mix(in srgb,var(--pi-chat-link) 45%,transparent)}
|
|
177
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 a:is(:hover,:focus-visible){text-decoration-color:currentColor}
|
|
178
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 a:focus-visible{outline:2px solid var(--pi-chat-link);outline-offset:3px;border-radius:2px}
|
|
179
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 :not(pre)>code{color:var(--pi-chat-code);background:var(--pi-chat-inline-bg);border-color:var(--pi-chat-inline-border)}
|
|
180
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 :is(ul,ol)>li::marker{color:var(--pi-chat-link)}
|
|
181
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 ul>li:not(.md-task-item)::marker{content:"◉ ";font-size:.75em}
|
|
182
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 .md-task-item input{accent-color:var(--pi-chat-green)}
|
|
183
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 blockquote{color:var(--pi-chat-muted);border-left-color:var(--pi-chat-border)}
|
|
184
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 hr{background:var(--pi-chat-border)}
|
|
185
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 :is(.md-code-container,.md-code-block,.md-code-language){border-color:var(--pi-chat-border)}
|
|
186
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 .md-code-language{color:var(--pi-chat-muted);background:var(--dsw-alias-markdown-code-block-banner);font-size:11px;letter-spacing:.03em}
|
|
187
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 .md-code-block{color:var(--pi-chat-text)}
|
|
188
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 .md-table-wrap th{color:var(--pi-chat-heading)}
|
|
189
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 :is(.hljs-comment,.hljs-quote){color:var(--pi-chat-muted);font-style:italic}
|
|
190
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 :is(.hljs-keyword,.hljs-selector-tag,.hljs-literal,.hljs-operator){color:var(--pi-chat-purple)}
|
|
191
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 :is(.hljs-string,.hljs-regexp){color:var(--pi-chat-green)}
|
|
192
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 :is(.hljs-title,.hljs-section){color:var(--pi-chat-blue)}
|
|
193
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 :is(.hljs-number,.hljs-symbol,.hljs-variable,.hljs-template-variable,.hljs-attr){color:var(--pi-chat-orange)}
|
|
194
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 :is(.hljs-type,.hljs-built_in,.hljs-selector-class,.hljs-selector-id){color:var(--pi-chat-link)}
|
|
195
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 :is(.hljs-meta,.hljs-doctag,.hljs-attribute){color:var(--pi-chat-yellow)}
|
|
196
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 .hljs-addition{color:var(--pi-chat-green);background:color-mix(in srgb,var(--pi-chat-green) 10%,transparent)}
|
|
197
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] ._markdown_1nba0_5 .hljs-deletion{color:var(--pi-chat-red);background:color-mix(in srgb,var(--pi-chat-red) 10%,transparent)}
|
|
198
|
+
body[data-ds-dark-theme] [data-chat-flow-kind=assistant-step] :is(.QWLzlG_leading,.QWLzlG_title,.QWLzlG_summary){color:var(--pi-chat-thinking)}
|
|
199
|
+
body[data-ds-dark-theme] [data-chat-flow-kind=assistant-step] .Y0dWHa_thinkingQuote{border-left-color:var(--pi-chat-border)}
|
|
200
|
+
body[data-ds-dark-theme] [data-chat-flow-kind=assistant-step] .Y0dWHa_thinkingQuote .Y0dWHa_payload{color:var(--pi-chat-thinking);font-family:var(--dsw-font-family);line-height:1.7}
|
|
201
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] .CY-8Ka_root .CY-8Ka_title{color:var(--pi-chat-blue);font-weight:500}
|
|
202
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] .CY-8Ka_root[data-state=ok] .CY-8Ka_leading{color:var(--pi-chat-green)}
|
|
203
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] .CY-8Ka_root[data-state=running] :is(.CY-8Ka_leading,.CY-8Ka_title){color:var(--pi-chat-green)}
|
|
204
|
+
body[data-ds-dark-theme] [data-chat-flow-kind] .CY-8Ka_root[data-state=error] :is(.CY-8Ka_leading,.CY-8Ka_title,.CY-8Ka_errorSummary){color:var(--pi-chat-red)}
|