feat: add Mermaid diagrams across web and mobile

This commit is contained in:
tianma-if committed 2026-07-22 10:31:59 +08:00
1 parent c21f4213c1
commit 2b059aa39f
28 files changed
+1116 -17

No files matched your search

+1
View File
@@ -41,6 +41,7 @@ The public demo resets every Monday at 1:00 AM (China Standard Time) and restore
- Unlimited nested notebooks.
- Rich text editing.
- Switch between Markdown source and rich text views on desktop.
- Mermaid diagrams rendered from standard fenced code blocks on the Web and native app, with editable source preserved across rich text and Markdown views.
- Note version history for reviewing previous content changes.
- Local browser-side image compression before upload, often reducing screenshots and large photos by about 50%-90%.
- Batch note merging.
+1
View File
@@ -40,6 +40,7 @@ EdgeEver 是一个开源、自托管、Cloudflare-native 的现代笔记工作
- 无限级嵌套笔记本。
- 支持富文本编辑。
- 桌面端支持 Markdown 源码与富文本视图切换。
- Web 与原生 App 均支持渲染标准 Mermaid 围栏代码块,并在富文本与 Markdown 视图之间保留可编辑源码。
- 支持查看笔记历史版本,便于回溯内容变化。
- 笔记图片上传前支持 Web 端本地压缩,常见截图和大尺寸照片通常可减少约 50%-90% 体积,减少资源占用且不消耗 Cloudflare Images 额度。
- 多选合并笔记。
+36
View File
@@ -345,6 +345,42 @@ const DEMO_SEED_MEMOS = [
markdown:
"## Agent-ready:REST API 与 MCP\n\nEdgeEver 提供 REST API、OpenAPI schema 和 MCP endpoint。AI Agent 可以读取笔记本、创建笔记、整理标签,并把导入资料迁移到你的自托管实例。\n\n### 从这里开始\n\n- OpenAPI schema:`/api/openapi.json`\n- MCP endpoint:`/mcp`\n\n一个很小的 Agent 工作流是:先读取「功能演示」笔记本,再把这两条合并素材整理成一条带结论的长期笔记。",
},
{
id: "memo_demo_mermaid_flowchart",
notebookId: "nb_demo_features",
title: "Mermaid 示例:笔记整理流程",
tags: ["mermaid", "flowchart", "demo"],
isPinned: true,
markdown:
"## 笔记整理流程\n\n流程图适合表达判断、分支和处理步骤。进入编辑模式后,可以直接修改下方 Mermaid 源码并查看预览。\n\n```mermaid\nflowchart TD\n A[\"记录灵感\"] --> B{\"需要立即处理?\"}\n B -- \"是\" --> C[\"加入今日行动\"]\n B -- \"否\" --> D[\"放入等待分类\"]\n D --> E{\"是否属于长期主题?\"}\n E -- \"是\" --> F[\"移动到主题笔记本\"]\n E -- \"否\" --> G[\"添加标签并归档\"]\n C --> H[\"完成后沉淀结论\"]\n F --> H\n```\n\n修改节点文字或连线后,图表会自动重新渲染;Markdown 中仍保存标准的 `mermaid` 围栏代码块。",
},
{
id: "memo_demo_mermaid_sequence",
notebookId: "nb_demo_features",
title: "Mermaid 示例:离线同步时序",
tags: ["mermaid", "sequence", "sync"],
isPinned: false,
markdown:
"## 离线同步时序\n\n时序图适合说明多个角色或系统之间按时间发生的交互。\n\n```mermaid\nsequenceDiagram\n actor U as 用户\n participant A as EdgeEver App\n participant Q as 本地同步队列\n participant API as EdgeEver API\n participant DB as D1\n\n U->>A: 编辑并保存笔记\n A->>Q: 写入本地草稿与待同步记录\n A-->>U: 立即显示“已保存到本地”\n Q->>API: 网络恢复后提交更新\n API->>DB: 校验版本并持久化\n DB-->>API: 返回新版本\n API-->>Q: 同步成功\n Q-->>A: 清除待同步记录\n```\n\n这种图很适合记录 API 调用、登录流程、消息队列和跨服务协作。",
},
{
id: "memo_demo_mermaid_state",
notebookId: "nb_demo_features",
title: "Mermaid 示例:笔记生命周期",
tags: ["mermaid", "state-diagram", "workflow"],
isPinned: false,
markdown:
"## 笔记生命周期\n\n状态图强调一个对象会处于哪些状态,以及什么事件会触发状态变化。\n\n```mermaid\nstateDiagram-v2\n [*] --> 草稿\n 草稿 --> 待同步: 离线保存\n 草稿 --> 已保存: 在线保存\n 待同步 --> 已保存: 同步成功\n 待同步 --> 冲突: 服务端版本已变化\n 冲突 --> 草稿: 选择本地版本继续编辑\n 冲突 --> 已保存: 接受服务端版本\n 已保存 --> 已归档: 归档\n 已归档 --> 已保存: 恢复\n 已保存 --> 回收站: 删除\n 回收站 --> 已保存: 恢复\n 回收站 --> [*]: 永久删除\n```\n\n它也适合描述订单、审批单、任务或发布流程。",
},
{
id: "memo_demo_mermaid_gantt",
notebookId: "nb_demo_features",
title: "Mermaid 示例:一周发布计划",
tags: ["mermaid", "gantt", "planning"],
isPinned: false,
markdown:
"## 一周发布计划\n\n甘特图可以把任务、依赖关系和时间安排放在一张图里。\n\n```mermaid\ngantt\n title EdgeEver 功能发布计划\n dateFormat YYYY-MM-DD\n axisFormat %m-%d\n\n section 开发\n 完成 Mermaid 渲染 :done, dev1, 2026-07-20, 2d\n 补齐 App 编辑能力 :done, dev2, after dev1, 1d\n\n section 验证\n 自动化测试 :active, qa1, after dev2, 1d\n Android 与 Web 验收 :qa2, after qa1, 1d\n\n section 发布\n 整理说明与发布 :milestone, release, after qa2, 0d\n```\n\n日期和持续时间都是普通文本,因此可以直接在笔记里维护轻量项目计划。",
},
{
id: "memo_demo_mobile",
notebookId: "nb_personal",
+2 -2
View File
@@ -3,7 +3,7 @@
"name": "EdgeEver",
"slug": "edgeever",
"scheme": "edgeever",
"version": "1.4.0",
"version": "1.5.0",
"runtimeVersion": {
"policy": "appVersion"
},
@@ -28,7 +28,7 @@
},
"android": {
"package": "org.edgeever.mobile",
"versionCode": 32,
"versionCode": 33,
"adaptiveIcon": {
"backgroundColor": "#d1fae5",
"backgroundImage": "./assets/icon.png",
+2
View File
@@ -20,6 +20,7 @@
"@tanstack/query-async-storage-persister": "^5.101.2",
"@tanstack/react-query": "latest",
"@tanstack/react-query-persist-client": "^5.101.2",
"@tiptap/extension-code-block": "3.27.1",
"@tiptap/extension-image": "3.27.1",
"@tiptap/extension-placeholder": "3.27.1",
"@tiptap/extension-table": "3.27.1",
@@ -38,6 +39,7 @@
"expo-sqlite": "~57.0.1",
"expo-status-bar": "latest",
"expo-updates": "~57.0.8",
"mermaid": "^11.16.0",
"react": "19.2.3",
"react-dom": "19.2.3",
"react-native": "latest",
@@ -1,6 +1,8 @@
'use dom';
import "mermaid/dist/mermaid.min.js";
import Image from "@tiptap/extension-image";
import CodeBlock from "@tiptap/extension-code-block";
import Placeholder from "@tiptap/extension-placeholder";
import { TableKit } from "@tiptap/extension-table";
import { EditorContent, useEditor, useEditorState } from "@tiptap/react";
@@ -49,6 +51,7 @@ export interface LocalTiptapEditorRef extends DOMImperativeFactory {
}
type LocalTiptapEditorProps = {
mode?: "editor";
autoFocus?: boolean;
baseUrl: string;
content: EditorDoc;
@@ -63,11 +66,148 @@ type LocalTiptapEditorProps = {
theme: "light" | "dark";
};
type MermaidRendererProps = {
diagramsJson: string;
dom?: DOMProps;
mode: "mermaid-renderer";
onRendered: (resultsJson: string) => Promise<void>;
theme: "light" | "dark";
};
const CHANGE_IDLE_MS = 500;
const TRANSIENT_IMAGE_UPLOAD_META = "edgeeverImageUploadPlaceholder";
const ignoreSearchResult = async () => undefined;
export default function LocalTiptapEditor(props: LocalTiptapEditorProps) {
export default function LocalTiptapEditor(props: LocalTiptapEditorProps | MermaidRendererProps) {
return props.mode === "mermaid-renderer"
? <MermaidRenderRuntime {...props} />
: <LocalTiptapEditorImpl {...props} />;
}
const MermaidRenderRuntime = (props: MermaidRendererProps) => {
useEffect(() => {
let cancelled = false;
const renderDiagrams = async () => {
let sources: string[] = [];
try {
const parsed = JSON.parse(props.diagramsJson) as unknown;
sources = Array.isArray(parsed)
? parsed.filter((source): source is string => typeof source === "string" && source.trim().length > 0)
: [];
} catch {
sources = [];
}
const mermaid = await loadMermaid();
mermaid.initialize({
startOnLoad: false,
securityLevel: "strict",
suppressErrorRendering: true,
theme: props.theme === "dark" ? "dark" : "neutral",
flowchart: { htmlLabels: false },
});
const results: Array<{ source: string; svg: string | null }> = [];
for (const source of sources) {
try {
const valid = await mermaid.parse(source, { suppressErrors: true });
if (!valid) {
throw new Error("Invalid Mermaid diagram");
}
mermaidRenderSequence += 1;
const { svg } = await mermaid.render(`edgeever-mobile-mermaid-${mermaidRenderSequence}`, source);
results.push({ source, svg: inlineMermaidSvgStyles(svg) });
} catch {
results.push({ source, svg: null });
}
}
if (!cancelled) {
await props.onRendered(JSON.stringify(results));
}
};
void renderDiagrams().catch(() => {
if (!cancelled) {
void props.onRendered("[]");
}
});
return () => {
cancelled = true;
};
}, [props.diagramsJson, props.onRendered, props.theme]);
return null;
};
const inlineMermaidSvgStyles = (svg: string) => {
const container = document.createElement("div");
container.style.cssText = "position:fixed;left:-10000px;top:-10000px;visibility:hidden;";
container.innerHTML = svg;
document.body.append(container);
const root = container.querySelector("svg");
if (!root) {
container.remove();
return svg;
}
for (const foreignObject of root.querySelectorAll("foreignObject")) {
const label = foreignObject.textContent?.replace(/\s+/g, " ").trim();
if (!label) {
foreignObject.remove();
continue;
}
const x = Number.parseFloat(foreignObject.getAttribute("x") ?? "0");
const y = Number.parseFloat(foreignObject.getAttribute("y") ?? "0");
const width = Number.parseFloat(foreignObject.getAttribute("width") ?? "0");
const height = Number.parseFloat(foreignObject.getAttribute("height") ?? "0");
const text = document.createElementNS("http://www.w3.org/2000/svg", "text");
text.setAttribute("x", String(x + width / 2));
text.setAttribute("y", String(y + height / 2));
text.setAttribute("text-anchor", "middle");
text.setAttribute("dominant-baseline", "central");
text.setAttribute("font-size", "16px");
text.textContent = label;
foreignObject.replaceWith(text);
}
const properties = [
"color",
"fill",
"fill-opacity",
"font-family",
"font-size",
"font-style",
"font-weight",
"opacity",
"stroke",
"stroke-dasharray",
"stroke-dashoffset",
"stroke-linecap",
"stroke-linejoin",
"stroke-opacity",
"stroke-width",
"text-anchor",
] as const;
for (const element of root.querySelectorAll<SVGElement>("*")) {
const computed = getComputedStyle(element);
for (const property of properties) {
const value = computed.getPropertyValue(property);
if (value) {
element.setAttribute(property, value);
}
}
}
const serialized = new XMLSerializer().serializeToString(root);
container.remove();
return serialized;
};
function LocalTiptapEditorImpl(props: LocalTiptapEditorProps) {
const [tableMenuOpen, setTableMenuOpen] = useState(false);
const startedAtRef = useRef(performance.now());
const changeTimerRef = useRef<number | null>(null);
@@ -88,11 +228,16 @@ export default function LocalTiptapEditor(props: LocalTiptapEditorProps) {
() => createProtectedImageExtension(props.baseUrl, props.locale, (source) => onLoadResourceRef.current(source)),
[props.baseUrl, props.locale]
);
const mermaidCodeBlockExtension = useMemo(
() => createMobileCodeBlockExtension(props.locale, props.theme),
[props.locale, props.theme]
);
const editor = useEditor({
autofocus: props.autoFocus ? "end" : false,
extensions: [
StarterKit,
StarterKit.configure({ codeBlock: false }),
mermaidCodeBlockExtension,
protectedImageExtension,
TableKit.configure({
table: { renderWrapper: true },
@@ -257,6 +402,7 @@ export default function LocalTiptapEditor(props: LocalTiptapEditorProps) {
editor,
selector: ({ editor: activeEditor }) =>
(activeEditor?.isActive("bold") ? MOBILE_EDITOR_ACTIVE_FLAGS.bold : 0) |
(activeEditor?.isActive("codeBlock", { language: "mermaid" }) ? MOBILE_EDITOR_ACTIVE_FLAGS.mermaid : 0) |
(activeEditor?.isActive("bulletList") ? MOBILE_EDITOR_ACTIVE_FLAGS.bulletList : 0) |
(activeEditor?.isActive("blockquote") ? MOBILE_EDITOR_ACTIVE_FLAGS.blockquote : 0) |
(activeEditor?.isActive("table") ? MOBILE_EDITOR_ACTIVE_FLAGS.table : 0) |
@@ -323,6 +469,7 @@ export default function LocalTiptapEditor(props: LocalTiptapEditorProps) {
const toolbarIcons: Record<MobileEditorToolbarActionId, ReactNode> = {
image: <ImagePlusIcon />,
mermaid: <DiagramIcon />,
bold: <BoldIcon />,
bulletList: <ListIcon />,
blockquote: <QuoteIcon />,
@@ -337,6 +484,20 @@ export default function LocalTiptapEditor(props: LocalTiptapEditorProps) {
};
const toolbarHandlers: Record<MobileEditorToolbarActionId, () => void> = {
image: () => void insertImage(),
mermaid: () => {
if (!editor) {
return;
}
if (editor.isActive("codeBlock")) {
editor.chain().focus().updateAttributes("codeBlock", { language: "mermaid" }).run();
return;
}
editor.chain().focus().insertContent({
type: "codeBlock",
attrs: { language: "mermaid" },
content: [{ type: "text", text: "flowchart LR\n A[Start] --> B[End]" }],
}).run();
},
bold: () => editor?.chain().focus().toggleBold().run(),
bulletList: () => editor?.chain().focus().toggleBulletList().run(),
blockquote: () => editor?.chain().focus().toggleBlockquote().run(),
@@ -495,6 +656,15 @@ const BoldIcon = () => (
</EditorIcon>
);
const DiagramIcon = () => (
<EditorIcon size={18} strokeWidth={2}>
<rect height="5" rx="1" width="7" x="2" y="3" />
<rect height="5" rx="1" width="7" x="15" y="16" />
<path d="M9 5.5h3a3 3 0 0 1 3 3v5a3 3 0 0 0 3 3" />
<path d="m15 13 3 3-3 3" />
</EditorIcon>
);
const ListIcon = () => (
<EditorIcon size={18} strokeWidth={2.2}>
<path d="M3 5h.01M3 12h.01M3 19h.01M8 5h13M8 12h13M8 19h13" />
@@ -576,6 +746,134 @@ const applyImageWidth = (
return width;
};
let mermaidRenderSequence = 0;
const loadMermaid = () => {
const mermaid = (globalThis as typeof globalThis & {
mermaid?: typeof import("mermaid")["default"];
}).mermaid;
if (!mermaid) {
return Promise.reject(new Error("Mermaid runtime unavailable"));
}
return Promise.resolve(mermaid);
};
const createMobileCodeBlockExtension = (
locale: "zh-CN" | "en-US",
theme: "light" | "dark"
) => CodeBlock.extend({
addNodeView() {
return ({ node }) => {
const wrapper = document.createElement("div");
const preview = document.createElement("div");
const message = document.createElement("p");
const svgContainer = document.createElement("div");
const pre = document.createElement("pre");
const code = document.createElement("code");
preview.contentEditable = "false";
preview.className = "edgeever-mermaid-preview";
message.className = "edgeever-mermaid-message";
svgContainer.className = "edgeever-mermaid-svg";
svgContainer.setAttribute("role", "img");
svgContainer.setAttribute("aria-label", locale === "en-US" ? "Mermaid diagram preview" : "Mermaid 图表预览");
pre.append(code);
wrapper.append(preview, pre);
let currentNode = node;
let renderTimer: number | null = null;
let renderRequest = 0;
const clearRender = () => {
renderRequest += 1;
if (renderTimer !== null) {
window.clearTimeout(renderTimer);
renderTimer = null;
}
};
const renderNode = () => {
clearRender();
const language = typeof currentNode.attrs.language === "string"
? currentNode.attrs.language.toLowerCase()
: "plaintext";
const isMermaid = language === "mermaid";
wrapper.className = isMermaid ? "edgeever-mermaid-code-block" : "edgeever-code-block";
wrapper.dataset.language = language;
preview.hidden = !isMermaid;
code.setAttribute("aria-label", isMermaid
? (locale === "en-US" ? "Mermaid source" : "Mermaid 源码")
: (locale === "en-US" ? "Code source" : "代码源码"));
if (!isMermaid) {
preview.replaceChildren();
return;
}
const source = currentNode.textContent.trim();
if (!source) {
message.className = "edgeever-mermaid-message";
message.textContent = locale === "en-US" ? "Enter Mermaid source below." : "请在下方输入 Mermaid 源码。";
preview.replaceChildren(message);
return;
}
const activeRequest = renderRequest;
renderTimer = window.setTimeout(() => {
message.className = "edgeever-mermaid-message";
message.textContent = locale === "en-US" ? "Rendering diagram…" : "正在渲染图表…";
preview.replaceChildren(message);
void loadMermaid()
.then(async (mermaid) => {
mermaid.initialize({
startOnLoad: false,
securityLevel: "strict",
suppressErrorRendering: true,
theme: theme === "dark" ? "dark" : "neutral",
});
const valid = await mermaid.parse(source, { suppressErrors: true });
if (!valid) {
throw new Error("Invalid Mermaid diagram");
}
mermaidRenderSequence += 1;
return mermaid.render(`edgeever-mobile-editor-mermaid-${mermaidRenderSequence}`, source);
})
.then(({ svg }) => {
if (activeRequest !== renderRequest) {
return;
}
svgContainer.innerHTML = svg;
preview.replaceChildren(svgContainer);
})
.catch(() => {
if (activeRequest !== renderRequest) {
return;
}
message.className = "edgeever-mermaid-error";
message.textContent = locale === "en-US"
? "Unable to render this diagram. Check its syntax."
: "无法渲染此图表,请检查语法。";
preview.replaceChildren(message);
});
}, 300);
};
renderNode();
return {
dom: wrapper,
contentDOM: code,
update: (updatedNode) => {
if (updatedNode.type !== currentNode.type) {
return false;
}
currentNode = updatedNode;
renderNode();
return true;
},
destroy: clearRender,
};
};
},
});
const createMobileImageSizeControls = (
locale: "zh-CN" | "en-US",
updateWidth: (width: number) => void
@@ -977,6 +1275,15 @@ const getEditorStyles = (theme: "light" | "dark") => `
.edgeever-editor-content pre { overflow-x: auto; border-radius: 10px; padding: 14px; background: #0f172a; color: #e2e8f0; }
.edgeever-editor-content code { border-radius: 4px; padding: 2px 4px; background: ${theme === "dark" ? "#1e293b" : "#f1f5f9"}; }
.edgeever-editor-content pre code { padding: 0; background: transparent; }
.edgeever-mermaid-code-block { margin: 18px 0; overflow: hidden; border: 1px solid ${theme === "dark" ? "#334155" : "#e2e8f0"}; border-radius: 12px; background: ${theme === "dark" ? "#111827" : "#fff"}; }
.edgeever-mermaid-code-block > pre { margin: 0; border-radius: 0; border-top: 1px solid ${theme === "dark" ? "#334155" : "#e2e8f0"}; }
.edgeever-mermaid-preview { display: flex; min-height: 116px; align-items: center; justify-content: center; overflow-x: auto; padding: 14px; background: ${theme === "dark" ? "#0f172a" : "#fff"}; }
.edgeever-mermaid-preview[hidden] { display: none; }
.edgeever-mermaid-svg { width: 100%; text-align: center; }
.edgeever-mermaid-svg svg { display: block; width: 100%; max-width: 100%; height: auto; max-height: 420px; margin: auto; }
.edgeever-mermaid-message, .edgeever-mermaid-error { margin: 0; font-size: 14px; line-height: 1.5; text-align: center; }
.edgeever-mermaid-message { color: ${theme === "dark" ? "#94a3b8" : "#64748b"}; }
.edgeever-mermaid-error { color: ${theme === "dark" ? "#fda4af" : "#be123c"}; }
.edgeever-editor-content img { display: block; max-width: 100%; height: auto; margin: 14px auto; border-radius: 10px; }
.edgeever-editor-content .tableWrapper { --mobile-table-column-width: clamp(5.5rem, calc((100vw - 3rem) / 3), 14rem); width: 100%; max-width: 100%; overflow-x: auto; margin-top: 20px; margin-right: auto; margin-bottom: 20px; margin-left: 0; border: 1px solid ${theme === "dark" ? "#334155" : "#d8d8d8"}; border-radius: 2px; background: ${theme === "dark" ? "#0f172a" : "#fff"}; overscroll-behavior-inline: contain; scrollbar-color: rgba(100, 116, 139, 0.28) transparent; }
.edgeever-editor-content table { width: max-content; min-width: 100% !important; border-collapse: separate; border-spacing: 0; table-layout: fixed; }
@@ -0,0 +1,161 @@
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, type ReactNode } from "react";
import { StyleSheet, Text, useWindowDimensions, View } from "react-native";
import { SvgXml } from "react-native-svg";
import LocalTiptapEditor from "./LocalTiptapEditor";
import { getMermaidSvgAspectRatio } from "../lib/mobile-mermaid";
type MermaidResult = { source: string; svg: string | null };
type MermaidContextValue = {
register: (source: string) => () => void;
results: ReadonlyMap<string, string | null>;
};
const MermaidContext = createContext<MermaidContextValue | null>(null);
export const MobileMermaidProvider = ({
children,
theme,
}: {
children: ReactNode;
theme: "light" | "dark";
}) => {
const [sources, setSources] = useState<string[]>([]);
const [results, setResults] = useState<ReadonlyMap<string, string | null>>(new Map());
const sourceCountsRef = useRef(new Map<string, number>());
const diagramsJson = useMemo(() => JSON.stringify(sources), [sources]);
const register = useCallback((source: string) => {
const count = sourceCountsRef.current.get(source) ?? 0;
sourceCountsRef.current.set(source, count + 1);
if (count === 0) {
setSources((current) => [...current, source]);
}
return () => {
const nextCount = (sourceCountsRef.current.get(source) ?? 1) - 1;
if (nextCount > 0) {
sourceCountsRef.current.set(source, nextCount);
return;
}
sourceCountsRef.current.delete(source);
setSources((current) => current.filter((item) => item !== source));
};
}, []);
const handleRendered = useCallback(async (resultsJson: string) => {
try {
const parsed = JSON.parse(resultsJson) as MermaidResult[];
setResults(new Map(parsed.map((result) => [result.source, result.svg])));
} catch {
setResults(new Map());
}
}, []);
const contextValue = useMemo<MermaidContextValue>(() => ({
register,
results,
}), [register, results]);
useEffect(() => {
setResults(new Map());
}, [theme]);
return (
<MermaidContext.Provider value={contextValue}>
{children}
{sources.length > 0 ? (
<LocalTiptapEditor
diagramsJson={diagramsJson}
dom={{
bounces: false,
containerStyle: styles.renderer,
scrollEnabled: false,
style: styles.renderer,
}}
onRendered={handleRendered}
mode="mermaid-renderer"
theme={theme}
/>
) : null}
</MermaidContext.Provider>
);
};
export const MobileMermaidDiagram = ({
locale,
source,
theme,
}: {
locale: "zh-CN" | "en-US";
source: string;
theme: "light" | "dark";
}) => {
const context = useContext(MermaidContext);
const register = context?.register;
const { width } = useWindowDimensions();
const normalizedSource = source.trim();
useEffect(() => normalizedSource ? register?.(normalizedSource) : undefined, [normalizedSource, register]);
if (!normalizedSource) {
return <Text style={[styles.message, theme === "dark" && styles.messageDark]}>{locale === "en-US" ? "This Mermaid diagram is empty." : "此 Mermaid 图表暂无内容。"}</Text>;
}
const hasResult = context?.results.has(normalizedSource) ?? false;
const svg = context?.results.get(normalizedSource) ?? null;
if (!hasResult) {
return <Text style={[styles.message, theme === "dark" && styles.messageDark]}>{locale === "en-US" ? "Rendering diagram…" : "正在渲染图表…"}</Text>;
}
if (!svg) {
return <Text accessibilityRole="alert" style={styles.error}>{locale === "en-US" ? "Unable to render this Mermaid diagram. Check its syntax." : "无法渲染此 Mermaid 图表,请检查语法。"}</Text>;
}
const aspectRatio = getMermaidSvgAspectRatio(svg);
const availableWidth = Math.max(1, width - 48);
const height = Math.min(420, Math.max(120, availableWidth / aspectRatio));
return (
<View accessibilityLabel={locale === "en-US" ? "Mermaid diagram" : "Mermaid 图表"} accessible style={[styles.diagram, theme === "dark" && styles.diagramDark, { height }]}>
<SvgXml height="100%" width="100%" xml={svg} />
</View>
);
};
const styles = StyleSheet.create({
diagram: {
width: "100%",
marginVertical: 12,
borderWidth: 1,
borderColor: "#e2e8f0",
borderRadius: 12,
padding: 10,
backgroundColor: "#ffffff",
},
diagramDark: {
borderColor: "#334155",
backgroundColor: "#0f172a",
},
error: {
marginVertical: 10,
borderRadius: 10,
padding: 12,
color: "#be123c",
backgroundColor: "#fff1f2",
fontSize: 14,
lineHeight: 20,
},
message: {
marginVertical: 10,
borderRadius: 10,
padding: 12,
color: "#64748b",
backgroundColor: "#f8fafc",
fontSize: 14,
lineHeight: 20,
},
messageDark: {
color: "#cbd5e1",
backgroundColor: "#1e293b",
},
renderer: {
position: "absolute",
width: 1,
height: 1,
opacity: 0,
},
});
@@ -0,0 +1,23 @@
import { describe, expect, test } from "bun:test";
import {
getMermaidSvgAspectRatio,
getMobileMarkdownFenceLanguage,
trimMobileMarkdownFenceContent,
} from "./mobile-mermaid";
describe("mobile Mermaid rendering", () => {
test("recognizes Mermaid fence info case-insensitively", () => {
expect(getMobileMarkdownFenceLanguage(" Mermaid ")).toBe("mermaid");
expect(getMobileMarkdownFenceLanguage("typescript title=example")).toBe("typescript");
});
test("removes only the parser-added trailing newline", () => {
expect(trimMobileMarkdownFenceContent("flowchart LR\n A --> B\n")).toBe("flowchart LR\n A --> B");
expect(trimMobileMarkdownFenceContent("flowchart LR")).toBe("flowchart LR");
});
test("derives a stable native layout ratio from Mermaid SVG output", () => {
expect(getMermaidSvgAspectRatio('<svg viewBox="0 0 800 400"></svg>')).toBe(2);
expect(getMermaidSvgAspectRatio("<svg></svg>")).toBe(1.6);
});
});
+12
View File
@@ -0,0 +1,12 @@
export const getMobileMarkdownFenceLanguage = (sourceInfo: unknown) =>
typeof sourceInfo === "string" ? sourceInfo.trim().split(/\s+/)[0]?.toLowerCase() ?? "" : "";
export const trimMobileMarkdownFenceContent = (content: string) =>
content.endsWith("\n") ? content.slice(0, -1) : content;
export const getMermaidSvgAspectRatio = (svg: string) => {
const viewBox = /viewBox=["']\s*[-\d.]+\s+[-\d.]+\s+([\d.]+)\s+([\d.]+)\s*["']/i.exec(svg);
const width = Number(viewBox?.[1]);
const height = Number(viewBox?.[2]);
return width > 0 && height > 0 ? width / height : 1.6;
};
+1
View File
@@ -0,0 +1 @@
declare module "mermaid/dist/mermaid.min.js";
+23 -2
View File
@@ -68,6 +68,7 @@ import {
RefreshControl,
ScrollView,
StyleSheet,
Text as RNText,
type StyleProp,
Switch,
useWindowDimensions,
@@ -125,6 +126,8 @@ import { showEdgeEverKeyboard } from "../../modules/edgeever-keyboard";
import LocalTiptapEditor, { type LocalTiptapEditorRef } from "../components/LocalTiptapEditor";
import { resolveMobileThemeStyles, useMobileTheme, type MobileResolvedTheme } from "../lib/mobile-theme";
import { MobileUpdateCard } from "../components/MobileUpdateCard";
import { MobileMermaidDiagram, MobileMermaidProvider } from "../components/MobileMermaid";
import { getMobileMarkdownFenceLanguage, trimMobileMarkdownFenceContent } from "../lib/mobile-mermaid";
const ALL_NOTES_ID = "all";
const DEFAULT_MEMO_TITLE = "无标题笔记";
@@ -4025,6 +4028,7 @@ const MemoDetailModal = ({
}) => {
const { session } = useSession();
const { resolvedTheme } = useMobileTheme();
const { resolvedLocale } = useMobileLocale();
const { width: viewportWidth } = useWindowDimensions();
const safeAreaInsets = useSafeAreaInsets();
const [actionsOpen, setActionsOpen] = useState(false);
@@ -4069,6 +4073,21 @@ const MemoDetailModal = ({
};
return {
fence: (node, _children, _parents, markdownStyles, inheritedStyles = {}) => {
const language = getMobileMarkdownFenceLanguage((node as ASTNode & { sourceInfo?: string }).sourceInfo);
const content = trimMobileMarkdownFenceContent(node.content);
if (language === "mermaid") {
return (
<MobileMermaidDiagram
key={node.key}
locale={resolvedLocale}
source={content}
theme={resolvedTheme}
/>
);
}
return <RNText key={node.key} style={[inheritedStyles, markdownStyles.fence]}>{content}</RNText>;
},
image: (node, _children, _parents, markdownStyles) => (
<AuthenticatedResourceImage
alt={String(node.attributes.alt ?? "")}
@@ -4101,7 +4120,7 @@ const MemoDetailModal = ({
td: (node, children, parents, markdownStyles) => renderTableCell(node, children, parents, markdownStyles, false),
th: (node, children, parents, markdownStyles) => renderTableCell(node, children, parents, markdownStyles, true),
};
}, [session, viewportWidth]);
}, [resolvedLocale, resolvedTheme, session, viewportWidth]);
const detailText = memo?.contentMarkdown || memo?.contentText || "没有正文内容";
const searchMatches = useMemo(() => getTextSearchMatches(detailText, searchQuery), [detailText, searchQuery]);
const searchMatchLabel = searchQuery.trim() ? `${searchMatches.length > 0 ? activeMatchIndex + 1 : 0}/${searchMatches.length}` : "0/0";
@@ -4221,7 +4240,9 @@ const MemoDetailModal = ({
{searchOpen && searchQuery.trim() ? (
<HighlightedDetailText activeIndex={activeMatchIndex} matches={searchMatches} text={detailText} />
) : (
<Markdown rules={detailMarkdownRules} style={themedDetailMarkdownStyles}>{detailText}</Markdown>
<MobileMermaidProvider theme={resolvedTheme}>
<Markdown rules={detailMarkdownRules} style={themedDetailMarkdownStyles}>{detailText}</Markdown>
</MobileMermaidProvider>
)}
</ScrollView>
) : (
+2 -1
View File
@@ -5,6 +5,7 @@
"type": "module",
"dependencies": {
"@tiptap/extension-code-block-lowlight": "3.27.1",
"lowlight": "^3.3.0"
"lowlight": "^3.3.0",
"mermaid": "^11.16.0"
}
}
+2 -3
View File
@@ -2,7 +2,6 @@ import { useRef, useState, useEffect, useCallback, useMemo, type PointerEvent as
import { useQueryClient, useMutation } from "@tanstack/react-query";
import { NodeViewWrapper, ReactNodeViewRenderer, useEditor, EditorContent, type Editor, type NodeViewProps } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
import Image from "@tiptap/extension-image";
import Placeholder from "@tiptap/extension-placeholder";
import { TableKit } from "@tiptap/extension-table";
@@ -75,7 +74,7 @@ import {
clampImageWidth,
parseImageWidth,
} from "@edgeever/shared/image-display";
import { codeBlockLowlight } from "@/lib/code-block";
import { codeBlockLowlight, EdgeEverCodeBlock } from "@/lib/code-block";
import { compressImageForUpload } from "@/lib/image-compression";
import { localDb, type MemoUpdateSyncPayload } from "@/lib/local-db";
import { getMemoUpdateQueueId, isMemoUpdateAlreadyApplied, queueMemoUpdate, shouldQueueMemoSaveError } from "@/lib/sync-queue";
@@ -1329,7 +1328,7 @@ const RichEditorPane = ({
const editor = useEditor({
extensions: [
StarterKit.configure({ codeBlock: false }),
CodeBlockLowlight.configure({ lowlight: codeBlockLowlight, defaultLanguage: "plaintext" }),
EdgeEverCodeBlock.configure({ lowlight: codeBlockLowlight, defaultLanguage: "plaintext" }),
ResizableImage.configure({
allowBase64: false,
inline: false,
+33
View File
@@ -12,6 +12,7 @@ import {
ListOrdered,
Quote,
SquareCode,
Workflow,
Minus,
} from "lucide-react";
import { cn } from "@/lib/utils";
@@ -99,6 +100,30 @@ const toggleCodeBlock = (editor: Editor) => {
.run();
};
const insertMermaidDiagram = (editor: Editor) => {
if (editor.isActive("codeBlock")) {
editor.chain().focus().updateAttributes("codeBlock", { language: "mermaid" }).run();
return;
}
const { from, to } = editor.state.selection;
const selectedText = editor.state.doc.textBetween(from, to, "\n", "\n").trim();
const source = selectedText || "flowchart LR\n A[Start] --> B[End]";
editor
.chain()
.focus()
.insertContentAt(
{ from, to },
{
type: "codeBlock",
attrs: { language: "mermaid" },
content: [{ type: "text", text: source }],
}
)
.run();
};
export const EditorToolbar = ({
editor,
readOnly,
@@ -315,6 +340,14 @@ export const EditorToolbar = ({
>
<SquareCode className="h-4 w-4" />
</EditorToolbarButton>
<EditorToolbarButton
title={t("editorToolbar.mermaidDiagram")}
active={codeBlockActive && codeBlockLanguage === "mermaid"}
disabled={disabled}
onClick={() => run(insertMermaidDiagram)}
>
<Workflow className="h-4 w-4" />
</EditorToolbarButton>
{showCodeLanguageSelector && (
<Select
value={codeBlockLanguage}
@@ -0,0 +1,111 @@
import { useEffect, useState } from "react";
import { NodeViewContent, NodeViewWrapper, type NodeViewProps } from "@tiptap/react";
import { useTranslation } from "react-i18next";
type MermaidModule = typeof import("mermaid")["default"];
let mermaidModulePromise: Promise<MermaidModule> | null = null;
let mermaidRenderSequence = 0;
const loadMermaid = () => {
if (!mermaidModulePromise) {
mermaidModulePromise = import("mermaid").then(({ default: mermaid }) => {
mermaid.initialize({
startOnLoad: false,
securityLevel: "strict",
suppressErrorRendering: true,
theme: "neutral",
});
return mermaid;
});
}
return mermaidModulePromise;
};
export const MermaidCodeBlock = ({ editor, node }: NodeViewProps) => {
const { t } = useTranslation();
const language = typeof node.attrs.language === "string" ? node.attrs.language.toLowerCase() : "plaintext";
const source = node.textContent.trim();
const isMermaid = language === "mermaid";
const [svg, setSvg] = useState("");
const [renderState, setRenderState] = useState<"idle" | "loading" | "ready" | "error">("idle");
useEffect(() => {
if (!isMermaid || !source) {
setSvg("");
setRenderState("idle");
return;
}
let cancelled = false;
const timer = window.setTimeout(() => {
setRenderState("loading");
void loadMermaid()
.then(async (mermaid) => {
const valid = await mermaid.parse(source, { suppressErrors: true });
if (!valid) {
throw new Error("Invalid Mermaid diagram");
}
mermaidRenderSequence += 1;
return mermaid.render(`edgeever-mermaid-${mermaidRenderSequence}`, source);
})
.then(({ svg: nextSvg }) => {
if (!cancelled) {
setSvg(nextSvg);
setRenderState("ready");
}
})
.catch(() => {
if (!cancelled) {
setSvg("");
setRenderState("error");
}
});
}, 300);
return () => {
cancelled = true;
window.clearTimeout(timer);
};
}, [isMermaid, source]);
return (
<NodeViewWrapper
className={isMermaid ? "edgeever-mermaid-code-block" : "edgeever-code-block"}
data-language={language}
>
{isMermaid && (
<div className="edgeever-mermaid-preview" contentEditable={false}>
{!source && <p className="edgeever-mermaid-message">{t("editorToolbar.mermaidEmpty")}</p>}
{source && renderState === "loading" && !svg && (
<p className="edgeever-mermaid-message">{t("editorToolbar.mermaidRendering")}</p>
)}
{renderState === "error" && (
<p className="edgeever-mermaid-error" role="alert">
{t("editorToolbar.mermaidInvalid")}
</p>
)}
{svg && (
<div
className="edgeever-mermaid-svg"
role="img"
aria-label={t("editorToolbar.mermaidPreview")}
dangerouslySetInnerHTML={{ __html: svg }}
/>
)}
</div>
)}
<NodeViewContent
className={isMermaid ? "edgeever-code-source edgeever-mermaid-source" : "edgeever-code-source"}
role="textbox"
aria-label={isMermaid ? t("editorToolbar.mermaidSource") : undefined}
aria-multiline="true"
aria-readonly={!editor.isEditable}
/>
</NodeViewWrapper>
);
};
@@ -1,4 +1,4 @@
import { Bold, Check, ChevronDown, ImagePlus, List, Minus, Quote, Table2 } from "lucide-react";
import { Bold, Check, ChevronDown, ImagePlus, List, Minus, Quote, Table2, Workflow } from "lucide-react";
import {
MOBILE_EDITOR_TOOLBAR_ACTIONS,
getMobileEditorTableMenuCopy,
@@ -40,9 +40,11 @@ export const MobileEditorToolbar = ({
boldActive,
bulletListActive,
blockquoteActive,
mermaidActive,
tableActive,
tableHeaderActive,
onPickImage,
onInsertMermaid,
onToggleBold,
onToggleBulletList,
onToggleBlockquote,
@@ -53,9 +55,11 @@ export const MobileEditorToolbar = ({
boldActive: boolean;
bulletListActive: boolean;
blockquoteActive: boolean;
mermaidActive: boolean;
tableActive: boolean;
tableHeaderActive: boolean;
onPickImage: () => void;
onInsertMermaid: () => void;
onToggleBold: () => void;
onToggleBulletList: () => void;
onToggleBlockquote: () => void;
@@ -66,6 +70,7 @@ export const MobileEditorToolbar = ({
const tableMenuCopy = getMobileEditorTableMenuCopy("zh-CN");
const icons: Record<MobileEditorToolbarActionId, ReactNode> = {
image: <ImagePlus aria-hidden="true" size={18} strokeWidth={2} />,
mermaid: <Workflow aria-hidden="true" size={18} strokeWidth={2} />,
bold: <Bold aria-hidden="true" size={17} strokeWidth={2.4} />,
bulletList: <List aria-hidden="true" size={18} strokeWidth={2.2} />,
blockquote: <Quote aria-hidden="true" size={17} strokeWidth={2.2} />,
@@ -80,6 +85,7 @@ export const MobileEditorToolbar = ({
};
const handlers: Record<MobileEditorToolbarActionId, () => void> = {
image: onPickImage,
mermaid: onInsertMermaid,
bold: onToggleBold,
bulletList: onToggleBulletList,
blockquote: onToggleBlockquote,
@@ -96,6 +102,7 @@ export const MobileEditorToolbar = ({
bold: boldActive,
bulletList: bulletListActive,
blockquote: blockquoteActive,
mermaid: mermaidActive,
};
useEffect(() => {
@@ -39,6 +39,7 @@ import {
type MobileEditorSaveState,
} from "@/lib/mobile-editor-standalone";
import { getMemoUpdateQueueId, isMemoUpdateAlreadyApplied, queueMemoUpdate, shouldQueueMemoSaveError } from "@/lib/sync-queue";
import { EdgeEverCodeBlock } from "@/lib/code-block";
type ListNotebooksResponse = {
notebooks: Notebook[];
@@ -167,7 +168,8 @@ export const MobileStandaloneTiptapEditor = ({
const editor = useEditor({
extensions: [
StarterKit,
StarterKit.configure({ codeBlock: false }),
EdgeEverCodeBlock,
Image.configure({
allowBase64: false,
inline: false,
@@ -871,9 +873,23 @@ export const MobileStandaloneTiptapEditor = ({
boldActive={Boolean(editor?.isActive("bold"))}
bulletListActive={Boolean(editor?.isActive("bulletList"))}
blockquoteActive={Boolean(editor?.isActive("blockquote"))}
mermaidActive={Boolean(editor?.isActive("codeBlock", { language: "mermaid" }))}
tableActive={tableActive}
tableHeaderActive={tableHeaderActive}
onPickImage={() => imageInputRef.current?.click()}
onInsertMermaid={() => runEditorCommand(() => {
if (!editor) {
return false;
}
if (editor.isActive("codeBlock")) {
return editor.chain().focus().updateAttributes("codeBlock", { language: "mermaid" }).run();
}
return editor.chain().focus().insertContent({
type: "codeBlock",
attrs: { language: "mermaid" },
content: [{ type: "text", text: "flowchart LR\n A[Start] --> B[End]" }],
}).run();
})}
onToggleBold={() => runEditorCommand(() => editor?.chain().focus().toggleBold().run() ?? false)}
onToggleBulletList={() => runEditorCommand(() => editor?.chain().focus().toggleBulletList().run() ?? false)}
onToggleBlockquote={() => runEditorCommand(() => editor?.chain().focus().toggleBlockquote().run() ?? false)}
+10
View File
@@ -1,7 +1,16 @@
import { common, createLowlight } from "lowlight";
import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
import { ReactNodeViewRenderer } from "@tiptap/react";
import { MermaidCodeBlock } from "@/components/MermaidCodeBlock";
export const codeBlockLowlight = createLowlight(common);
export const EdgeEverCodeBlock = CodeBlockLowlight.extend({
addNodeView() {
return ReactNodeViewRenderer(MermaidCodeBlock);
},
});
export const CODE_BLOCK_LANGUAGES = [
{ value: "plaintext", label: "Plain text" },
{ value: "bash", label: "Bash" },
@@ -10,6 +19,7 @@ export const CODE_BLOCK_LANGUAGES = [
{ value: "javascript", label: "JavaScript" },
{ value: "json", label: "JSON" },
{ value: "markdown", label: "Markdown" },
{ value: "mermaid", label: "Mermaid" },
{ value: "python", label: "Python" },
{ value: "sql", label: "SQL" },
{ value: "typescript", label: "TypeScript" },
+82
View File
@@ -261,6 +261,69 @@ textarea {
color: inherit;
}
.ProseMirror .edgeever-code-block,
.ProseMirror .edgeever-mermaid-code-block {
margin: 0 0 1rem;
}
.ProseMirror .edgeever-code-source {
overflow-x: auto;
border: 1px solid #d9eadf;
border-radius: 8px;
background: #f7fbf8;
padding: 0.9rem 1rem;
color: #1e293b;
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 0.875em;
white-space: pre;
}
.ProseMirror .edgeever-mermaid-code-block {
overflow: hidden;
border: 1px solid #d9eadf;
border-radius: 10px;
background: #fff;
}
.ProseMirror .edgeever-mermaid-preview {
display: flex;
min-height: 8rem;
align-items: center;
justify-content: center;
overflow-x: auto;
padding: 1rem;
background: #fff;
}
.ProseMirror .edgeever-mermaid-message,
.ProseMirror .edgeever-mermaid-error {
margin: 0;
font-size: 0.82rem;
color: #64748b;
}
.ProseMirror .edgeever-mermaid-error {
color: #be123c;
}
.ProseMirror .edgeever-mermaid-svg {
display: flex;
width: 100%;
justify-content: center;
}
.ProseMirror .edgeever-mermaid-svg svg {
display: block;
max-width: 100%;
height: auto;
}
.ProseMirror .edgeever-mermaid-source {
border: 0;
border-top: 1px solid #d9eadf;
border-radius: 0;
}
/* Highlight.js-compatible token classes emitted by Tiptap/lowlight. */
.ProseMirror pre .hljs-comment,
.ProseMirror pre .hljs-quote {
@@ -803,6 +866,25 @@ textarea {
color: #cbd5e1;
}
:root.dark .ProseMirror .edgeever-mermaid-code-block {
border-color: #166534;
background: #13261a;
}
:root.dark .ProseMirror .edgeever-code-source {
border-color: #166534;
background: #13261a;
color: #cbd5e1;
}
:root.dark .ProseMirror .edgeever-mermaid-preview {
background: #f8fafc;
}
:root.dark .ProseMirror .edgeever-mermaid-source {
border-top-color: #166534;
}
:root.dark .markdown-content {
color: #cbd5e1;
}
+18 -1
View File
@@ -195,6 +195,21 @@ export default defineConfig({
test: /node_modules[\\/](class-variance-authority|clsx|tailwind-merge)[\\/]/,
priority: 12,
},
{
name: "vendor-mermaid-d3",
test: /[\\/](?:d3(?:-[^\\/@]+)?|internmap|delaunator|robust-predicates)(?:@|[\\/])/,
priority: 11,
},
{
name: "vendor-mermaid-layout",
test: /[\\/](?:cytoscape(?:-[^\\/@]+)?|dagre-d3-es|graphlib|roughjs|khroma|@upsetjs[\\/]venn\.js)(?:@|[\\/])/,
priority: 11,
},
{
name: "vendor-mermaid-render",
test: /[\\/](?:@mermaid-js[\\/](?:parser|tiny)|katex|dompurify|stylis|dayjs|@iconify[\\/]utils)(?:@|[\\/])/,
priority: 11,
},
{
name: "ui-primitives",
test: /src[\\/]components[\\/]ui[\\/]/,
@@ -202,7 +217,9 @@ export default defineConfig({
},
{
name: "vendor",
test: /node_modules[\\/]/,
// Keep Mermaid's internally lazy-loaded diagram modules out of the
// catch-all vendor chunk so they remain on-demand.
test: /^(?!.*(?:[\\/]mermaid@|node_modules[\\/]mermaid[\\/])).*node_modules[\\/]/,
priority: 5,
},
],
+216 -4
View File
@@ -90,6 +90,7 @@
"@tanstack/query-async-storage-persister": "^5.101.2",
"@tanstack/react-query": "latest",
"@tanstack/react-query-persist-client": "^5.101.2",
"@tiptap/extension-code-block": "3.27.1",
"@tiptap/extension-image": "3.27.1",
"@tiptap/extension-placeholder": "3.27.1",
"@tiptap/extension-table": "3.27.1",
@@ -108,6 +109,7 @@
"expo-sqlite": "~57.0.1",
"expo-status-bar": "latest",
"expo-updates": "~57.0.8",
"mermaid": "^11.16.0",
"react": "19.2.3",
"react-dom": "19.2.3",
"react-native": "latest",
@@ -163,6 +165,7 @@
"dependencies": {
"@tiptap/extension-code-block-lowlight": "3.27.1",
"lowlight": "^3.3.0",
"mermaid": "^11.16.0",
},
},
"packages/client": {
@@ -183,6 +186,9 @@
},
},
},
"patchedDependencies": {
"mermaid@11.16.0": "patches/mermaid@11.16.0.patch",
},
"packages": {
"@adobe/css-tools": ["@adobe/css-tools@4.5.0", "", {}, "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q=="],
@@ -442,8 +448,12 @@
"@babel/types": ["@babel/types@7.29.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" } }, "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA=="],
"@braintree/sanitize-url": ["@braintree/sanitize-url@7.1.2", "", {}, "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA=="],
"@capsizecss/unpack": ["@capsizecss/unpack@4.0.1", "", { "dependencies": { "fontkitten": "^1.0.3" } }, "sha512-CuNiSqg7+e1cO/GjffyMOm5Tt2jUF9CWHHnvQ/UkqvtkGfHdgwEC0wpmq7fkN3gxwpRnrAN0WzO3vREKmNolMQ=="],
"@chevrotain/types": ["@chevrotain/types@11.1.2", "", {}, "sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw=="],
"@clack/core": ["@clack/core@0.3.5", "", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-5cfhQNH+1VQ2xLQlmzXMqUoiaH0lRBq9/CLW9lTyMbuKLC3+xEK01tHVvyut++mLOn5urSHmkm6I0Lg9MaJSTQ=="],
"@clack/prompts": ["@clack/prompts@0.6.3", "", { "dependencies": { "@clack/core": "^0.3.2", "is-unicode-supported": "*", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-AM+kFmAHawpUQv2q9+mcB6jLKxXGjgu/r2EQjEwujgpCdzrST6BJqYw00GRn56/L/Izw5U7ImoLmy00X/r80Pw=="],
@@ -652,7 +662,7 @@
"@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
"@iconify/utils": ["@iconify/utils@2.3.0", "", { "dependencies": { "@antfu/install-pkg": "^1.0.0", "@antfu/utils": "^8.1.0", "@iconify/types": "^2.0.0", "debug": "^4.4.0", "globals": "^15.14.0", "kolorist": "^1.8.0", "local-pkg": "^1.0.0", "mlly": "^1.7.4" } }, "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA=="],
"@iconify/utils": ["@iconify/utils@3.1.4", "", { "dependencies": { "@antfu/install-pkg": "^1.1.0", "@iconify/types": "^2.0.0", "import-meta-resolve": "^4.2.0" } }, "sha512-b1S7B1k9ohZ+iNTi2ATxbRYG9fTrJmUT0rc46bvVnNxqNRGW7dyo/vRREwyniI5IRN2RSJHDcm+s3BjWrSAjHw=="],
"@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="],
@@ -742,6 +752,8 @@
"@mdx-js/mdx": ["@mdx-js/mdx@3.1.1", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdx": "^2.0.0", "acorn": "^8.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-util-scope": "^1.0.0", "estree-walker": "^3.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", "recma-build-jsx": "^1.0.0", "recma-jsx": "^1.0.0", "recma-stringify": "^1.0.0", "rehype-recma": "^1.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "source-map": "^0.7.0", "unified": "^11.0.0", "unist-util-position-from-estree": "^2.0.0", "unist-util-stringify-position": "^4.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ=="],
"@mermaid-js/parser": ["@mermaid-js/parser@1.2.0", "", { "dependencies": { "@chevrotain/types": "~11.1.2" } }, "sha512-oYPyv8A4As1yH5Bx+04iQEQxXuIQDe0GKCNSRgao6z8AM9jixXIfP0vsppRLvGf+nKIOb9/LdpWA4YuJiVvESA=="],
"@mixmark-io/domino": ["@mixmark-io/domino@2.2.0", "", {}, "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw=="],
"@mozilla/readability": ["@mozilla/readability@0.6.0", "", {}, "sha512-juG5VWh4qAivzTAeMzvY9xs9HY5rAcr2E4I7tiSSCokRFi7XIZCAu92ZkSTsIj1OPceCifL3cpfteP3pDT9/QQ=="],
@@ -1128,12 +1140,76 @@
"@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],
"@types/d3": ["@types/d3@7.4.3", "", { "dependencies": { "@types/d3-array": "*", "@types/d3-axis": "*", "@types/d3-brush": "*", "@types/d3-chord": "*", "@types/d3-color": "*", "@types/d3-contour": "*", "@types/d3-delaunay": "*", "@types/d3-dispatch": "*", "@types/d3-drag": "*", "@types/d3-dsv": "*", "@types/d3-ease": "*", "@types/d3-fetch": "*", "@types/d3-force": "*", "@types/d3-format": "*", "@types/d3-geo": "*", "@types/d3-hierarchy": "*", "@types/d3-interpolate": "*", "@types/d3-path": "*", "@types/d3-polygon": "*", "@types/d3-quadtree": "*", "@types/d3-random": "*", "@types/d3-scale": "*", "@types/d3-scale-chromatic": "*", "@types/d3-selection": "*", "@types/d3-shape": "*", "@types/d3-time": "*", "@types/d3-time-format": "*", "@types/d3-timer": "*", "@types/d3-transition": "*", "@types/d3-zoom": "*" } }, "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww=="],
"@types/d3-array": ["@types/d3-array@3.2.2", "", {}, "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw=="],
"@types/d3-axis": ["@types/d3-axis@3.0.6", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw=="],
"@types/d3-brush": ["@types/d3-brush@3.0.6", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A=="],
"@types/d3-chord": ["@types/d3-chord@3.0.6", "", {}, "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg=="],
"@types/d3-color": ["@types/d3-color@3.1.3", "", {}, "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A=="],
"@types/d3-contour": ["@types/d3-contour@3.0.6", "", { "dependencies": { "@types/d3-array": "*", "@types/geojson": "*" } }, "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg=="],
"@types/d3-delaunay": ["@types/d3-delaunay@6.0.4", "", {}, "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw=="],
"@types/d3-dispatch": ["@types/d3-dispatch@3.0.7", "", {}, "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA=="],
"@types/d3-drag": ["@types/d3-drag@3.0.7", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ=="],
"@types/d3-dsv": ["@types/d3-dsv@3.0.7", "", {}, "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g=="],
"@types/d3-ease": ["@types/d3-ease@3.0.2", "", {}, "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA=="],
"@types/d3-fetch": ["@types/d3-fetch@3.0.7", "", { "dependencies": { "@types/d3-dsv": "*" } }, "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA=="],
"@types/d3-force": ["@types/d3-force@3.0.10", "", {}, "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw=="],
"@types/d3-format": ["@types/d3-format@3.0.4", "", {}, "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g=="],
"@types/d3-geo": ["@types/d3-geo@3.1.0", "", { "dependencies": { "@types/geojson": "*" } }, "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ=="],
"@types/d3-hierarchy": ["@types/d3-hierarchy@3.1.7", "", {}, "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg=="],
"@types/d3-interpolate": ["@types/d3-interpolate@3.0.4", "", { "dependencies": { "@types/d3-color": "*" } }, "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA=="],
"@types/d3-path": ["@types/d3-path@3.1.1", "", {}, "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg=="],
"@types/d3-polygon": ["@types/d3-polygon@3.0.2", "", {}, "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA=="],
"@types/d3-quadtree": ["@types/d3-quadtree@3.0.6", "", {}, "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg=="],
"@types/d3-random": ["@types/d3-random@3.0.4", "", {}, "sha512-UHYId5WTCx4L4YNel7NU00XUXXgvgpgZOvp10PuvsQENjMDXhh2RyFc0KBjO7B45ne4Ha1yVH7ii0vnzKkuzWA=="],
"@types/d3-scale": ["@types/d3-scale@4.0.9", "", { "dependencies": { "@types/d3-time": "*" } }, "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw=="],
"@types/d3-scale-chromatic": ["@types/d3-scale-chromatic@3.1.0", "", {}, "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ=="],
"@types/d3-selection": ["@types/d3-selection@3.0.11", "", {}, "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w=="],
"@types/d3-shape": ["@types/d3-shape@3.1.8", "", { "dependencies": { "@types/d3-path": "*" } }, "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w=="],
"@types/d3-time": ["@types/d3-time@3.0.4", "", {}, "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g=="],
"@types/d3-time-format": ["@types/d3-time-format@4.0.3", "", {}, "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg=="],
"@types/d3-timer": ["@types/d3-timer@3.0.2", "", {}, "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw=="],
"@types/d3-transition": ["@types/d3-transition@3.0.9", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg=="],
"@types/d3-zoom": ["@types/d3-zoom@3.0.8", "", { "dependencies": { "@types/d3-interpolate": "*", "@types/d3-selection": "*" } }, "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw=="],
"@types/debug": ["@types/debug@4.1.13", "", { "dependencies": { "@types/ms": "*" } }, "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw=="],
"@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="],
"@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="],
"@types/geojson": ["@types/geojson@7946.0.16", "", {}, "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="],
"@types/hammerjs": ["@types/hammerjs@2.0.46", "", {}, "sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw=="],
"@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="],
@@ -1184,6 +1260,8 @@
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.2", "", {}, "sha512-5jsZFwgR5rTdKwidH9Qmat75RKwqfpKlWWB1frDkljN127mwqBu8K0PYo7/hFpF03IEJpfVPpCQDY/eDx3iHvA=="],
"@upsetjs/venn.js": ["@upsetjs/venn.js@2.0.0", "", { "optionalDependencies": { "d3-selection": "^3.0.0", "d3-transition": "^3.0.1" } }, "sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw=="],
"@vitejs/plugin-react": ["@vitejs/plugin-react@6.0.3", "", { "dependencies": { "@rolldown/pluginutils": "^1.0.1" }, "peerDependencies": { "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", "babel-plugin-react-compiler": "^1.0.0", "vite": "^8.0.0" }, "optionalPeers": ["@rolldown/plugin-babel", "babel-plugin-react-compiler"] }, "sha512-vmFvco5/QuC2f9Oj+wTk0+9XeDFkHxSamwZKYc7MxYwKICfvUvlMhqKI0VuICPltGqh1neqBKDvO4kes1ya8vg=="],
"@volar/kit": ["@volar/kit@2.4.28", "", { "dependencies": { "@volar/language-service": "2.4.28", "@volar/typescript": "2.4.28", "typesafe-path": "^0.2.2", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.8" }, "peerDependencies": { "typescript": "*" } }, "sha512-cKX4vK9dtZvDRaAzeoUdaAJEew6IdxHNCRrdp5Kvcl6zZOqb6jTOfk3kXkIkG3T7oTFXguEMt5+9ptyqYR84Pg=="],
@@ -1438,6 +1516,8 @@
"core-js-compat": ["core-js-compat@3.49.0", "", { "dependencies": { "browserslist": "^4.28.1" } }, "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA=="],
"cose-base": ["cose-base@1.0.3", "", { "dependencies": { "layout-base": "^1.0.0" } }, "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg=="],
"cross-fetch": ["cross-fetch@3.2.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q=="],
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
@@ -1466,12 +1546,86 @@
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
"cytoscape": ["cytoscape@3.34.0", "", {}, "sha512-62rNSrioXw93uliKFBwjukeQyeWwH2PqDrTac31r2P6464u3AUvTk0xS4LVvT251g7IgkFunrI48ZEZGjywSOg=="],
"cytoscape-cose-bilkent": ["cytoscape-cose-bilkent@4.1.0", "", { "dependencies": { "cose-base": "^1.0.0" }, "peerDependencies": { "cytoscape": "^3.2.0" } }, "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ=="],
"cytoscape-fcose": ["cytoscape-fcose@2.2.0", "", { "dependencies": { "cose-base": "^2.2.0" }, "peerDependencies": { "cytoscape": "^3.2.0" } }, "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ=="],
"d3": ["d3@7.9.0", "", { "dependencies": { "d3-array": "3", "d3-axis": "3", "d3-brush": "3", "d3-chord": "3", "d3-color": "3", "d3-contour": "4", "d3-delaunay": "6", "d3-dispatch": "3", "d3-drag": "3", "d3-dsv": "3", "d3-ease": "3", "d3-fetch": "3", "d3-force": "3", "d3-format": "3", "d3-geo": "3", "d3-hierarchy": "3", "d3-interpolate": "3", "d3-path": "3", "d3-polygon": "3", "d3-quadtree": "3", "d3-random": "3", "d3-scale": "4", "d3-scale-chromatic": "3", "d3-selection": "3", "d3-shape": "3", "d3-time": "3", "d3-time-format": "4", "d3-timer": "3", "d3-transition": "3", "d3-zoom": "3" } }, "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA=="],
"d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="],
"d3-axis": ["d3-axis@3.0.0", "", {}, "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw=="],
"d3-brush": ["d3-brush@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-drag": "2 - 3", "d3-interpolate": "1 - 3", "d3-selection": "3", "d3-transition": "3" } }, "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ=="],
"d3-chord": ["d3-chord@3.0.1", "", { "dependencies": { "d3-path": "1 - 3" } }, "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g=="],
"d3-color": ["d3-color@3.1.0", "", {}, "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="],
"d3-contour": ["d3-contour@4.0.2", "", { "dependencies": { "d3-array": "^3.2.0" } }, "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA=="],
"d3-delaunay": ["d3-delaunay@6.0.4", "", { "dependencies": { "delaunator": "5" } }, "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A=="],
"d3-dispatch": ["d3-dispatch@3.0.1", "", {}, "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg=="],
"d3-drag": ["d3-drag@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-selection": "3" } }, "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg=="],
"d3-dsv": ["d3-dsv@3.0.1", "", { "dependencies": { "commander": "7", "iconv-lite": "0.6", "rw": "1" }, "bin": { "csv2json": "bin/dsv2json.js", "csv2tsv": "bin/dsv2dsv.js", "dsv2dsv": "bin/dsv2dsv.js", "dsv2json": "bin/dsv2json.js", "json2csv": "bin/json2dsv.js", "json2dsv": "bin/json2dsv.js", "json2tsv": "bin/json2dsv.js", "tsv2csv": "bin/dsv2dsv.js", "tsv2json": "bin/dsv2json.js" } }, "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q=="],
"d3-ease": ["d3-ease@3.0.1", "", {}, "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w=="],
"d3-fetch": ["d3-fetch@3.0.1", "", { "dependencies": { "d3-dsv": "1 - 3" } }, "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw=="],
"d3-force": ["d3-force@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-quadtree": "1 - 3", "d3-timer": "1 - 3" } }, "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg=="],
"d3-format": ["d3-format@3.1.2", "", {}, "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg=="],
"d3-geo": ["d3-geo@3.1.1", "", { "dependencies": { "d3-array": "2.5.0 - 3" } }, "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q=="],
"d3-hierarchy": ["d3-hierarchy@3.1.2", "", {}, "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA=="],
"d3-interpolate": ["d3-interpolate@3.0.1", "", { "dependencies": { "d3-color": "1 - 3" } }, "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g=="],
"d3-path": ["d3-path@3.1.0", "", {}, "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ=="],
"d3-polygon": ["d3-polygon@3.0.1", "", {}, "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg=="],
"d3-quadtree": ["d3-quadtree@3.0.1", "", {}, "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw=="],
"d3-random": ["d3-random@3.0.1", "", {}, "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ=="],
"d3-sankey": ["d3-sankey@0.12.3", "", { "dependencies": { "d3-array": "1 - 2", "d3-shape": "^1.2.0" } }, "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ=="],
"d3-scale": ["d3-scale@4.0.2", "", { "dependencies": { "d3-array": "2.10.0 - 3", "d3-format": "1 - 3", "d3-interpolate": "1.2.0 - 3", "d3-time": "2.1.1 - 3", "d3-time-format": "2 - 4" } }, "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ=="],
"d3-scale-chromatic": ["d3-scale-chromatic@3.1.0", "", { "dependencies": { "d3-color": "1 - 3", "d3-interpolate": "1 - 3" } }, "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ=="],
"d3-selection": ["d3-selection@3.0.0", "", {}, "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ=="],
"d3-shape": ["d3-shape@3.2.0", "", { "dependencies": { "d3-path": "^3.1.0" } }, "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA=="],
"d3-time": ["d3-time@3.1.0", "", { "dependencies": { "d3-array": "2 - 3" } }, "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q=="],
"d3-time-format": ["d3-time-format@4.1.0", "", { "dependencies": { "d3-time": "1 - 3" } }, "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg=="],
"d3-timer": ["d3-timer@3.0.1", "", {}, "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA=="],
"d3-transition": ["d3-transition@3.0.1", "", { "dependencies": { "d3-color": "1 - 3", "d3-dispatch": "1 - 3", "d3-ease": "1 - 3", "d3-interpolate": "1 - 3", "d3-timer": "1 - 3" }, "peerDependencies": { "d3-selection": "2 - 3" } }, "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w=="],
"d3-zoom": ["d3-zoom@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-drag": "2 - 3", "d3-interpolate": "1 - 3", "d3-selection": "2 - 3", "d3-transition": "2 - 3" } }, "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw=="],
"dagre-d3-es": ["dagre-d3-es@7.0.14", "", { "dependencies": { "d3": "^7.9.0", "lodash-es": "^4.17.21" } }, "sha512-P4rFMVq9ESWqmOgK+dlXvOtLwYg0i7u0HBGJER0LZDJT2VHIPAMZ/riPxqJceWMStH5+E61QxFra9kIS3AqdMg=="],
"data-view-buffer": ["data-view-buffer@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ=="],
"data-view-byte-length": ["data-view-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ=="],
"data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="],
"dayjs": ["dayjs@1.11.21", "", {}, "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA=="],
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" }, "peerDependencies": { "supports-color": "*" }, "optionalPeers": ["supports-color"] }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
"decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="],
@@ -1488,6 +1642,8 @@
"defu": ["defu@6.1.7", "", {}, "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ=="],
"delaunator": ["delaunator@5.1.0", "", { "dependencies": { "robust-predicates": "^3.0.2" } }, "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ=="],
"depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],
"dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
@@ -1524,6 +1680,8 @@
"domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="],
"dompurify": ["dompurify@3.4.12", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-zQvGet8Z2sWbQhCmfFz/T5QWH2oBmjnqK3qvOjaqaNLrLEF912WamU+ohnTp0TCep/MFVHpdJuCZEdFOdTnEFg=="],
"domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
"dset": ["dset@3.1.4", "", {}, "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA=="],
@@ -1570,6 +1728,8 @@
"es-to-primitive": ["es-to-primitive@1.3.4", "", { "dependencies": { "es-abstract-get": "^1.0.0", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "is-callable": "^1.2.7", "is-date-object": "^1.1.0", "is-symbol": "^1.1.1" } }, "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw=="],
"es-toolkit": ["es-toolkit@1.49.0", "", {}, "sha512-G5iZ6Pc/FNRY/soKZHC+TxGDD83rHUDXxzaWhGCX44vAv/tMs56WMusnm/KMNK+luUPsgA9U28cGr4RDlSzL2g=="],
"esast-util-from-estree": ["esast-util-from-estree@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "devlop": "^1.0.0", "estree-util-visit": "^2.0.0", "unist-util-position-from-estree": "^2.0.0" } }, "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ=="],
"esast-util-from-js": ["esast-util-from-js@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "acorn": "^8.0.0", "esast-util-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw=="],
@@ -1798,6 +1958,8 @@
"h3": ["h3@1.15.11", "", { "dependencies": { "cookie-es": "^1.2.3", "crossws": "^0.3.5", "defu": "^6.1.6", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.4", "radix3": "^1.1.2", "ufo": "^1.6.3", "uncrypto": "^0.1.3" } }, "sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg=="],
"hachure-fill": ["hachure-fill@0.5.2", "", {}, "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg=="],
"has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="],
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
@@ -1890,6 +2052,8 @@
"internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="],
"internmap": ["internmap@1.0.1", "", {}, "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw=="],
"invariant": ["invariant@2.2.4", "", { "dependencies": { "loose-envify": "^1.0.0" } }, "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA=="],
"iron-webcrypto": ["iron-webcrypto@1.2.1", "", {}, "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg=="],
@@ -2022,6 +2186,10 @@
"jsonpointer": ["jsonpointer@5.0.1", "", {}, "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ=="],
"katex": ["katex@0.16.47", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg=="],
"khroma": ["khroma@2.1.0", "", {}, "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw=="],
"kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="],
"kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="],
@@ -2030,6 +2198,8 @@
"lan-network": ["lan-network@0.2.1", "", { "bin": { "lan-network": "dist/lan-network-cli.js" } }, "sha512-ONPnazC96VKDntab9j9JKwIWhZ4ZUceB4A9Epu4Ssg0hYFmtHZSeQ+n15nIwTFmcBUKtExOer8WTJ4GF9MO64A=="],
"layout-base": ["layout-base@1.0.2", "", {}, "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg=="],
"leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="],
"lighthouse-logger": ["lighthouse-logger@1.4.2", "", { "dependencies": { "debug": "^2.6.9", "marky": "^1.2.2" } }, "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g=="],
@@ -2070,6 +2240,8 @@
"locate-path": ["locate-path@3.0.0", "", { "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A=="],
"lodash-es": ["lodash-es@4.18.1", "", {}, "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A=="],
"lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="],
"lodash.sortby": ["lodash.sortby@4.7.0", "", {}, "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA=="],
@@ -2156,6 +2328,8 @@
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
"mermaid": ["mermaid@11.16.0", "", { "dependencies": { "@braintree/sanitize-url": "^7.1.2", "@iconify/utils": "^3.0.2", "@mermaid-js/parser": "^1.2.0", "@types/d3": "^7.4.3", "@upsetjs/venn.js": "^2.0.0", "cytoscape": "^3.33.3", "cytoscape-cose-bilkent": "^4.1.0", "cytoscape-fcose": "^2.2.0", "d3": "^7.9.0", "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.14", "dayjs": "^1.11.20", "dompurify": "^3.3.3", "es-toolkit": "^1.45.1", "katex": "^0.16.45", "khroma": "^2.1.0", "marked": "^16.3.0", "roughjs": "^4.6.6", "stylis": "^4.3.6", "ts-dedent": "^2.2.0", "uuid": "^11.1.0 || ^12 || ^13 || ^14.0.0" } }, "sha512-Zvm3kbstgdpvIJPPItlL7fppIZ3kibvc1oZIGxdvk9t6UFz6flv+Jw7FtRGKwfcI8OckmH04LqG6LlS6X4B1pA=="],
"metro": ["metro@0.84.4", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/core": "^7.25.2", "@babel/generator": "^7.29.1", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "accepts": "^2.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.35.0", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.84.4", "metro-cache": "0.84.4", "metro-cache-key": "0.84.4", "metro-config": "0.84.4", "metro-core": "0.84.4", "metro-file-map": "0.84.4", "metro-resolver": "0.84.4", "metro-runtime": "0.84.4", "metro-source-map": "0.84.4", "metro-symbolicate": "0.84.4", "metro-transform-plugins": "0.84.4", "metro-transform-worker": "0.84.4", "mime-types": "^3.0.1", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-8ETTubqfD6ornDy2zYDvRcKnVDOXdFJsjetYDBsY4oAsb6NJkiwFR+FaMESyGppFmQUyBQA4H4sFGxzcQSGtFA=="],
"metro-babel-transformer": ["metro-babel-transformer@0.84.4", "", { "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.35.0", "metro-cache-key": "0.84.4", "nullthrows": "^1.1.1" } }, "sha512-rvCfz8snl9h20VcvpOHxZuHP1SlAkv4HXbzw7nyyVwu6Eqo5PRerbakQ9XmUCOsRy70spJ37O+G1TK8oMzo48g=="],
@@ -2390,6 +2564,8 @@
"path-browserify": ["path-browserify@1.0.1", "", {}, "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="],
"path-data-parser": ["path-data-parser@0.1.0", "", {}, "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w=="],
"path-exists": ["path-exists@3.0.0", "", {}, "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ=="],
"path-expression-matcher": ["path-expression-matcher@1.6.1", "", {}, "sha512-h7bxdzhHk8Knyc4Tj+jMaa7fEEoUJy7p1qtbVgkYg1Uhpe5Np5VuGXCRZnkZvU+Q42M1vStt0ifa3ueykRJPmQ=="],
@@ -2424,6 +2600,10 @@
"pngjs": ["pngjs@3.4.0", "", {}, "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w=="],
"points-on-curve": ["points-on-curve@0.2.0", "", {}, "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A=="],
"points-on-path": ["points-on-path@0.2.1", "", { "dependencies": { "path-data-parser": "0.1.0", "points-on-curve": "0.2.0" } }, "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g=="],
"possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
"postcss": ["postcss@8.5.15", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A=="],
@@ -2644,14 +2824,20 @@
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
"robust-predicates": ["robust-predicates@3.0.3", "", {}, "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA=="],
"rolldown": ["rolldown@1.1.3", "", { "dependencies": { "@oxc-project/types": "=0.137.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.1.3", "@rolldown/binding-darwin-arm64": "1.1.3", "@rolldown/binding-darwin-x64": "1.1.3", "@rolldown/binding-freebsd-x64": "1.1.3", "@rolldown/binding-linux-arm-gnueabihf": "1.1.3", "@rolldown/binding-linux-arm64-gnu": "1.1.3", "@rolldown/binding-linux-arm64-musl": "1.1.3", "@rolldown/binding-linux-ppc64-gnu": "1.1.3", "@rolldown/binding-linux-s390x-gnu": "1.1.3", "@rolldown/binding-linux-x64-gnu": "1.1.3", "@rolldown/binding-linux-x64-musl": "1.1.3", "@rolldown/binding-openharmony-arm64": "1.1.3", "@rolldown/binding-wasm32-wasi": "1.1.3", "@rolldown/binding-win32-arm64-msvc": "1.1.3", "@rolldown/binding-win32-x64-msvc": "1.1.3" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-1F1eEtUBtFvcGm1HQ9TiUIUHPQG7mSAODrhIzjxoUEFuo8OcbrGLiVLkevNgj84TE4lnHvnumwFjhJO5Eu135g=="],
"rollup": ["rollup@4.62.2", "", { "dependencies": { "@types/estree": "1.0.9" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.62.2", "@rollup/rollup-android-arm64": "4.62.2", "@rollup/rollup-darwin-arm64": "4.62.2", "@rollup/rollup-darwin-x64": "4.62.2", "@rollup/rollup-freebsd-arm64": "4.62.2", "@rollup/rollup-freebsd-x64": "4.62.2", "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", "@rollup/rollup-linux-arm-musleabihf": "4.62.2", "@rollup/rollup-linux-arm64-gnu": "4.62.2", "@rollup/rollup-linux-arm64-musl": "4.62.2", "@rollup/rollup-linux-loong64-gnu": "4.62.2", "@rollup/rollup-linux-loong64-musl": "4.62.2", "@rollup/rollup-linux-ppc64-gnu": "4.62.2", "@rollup/rollup-linux-ppc64-musl": "4.62.2", "@rollup/rollup-linux-riscv64-gnu": "4.62.2", "@rollup/rollup-linux-riscv64-musl": "4.62.2", "@rollup/rollup-linux-s390x-gnu": "4.62.2", "@rollup/rollup-linux-x64-gnu": "4.62.2", "@rollup/rollup-linux-x64-musl": "4.62.2", "@rollup/rollup-openbsd-x64": "4.62.2", "@rollup/rollup-openharmony-arm64": "4.62.2", "@rollup/rollup-win32-arm64-msvc": "4.62.2", "@rollup/rollup-win32-ia32-msvc": "4.62.2", "@rollup/rollup-win32-x64-gnu": "4.62.2", "@rollup/rollup-win32-x64-msvc": "4.62.2", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA=="],
"rope-sequence": ["rope-sequence@1.3.4", "", {}, "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ=="],
"roughjs": ["roughjs@4.6.6", "", { "dependencies": { "hachure-fill": "^0.5.2", "path-data-parser": "^0.1.0", "points-on-curve": "^0.2.0", "points-on-path": "^0.2.1" } }, "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ=="],
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
"rw": ["rw@1.3.3", "", {}, "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="],
"rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="],
"safe-array-concat": ["safe-array-concat@1.1.4", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "get-intrinsic": "^1.3.0", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg=="],
@@ -2790,6 +2976,8 @@
"styleq": ["styleq@0.1.3", "", {}, "sha512-3ZUifmCDCQanjeej1f6kyl/BeP/Vae5EYkQ9iJfUm/QwZvlgnZzyflqAsAWYURdtea8Vkvswu2GrC57h3qffcA=="],
"stylis": ["stylis@4.4.0", "", {}, "sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA=="],
"sucrase": ["sucrase@3.35.1", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "tinyglobby": "^0.2.11", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw=="],
"supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="],
@@ -2850,6 +3038,8 @@
"trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="],
"ts-dedent": ["ts-dedent@2.3.0", "", {}, "sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg=="],
"ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="],
"tsconfck": ["tsconfck@3.1.6", "", { "peerDependencies": { "typescript": "^5.0.0" }, "optionalPeers": ["typescript"], "bin": { "tsconfck": "bin/tsconfck.js" } }, "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w=="],
@@ -2948,7 +3138,7 @@
"utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="],
"uuid": ["uuid@7.0.3", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg=="],
"uuid": ["uuid@14.0.1", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew=="],
"validate-npm-package-name": ["validate-npm-package-name@5.0.1", "", {}, "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ=="],
@@ -3160,7 +3350,7 @@
"@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="],
"@edgeever/mobile/@tanstack/react-query": ["@tanstack/react-query@5.101.3", "", { "dependencies": { "@tanstack/query-core": "5.101.3" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-ZjgcRwmQUSCythDPj6pE2NKFi9bpQegxIBxgt3hPytXI1ElFHNaa3A7aWW8vFaLCIRjPv467rbREYHbxcdgQbg=="],
"@edgeever/mobile/@tanstack/react-query": ["@tanstack/react-query@5.101.4", "", { "dependencies": { "@tanstack/query-core": "5.101.4" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-yRg2pfOCxIs4ZJW3XYYHU/WgtD04FHSnfHlpRT7h7pR77hwkdRG4wxbKe4aq6P0RvXUTBSQpQeadS1SUYUe+KA=="],
"@edgeever/mobile/react": ["react@19.2.3", "", {}, "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA=="],
@@ -3202,6 +3392,8 @@
"@expo/xcpretty/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"@iconify/tools/@iconify/utils": ["@iconify/utils@2.3.0", "", { "dependencies": { "@antfu/install-pkg": "^1.0.0", "@antfu/utils": "^8.1.0", "@iconify/types": "^2.0.0", "debug": "^4.4.0", "globals": "^15.14.0", "kolorist": "^1.8.0", "local-pkg": "^1.0.0", "mlly": "^1.7.4" } }, "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA=="],
"@iconify/tools/svgo": ["svgo@3.3.3", "", { "dependencies": { "commander": "^7.2.0", "css-select": "^5.1.0", "css-tree": "^2.3.1", "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.0.0", "sax": "^1.5.0" }, "bin": "./bin/svgo" }, "sha512-+wn7I4p7YgJhHs38k2TNjy1vCfPIfLIJWR5MnCStsN8WuuTcBnRKcMHQLMM2ijxGZmDoZwNv8ipl5aTTen62ng=="],
"@img/sharp-freebsd-wasm32/@img/sharp-wasm32": ["@img/sharp-wasm32@0.35.2", "", { "dependencies": { "@emnapi/runtime": "^1.11.1" } }, "sha512-Mrv4JQNYVQ94xH+jzZ9r+gowleN8mv2FTgKT+PI6bx5C0G8TdNYndu161pg2i7uoBwxy2ImPMHrJOM2LZef7Bw=="],
@@ -3280,6 +3472,8 @@
"astro/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
"astro-icon/@iconify/utils": ["@iconify/utils@2.3.0", "", { "dependencies": { "@antfu/install-pkg": "^1.0.0", "@antfu/utils": "^8.1.0", "@iconify/types": "^2.0.0", "debug": "^4.4.0", "globals": "^15.14.0", "kolorist": "^1.8.0", "local-pkg": "^1.0.0", "mlly": "^1.7.4" } }, "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA=="],
"babel-plugin-polyfill-corejs2/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"boxen/type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
@@ -3306,6 +3500,14 @@
"csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="],
"cytoscape-fcose/cose-base": ["cose-base@2.2.0", "", { "dependencies": { "layout-base": "^2.0.0" } }, "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g=="],
"d3-dsv/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="],
"d3-sankey/d3-array": ["d3-array@2.12.1", "", { "dependencies": { "internmap": "^1.0.0" } }, "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ=="],
"d3-sankey/d3-shape": ["d3-shape@1.3.7", "", { "dependencies": { "d3-path": "1" } }, "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw=="],
"dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
"expo/react-refresh": ["react-refresh@0.14.2", "", {}, "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA=="],
@@ -3364,6 +3566,8 @@
"js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
"katex/commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="],
"lighthouse-logger/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
"log-symbols/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
@@ -3374,6 +3578,8 @@
"mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
"mermaid/marked": ["marked@16.4.2", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA=="],
"metro/accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
"metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="],
@@ -3488,6 +3694,8 @@
"wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"xcode/uuid": ["uuid@7.0.3", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg=="],
"yaml-language-server/request-light": ["request-light@0.5.8", "", {}, "sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg=="],
"yargs/yargs-parser": ["yargs-parser@22.0.0", "", {}, "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw=="],
@@ -3512,7 +3720,7 @@
"@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
"@edgeever/mobile/@tanstack/react-query/@tanstack/query-core": ["@tanstack/query-core@5.101.3", "", {}, "sha512-pWLyu7AjFFVM5G+frjcL81kKEW9R8GCCPKnL3uaWbMwd2f3ZINFCuy+PtKkdz/+pKw/f/XMsFsYq/H+uJHM4GQ=="],
"@edgeever/mobile/@tanstack/react-query/@tanstack/query-core": ["@tanstack/query-core@5.101.4", "", {}, "sha512-gNwcvOJcRbLWPOLG/2OBm+zM+Yv+MKsXKEOWC57USuZDEsI71hEErQsiEGx5wX9rzWWkfwM0fVSPoiIFSsxfiw=="],
"@edgeever/site/sharp/@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="],
@@ -3706,6 +3914,10 @@
"csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="],
"cytoscape-fcose/cose-base/layout-base": ["layout-base@2.0.1", "", {}, "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg=="],
"d3-sankey/d3-shape/d3-path": ["d3-path@1.0.9", "", {}, "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="],
"expo-linking/expo-constants/@expo/env": ["@expo/env@2.4.1", "", { "dependencies": { "chalk": "^4.0.0", "debug": "^4.3.4", "getenv": "^2.0.0" } }, "sha512-3c9Mg9x0HmGPEsVrGAGyEDJsNUOZ55cZvZ47/HLmXh7MHV9Zv7My73wThklKrObaBBoMfE4YqpKjYKDRzojpjQ=="],
"expo-modules-autolinking/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
+3
View File
@@ -125,5 +125,8 @@
"vite": "latest",
"vite-plugin-pwa": "^1.3.0",
"wrangler": "^4.112.0"
},
"patchedDependencies": {
"mermaid@11.16.0": "patches/mermaid@11.16.0.patch"
}
}
+14
View File
@@ -58,3 +58,17 @@ describe("Markdown table conversion", () => {
expect(resolveMemoContentDoc(legacyDoc, "Legacy note")).toBe(legacyDoc);
});
});
describe("Mermaid Markdown conversion", () => {
const markdown = "```mermaid\nflowchart LR\n A --> B\n```";
test("preserves Mermaid fenced code blocks through a Markdown round trip", () => {
const doc = markdownToDoc(markdown);
expect(doc.content[0]).toMatchObject({
type: "codeBlock",
attrs: { language: "mermaid" },
});
expect(docToMarkdown(doc)).toBe(markdown);
});
});
+6
View File
@@ -513,6 +513,12 @@ export const enUS = {
codeBlock: "Code block",
codeLanguage: "Code language",
plainText: "Plain text",
mermaidDiagram: "Insert Mermaid diagram",
mermaidPreview: "Mermaid diagram preview",
mermaidRendering: "Rendering diagram...",
mermaidInvalid: "Invalid Mermaid syntax. Edit the source below.",
mermaidEmpty: "Enter Mermaid source below to generate a diagram.",
mermaidSource: "Mermaid source",
horizontalRule: "Divider",
table: "Table",
insertTable: "Insert 3 × 3 table",
+6
View File
@@ -513,6 +513,12 @@ export const zhCN = {
codeBlock: "代码块",
codeLanguage: "代码语言",
plainText: "纯文本",
mermaidDiagram: "插入 Mermaid 图表",
mermaidPreview: "Mermaid 图表预览",
mermaidRendering: "图表渲染中...",
mermaidInvalid: "Mermaid 语法有误,请修改下方源码。",
mermaidEmpty: "在下方输入 Mermaid 源码以生成图表。",
mermaidSource: "Mermaid 源码",
horizontalRule: "分割线",
table: "表格",
insertTable: "插入 3 × 3 表格",
@@ -16,6 +16,7 @@ describe("mobile editor contract", () => {
test("keeps the core toolbar compact and ordered by editing frequency", () => {
expect(MOBILE_EDITOR_TOOLBAR_ACTIONS.map(({ id }) => id)).toEqual([
"image",
"mermaid",
"bold",
"bulletList",
"blockquote",
@@ -43,6 +44,7 @@ describe("mobile editor contract", () => {
expect(getMobileEditorTableMenuCopy("zh-CN")).toEqual({ title: "表格操作", close: "关闭" });
expect(getMobileEditorTableMenuCopy("en-US")).toEqual({ title: "Table actions", close: "Close" });
expect(getMobileEditorToolbarActionLabel("bulletList", "en-US")).toBe("Bullet list");
expect(getMobileEditorToolbarActionLabel("mermaid", "zh-CN")).toBe("插入 Mermaid 图表");
expect(getMobileEditorToolbarActionLabel("insertTable", "zh-CN")).toBe("插入表格");
expect(getMobileEditorImageScaleLabel("zh-CN")).toBe("图片显示尺寸");
expect(getMobileEditorImageWidthPresetLabel("medium", "en-US")).toBe("Medium");
+5
View File
@@ -4,6 +4,7 @@ export type MobileEditorLocale = "zh-CN" | "en-US";
export type MobileEditorToolbarActionId =
| "image"
| "mermaid"
| "bold"
| "bulletList"
| "blockquote"
@@ -21,6 +22,7 @@ export type MobileEditorTableActionId =
export const MOBILE_EDITOR_ACTIVE_FLAGS = {
bold: 1,
mermaid: 2,
bulletList: 8,
blockquote: 16,
table: 32,
@@ -29,6 +31,7 @@ export const MOBILE_EDITOR_ACTIVE_FLAGS = {
export const MOBILE_EDITOR_TOOLBAR_ACTIONS = [
{ id: "image", activeFlag: 0, requiresTable: false },
{ id: "mermaid", activeFlag: MOBILE_EDITOR_ACTIVE_FLAGS.mermaid, requiresTable: false },
{ id: "bold", activeFlag: MOBILE_EDITOR_ACTIVE_FLAGS.bold, requiresTable: false },
{ id: "bulletList", activeFlag: MOBILE_EDITOR_ACTIVE_FLAGS.bulletList, requiresTable: false },
{ id: "blockquote", activeFlag: MOBILE_EDITOR_ACTIVE_FLAGS.blockquote, requiresTable: false },
@@ -60,6 +63,7 @@ const MOBILE_EDITOR_COPY = {
},
actions: {
image: "上传图片",
mermaid: "插入 Mermaid 图表",
bold: "加粗",
bulletList: "无序列表",
blockquote: "引用",
@@ -89,6 +93,7 @@ const MOBILE_EDITOR_COPY = {
},
actions: {
image: "Upload image",
mermaid: "Insert Mermaid diagram",
bold: "Bold",
bulletList: "Bullet list",
blockquote: "Quote",
+10
View File
@@ -0,0 +1,10 @@
diff --git a/dist/mermaid.min.js b/dist/mermaid.min.js
index 055db5c7be9c120471123323e9e7ec2b7a55eddc..8b2272820efd1b214472bb6b6f54b4ab0b8c5568 100644
--- a/dist/mermaid.min.js
+++ b/dist/mermaid.min.js
@@ -1,4 +1,4 @@
-"use strict";var __esbuild_esm_mermaid_nm;(__esbuild_esm_mermaid_nm||={}).mermaid=(()=>{var ize=Object.create;var Ox=Object.defineProperty;var aze=Object.getOwnPropertyDescriptor;var sze=Object.getOwnPropertyNames;var oze=Object.getPrototypeOf,lze=Object.prototype.hasOwnProperty;var o=(e,t)=>Ox(e,"name",{value:t,configurable:!0});var F=(e,t)=>()=>(e&&(t=e(e=0)),t);var Io=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),ir=(e,t)=>{for(var r in t)Ox(e,r,{get:t[r],enumerable:!0})},BX=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of sze(t))!lze.call(e,i)&&i!==r&&Ox(e,i,{get:()=>t[i],enumerable:!(n=aze(t,i))||n.enumerable});return e};var Xs=(e,t,r)=>(r=e!=null?ize(oze(e)):{},BX(t||!e||!e.__esModule?Ox(r,"default",{value:e,enumerable:!0}):r,e)),cze=e=>BX(Ox({},"__esModule",{value:!0}),e);var uze,z0,ID,$X,gk=F(()=>{"use strict";uze=Object.freeze({left:0,top:0,width:16,height:16}),z0=Object.freeze({rotate:0,vFlip:!1,hFlip:!1}),ID=Object.freeze({...uze,...z0}),$X=Object.freeze({...ID,body:"",hidden:!1})});var hze,FX,zX=F(()=>{"use strict";gk();hze=Object.freeze({width:null,height:null}),FX=Object.freeze({...hze,...z0})});var MD,yk,GX=F(()=>{"use strict";MD=o((e,t,r,n="")=>{let i=e.split(":");if(e.slice(0,1)==="@"){if(i.length<2||i.length>3)return null;n=i.shift().slice(1)}if(i.length>3||!i.length)return null;if(i.length>1){let l=i.pop(),u=i.pop(),h={provider:i.length>0?i[0]:n,prefix:u,name:l};return t&&!yk(h)?null:h}let a=i[0],s=a.split("-");if(s.length>1){let l={provider:n,prefix:s.shift(),name:s.join("-")};return t&&!yk(l)?null:l}if(r&&n===""){let l={provider:n,prefix:"",name:a};return t&&!yk(l,r)?null:l}return null},"stringToIcon"),yk=o((e,t)=>e?!!((t&&e.prefix===""||e.prefix)&&e.name):!1,"validateIconName")});function VX(e,t){let r={};!e.hFlip!=!t.hFlip&&(r.hFlip=!0),!e.vFlip!=!t.vFlip&&(r.vFlip=!0);let n=((e.rotate||0)+(t.rotate||0))%4;return n&&(r.rotate=n),r}var WX=F(()=>{"use strict";o(VX,"mergeIconTransformations")});function ND(e,t){let r=VX(e,t);for(let n in $X)n in z0?n in e&&!(n in r)&&(r[n]=z0[n]):n in t?r[n]=t[n]:n in e&&(r[n]=e[n]);return r}var qX=F(()=>{"use strict";gk();WX();o(ND,"mergeIconData")});function HX(e,t){let r=e.icons,n=e.aliases||Object.create(null),i=Object.create(null);function a(s){if(r[s])return i[s]=[];if(!(s in i)){i[s]=null;let l=n[s]&&n[s].parent,u=l&&a(l);u&&(i[s]=[l].concat(u))}return i[s]}return o(a,"resolve"),(t||Object.keys(r).concat(Object.keys(n))).forEach(a),i}var UX=F(()=>{"use strict";o(HX,"getIconsTree")});function YX(e,t,r){let n=e.icons,i=e.aliases||Object.create(null),a={};function s(l){a=ND(n[l]||i[l],a)}return o(s,"parse"),s(t),r.forEach(s),ND(e,a)}function PD(e,t){if(e.icons[t])return YX(e,t,[]);let r=HX(e,[t])[t];return r?YX(e,t,r):null}var jX=F(()=>{"use strict";qX();UX();o(YX,"internalGetIconData");o(PD,"getIconData")});function OD(e,t,r){if(t===1)return e;if(r=r||100,typeof e=="number")return Math.ceil(e*t*r)/r;if(typeof e!="string")return e;let n=e.split(dze);if(n===null||!n.length)return e;let i=[],a=n.shift(),s=fze.test(a);for(;;){if(s){let l=parseFloat(a);isNaN(l)?i.push(a):i.push(Math.ceil(l*t*r)/r)}else i.push(a);if(a=n.shift(),a===void 0)return i.join("");s=!s}}var dze,fze,XX=F(()=>{"use strict";dze=/(-?[0-9.]*[0-9]+[0-9.]*)/g,fze=/^-?[0-9.]*[0-9]+[0-9.]*$/g;o(OD,"calculateSize")});function pze(e,t="defs"){let r="",n=e.indexOf("<"+t);for(;n>=0;){let i=e.indexOf(">",n),a=e.indexOf("</"+t);if(i===-1||a===-1)break;let s=e.indexOf(">",a);if(s===-1)break;r+=e.slice(i+1,a).trim(),e=e.slice(0,n).trim()+e.slice(s+1)}return{defs:r,content:e}}function mze(e,t){return e?"<defs>"+e+"</defs>"+t:t}function KX(e,t,r){let n=pze(e);return mze(n.defs,t+n.content+r)}var ZX=F(()=>{"use strict";o(pze,"splitSVGDefs");o(mze,"mergeDefsAndContent");o(KX,"wrapSVGContent")});function BD(e,t){let r={...ID,...e},n={...FX,...t},i={left:r.left,top:r.top,width:r.width,height:r.height},a=r.body;[r,n].forEach(y=>{let v=[],x=y.hFlip,b=y.vFlip,T=y.rotate;x?b?T+=2:(v.push("translate("+(i.width+i.left).toString()+" "+(0-i.top).toString()+")"),v.push("scale(-1 1)"),i.top=i.left=0):b&&(v.push("translate("+(0-i.left).toString()+" "+(i.height+i.top).toString()+")"),v.push("scale(1 -1)"),i.top=i.left=0);let k;switch(T<0&&(T-=Math.floor(T/4)*4),T=T%4,T){case 1:k=i.height/2+i.top,v.unshift("rotate(90 "+k.toString()+" "+k.toString()+")");break;case 2:v.unshift("rotate(180 "+(i.width/2+i.left).toString()+" "+(i.height/2+i.top).toString()+")");break;case 3:k=i.width/2+i.left,v.unshift("rotate(-90 "+k.toString()+" "+k.toString()+")");break}T%2===1&&(i.left!==i.top&&(k=i.left,i.left=i.top,i.top=k),i.width!==i.height&&(k=i.width,i.width=i.height,i.height=k)),v.length&&(a=KX(a,'<g transform="'+v.join(" ")+'">',"</g>"))});let s=n.width,l=n.height,u=i.width,h=i.height,d,f;s===null?(f=l===null?"1em":l==="auto"?h:l,d=OD(f,u/h)):(d=s==="auto"?u:s,f=l===null?OD(d,h/u):l==="auto"?h:l);let p={},m=o((y,v)=>{gze(v)||(p[y]=v.toString())},"setAttr");m("width",d),m("height",f);let g= Line truncated
+"use strict";var __esbuild_esm_mermaid_nm=globalThis.__esbuild_esm_mermaid_nm||(globalThis.__esbuild_esm_mermaid_nm={});(__esbuild_esm_mermaid_nm||={}).mermaid=(()=>{var ize=Object.create;var Ox=Object.defineProperty;var aze=Object.getOwnPropertyDescriptor;var sze=Object.getOwnPropertyNames;var oze=Object.getPrototypeOf,lze=Object.prototype.hasOwnProperty;var o=(e,t)=>Ox(e,"name",{value:t,configurable:!0});var F=(e,t)=>()=>(e&&(t=e(e=0)),t);var Io=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),ir=(e,t)=>{for(var r in t)Ox(e,r,{get:t[r],enumerable:!0})},BX=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of sze(t))!lze.call(e,i)&&i!==r&&Ox(e,i,{get:()=>t[i],enumerable:!(n=aze(t,i))||n.enumerable});return e};var Xs=(e,t,r)=>(r=e!=null?ize(oze(e)):{},BX(t||!e||!e.__esModule?Ox(r,"default",{value:e,enumerable:!0}):r,e)),cze=e=>BX(Ox({},"__esModule",{value:!0}),e);var uze,z0,ID,$X,gk=F(()=>{"use strict";uze=Object.freeze({left:0,top:0,width:16,height:16}),z0=Object.freeze({rotate:0,vFlip:!1,hFlip:!1}),ID=Object.freeze({...uze,...z0}),$X=Object.freeze({...ID,body:"",hidden:!1})});var hze,FX,zX=F(()=>{"use strict";gk();hze=Object.freeze({width:null,height:null}),FX=Object.freeze({...hze,...z0})});var MD,yk,GX=F(()=>{"use strict";MD=o((e,t,r,n="")=>{let i=e.split(":");if(e.slice(0,1)==="@"){if(i.length<2||i.length>3)return null;n=i.shift().slice(1)}if(i.length>3||!i.length)return null;if(i.length>1){let l=i.pop(),u=i.pop(),h={provider:i.length>0?i[0]:n,prefix:u,name:l};return t&&!yk(h)?null:h}let a=i[0],s=a.split("-");if(s.length>1){let l={provider:n,prefix:s.shift(),name:s.join("-")};return t&&!yk(l)?null:l}if(r&&n===""){let l={provider:n,prefix:"",name:a};return t&&!yk(l,r)?null:l}return null},"stringToIcon"),yk=o((e,t)=>e?!!((t&&e.prefix===""||e.prefix)&&e.name):!1,"validateIconName")});function VX(e,t){let r={};!e.hFlip!=!t.hFlip&&(r.hFlip=!0),!e.vFlip!=!t.vFlip&&(r.vFlip=!0);let n=((e.rotate||0)+(t.rotate||0))%4;return n&&(r.rotate=n),r}var WX=F(()=>{"use strict";o(VX,"mergeIconTransformations")});function ND(e,t){let r=VX(e,t);for(let n in $X)n in z0?n in e&&!(n in r)&&(r[n]=z0[n]):n in t?r[n]=t[n]:n in e&&(r[n]=e[n]);return r}var qX=F(()=>{"use strict";gk();WX();o(ND,"mergeIconData")});function HX(e,t){let r=e.icons,n=e.aliases||Object.create(null),i=Object.create(null);function a(s){if(r[s])return i[s]=[];if(!(s in i)){i[s]=null;let l=n[s]&&n[s].parent,u=l&&a(l);u&&(i[s]=[l].concat(u))}return i[s]}return o(a,"resolve"),(t||Object.keys(r).concat(Object.keys(n))).forEach(a),i}var UX=F(()=>{"use strict";o(HX,"getIconsTree")});function YX(e,t,r){let n=e.icons,i=e.aliases||Object.create(null),a={};function s(l){a=ND(n[l]||i[l],a)}return o(s,"parse"),s(t),r.forEach(s),ND(e,a)}function PD(e,t){if(e.icons[t])return YX(e,t,[]);let r=HX(e,[t])[t];return r?YX(e,t,r):null}var jX=F(()=>{"use strict";qX();UX();o(YX,"internalGetIconData");o(PD,"getIconData")});function OD(e,t,r){if(t===1)return e;if(r=r||100,typeof e=="number")return Math.ceil(e*t*r)/r;if(typeof e!="string")return e;let n=e.split(dze);if(n===null||!n.length)return e;let i=[],a=n.shift(),s=fze.test(a);for(;;){if(s){let l=parseFloat(a);isNaN(l)?i.push(a):i.push(Math.ceil(l*t*r)/r)}else i.push(a);if(a=n.shift(),a===void 0)return i.join("");s=!s}}var dze,fze,XX=F(()=>{"use strict";dze=/(-?[0-9.]*[0-9]+[0-9.]*)/g,fze=/^-?[0-9.]*[0-9]+[0-9.]*$/g;o(OD,"calculateSize")});function pze(e,t="defs"){let r="",n=e.indexOf("<"+t);for(;n>=0;){let i=e.indexOf(">",n),a=e.indexOf("</"+t);if(i===-1||a===-1)break;let s=e.indexOf(">",a);if(s===-1)break;r+=e.slice(i+1,a).trim(),e=e.slice(0,n).trim()+e.slice(s+1)}return{defs:r,content:e}}function mze(e,t){return e?"<defs>"+e+"</defs>"+t:t}function KX(e,t,r){let n=pze(e);return mze(n.defs,t+n.content+r)}var ZX=F(()=>{"use strict";o(pze,"splitSVGDefs");o(mze,"mergeDefsAndContent");o(KX,"wrapSVGContent")});function BD(e,t){let r={...ID,...e},n={...FX,...t},i={left:r.left,top:r.top,width:r.width,height:r.height},a=r.body;[r,n].forEach(y=>{let v=[],x=y.hFlip,b=y.vFlip,T=y.rotate;x?b?T+=2:(v.push("translate("+(i.width+i.left).toString()+" "+(0-i.top).toString()+")"),v.push("scale(-1 1)"),i.top=i.left=0):b&&(v.push("translate("+(0-i.left).toString()+" "+(i.height+i.top).toString()+")"),v.push("scale(1 -1)"),i.top=i.left=0);let k;switch(T<0&&(T-=Math.floor(T/4)*4),T=T%4,T){case 1:k=i.height/2+i.top,v.unshift("rotate(90 "+k.toString()+" "+k.toString()+")");break;case 2:v.unshift("rotate(180 "+(i.width/2+i.left).toString()+" "+(i.height/2+i.top).toString()+")");break;case 3:k=i.width/2+i.left,v.unshift("rotate(-90 "+k.toString()+" "+k.toString()+")");break}T%2===1&&(i.left!==i.top&&(k=i.left,i.left=i.top,i.top=k),i.width!==i.height&&(k=i.width,i.width=i.height,i.height=k)),v.length&&(a=KX(a,'<g transform="'+v.join(" ")+'">',"</g>"))});let s=n.width,l=n.height,u=i.width,h=i.height,d,f;s===null?(f=l===null?"1em":l==="auto"?h:l,d=OD(f,u/h)):(d=s==="auto"?u:s,f=l===null?OD(d,h/u):l==="auto"?h:l);let p={},m=o((y, Line truncated
`+Ht),Re&&qx([_,A,M],pr=>{Ht=q0(Ht,pr," ")}),k&&ke?k.createHTML(Ht):Ht},t.setConfig=function(){let Tt=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};zt(Tt),Ge=!0},t.clearConfig=function(){Le=null,Ge=!1},t.isValidAttribute=function(Tt,De,it){Le||zt({});let We=mt(Tt),rt=mt(De);return Wt(We,rt,it)},t.addHook=function(Tt,De){typeof De=="function"&&Hx(I[Tt],De)},t.removeHook=function(Tt,De){if(De!==void 0){let it=qze(I[Tt],De);return it===-1?void 0:Hze(I[Tt],it,1)[0]}return uZ(I[Tt])},t.removeHooks=function(Tt){I[Tt]=[]},t.removeAllHooks=function(){I=gZ()},t}var yZ,cZ,Gze,Vze,Wze,xs,ol,Xx,g7,y7,qx,qze,uZ,Hx,Hze,Ik,u7,h7,q0,Uze,Yze,zl,vs,Ux,hZ,d7,f7,Kze,p7,Zze,dZ,fZ,m7,pZ,Dk,Qze,Jze,eGe,tGe,rGe,vZ,nGe,iGe,xZ,aGe,mZ,jx,sGe,oGe,gZ,Zs,H0=F(()=>{"use strict";({entries:yZ,setPrototypeOf:cZ,isFrozen:Gze,getPrototypeOf:Vze,getOwnPropertyDescriptor:Wze}=Object),{freeze:xs,seal:ol,create:Xx}=Object,{apply:g7,construct:y7}=typeof Reflect<"u"&&Reflect;xs||(xs=o(function(t){return t},"freeze"));ol||(ol=o(function(t){return t},"seal"));g7||(g7=o(function(t,r){for(var n=arguments.length,i=new Array(n>2?n-2:0),a=2;a<n;a++)i[a-2]=arguments[a];return t.apply(r,i)},"apply"));y7||(y7=o(function(t){for(var r=arguments.length,n=new Array(r>1?r-1:0),i=1;i<r;i++)n[i-1]=arguments[i];return new t(...n)},"construct"));qx=bs(Array.prototype.forEach),qze=bs(Array.prototype.lastIndexOf),uZ=bs(Array.prototype.pop),Hx=bs(Array.prototype.push),Hze=bs(Array.prototype.splice),Ik=bs(String.prototype.toLowerCase),u7=bs(String.prototype.toString),h7=bs(String.prototype.match),q0=bs(String.prototype.replace),Uze=bs(String.prototype.indexOf),Yze=bs(String.prototype.trim),zl=bs(Object.prototype.hasOwnProperty),vs=bs(RegExp.prototype.test),Ux=jze(TypeError);o(bs,"unapply");o(jze,"unconstruct");o(Zr,"addToSet");o(Xze,"cleanArray");o(Oc,"clone");o(Yx,"lookupGetter");hZ=xs(["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","search","section","select","shadow","slot","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"]),d7=xs(["svg","a","altglyph","altglyphdef","altglyphitem","animatecolor","animatemotion","animatetransform","circle","clippath","defs","desc","ellipse","enterkeyhint","exportparts","filter","font","g","glyph","glyphref","hkern","image","inputmode","line","lineargradient","marker","mask","metadata","mpath","part","path","pattern","polygon","polyline","radialgradient","rect","stop","style","switch","symbol","text","textpath","title","tref","tspan","view","vkern"]),f7=xs(["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"]),Kze=xs(["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"]),p7=xs(["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"]),Zze=xs(["maction","maligngroup","malignmark","mlongdiv","mscarries","mscarry","msgroup","mstack","msline","msrow","semantics","annotation","annotation-xml","mprescripts","none"]),dZ=xs(["#text"]),fZ=xs(["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","exportparts","face","for","headers","height","hidden","high","href","hreflang","id","inert","inputmode","integrity","ismap","kind","label","lang","list","loading","loop","low","max","maxlength","media","method","min","minlength","multiple","mu Line truncated
c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14
c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54