From 9a7dc28c14299ec6f0aaf03e248cc9479fc2faad Mon Sep 17 00:00:00 2001 From: Anion <1005128408@qq.com> Date: Mon, 30 Mar 2026 22:15:42 +0800 Subject: [PATCH 1/6] fix: unify trial-mode API settings storage keys --- .../src/services/apiSettingsService.ts | 27 ++++++++++++++----- .../src/services/apiSettingsService.ts | 27 ++++++++++++++----- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/frontend_en/src/services/apiSettingsService.ts b/frontend_en/src/services/apiSettingsService.ts index 6b474b1..48cafcc 100644 --- a/frontend_en/src/services/apiSettingsService.ts +++ b/frontend_en/src/services/apiSettingsService.ts @@ -16,16 +16,29 @@ export interface ApiSettings { } const STORAGE_KEY_PREFIX = 'kb_api_settings_'; +const TRIAL_STORAGE_SUFFIXES = ['default', 'local', 'global'] as const; + +function isTrialStorageUser(userId: string | null): boolean { + return !userId || TRIAL_STORAGE_SUFFIXES.includes(userId as typeof TRIAL_STORAGE_SUFFIXES[number]); +} + +function getStorageKeys(userId: string | null): string[] { + if (isTrialStorageUser(userId)) { + return TRIAL_STORAGE_SUFFIXES.map((suffix) => `${STORAGE_KEY_PREFIX}${suffix}`); + } + return [`${STORAGE_KEY_PREFIX}${userId}`]; +} /** * Get API settings for a user (or global if userId is null) */ export function getApiSettings(userId: string | null): ApiSettings | null { try { - const key = userId ? `${STORAGE_KEY_PREFIX}${userId}` : `${STORAGE_KEY_PREFIX}global`; - const stored = localStorage.getItem(key); - if (stored) { - return JSON.parse(stored); + for (const key of getStorageKeys(userId)) { + const stored = localStorage.getItem(key); + if (stored) { + return JSON.parse(stored); + } } } catch (err) { console.error('Failed to load API settings:', err); @@ -45,8 +58,10 @@ export function getApiSettings(userId: string | null): ApiSettings | null { */ export function saveApiSettings(userId: string | null, settings: ApiSettings): void { try { - const key = userId ? `${STORAGE_KEY_PREFIX}${userId}` : `${STORAGE_KEY_PREFIX}global`; - localStorage.setItem(key, JSON.stringify(settings)); + const serialized = JSON.stringify(settings); + for (const key of getStorageKeys(userId)) { + localStorage.setItem(key, serialized); + } } catch (err) { console.error('Failed to save API settings:', err); } diff --git a/frontend_zh/src/services/apiSettingsService.ts b/frontend_zh/src/services/apiSettingsService.ts index 6b474b1..48cafcc 100644 --- a/frontend_zh/src/services/apiSettingsService.ts +++ b/frontend_zh/src/services/apiSettingsService.ts @@ -16,16 +16,29 @@ export interface ApiSettings { } const STORAGE_KEY_PREFIX = 'kb_api_settings_'; +const TRIAL_STORAGE_SUFFIXES = ['default', 'local', 'global'] as const; + +function isTrialStorageUser(userId: string | null): boolean { + return !userId || TRIAL_STORAGE_SUFFIXES.includes(userId as typeof TRIAL_STORAGE_SUFFIXES[number]); +} + +function getStorageKeys(userId: string | null): string[] { + if (isTrialStorageUser(userId)) { + return TRIAL_STORAGE_SUFFIXES.map((suffix) => `${STORAGE_KEY_PREFIX}${suffix}`); + } + return [`${STORAGE_KEY_PREFIX}${userId}`]; +} /** * Get API settings for a user (or global if userId is null) */ export function getApiSettings(userId: string | null): ApiSettings | null { try { - const key = userId ? `${STORAGE_KEY_PREFIX}${userId}` : `${STORAGE_KEY_PREFIX}global`; - const stored = localStorage.getItem(key); - if (stored) { - return JSON.parse(stored); + for (const key of getStorageKeys(userId)) { + const stored = localStorage.getItem(key); + if (stored) { + return JSON.parse(stored); + } } } catch (err) { console.error('Failed to load API settings:', err); @@ -45,8 +58,10 @@ export function getApiSettings(userId: string | null): ApiSettings | null { */ export function saveApiSettings(userId: string | null, settings: ApiSettings): void { try { - const key = userId ? `${STORAGE_KEY_PREFIX}${userId}` : `${STORAGE_KEY_PREFIX}global`; - localStorage.setItem(key, JSON.stringify(settings)); + const serialized = JSON.stringify(settings); + for (const key of getStorageKeys(userId)) { + localStorage.setItem(key, serialized); + } } catch (err) { console.error('Failed to save API settings:', err); } From 74d49b4ef464ba7c1ce76eb4d93d6d0d82e47a6f Mon Sep 17 00:00:00 2001 From: Anion <1005128408@qq.com> Date: Tue, 31 Mar 2026 15:26:10 +0800 Subject: [PATCH 2/6] feat: merge two-step mindmap LLM into single-pass with improved prompt Combine analyze_structure + generate_mermaid into one LLM call that directly outputs Markdown. Uses a detailed knowledge-map prompt that adapts to article type, producing structured nodes instead of bare titles. --- workflow_engine/workflow/wf_kb_mindmap.py | 115 +++++++++------------- 1 file changed, 48 insertions(+), 67 deletions(-) diff --git a/workflow_engine/workflow/wf_kb_mindmap.py b/workflow_engine/workflow/wf_kb_mindmap.py index 7f04e7c..05552c6 100644 --- a/workflow_engine/workflow/wf_kb_mindmap.py +++ b/workflow_engine/workflow/wf_kb_mindmap.py @@ -13,6 +13,7 @@ from workflow_engine.utils import get_project_root log = get_logger(__name__) +_mindmap_structure_logged_once = False # Try importing office libraries try: @@ -156,95 +157,75 @@ async def process_file(file_path: str) -> Dict[str, Any]: return state async def analyze_structure_node(state: KBMindMapState) -> KBMindMapState: + """Skip — merged into generate_mermaid_node for single-pass generation.""" + state.content_structure = "merged" + return state + + async def generate_mermaid_node(state: KBMindMapState) -> KBMindMapState: """ - Analyze content structure using LLM + Single-pass: analyze documents and generate Markdown mindmap directly. """ if not state.file_contents: - state.content_structure = "No content available for analysis." + state.mermaid_code = "# Error\n## No content available" return state - # Format file contents contents_str = "" for item in state.file_contents: contents_str += f"=== {item['filename']} ===\n{item['content']}\n\n" - # Structure analysis prompt language = state.request.language max_depth = state.request.max_depth - prompt = f"""你是一位专业的知识结构分析师。请分析以下文档内容,提取出层级化的知识结构。 -要求: -1. 识别主要主题和子主题 -2. 提取关键概念和要点 -3. 建立清晰的层级关系(最多{max_depth}层) -4. 使用{language}语言 -5. 输出格式为层级化的文本结构,使用缩进表示层级 + prompt = f"""请基于以下文档内容,生成一张**层级清晰、主题归纳明确、适合快速把握全文结构的思维导图**。你的目标是把文章压缩成一张"知识地图",让读者能够迅速理解这篇文章的核心主题、主要模块、关键内容,以及各部分之间的层级关系。 -文档内容: -{contents_str} +请按照下面的方法完成: -请输出层级化的知识结构:""" +先通读全文,识别文章真正的中心主题,用一句高度概括的话作为根节点(# 一级标题)。这个根节点需要能够覆盖全文主旨,而不是局部内容。 - try: - agent = create_agent( - name="kb_prompt_agent", - model_name=state.request.model, - chat_api_url=state.request.chat_api_url, - temperature=0.3, - parser_type="text" - ) +然后围绕中心主题,提炼出 **4–8 个一级主题**(## 二级标题)。一级主题要能够代表全文最重要的几个结构板块。请优先从文章本身的结构、论述重心、主题模块、关键信息簇中提炼一级主题,使它们能够共同构成全文的主干。 - temp_state = MainState(request=state.request) - res_state = await agent.execute(temp_state, prompt=prompt) +接着在每个一级主题下继续拆分 **2–4 个二级主题**(### 三级标题)。二级主题要承接上级主题,概括该部分最值得保留的核心内容,例如关键概念、主要论点、重要机制、核心步骤、代表性案例、主要证据、结果表现、应用场景、影响因素、行动建议等。 - state.content_structure = _extract_text_result(res_state, "kb_prompt_agent") or "[Structure analysis failed]" - except Exception as e: - log.error(f"Structure analysis failed: {e}") - state.content_structure = f"[Structure analysis error: {e}]" +当某个二级主题中存在特别重要的细节时,继续提炼 **1–3 个三级要点**(#### 四级标题),用于补充最关键的信息,例如术语、条件、指标、例子、判断依据、具体表现、限制条件、后续影响等。 - return state +整体层级最多{max_depth}层。使用{language}语言。 - async def generate_mermaid_node(state: KBMindMapState) -> KBMindMapState: - """ - Generate Mermaid mindmap syntax using LLM - """ - if not state.content_structure or state.content_structure.startswith("["): - state.mermaid_code = "mindmap\n root((Error))\n No content structure available" - return state +整张思维导图要体现出一种**知识整理型、结构概览型、主题分解型**的风格。重点是帮助读者快速理解全文内容版图,而不是只罗列摘要句子。请让结构体现出"从总到分、由主到次、层层展开"的组织逻辑。 + +请根据文章类型,自适应选择最合适的组织框架: +* 研究型、分析型文章:背景、问题、核心观点、方法机制、证据结果、意义影响、局限延伸 +* 新闻、时评、纪实型文章:主题事件、背景脉络、关键事实、各方观点、原因影响、趋势走向 +* 科普、说明型文章:核心概念、原理机制、特征表现、应用场景、常见理解、总结启发 +* 教程、方法型文章:目标、前提条件、步骤模块、关键技巧、注意事项、应用建议 +* 商业、产品、行业文章:对象定位、背景环境、核心策略、运行方式、优势价值、风险挑战、发展趋势 +* 访谈、观点型文章:核心立场、主要观点、支撑理由、经验案例、延伸启示 - # Mermaid generation prompt - style = state.request.mindmap_style - prompt = f"""你是一位专业的Mermaid图表生成专家。请根据以下知识结构,生成Mermaid mindmap语法。 - -知识结构: -{state.content_structure} - -要求: -1. 使用Mermaid mindmap语法 -2. 风格:{style} -3. 保持层级关系清晰 -4. 节点名称简洁明了 -5. 只输出Mermaid代码,不要有其他解释 - -Mermaid mindmap语法示例: -``` -mindmap - root((中心主题)) - 主题1 - 子主题1.1 - 子主题1.2 - 主题2 - 子主题2.1 -``` - -请生成Mermaid mindmap代码:""" +节点命名请尽量简洁而有信息量。每个节点都使用**适合放入思维导图框中的短语式表达**,让人一眼就能理解该节点要表达的重点。 + +生成标准: +1. 忠实反映原文主线 +2. 节点之间要有明确层级关系 +3. 同一级节点尽量保持并列、均衡、可比较 +4. 优先保留能够帮助理解全文框架的内容 +5. 让整张图看起来像一张"文章结构与知识重点总览图" +6. 读者即使不读原文,也能通过这张导图把握文章的大体结构与核心内容 + +**输出格式要求:** +- 使用 Markdown 标题格式:# 根节点,## 一级主题,### 二级主题,#### 三级要点 +- 只输出 Markdown 内容,不要有其他解释 +- 不要使用代码块包裹 + +文档内容: +{contents_str} + +请直接输出思维导图:""" try: agent = create_agent( name="kb_prompt_agent", model_name=state.request.model, chat_api_url=state.request.chat_api_url, - temperature=0.5, + temperature=0.3, parser_type="text" ) @@ -253,7 +234,7 @@ async def generate_mermaid_node(state: KBMindMapState) -> KBMindMapState: mermaid_raw = _extract_text_result(res_state, "kb_prompt_agent") if mermaid_raw: - # Extract mermaid code from markdown code blocks if present + # Extract content from markdown code blocks if present if "```" in mermaid_raw: lines = mermaid_raw.split("\n") in_code_block = False @@ -268,10 +249,10 @@ async def generate_mermaid_node(state: KBMindMapState) -> KBMindMapState: else: state.mermaid_code = mermaid_raw else: - state.mermaid_code = "mindmap\n root((Error))\n Generation failed" + state.mermaid_code = "# Error\n## Generation failed" except Exception as e: - log.error(f"Mermaid generation failed: {e}") - state.mermaid_code = f"mindmap\n root((Error))\n {str(e)}" + log.error(f"Mindmap generation failed: {e}") + state.mermaid_code = f"# Error\n## {str(e)}" # Save mermaid code to file try: From a6897217589d6c1c6f6cc0555275a9254ce32048 Mon Sep 17 00:00:00 2001 From: Anion <1005128408@qq.com> Date: Tue, 31 Mar 2026 15:26:18 +0800 Subject: [PATCH 3/6] feat: add simple-mind-map dependency and utility functions - Replace mermaid with simple-mind-map in both frontends - Add mermaidToMarkdown/markdownToMermaid converters for format compat - Add TypeScript declarations for simple-mind-map --- frontend_en/package-lock.json | 1352 ++++++++++---------- frontend_en/package.json | 2 +- frontend_en/src/types/simple-mind-map.d.ts | 76 ++ frontend_en/src/utils/mermaidToMarkdown.ts | 124 ++ frontend_zh/package-lock.json | 1352 ++++++++++---------- frontend_zh/package.json | 2 +- frontend_zh/src/types/simple-mind-map.d.ts | 76 ++ frontend_zh/src/utils/mermaidToMarkdown.ts | 124 ++ 8 files changed, 1806 insertions(+), 1302 deletions(-) create mode 100644 frontend_en/src/types/simple-mind-map.d.ts create mode 100644 frontend_en/src/utils/mermaidToMarkdown.ts create mode 100644 frontend_zh/src/types/simple-mind-map.d.ts create mode 100644 frontend_zh/src/utils/mermaidToMarkdown.ts diff --git a/frontend_en/package-lock.json b/frontend_en/package-lock.json index 873bc08..7ca7edd 100644 --- a/frontend_en/package-lock.json +++ b/frontend_en/package-lock.json @@ -13,12 +13,12 @@ "framer-motion": "^10.16.4", "katex": "^0.16.28", "lucide-react": "^0.294.0", - "mermaid": "^10.6.1", "pdfjs-dist": "^5.4.296", "react": "^18.2.0", "react-dom": "^18.2.0", "react-markdown": "^9.1.0", "react-pdf": "^10.3.0", + "simple-mind-map": "^0.14.0-fix.2", "tailwind-merge": "^2.0.0", "zustand": "^4.4.7" }, @@ -328,12 +328,6 @@ "node": ">=6.9.0" } }, - "node_modules/@braintree/sanitize-url": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz", - "integrity": "sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==", - "license": "MIT" - }, "node_modules/@emotion/is-prop-valid": { "version": "0.8.8", "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", @@ -1080,6 +1074,24 @@ "node": ">= 8" } }, + "node_modules/@pdf-lib/standard-fonts": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz", + "integrity": "sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA==", + "license": "MIT", + "dependencies": { + "pako": "^1.0.6" + } + }, + "node_modules/@pdf-lib/upng": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@pdf-lib/upng/-/upng-1.0.1.tgz", + "integrity": "sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ==", + "license": "MIT", + "dependencies": { + "pako": "^1.0.10" + } + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.27", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", @@ -1517,6 +1529,16 @@ "node": ">=20.0.0" } }, + "node_modules/@svgdotjs/svg.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.js/-/svg.js-3.2.0.tgz", + "integrity": "sha512-Tr8p+QVP7y+QT1GBlq1Tt57IvedVH8zCPoYxdHLX0Oof3a/PqnC/tXAkVufv1JQJfsDHlH/UrjcDfgxSofqSNA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Fuzzyma" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -1562,27 +1584,6 @@ "@babel/types": "^7.28.2" } }, - "node_modules/@types/d3-scale": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", - "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", - "license": "MIT", - "dependencies": { - "@types/d3-time": "*" - } - }, - "node_modules/@types/d3-scale-chromatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", - "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", - "license": "MIT" - }, - "node_modules/@types/d3-time": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", - "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", - "license": "MIT" - }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -1672,13 +1673,6 @@ "@types/react": "^18.0.0" } }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", - "license": "MIT", - "optional": true - }, "node_modules/@types/unist": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", @@ -1721,6 +1715,39 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, + "node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-loose": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/acorn-loose/-/acorn-loose-6.1.0.tgz", + "integrity": "sha512-FHhXoiF0Uch3IqsrnPpWwCtiv5PYvipTpT1k9lDMgQVVYc9iDuSl5zdJV358aI8twfHCYMFBRVYvAVki9wC/ng==", + "license": "MIT", + "dependencies": { + "acorn": "^6.2.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -1796,6 +1823,32 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/baseline-browser-mapping": { "version": "2.9.19", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", @@ -1819,6 +1872,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/brace-expansion": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", @@ -1866,6 +1929,30 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", @@ -2004,14 +2091,11 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "license": "MIT", - "engines": { - "node": ">= 10" - } + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" }, "node_modules/convert-source-map": { "version": "2.0.0", @@ -2020,14 +2104,11 @@ "dev": true, "license": "MIT" }, - "node_modules/cose-base": { + "node_modules/core-util-is": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", - "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", - "license": "MIT", - "dependencies": { - "layout-base": "^1.0.0" - } + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" }, "node_modules/cssesc": { "version": "3.0.0", @@ -2048,484 +2129,6 @@ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "license": "MIT" }, - "node_modules/cytoscape": { - "version": "3.33.1", - "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.1.tgz", - "integrity": "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==", - "license": "MIT", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/cytoscape-cose-bilkent": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", - "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", - "license": "MIT", - "dependencies": { - "cose-base": "^1.0.0" - }, - "peerDependencies": { - "cytoscape": "^3.2.0" - } - }, - "node_modules/d3": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", - "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", - "license": "ISC", - "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" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-array": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", - "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", - "license": "ISC", - "dependencies": { - "internmap": "1 - 2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-axis": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", - "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-brush": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", - "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", - "license": "ISC", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "3", - "d3-transition": "3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-chord": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", - "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", - "license": "ISC", - "dependencies": { - "d3-path": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-contour": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", - "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", - "license": "ISC", - "dependencies": { - "d3-array": "^3.2.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-delaunay": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", - "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", - "license": "ISC", - "dependencies": { - "delaunator": "5" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-dispatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", - "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-drag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", - "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", - "license": "ISC", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-selection": "3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-dsv": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", - "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", - "license": "ISC", - "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" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-ease": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-fetch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", - "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", - "license": "ISC", - "dependencies": { - "d3-dsv": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-force": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", - "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", - "license": "ISC", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-quadtree": "1 - 3", - "d3-timer": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-format": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", - "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-geo": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", - "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", - "license": "ISC", - "dependencies": { - "d3-array": "2.5.0 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-hierarchy": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", - "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", - "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-polygon": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", - "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-quadtree": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", - "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-random": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", - "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-sankey": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", - "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", - "license": "BSD-3-Clause", - "dependencies": { - "d3-array": "1 - 2", - "d3-shape": "^1.2.0" - } - }, - "node_modules/d3-sankey/node_modules/d3-array": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", - "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", - "license": "BSD-3-Clause", - "dependencies": { - "internmap": "^1.0.0" - } - }, - "node_modules/d3-sankey/node_modules/d3-path": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", - "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", - "license": "BSD-3-Clause" - }, - "node_modules/d3-sankey/node_modules/d3-shape": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", - "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", - "license": "BSD-3-Clause", - "dependencies": { - "d3-path": "1" - } - }, - "node_modules/d3-sankey/node_modules/internmap": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", - "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", - "license": "ISC" - }, - "node_modules/d3-scale": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", - "license": "ISC", - "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" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-scale-chromatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", - "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3", - "d3-interpolate": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-shape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", - "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", - "license": "ISC", - "dependencies": { - "d3-path": "^3.1.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", - "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", - "license": "ISC", - "dependencies": { - "d3-array": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time-format": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", - "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", - "license": "ISC", - "dependencies": { - "d3-time": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-timer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-transition": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", - "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3", - "d3-dispatch": "1 - 3", - "d3-ease": "1 - 3", - "d3-interpolate": "1 - 3", - "d3-timer": "1 - 3" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "d3-selection": "2 - 3" - } - }, - "node_modules/d3-zoom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", - "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", - "license": "ISC", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "2 - 3", - "d3-transition": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/dagre-d3-es": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.13.tgz", - "integrity": "sha512-efEhnxpSuwpYOKRm/L5KbqoZmNNukHa/Flty4Wp62JRvgH2ojwVgPgdYyr4twpieZnyRDdIH7PY2mopX26+j2Q==", - "license": "MIT", - "dependencies": { - "d3": "^7.9.0", - "lodash-es": "^4.17.21" - } - }, - "node_modules/dayjs": { - "version": "1.11.19", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", - "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", - "license": "MIT" - }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -2556,13 +2159,13 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/delaunator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", - "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", - "license": "ISC", - "dependencies": { - "robust-predicates": "^3.0.2" + "node_modules/deepmerge": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz", + "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, "node_modules/dequal": { @@ -2610,15 +2213,6 @@ "dev": true, "license": "MIT" }, - "node_modules/dompurify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", - "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", - "license": "(MPL-2.0 OR Apache-2.0)", - "optionalDependencies": { - "@types/trusted-types": "^2.0.7" - } - }, "node_modules/electron-to-chromium": { "version": "1.5.283", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.283.tgz", @@ -2626,11 +2220,37 @@ "dev": true, "license": "ISC" }, - "node_modules/elkjs": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.3.tgz", - "integrity": "sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==", - "license": "EPL-2.0" + "node_modules/enhanced-resolve": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-2.3.0.tgz", + "integrity": "sha512-n6e4bsCpzsP0OB76X+vEWhySUQI8GHPVFVK+3QkX35tbryy2WoeGeK5kQ+oxzgDVHjIZyz5fyS60Mi3EpQLc0Q==", + "dependencies": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.3.0", + "object-assign": "^4.0.1", + "tapable": "^0.2.3" + }, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/err-code": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", + "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==", + "license": "MIT" + }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "license": "MIT", + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } }, "node_modules/esbuild": { "version": "0.21.5", @@ -2691,12 +2311,24 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "license": "MIT" }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "license": "Apache-2.0" + }, "node_modules/fast-glob": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", @@ -2788,6 +2420,12 @@ } } }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2823,6 +2461,33 @@ "node": ">=6.9.0" } }, + "node_modules/get-browser-rtc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-browser-rtc/-/get-browser-rtc-1.1.0.tgz", + "integrity": "sha512-MghbMJ61EJrRsDe7w1Bvqt3ZsBuqhce5nrn/XAwgwOXhcsz53/ltdxOse1h/8eKXj5slzxdsz56g5rzOFSGwfQ==", + "license": "MIT" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -2836,6 +2501,12 @@ "node": ">=10.13.0" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -2914,33 +2585,55 @@ "node": ">=20.0.0" } }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "license": "MIT", + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" + "once": "^1.3.0", + "wrappy": "1" } }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, "node_modules/inline-style-parser": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", "license": "MIT" }, - "node_modules/internmap": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/is-alphabetical": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", @@ -3059,6 +2752,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/isomorphic.js": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz", + "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==", + "license": "MIT", + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + }, "node_modules/jiti": { "version": "1.21.7", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", @@ -3101,6 +2810,18 @@ "node": ">=6" } }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, "node_modules/katex": { "version": "0.16.28", "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.28.tgz", @@ -3126,11 +2847,6 @@ "node": ">= 12" } }, - "node_modules/khroma": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", - "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==" - }, "node_modules/kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", @@ -3140,11 +2856,35 @@ "node": ">=6" } }, - "node_modules/layout-base": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", - "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", - "license": "MIT" + "node_modules/lib0": { + "version": "0.2.117", + "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.117.tgz", + "integrity": "sha512-DeXj9X5xDCjgKLU/7RR+/HQEVzuuEUiwldwOGsHK/sfAfELGWEyTcf0x+uOvCvK3O2zPmZePXWL85vtia6GyZw==", + "license": "MIT", + "dependencies": { + "isomorphic.js": "^0.2.4" + }, + "bin": { + "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js", + "0gentesthtml": "bin/gentesthtml.js", + "0serve": "bin/0serve.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } }, "node_modules/lilconfig": { "version": "3.1.3", @@ -3172,6 +2912,19 @@ "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", "license": "MIT" }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "license": "MIT" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" + }, "node_modules/longest-streak": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", @@ -5154,6 +4907,16 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/memory-fs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", + "integrity": "sha512-QTNXnl79X97kZ9jJk/meJrtDuvgvRakX5LU7HZW1L7MsXHuSTwoMIzN9tOLLH3Xfsj/gbsSqX/ovnsqz246zKQ==", + "license": "MIT", + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, "node_modules/merge-refs": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-refs/-/merge-refs-2.0.0.tgz", @@ -5181,34 +4944,6 @@ "node": ">= 8" } }, - "node_modules/mermaid": { - "version": "10.9.5", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.9.5.tgz", - "integrity": "sha512-eRlKEjzak4z1rcXeCd1OAlyawhrptClQDo8OuI8n6bSVqJ9oMfd5Lrf3Q+TdJHewi/9AIOc3UmEo8Fz+kNzzuQ==", - "license": "MIT", - "dependencies": { - "@braintree/sanitize-url": "^6.0.1", - "@types/d3-scale": "^4.0.3", - "@types/d3-scale-chromatic": "^3.0.0", - "cytoscape": "^3.28.1", - "cytoscape-cose-bilkent": "^4.1.0", - "d3": "^7.4.0", - "d3-sankey": "^0.12.3", - "dagre-d3-es": "7.0.13", - "dayjs": "^1.11.7", - "dompurify": "^3.2.4", - "elkjs": "^0.9.0", - "katex": "^0.16.9", - "khroma": "^2.0.0", - "lodash-es": "^4.17.21", - "mdast-util-from-markdown": "^1.3.0", - "non-layered-tidy-tree-layout": "^2.0.2", - "stylis": "^4.1.3", - "ts-dedent": "^2.2.0", - "uuid": "^9.0.0", - "web-worker": "^1.2.0" - } - }, "node_modules/micromark": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz", @@ -5665,6 +5400,18 @@ "node": ">=8.6" } }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -5718,12 +5465,6 @@ "dev": true, "license": "MIT" }, - "node_modules/non-layered-tidy-tree-layout": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz", - "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==", - "license": "MIT" - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -5738,7 +5479,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -5754,6 +5494,27 @@ "node": ">= 6" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" + }, + "node_modules/parchment": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/parchment/-/parchment-3.0.0.tgz", + "integrity": "sha512-HUrJFQ/StvgmXRcQ1ftY6VEZUq3jA2t9ncFN4F84J/vN0/FPpQF+8FKXb3l6fLces6q0uOHj6NJn+2xvZnxO6A==", + "license": "BSD-3-Clause" + }, "node_modules/parse-entities": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", @@ -5773,6 +5534,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -5780,6 +5550,24 @@ "dev": true, "license": "MIT" }, + "node_modules/pdf-lib": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/pdf-lib/-/pdf-lib-1.17.1.tgz", + "integrity": "sha512-V/mpyJAoTsN4cnP31vc0wfNA1+p20evqqnap0KLoRUN0Yk/p3wN52DOEsL4oBFcLdb76hlpKPtzJIgo67j/XLw==", + "license": "MIT", + "dependencies": { + "@pdf-lib/standard-fonts": "^1.0.0", + "@pdf-lib/upng": "^1.0.1", + "pako": "^1.0.11", + "tslib": "^1.11.1" + } + }, + "node_modules/pdf-lib/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, "node_modules/pdfjs-dist": { "version": "5.4.296", "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.4.296.tgz", @@ -5995,6 +5783,12 @@ "dev": true, "license": "MIT" }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, "node_modules/property-information": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", @@ -6005,11 +5799,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "license": "MIT" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -6026,6 +5825,50 @@ ], "license": "MIT" }, + "node_modules/quill": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/quill/-/quill-2.0.3.tgz", + "integrity": "sha512-xEYQBqfYx/sfb33VJiKnSJp8ehloavImQ2A6564GAbqG55PGw1dAWUn1MUbQB62t0azawUS2CZZhWCjO8gRvTw==", + "license": "BSD-3-Clause", + "dependencies": { + "eventemitter3": "^5.0.1", + "lodash-es": "^4.17.21", + "parchment": "^3.0.0", + "quill-delta": "^5.1.0" + }, + "engines": { + "npm": ">=8.2.3" + } + }, + "node_modules/quill-delta": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz", + "integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==", + "license": "MIT", + "dependencies": { + "fast-diff": "^1.3.0", + "lodash.clonedeep": "^4.5.0", + "lodash.isequal": "^4.5.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/quill/node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "license": "MIT" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", @@ -6136,6 +5979,21 @@ "pify": "^2.3.0" } }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -6719,6 +6577,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -6730,12 +6597,6 @@ "node": ">=0.10.0" } }, - "node_modules/robust-predicates": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", - "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", - "license": "Unlicense" - }, "node_modules/rollup": { "version": "4.57.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", @@ -6805,12 +6666,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/rw": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", - "license": "BSD-3-Clause" - }, "node_modules/sade": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", @@ -6823,12 +6678,21 @@ "node": ">=6" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "license": "MIT" }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", @@ -6848,6 +6712,98 @@ "semver": "bin/semver.js" } }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT" + }, + "node_modules/simple-mind-map": { + "version": "0.14.0-fix.2", + "resolved": "https://registry.npmjs.org/simple-mind-map/-/simple-mind-map-0.14.0-fix.2.tgz", + "integrity": "sha512-31EWUozONl7Nn8b2Idf6UdPcAGtS8prVBjz/j0TZ9/zJcvmcEaJd1utX4sI/DGrr0ZW51ZNrfk09dYYCMaG7AA==", + "license": "MIT", + "dependencies": { + "@svgdotjs/svg.js": "3.2.0", + "deepmerge": "^1.5.2", + "eventemitter3": "^4.0.7", + "jszip": "^3.10.1", + "katex": "^0.16.8", + "mdast-util-from-markdown": "^1.3.0", + "pdf-lib": "^1.17.1", + "quill": "^2.0.3", + "tern": "^0.24.3", + "uuid": "^9.0.0", + "ws": "^7.5.9", + "xml-js": "^1.6.11", + "y-webrtc": "^10.2.5", + "yjs": "^13.6.8" + } + }, + "node_modules/simple-mind-map/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/simple-peer": { + "version": "9.11.1", + "resolved": "https://registry.npmjs.org/simple-peer/-/simple-peer-9.11.1.tgz", + "integrity": "sha512-D1SaWpOW8afq1CZGWB8xTfrT3FekjQmPValrqncJMX7QFl8YwhrPTZvMCANLtgBwwdS+7zURyqxDDEmY558tTw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "debug": "^4.3.2", + "err-code": "^3.0.1", + "get-browser-rtc": "^1.1.0", + "queue-microtask": "^1.2.3", + "randombytes": "^2.1.0", + "readable-stream": "^3.6.0" + } + }, + "node_modules/simple-peer/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -6868,6 +6824,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/stringify-entities": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", @@ -6900,12 +6865,6 @@ "inline-style-parser": "0.2.7" } }, - "node_modules/stylis": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", - "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", - "license": "MIT" - }, "node_modules/sucrase": { "version": "3.35.1", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", @@ -7000,6 +6959,33 @@ "node": ">=14.0.0" } }, + "node_modules/tapable": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.9.tgz", + "integrity": "sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tern": { + "version": "0.24.3", + "resolved": "https://registry.npmjs.org/tern/-/tern-0.24.3.tgz", + "integrity": "sha512-Z8uvtdWIlFn1GWy0HW5FhZ8VDryZwoJUdnjZU25C7/PBOltLIn1uv+WF3rVq6S1761YbsmbZYRP/l0ZJBCkvrw==", + "license": "MIT", + "dependencies": { + "acorn": "^6.0.0", + "acorn-loose": "^6.0.0", + "acorn-walk": "^6.0.0", + "enhanced-resolve": "^2.2.2", + "glob": "^7.1.1", + "minimatch": "^3.0.3", + "resolve-from": "2.0.0" + }, + "bin": { + "tern": "bin/tern" + } + }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -7110,15 +7096,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/ts-dedent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", - "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", - "license": "MIT", - "engines": { - "node": ">=6.10" - } - }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", @@ -7313,7 +7290,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, "license": "MIT" }, "node_modules/uuid": { @@ -7469,11 +7445,11 @@ "loose-envify": "^1.0.0" } }, - "node_modules/web-worker": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.5.0.tgz", - "integrity": "sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==", - "license": "Apache-2.0" + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" }, "node_modules/ws": { "version": "8.19.0", @@ -7496,6 +7472,65 @@ } } }, + "node_modules/xml-js": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "license": "MIT", + "dependencies": { + "sax": "^1.2.4" + }, + "bin": { + "xml-js": "bin/cli.js" + } + }, + "node_modules/y-protocols": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.7.tgz", + "integrity": "sha512-YSVsLoXxO67J6eE/nV4AtFtT3QEotZf5sK5BHxFBXso7VDUT3Tx07IfA6hsu5Q5OmBdMkQVmFZ9QOA7fikWvnw==", + "license": "MIT", + "dependencies": { + "lib0": "^0.2.85" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + }, + "peerDependencies": { + "yjs": "^13.0.0" + } + }, + "node_modules/y-webrtc": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/y-webrtc/-/y-webrtc-10.3.0.tgz", + "integrity": "sha512-KalJr7dCgUgyVFxoG3CQYbpS0O2qybegD0vI4bYnYHI0MOwoVbucED3RZ5f2o1a5HZb1qEssUKS0H/Upc6p1lA==", + "license": "MIT", + "dependencies": { + "lib0": "^0.2.42", + "simple-peer": "^9.11.0", + "y-protocols": "^1.0.6" + }, + "bin": { + "y-webrtc-signaling": "bin/server.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + }, + "optionalDependencies": { + "ws": "^8.14.2" + }, + "peerDependencies": { + "yjs": "^13.6.8" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -7503,6 +7538,23 @@ "dev": true, "license": "ISC" }, + "node_modules/yjs": { + "version": "13.6.30", + "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.30.tgz", + "integrity": "sha512-vv/9h42eCMC81ZHDFswuu/MKzkl/vyq1BhaNGfHyOonwlG4CJbQF4oiBBJPvfdeCt/PlVDWh7Nov9D34YY09uQ==", + "license": "MIT", + "dependencies": { + "lib0": "^0.2.99" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + }, "node_modules/zustand": { "version": "4.5.7", "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz", diff --git a/frontend_en/package.json b/frontend_en/package.json index b6d9db4..a28bdda 100644 --- a/frontend_en/package.json +++ b/frontend_en/package.json @@ -14,12 +14,12 @@ "framer-motion": "^10.16.4", "katex": "^0.16.28", "lucide-react": "^0.294.0", - "mermaid": "^10.6.1", "pdfjs-dist": "^5.4.296", "react": "^18.2.0", "react-dom": "^18.2.0", "react-markdown": "^9.1.0", "react-pdf": "^10.3.0", + "simple-mind-map": "^0.14.0-fix.2", "tailwind-merge": "^2.0.0", "zustand": "^4.4.7" }, diff --git a/frontend_en/src/types/simple-mind-map.d.ts b/frontend_en/src/types/simple-mind-map.d.ts new file mode 100644 index 0000000..fa2911a --- /dev/null +++ b/frontend_en/src/types/simple-mind-map.d.ts @@ -0,0 +1,76 @@ +declare module 'simple-mind-map' { + interface MindMapData { + data: { + text: string; + [key: string]: any; + }; + children?: MindMapData[]; + } + + interface MindMapOptions { + el: HTMLElement; + data?: MindMapData; + theme?: string; + layout?: string; + scaleRatio?: number; + minZoomRatio?: number; + maxZoomRatio?: number; + readonly?: boolean; + enableFreeDrag?: boolean; + [key: string]: any; + } + + interface MindMapNode { + data: { text: string; [key: string]: any }; + children?: MindMapNode[]; + nodeData: MindMapData; + [key: string]: any; + } + + interface MindMapView { + enlarge(cx?: number, cy?: number): void; + narrow(cx?: number, cy?: number): void; + setScale(scale: number, cx?: number, cy?: number): void; + fit(): void; + reset(): void; + translateXY(x: number, y: number): void; + getTransformData(): { state: { scale: number; x: number; y: number } }; + setTransformData(data: { state: { scale: number; x: number; y: number } }): void; + } + + class MindMap { + constructor(options: MindMapOptions); + + static usePlugin(plugin: any): typeof MindMap; + static defineTheme(name: string, config: Record): void; + + view: MindMapView; + + setData(data: MindMapData): void; + setTheme(theme: string): void; + setThemeConfig(config: Record): void; + setLayout(layout: string): void; + execCommand(command: string, ...args: any[]): void; + export( + type: 'png' | 'jpg' | 'svg' | 'json' | 'pdf' | 'smm' | 'md' | 'txt', + isDownload?: boolean, + fileName?: string, + ...args: any[] + ): Promise | any; + on(event: string, callback: (...args: any[]) => void): void; + off(event: string, callback: (...args: any[]) => void): void; + destroy(): void; + } + + export default MindMap; +} + +declare module 'simple-mind-map/src/plugins/Export.js' { + const Export: any; + export default Export; +} + +declare module 'simple-mind-map/src/parse/markdown.js' { + export function transformMarkdownTo(markdown: string): any; + export function transformToMarkdown(data: any): string; +} diff --git a/frontend_en/src/utils/mermaidToMarkdown.ts b/frontend_en/src/utils/mermaidToMarkdown.ts new file mode 100644 index 0000000..e00ade1 --- /dev/null +++ b/frontend_en/src/utils/mermaidToMarkdown.ts @@ -0,0 +1,124 @@ +/** + * Convert Mermaid mindmap syntax to Markdown headings format. + * Used as fallback for legacy .mmd files. + * + * Input example: + * mindmap + * root((Central Topic)) + * Topic 1 + * Sub 1.1 + * Topic 2 + * + * Output: + * # Central Topic + * ## Topic 1 + * ### Sub 1.1 + * ## Topic 2 + */ + +function stripShapeDecorators(text: string): string { + return text + .replace(/^\(\((.+?)\)\)$/, '$1') + .replace(/^\((.+?)\)$/, '$1') + .replace(/^\[(.+?)\]$/, '$1') + .replace(/^\{\{(.+?)\}\}$/, '$1') + .replace(/^\)(.+?)\($/, '$1') + .replace(/^>(.+?)\]$/, '$1'); +} + +export function mermaidToMarkdown(mermaidCode: string): string { + const lines = mermaidCode.split('\n'); + const result: string[] = []; + let baseIndent = -1; + let indentUnit = 2; + + for (const line of lines) { + const trimmed = line.trimEnd(); + if (!trimmed || trimmed.trim() === 'mindmap') continue; + + const indent = line.length - line.trimStart().length; + let text = trimmed.trim(); + + // Handle root line + if (text.startsWith('root')) { + text = text.replace(/^root\s*/, '').trim(); + text = stripShapeDecorators(text); + baseIndent = indent; + result.push(`# ${text}`); + continue; + } + + // Detect indent unit from first non-root indented line + if (baseIndent >= 0 && indent > baseIndent && indentUnit === 2) { + indentUnit = indent - baseIndent; + } + + text = stripShapeDecorators(text); + + const depth = Math.max(1, Math.floor((indent - baseIndent) / indentUnit) + 1); + const hashes = '#'.repeat(Math.min(depth, 6)); + result.push(`${hashes} ${text}`); + } + + return result.join('\n'); +} + +/** + * Detect if the input is Mermaid mindmap syntax (vs already Markdown). + */ +export function isMermaidMindmap(code: string): boolean { + const trimmed = code.trimStart(); + return trimmed.startsWith('mindmap'); +} + +/** + * Convert Markdown headings to Mermaid mindmap syntax. + * + * Input: + * # Central Topic + * ## Topic 1 + * ### Sub 1.1 + * + * Output: + * mindmap + * root((Central Topic)) + * Topic 1 + * Sub 1.1 + */ +let _nodeIdCounter = 0; + +function needsEscape(text: string): boolean { + return /[()[\]{}<>"'/\\,;:!?]/.test(text); +} + +export function markdownToMermaid(markdown: string): string { + _nodeIdCounter = 0; + const lines = markdown.split('\n'); + const result: string[] = ['mindmap']; + + for (const line of lines) { + const match = line.match(/^(#{1,6})\s+(.+)/); + if (!match) continue; + + const depth = match[1].length; + const text = match[2].trim(); + const indent = ' '.repeat(depth); + + if (depth === 1) { + // Root node: use round shape + if (needsEscape(text)) { + result.push(`${indent}root["${text}"]`); + } else { + result.push(`${indent}root(${text})`); + } + } else if (needsEscape(text)) { + // Nodes with special chars: use id["text"] syntax + const id = `n${++_nodeIdCounter}`; + result.push(`${indent}${id}["${text}"]`); + } else { + result.push(`${indent}${text}`); + } + } + + return result.join('\n'); +} diff --git a/frontend_zh/package-lock.json b/frontend_zh/package-lock.json index 873bc08..7ca7edd 100644 --- a/frontend_zh/package-lock.json +++ b/frontend_zh/package-lock.json @@ -13,12 +13,12 @@ "framer-motion": "^10.16.4", "katex": "^0.16.28", "lucide-react": "^0.294.0", - "mermaid": "^10.6.1", "pdfjs-dist": "^5.4.296", "react": "^18.2.0", "react-dom": "^18.2.0", "react-markdown": "^9.1.0", "react-pdf": "^10.3.0", + "simple-mind-map": "^0.14.0-fix.2", "tailwind-merge": "^2.0.0", "zustand": "^4.4.7" }, @@ -328,12 +328,6 @@ "node": ">=6.9.0" } }, - "node_modules/@braintree/sanitize-url": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz", - "integrity": "sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==", - "license": "MIT" - }, "node_modules/@emotion/is-prop-valid": { "version": "0.8.8", "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", @@ -1080,6 +1074,24 @@ "node": ">= 8" } }, + "node_modules/@pdf-lib/standard-fonts": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz", + "integrity": "sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA==", + "license": "MIT", + "dependencies": { + "pako": "^1.0.6" + } + }, + "node_modules/@pdf-lib/upng": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@pdf-lib/upng/-/upng-1.0.1.tgz", + "integrity": "sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ==", + "license": "MIT", + "dependencies": { + "pako": "^1.0.10" + } + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.27", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", @@ -1517,6 +1529,16 @@ "node": ">=20.0.0" } }, + "node_modules/@svgdotjs/svg.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.js/-/svg.js-3.2.0.tgz", + "integrity": "sha512-Tr8p+QVP7y+QT1GBlq1Tt57IvedVH8zCPoYxdHLX0Oof3a/PqnC/tXAkVufv1JQJfsDHlH/UrjcDfgxSofqSNA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Fuzzyma" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -1562,27 +1584,6 @@ "@babel/types": "^7.28.2" } }, - "node_modules/@types/d3-scale": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", - "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", - "license": "MIT", - "dependencies": { - "@types/d3-time": "*" - } - }, - "node_modules/@types/d3-scale-chromatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", - "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==", - "license": "MIT" - }, - "node_modules/@types/d3-time": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", - "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", - "license": "MIT" - }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -1672,13 +1673,6 @@ "@types/react": "^18.0.0" } }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", - "license": "MIT", - "optional": true - }, "node_modules/@types/unist": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", @@ -1721,6 +1715,39 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, + "node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-loose": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/acorn-loose/-/acorn-loose-6.1.0.tgz", + "integrity": "sha512-FHhXoiF0Uch3IqsrnPpWwCtiv5PYvipTpT1k9lDMgQVVYc9iDuSl5zdJV358aI8twfHCYMFBRVYvAVki9wC/ng==", + "license": "MIT", + "dependencies": { + "acorn": "^6.2.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -1796,6 +1823,32 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/baseline-browser-mapping": { "version": "2.9.19", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", @@ -1819,6 +1872,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/brace-expansion": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", @@ -1866,6 +1929,30 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", @@ -2004,14 +2091,11 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "license": "MIT", - "engines": { - "node": ">= 10" - } + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" }, "node_modules/convert-source-map": { "version": "2.0.0", @@ -2020,14 +2104,11 @@ "dev": true, "license": "MIT" }, - "node_modules/cose-base": { + "node_modules/core-util-is": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", - "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", - "license": "MIT", - "dependencies": { - "layout-base": "^1.0.0" - } + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" }, "node_modules/cssesc": { "version": "3.0.0", @@ -2048,484 +2129,6 @@ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "license": "MIT" }, - "node_modules/cytoscape": { - "version": "3.33.1", - "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.1.tgz", - "integrity": "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==", - "license": "MIT", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/cytoscape-cose-bilkent": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", - "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", - "license": "MIT", - "dependencies": { - "cose-base": "^1.0.0" - }, - "peerDependencies": { - "cytoscape": "^3.2.0" - } - }, - "node_modules/d3": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", - "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", - "license": "ISC", - "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" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-array": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", - "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", - "license": "ISC", - "dependencies": { - "internmap": "1 - 2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-axis": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", - "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-brush": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", - "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", - "license": "ISC", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "3", - "d3-transition": "3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-chord": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", - "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", - "license": "ISC", - "dependencies": { - "d3-path": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-contour": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", - "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", - "license": "ISC", - "dependencies": { - "d3-array": "^3.2.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-delaunay": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", - "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", - "license": "ISC", - "dependencies": { - "delaunator": "5" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-dispatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", - "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-drag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", - "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", - "license": "ISC", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-selection": "3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-dsv": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", - "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", - "license": "ISC", - "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" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-ease": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-fetch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", - "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", - "license": "ISC", - "dependencies": { - "d3-dsv": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-force": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", - "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", - "license": "ISC", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-quadtree": "1 - 3", - "d3-timer": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-format": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", - "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-geo": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", - "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", - "license": "ISC", - "dependencies": { - "d3-array": "2.5.0 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-hierarchy": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", - "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", - "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-polygon": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", - "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-quadtree": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", - "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-random": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", - "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-sankey": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", - "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", - "license": "BSD-3-Clause", - "dependencies": { - "d3-array": "1 - 2", - "d3-shape": "^1.2.0" - } - }, - "node_modules/d3-sankey/node_modules/d3-array": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", - "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", - "license": "BSD-3-Clause", - "dependencies": { - "internmap": "^1.0.0" - } - }, - "node_modules/d3-sankey/node_modules/d3-path": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", - "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", - "license": "BSD-3-Clause" - }, - "node_modules/d3-sankey/node_modules/d3-shape": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", - "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", - "license": "BSD-3-Clause", - "dependencies": { - "d3-path": "1" - } - }, - "node_modules/d3-sankey/node_modules/internmap": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", - "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", - "license": "ISC" - }, - "node_modules/d3-scale": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", - "license": "ISC", - "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" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-scale-chromatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", - "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3", - "d3-interpolate": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-shape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", - "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", - "license": "ISC", - "dependencies": { - "d3-path": "^3.1.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", - "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", - "license": "ISC", - "dependencies": { - "d3-array": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-time-format": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", - "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", - "license": "ISC", - "dependencies": { - "d3-time": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-timer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-transition": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", - "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3", - "d3-dispatch": "1 - 3", - "d3-ease": "1 - 3", - "d3-interpolate": "1 - 3", - "d3-timer": "1 - 3" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "d3-selection": "2 - 3" - } - }, - "node_modules/d3-zoom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", - "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", - "license": "ISC", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "2 - 3", - "d3-transition": "2 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/dagre-d3-es": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.13.tgz", - "integrity": "sha512-efEhnxpSuwpYOKRm/L5KbqoZmNNukHa/Flty4Wp62JRvgH2ojwVgPgdYyr4twpieZnyRDdIH7PY2mopX26+j2Q==", - "license": "MIT", - "dependencies": { - "d3": "^7.9.0", - "lodash-es": "^4.17.21" - } - }, - "node_modules/dayjs": { - "version": "1.11.19", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", - "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", - "license": "MIT" - }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -2556,13 +2159,13 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/delaunator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", - "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", - "license": "ISC", - "dependencies": { - "robust-predicates": "^3.0.2" + "node_modules/deepmerge": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz", + "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, "node_modules/dequal": { @@ -2610,15 +2213,6 @@ "dev": true, "license": "MIT" }, - "node_modules/dompurify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", - "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", - "license": "(MPL-2.0 OR Apache-2.0)", - "optionalDependencies": { - "@types/trusted-types": "^2.0.7" - } - }, "node_modules/electron-to-chromium": { "version": "1.5.283", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.283.tgz", @@ -2626,11 +2220,37 @@ "dev": true, "license": "ISC" }, - "node_modules/elkjs": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.3.tgz", - "integrity": "sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==", - "license": "EPL-2.0" + "node_modules/enhanced-resolve": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-2.3.0.tgz", + "integrity": "sha512-n6e4bsCpzsP0OB76X+vEWhySUQI8GHPVFVK+3QkX35tbryy2WoeGeK5kQ+oxzgDVHjIZyz5fyS60Mi3EpQLc0Q==", + "dependencies": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.3.0", + "object-assign": "^4.0.1", + "tapable": "^0.2.3" + }, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/err-code": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz", + "integrity": "sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==", + "license": "MIT" + }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "license": "MIT", + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } }, "node_modules/esbuild": { "version": "0.21.5", @@ -2691,12 +2311,24 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "license": "MIT" }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "license": "Apache-2.0" + }, "node_modules/fast-glob": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", @@ -2788,6 +2420,12 @@ } } }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2823,6 +2461,33 @@ "node": ">=6.9.0" } }, + "node_modules/get-browser-rtc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-browser-rtc/-/get-browser-rtc-1.1.0.tgz", + "integrity": "sha512-MghbMJ61EJrRsDe7w1Bvqt3ZsBuqhce5nrn/XAwgwOXhcsz53/ltdxOse1h/8eKXj5slzxdsz56g5rzOFSGwfQ==", + "license": "MIT" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -2836,6 +2501,12 @@ "node": ">=10.13.0" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -2914,33 +2585,55 @@ "node": ">=20.0.0" } }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "license": "MIT", + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "license": "MIT" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" + "once": "^1.3.0", + "wrappy": "1" } }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, "node_modules/inline-style-parser": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", "license": "MIT" }, - "node_modules/internmap": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "node_modules/is-alphabetical": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", @@ -3059,6 +2752,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/isomorphic.js": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz", + "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==", + "license": "MIT", + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + }, "node_modules/jiti": { "version": "1.21.7", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", @@ -3101,6 +2810,18 @@ "node": ">=6" } }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, "node_modules/katex": { "version": "0.16.28", "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.28.tgz", @@ -3126,11 +2847,6 @@ "node": ">= 12" } }, - "node_modules/khroma": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", - "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==" - }, "node_modules/kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", @@ -3140,11 +2856,35 @@ "node": ">=6" } }, - "node_modules/layout-base": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", - "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", - "license": "MIT" + "node_modules/lib0": { + "version": "0.2.117", + "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.117.tgz", + "integrity": "sha512-DeXj9X5xDCjgKLU/7RR+/HQEVzuuEUiwldwOGsHK/sfAfELGWEyTcf0x+uOvCvK3O2zPmZePXWL85vtia6GyZw==", + "license": "MIT", + "dependencies": { + "isomorphic.js": "^0.2.4" + }, + "bin": { + "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js", + "0gentesthtml": "bin/gentesthtml.js", + "0serve": "bin/0serve.js" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } }, "node_modules/lilconfig": { "version": "3.1.3", @@ -3172,6 +2912,19 @@ "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", "license": "MIT" }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "license": "MIT" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" + }, "node_modules/longest-streak": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", @@ -5154,6 +4907,16 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/memory-fs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.3.0.tgz", + "integrity": "sha512-QTNXnl79X97kZ9jJk/meJrtDuvgvRakX5LU7HZW1L7MsXHuSTwoMIzN9tOLLH3Xfsj/gbsSqX/ovnsqz246zKQ==", + "license": "MIT", + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, "node_modules/merge-refs": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-refs/-/merge-refs-2.0.0.tgz", @@ -5181,34 +4944,6 @@ "node": ">= 8" } }, - "node_modules/mermaid": { - "version": "10.9.5", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.9.5.tgz", - "integrity": "sha512-eRlKEjzak4z1rcXeCd1OAlyawhrptClQDo8OuI8n6bSVqJ9oMfd5Lrf3Q+TdJHewi/9AIOc3UmEo8Fz+kNzzuQ==", - "license": "MIT", - "dependencies": { - "@braintree/sanitize-url": "^6.0.1", - "@types/d3-scale": "^4.0.3", - "@types/d3-scale-chromatic": "^3.0.0", - "cytoscape": "^3.28.1", - "cytoscape-cose-bilkent": "^4.1.0", - "d3": "^7.4.0", - "d3-sankey": "^0.12.3", - "dagre-d3-es": "7.0.13", - "dayjs": "^1.11.7", - "dompurify": "^3.2.4", - "elkjs": "^0.9.0", - "katex": "^0.16.9", - "khroma": "^2.0.0", - "lodash-es": "^4.17.21", - "mdast-util-from-markdown": "^1.3.0", - "non-layered-tidy-tree-layout": "^2.0.2", - "stylis": "^4.1.3", - "ts-dedent": "^2.2.0", - "uuid": "^9.0.0", - "web-worker": "^1.2.0" - } - }, "node_modules/micromark": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz", @@ -5665,6 +5400,18 @@ "node": ">=8.6" } }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -5718,12 +5465,6 @@ "dev": true, "license": "MIT" }, - "node_modules/non-layered-tidy-tree-layout": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz", - "integrity": "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==", - "license": "MIT" - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -5738,7 +5479,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -5754,6 +5494,27 @@ "node": ">= 6" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" + }, + "node_modules/parchment": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/parchment/-/parchment-3.0.0.tgz", + "integrity": "sha512-HUrJFQ/StvgmXRcQ1ftY6VEZUq3jA2t9ncFN4F84J/vN0/FPpQF+8FKXb3l6fLces6q0uOHj6NJn+2xvZnxO6A==", + "license": "BSD-3-Clause" + }, "node_modules/parse-entities": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", @@ -5773,6 +5534,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -5780,6 +5550,24 @@ "dev": true, "license": "MIT" }, + "node_modules/pdf-lib": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/pdf-lib/-/pdf-lib-1.17.1.tgz", + "integrity": "sha512-V/mpyJAoTsN4cnP31vc0wfNA1+p20evqqnap0KLoRUN0Yk/p3wN52DOEsL4oBFcLdb76hlpKPtzJIgo67j/XLw==", + "license": "MIT", + "dependencies": { + "@pdf-lib/standard-fonts": "^1.0.0", + "@pdf-lib/upng": "^1.0.1", + "pako": "^1.0.11", + "tslib": "^1.11.1" + } + }, + "node_modules/pdf-lib/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, "node_modules/pdfjs-dist": { "version": "5.4.296", "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.4.296.tgz", @@ -5995,6 +5783,12 @@ "dev": true, "license": "MIT" }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, "node_modules/property-information": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", @@ -6005,11 +5799,16 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "license": "MIT" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -6026,6 +5825,50 @@ ], "license": "MIT" }, + "node_modules/quill": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/quill/-/quill-2.0.3.tgz", + "integrity": "sha512-xEYQBqfYx/sfb33VJiKnSJp8ehloavImQ2A6564GAbqG55PGw1dAWUn1MUbQB62t0azawUS2CZZhWCjO8gRvTw==", + "license": "BSD-3-Clause", + "dependencies": { + "eventemitter3": "^5.0.1", + "lodash-es": "^4.17.21", + "parchment": "^3.0.0", + "quill-delta": "^5.1.0" + }, + "engines": { + "npm": ">=8.2.3" + } + }, + "node_modules/quill-delta": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz", + "integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==", + "license": "MIT", + "dependencies": { + "fast-diff": "^1.3.0", + "lodash.clonedeep": "^4.5.0", + "lodash.isequal": "^4.5.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/quill/node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "license": "MIT" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", @@ -6136,6 +5979,21 @@ "pify": "^2.3.0" } }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -6719,6 +6577,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -6730,12 +6597,6 @@ "node": ">=0.10.0" } }, - "node_modules/robust-predicates": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", - "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==", - "license": "Unlicense" - }, "node_modules/rollup": { "version": "4.57.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", @@ -6805,12 +6666,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/rw": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", - "license": "BSD-3-Clause" - }, "node_modules/sade": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", @@ -6823,12 +6678,21 @@ "node": ">=6" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "license": "MIT" }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", @@ -6848,6 +6712,98 @@ "semver": "bin/semver.js" } }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "license": "MIT" + }, + "node_modules/simple-mind-map": { + "version": "0.14.0-fix.2", + "resolved": "https://registry.npmjs.org/simple-mind-map/-/simple-mind-map-0.14.0-fix.2.tgz", + "integrity": "sha512-31EWUozONl7Nn8b2Idf6UdPcAGtS8prVBjz/j0TZ9/zJcvmcEaJd1utX4sI/DGrr0ZW51ZNrfk09dYYCMaG7AA==", + "license": "MIT", + "dependencies": { + "@svgdotjs/svg.js": "3.2.0", + "deepmerge": "^1.5.2", + "eventemitter3": "^4.0.7", + "jszip": "^3.10.1", + "katex": "^0.16.8", + "mdast-util-from-markdown": "^1.3.0", + "pdf-lib": "^1.17.1", + "quill": "^2.0.3", + "tern": "^0.24.3", + "uuid": "^9.0.0", + "ws": "^7.5.9", + "xml-js": "^1.6.11", + "y-webrtc": "^10.2.5", + "yjs": "^13.6.8" + } + }, + "node_modules/simple-mind-map/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/simple-peer": { + "version": "9.11.1", + "resolved": "https://registry.npmjs.org/simple-peer/-/simple-peer-9.11.1.tgz", + "integrity": "sha512-D1SaWpOW8afq1CZGWB8xTfrT3FekjQmPValrqncJMX7QFl8YwhrPTZvMCANLtgBwwdS+7zURyqxDDEmY558tTw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "debug": "^4.3.2", + "err-code": "^3.0.1", + "get-browser-rtc": "^1.1.0", + "queue-microtask": "^1.2.3", + "randombytes": "^2.1.0", + "readable-stream": "^3.6.0" + } + }, + "node_modules/simple-peer/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -6868,6 +6824,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/stringify-entities": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", @@ -6900,12 +6865,6 @@ "inline-style-parser": "0.2.7" } }, - "node_modules/stylis": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", - "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", - "license": "MIT" - }, "node_modules/sucrase": { "version": "3.35.1", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", @@ -7000,6 +6959,33 @@ "node": ">=14.0.0" } }, + "node_modules/tapable": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.9.tgz", + "integrity": "sha512-2wsvQ+4GwBvLPLWsNfLCDYGsW6xb7aeC6utq2Qh0PFwgEy7K7dsma9Jsmb2zSQj7GvYAyUGSntLtsv++GmgL1A==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tern": { + "version": "0.24.3", + "resolved": "https://registry.npmjs.org/tern/-/tern-0.24.3.tgz", + "integrity": "sha512-Z8uvtdWIlFn1GWy0HW5FhZ8VDryZwoJUdnjZU25C7/PBOltLIn1uv+WF3rVq6S1761YbsmbZYRP/l0ZJBCkvrw==", + "license": "MIT", + "dependencies": { + "acorn": "^6.0.0", + "acorn-loose": "^6.0.0", + "acorn-walk": "^6.0.0", + "enhanced-resolve": "^2.2.2", + "glob": "^7.1.1", + "minimatch": "^3.0.3", + "resolve-from": "2.0.0" + }, + "bin": { + "tern": "bin/tern" + } + }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -7110,15 +7096,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/ts-dedent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", - "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", - "license": "MIT", - "engines": { - "node": ">=6.10" - } - }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", @@ -7313,7 +7290,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, "license": "MIT" }, "node_modules/uuid": { @@ -7469,11 +7445,11 @@ "loose-envify": "^1.0.0" } }, - "node_modules/web-worker": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.5.0.tgz", - "integrity": "sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==", - "license": "Apache-2.0" + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" }, "node_modules/ws": { "version": "8.19.0", @@ -7496,6 +7472,65 @@ } } }, + "node_modules/xml-js": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "license": "MIT", + "dependencies": { + "sax": "^1.2.4" + }, + "bin": { + "xml-js": "bin/cli.js" + } + }, + "node_modules/y-protocols": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.7.tgz", + "integrity": "sha512-YSVsLoXxO67J6eE/nV4AtFtT3QEotZf5sK5BHxFBXso7VDUT3Tx07IfA6hsu5Q5OmBdMkQVmFZ9QOA7fikWvnw==", + "license": "MIT", + "dependencies": { + "lib0": "^0.2.85" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + }, + "peerDependencies": { + "yjs": "^13.0.0" + } + }, + "node_modules/y-webrtc": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/y-webrtc/-/y-webrtc-10.3.0.tgz", + "integrity": "sha512-KalJr7dCgUgyVFxoG3CQYbpS0O2qybegD0vI4bYnYHI0MOwoVbucED3RZ5f2o1a5HZb1qEssUKS0H/Upc6p1lA==", + "license": "MIT", + "dependencies": { + "lib0": "^0.2.42", + "simple-peer": "^9.11.0", + "y-protocols": "^1.0.6" + }, + "bin": { + "y-webrtc-signaling": "bin/server.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + }, + "optionalDependencies": { + "ws": "^8.14.2" + }, + "peerDependencies": { + "yjs": "^13.6.8" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -7503,6 +7538,23 @@ "dev": true, "license": "ISC" }, + "node_modules/yjs": { + "version": "13.6.30", + "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.30.tgz", + "integrity": "sha512-vv/9h42eCMC81ZHDFswuu/MKzkl/vyq1BhaNGfHyOonwlG4CJbQF4oiBBJPvfdeCt/PlVDWh7Nov9D34YY09uQ==", + "license": "MIT", + "dependencies": { + "lib0": "^0.2.99" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + }, "node_modules/zustand": { "version": "4.5.7", "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz", diff --git a/frontend_zh/package.json b/frontend_zh/package.json index b6d9db4..a28bdda 100644 --- a/frontend_zh/package.json +++ b/frontend_zh/package.json @@ -14,12 +14,12 @@ "framer-motion": "^10.16.4", "katex": "^0.16.28", "lucide-react": "^0.294.0", - "mermaid": "^10.6.1", "pdfjs-dist": "^5.4.296", "react": "^18.2.0", "react-dom": "^18.2.0", "react-markdown": "^9.1.0", "react-pdf": "^10.3.0", + "simple-mind-map": "^0.14.0-fix.2", "tailwind-merge": "^2.0.0", "zustand": "^4.4.7" }, diff --git a/frontend_zh/src/types/simple-mind-map.d.ts b/frontend_zh/src/types/simple-mind-map.d.ts new file mode 100644 index 0000000..fa2911a --- /dev/null +++ b/frontend_zh/src/types/simple-mind-map.d.ts @@ -0,0 +1,76 @@ +declare module 'simple-mind-map' { + interface MindMapData { + data: { + text: string; + [key: string]: any; + }; + children?: MindMapData[]; + } + + interface MindMapOptions { + el: HTMLElement; + data?: MindMapData; + theme?: string; + layout?: string; + scaleRatio?: number; + minZoomRatio?: number; + maxZoomRatio?: number; + readonly?: boolean; + enableFreeDrag?: boolean; + [key: string]: any; + } + + interface MindMapNode { + data: { text: string; [key: string]: any }; + children?: MindMapNode[]; + nodeData: MindMapData; + [key: string]: any; + } + + interface MindMapView { + enlarge(cx?: number, cy?: number): void; + narrow(cx?: number, cy?: number): void; + setScale(scale: number, cx?: number, cy?: number): void; + fit(): void; + reset(): void; + translateXY(x: number, y: number): void; + getTransformData(): { state: { scale: number; x: number; y: number } }; + setTransformData(data: { state: { scale: number; x: number; y: number } }): void; + } + + class MindMap { + constructor(options: MindMapOptions); + + static usePlugin(plugin: any): typeof MindMap; + static defineTheme(name: string, config: Record): void; + + view: MindMapView; + + setData(data: MindMapData): void; + setTheme(theme: string): void; + setThemeConfig(config: Record): void; + setLayout(layout: string): void; + execCommand(command: string, ...args: any[]): void; + export( + type: 'png' | 'jpg' | 'svg' | 'json' | 'pdf' | 'smm' | 'md' | 'txt', + isDownload?: boolean, + fileName?: string, + ...args: any[] + ): Promise | any; + on(event: string, callback: (...args: any[]) => void): void; + off(event: string, callback: (...args: any[]) => void): void; + destroy(): void; + } + + export default MindMap; +} + +declare module 'simple-mind-map/src/plugins/Export.js' { + const Export: any; + export default Export; +} + +declare module 'simple-mind-map/src/parse/markdown.js' { + export function transformMarkdownTo(markdown: string): any; + export function transformToMarkdown(data: any): string; +} diff --git a/frontend_zh/src/utils/mermaidToMarkdown.ts b/frontend_zh/src/utils/mermaidToMarkdown.ts new file mode 100644 index 0000000..e00ade1 --- /dev/null +++ b/frontend_zh/src/utils/mermaidToMarkdown.ts @@ -0,0 +1,124 @@ +/** + * Convert Mermaid mindmap syntax to Markdown headings format. + * Used as fallback for legacy .mmd files. + * + * Input example: + * mindmap + * root((Central Topic)) + * Topic 1 + * Sub 1.1 + * Topic 2 + * + * Output: + * # Central Topic + * ## Topic 1 + * ### Sub 1.1 + * ## Topic 2 + */ + +function stripShapeDecorators(text: string): string { + return text + .replace(/^\(\((.+?)\)\)$/, '$1') + .replace(/^\((.+?)\)$/, '$1') + .replace(/^\[(.+?)\]$/, '$1') + .replace(/^\{\{(.+?)\}\}$/, '$1') + .replace(/^\)(.+?)\($/, '$1') + .replace(/^>(.+?)\]$/, '$1'); +} + +export function mermaidToMarkdown(mermaidCode: string): string { + const lines = mermaidCode.split('\n'); + const result: string[] = []; + let baseIndent = -1; + let indentUnit = 2; + + for (const line of lines) { + const trimmed = line.trimEnd(); + if (!trimmed || trimmed.trim() === 'mindmap') continue; + + const indent = line.length - line.trimStart().length; + let text = trimmed.trim(); + + // Handle root line + if (text.startsWith('root')) { + text = text.replace(/^root\s*/, '').trim(); + text = stripShapeDecorators(text); + baseIndent = indent; + result.push(`# ${text}`); + continue; + } + + // Detect indent unit from first non-root indented line + if (baseIndent >= 0 && indent > baseIndent && indentUnit === 2) { + indentUnit = indent - baseIndent; + } + + text = stripShapeDecorators(text); + + const depth = Math.max(1, Math.floor((indent - baseIndent) / indentUnit) + 1); + const hashes = '#'.repeat(Math.min(depth, 6)); + result.push(`${hashes} ${text}`); + } + + return result.join('\n'); +} + +/** + * Detect if the input is Mermaid mindmap syntax (vs already Markdown). + */ +export function isMermaidMindmap(code: string): boolean { + const trimmed = code.trimStart(); + return trimmed.startsWith('mindmap'); +} + +/** + * Convert Markdown headings to Mermaid mindmap syntax. + * + * Input: + * # Central Topic + * ## Topic 1 + * ### Sub 1.1 + * + * Output: + * mindmap + * root((Central Topic)) + * Topic 1 + * Sub 1.1 + */ +let _nodeIdCounter = 0; + +function needsEscape(text: string): boolean { + return /[()[\]{}<>"'/\\,;:!?]/.test(text); +} + +export function markdownToMermaid(markdown: string): string { + _nodeIdCounter = 0; + const lines = markdown.split('\n'); + const result: string[] = ['mindmap']; + + for (const line of lines) { + const match = line.match(/^(#{1,6})\s+(.+)/); + if (!match) continue; + + const depth = match[1].length; + const text = match[2].trim(); + const indent = ' '.repeat(depth); + + if (depth === 1) { + // Root node: use round shape + if (needsEscape(text)) { + result.push(`${indent}root["${text}"]`); + } else { + result.push(`${indent}root(${text})`); + } + } else if (needsEscape(text)) { + // Nodes with special chars: use id["text"] syntax + const id = `n${++_nodeIdCounter}`; + result.push(`${indent}${id}["${text}"]`); + } else { + result.push(`${indent}${text}`); + } + } + + return result.join('\n'); +} From 63eab617ddec0462e1dda5f3144e203ed856b73a Mon Sep 17 00:00:00 2001 From: Anion <1005128408@qq.com> Date: Tue, 31 Mar 2026 15:26:28 +0800 Subject: [PATCH 4/6] feat: replace MermaidPreview with interactive MindMapPreview - New MindMapPreview component using simple-mind-map with: expand/collapse all, zoom/pan/fit, node expand/collapse buttons, PNG/TXT/Mermaid export, click-to-ask popover with contextual questions - Wire onNodeClick to close modal, switch to chat, and focus input - Fix preview modal missing rounded corners and backdrop blur - Delete old MermaidPreview component --- .../src/components/knowledge-base/index.tsx | 4 +- .../knowledge-base/tools/MermaidPreview.tsx | 305 ------------------ .../knowledge-base/tools/MindMapPreview.tsx | 303 +++++++++++++++++ frontend_en/src/pages/NotebookView.tsx | 29 +- .../src/components/knowledge-base/index.tsx | 4 +- .../knowledge-base/tools/MermaidPreview.tsx | 305 ------------------ .../knowledge-base/tools/MindMapPreview.tsx | 302 +++++++++++++++++ frontend_zh/src/pages/NotebookView.tsx | 29 +- 8 files changed, 649 insertions(+), 632 deletions(-) delete mode 100644 frontend_en/src/components/knowledge-base/tools/MermaidPreview.tsx create mode 100644 frontend_en/src/components/knowledge-base/tools/MindMapPreview.tsx delete mode 100644 frontend_zh/src/components/knowledge-base/tools/MermaidPreview.tsx create mode 100644 frontend_zh/src/components/knowledge-base/tools/MindMapPreview.tsx diff --git a/frontend_en/src/components/knowledge-base/index.tsx b/frontend_en/src/components/knowledge-base/index.tsx index d88bef2..de9f21c 100644 --- a/frontend_en/src/components/knowledge-base/index.tsx +++ b/frontend_en/src/components/knowledge-base/index.tsx @@ -6,7 +6,7 @@ import { UploadView } from './UploadView'; import { OutputView } from './OutputView'; import { SettingsView } from './SettingsView'; import { RightPanel } from './RightPanel'; -import { MermaidPreview } from './tools/MermaidPreview'; +import { MindMapPreview } from './tools/MindMapPreview'; import { supabase } from '../../lib/supabase'; import { useAuthStore } from '../../stores/authStore'; import { X, Eye, Trash2, FileText, Image, Video, Link as LinkIcon, Headphones } from 'lucide-react'; @@ -493,7 +493,7 @@ const KnowledgeBase = () => { /> {mindmapPreviewCode ? ( - + ) : (
No preview
)} diff --git a/frontend_en/src/components/knowledge-base/tools/MermaidPreview.tsx b/frontend_en/src/components/knowledge-base/tools/MermaidPreview.tsx deleted file mode 100644 index 66b6b63..0000000 --- a/frontend_en/src/components/knowledge-base/tools/MermaidPreview.tsx +++ /dev/null @@ -1,305 +0,0 @@ -import { useEffect, useRef, useState } from 'react'; -import { createPortal } from 'react-dom'; -import mermaid from 'mermaid'; -import { Download, Eye, Code, Maximize2, X } from 'lucide-react'; - -interface MermaidPreviewProps { - mermaidCode: string; - title?: string; -} - -export const MermaidPreview = ({ mermaidCode, title = "Mind map preview" }: MermaidPreviewProps) => { - const mermaidRef = useRef(null); - const [showCode, setShowCode] = useState(false); - const [renderError, setRenderError] = useState(null); - const [renderedSvg, setRenderedSvg] = useState(''); - const [showModal, setShowModal] = useState(false); - const [modalSvg, setModalSvg] = useState(''); - const [zoom, setZoom] = useState(1); - const [offset, setOffset] = useState({ x: 0, y: 0 }); - const [isDragging, setIsDragging] = useState(false); - const [dragStart, setDragStart] = useState({ x: 0, y: 0 }); - const [dragOrigin, setDragOrigin] = useState({ x: 0, y: 0 }); - - useEffect(() => { - mermaid.initialize({ - startOnLoad: false, - theme: 'dark', - themeVariables: { - primaryColor: '#0ea5e9', - primaryTextColor: '#fff', - primaryBorderColor: '#0284c7', - lineColor: '#06b6d4', - secondaryColor: '#0891b2', - tertiaryColor: '#164e63', - }, - fontFamily: 'ui-sans-serif, system-ui, sans-serif', - }); - }, []); - - useEffect(() => { - const renderMermaid = async () => { - if (!mermaidCode || !mermaidRef.current) return; - - try { - setRenderError(null); - setRenderedSvg(''); - mermaidRef.current.innerHTML = ''; - - const id = `mermaid-${Date.now()}`; - const { svg } = await mermaid.render(id, mermaidCode); - setRenderedSvg(svg); - - if (mermaidRef.current) { - mermaidRef.current.innerHTML = svg; - } - } catch (error: any) { - console.error('Mermaid render error:', error); - setRenderError(error.message || 'Failed to render diagram'); - setRenderedSvg(''); - } - }; - - renderMermaid(); - }, [mermaidCode]); - - const renderSvgForExport = async () => { - if (renderedSvg) return renderedSvg; - const id = `mermaid-export-${Date.now()}`; - const { svg } = await mermaid.render(id, mermaidCode); - return svg; - }; - - const normalizeSvg = (svg: string) => { - return svg.replace(/]*?)>/i, (match, attrs) => { - let next = attrs - .replace(/\swidth="[^"]*"/i, '') - .replace(/\sheight="[^"]*"/i, ''); - - if (!/preserveAspectRatio=/i.test(next)) { - next += ' preserveAspectRatio="xMidYMid meet"'; - } - - if (/style="/i.test(next)) { - next = next.replace(/style="([^"]*)"/i, (_, style) => { - const merged = `${style}; width:100%; height:100%;`; - return `style="${merged}"`; - }); - } else { - next += ' style="width:100%; height:100%;"'; - } - - return ``; - }); - }; - - const handleDownloadSVG = async () => { - if (!mermaidCode) return; - try { - const svgData = await renderSvgForExport(); - const blob = new Blob([svgData], { type: 'image/svg+xml' }); - const url = URL.createObjectURL(blob); - const link = document.createElement('a'); - link.href = url; - link.download = `mindmap_${Date.now()}.svg`; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - URL.revokeObjectURL(url); - } catch (error) { - console.error('Download SVG failed:', error); - } - }; - - const handleDownloadCode = () => { - const blob = new Blob([mermaidCode], { type: 'text/plain' }); - const url = URL.createObjectURL(blob); - - const link = document.createElement('a'); - link.href = url; - link.download = `mindmap_${Date.now()}.mmd`; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - URL.revokeObjectURL(url); - }; - - const handleExpand = async () => { - if (!mermaidCode) return; - try { - const svgData = await renderSvgForExport(); - setModalSvg(normalizeSvg(svgData)); - setZoom(1); - setOffset({ x: 0, y: 0 }); - setShowModal(true); - } catch (error) { - console.error('Expand preview failed:', error); - } - }; - - const clampZoom = (value: number) => Math.min(5, Math.max(0.2, value)); - - const handleWheel = (e: React.WheelEvent) => { - e.preventDefault(); - const direction = e.deltaY > 0 ? 0.9 : 1.1; - setZoom(prev => clampZoom(prev * direction)); - }; - - const handleMouseDown = (e: React.MouseEvent) => { - setIsDragging(true); - setDragStart({ x: e.clientX, y: e.clientY }); - setDragOrigin(offset); - }; - - const handleMouseMove = (e: React.MouseEvent) => { - if (!isDragging) return; - const dx = e.clientX - dragStart.x; - const dy = e.clientY - dragStart.y; - setOffset({ x: dragOrigin.x + dx, y: dragOrigin.y + dy }); - }; - - const handleMouseUp = () => { - setIsDragging(false); - }; - - return ( -
-
-

{title}

-
- - - - -
-
- - {showCode ? ( -
-
Mermaid code:
-
-            {mermaidCode}
-          
-
- ) : ( -
- {renderError ? ( -
-
Render failed
-
{renderError}
- -
- ) : ( -
- )} -
- )} - -
- Tip: Toggle diagram/code view or download SVG / Mermaid code -
- - {showModal && createPortal( -
setShowModal(false)} - > -
e.stopPropagation()} - > -
-
Mind map zoom preview
-
- - - - -
-
-
- {modalSvg ? ( -
-
-
- ) : ( -
No preview
- )} -
-
-
, - document.body - )} -
- ); -}; diff --git a/frontend_en/src/components/knowledge-base/tools/MindMapPreview.tsx b/frontend_en/src/components/knowledge-base/tools/MindMapPreview.tsx new file mode 100644 index 0000000..23e6125 --- /dev/null +++ b/frontend_en/src/components/knowledge-base/tools/MindMapPreview.tsx @@ -0,0 +1,303 @@ +import { useEffect, useRef, useState, useCallback } from 'react'; +import MindMap from 'simple-mind-map'; +import Export from 'simple-mind-map/src/plugins/Export.js'; +import { transformMarkdownTo } from 'simple-mind-map/src/parse/markdownTo.js'; +import { Download, Expand, Shrink, ZoomIn, ZoomOut, Maximize2, MessageSquare, FileText, Code } from 'lucide-react'; +import { mermaidToMarkdown, isMermaidMindmap, markdownToMermaid } from '../../../utils/mermaidToMarkdown'; + +MindMap.usePlugin(Export); + +interface MindMapPreviewProps { + mermaidCode: string; + title?: string; + onNodeClick?: (nodeText: string) => void; +} + +export const MindMapPreview = ({ mermaidCode, title = "Mind map preview", onNodeClick }: MindMapPreviewProps) => { + const containerRef = useRef(null); + const mindMapRef = useRef(null); + const [renderError, setRenderError] = useState(null); + const [isReady, setIsReady] = useState(false); + const [tooltip, setTooltip] = useState<{ text: string; x: number; y: number } | null>(null); + const [askMenu, setAskMenu] = useState<{ nodeText: string; parentText: string; x: number; y: number } | null>(null); + + // Convert input to markdown if needed, then to mind map data + const parseData = useCallback(() => { + if (!mermaidCode) return null; + try { + const markdown = isMermaidMindmap(mermaidCode) + ? mermaidToMarkdown(mermaidCode) + : mermaidCode; + return transformMarkdownTo(markdown); + } catch { + return null; + } + }, [mermaidCode]); + + useEffect(() => { + if (!containerRef.current || !mermaidCode) return; + + const data = parseData(); + if (!data) { + setRenderError('Failed to parse mindmap data'); + return; + } + + setRenderError(null); + + // Destroy previous instance + if (mindMapRef.current) { + mindMapRef.current.destroy(); + mindMapRef.current = null; + setIsReady(false); + } + + try { + const mm = new MindMap({ + el: containerRef.current, + data, + theme: 'default', + layout: 'logicalStructure', + scaleRatio: 0.1, + minZoomRatio: 20, + maxZoomRatio: 500, + readonly: true, + enableFreeDrag: false, + alwaysShowExpandBtn: true, + initRootNodePosition: ['center', 'center'], + exportPaddingX: 20, + exportPaddingY: 20, + }); + + mindMapRef.current = mm; + + if (onNodeClick) { + mm.on('node_click', (node: any, e: any) => { + const text = node?.nodeData?.data?.text; + if (!text) return; + setTooltip(null); + const parentText = node?.parent?.nodeData?.data?.text || ''; + const raw = e?.originEvent || e?.event || e; + const rect = containerRef.current?.getBoundingClientRect(); + if (rect && raw?.clientX != null) { + setAskMenu({ + nodeText: text, + parentText, + x: raw.clientX - rect.left, + y: raw.clientY - rect.top, + }); + } else if (rect) { + setAskMenu({ + nodeText: text, + parentText, + x: rect.width / 2, + y: rect.height / 2, + }); + } + }); + mm.on('node_mouseenter', (node: any, e: any) => { + const text = node?.nodeData?.data?.text; + if (text) { + const raw = e?.originEvent || e?.event || e; + const rect = containerRef.current?.getBoundingClientRect(); + if (rect && raw?.clientX != null) { + setTooltip({ + text: 'Click to ask', + x: raw.clientX - rect.left, + y: raw.clientY - rect.top - 36, + }); + } + } + }); + mm.on('node_mouseleave', () => { + setTooltip(null); + }); + } + + // Fit view after render + // Only fit on initial render, not on expand/collapse + let firstRender = true; + mm.on('node_tree_render_end', () => { + if (firstRender) { + firstRender = false; + setIsReady(true); + setTimeout(() => mm.view.fit(), 100); + } + }); + } catch (e: any) { + console.error('MindMap render error:', e); + setRenderError(e.message || 'Failed to render mindmap'); + } + + return () => { + if (mindMapRef.current) { + mindMapRef.current.destroy(); + mindMapRef.current = null; + } + }; + }, [mermaidCode]); + + const handleExpandAll = () => { + mindMapRef.current?.execCommand('EXPAND_ALL'); + }; + + const handleCollapseAll = () => { + mindMapRef.current?.execCommand('UNEXPAND_ALL'); + }; + + const handleZoomIn = () => mindMapRef.current?.view.enlarge(); + const handleZoomOut = () => mindMapRef.current?.view.narrow(); + const handleFit = () => mindMapRef.current?.view.fit(); + + const handleDownloadPng = async () => { + if (!mindMapRef.current) return; + try { + // Save current view state + const viewState = mindMapRef.current.view.getTransformData(); + const fullData = mindMapRef.current.getData(); + // Expand all for export + mindMapRef.current.execCommand('EXPAND_ALL'); + await new Promise(r => setTimeout(r, 500)); + await mindMapRef.current.export('png', true, `mindmap_${Date.now()}`); + // Restore previous state + mindMapRef.current.setData(fullData); + await new Promise(r => setTimeout(r, 300)); + mindMapRef.current.view.setTransformData(viewState); + } catch (e) { + console.error('PNG export failed:', e); + } + }; + + const handleDownloadTxt = async () => { + if (!mindMapRef.current) return; + try { + await mindMapRef.current.export('txt', true, `mindmap_${Date.now()}`); + } catch (e) { + console.error('TXT export failed:', e); + } + }; + + const handleDownloadMermaid = () => { + const mermaid = isMermaidMindmap(mermaidCode) + ? mermaidCode + : markdownToMermaid(mermaidCode); + const blob = new Blob([mermaid], { type: 'text/plain' }); + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.download = `mindmap_${Date.now()}.mmd`; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + URL.revokeObjectURL(url); + }; + + const btnBase = "px-2.5 py-1.5 rounded-lg text-xs flex items-center gap-1.5 transition-colors"; + const btnGhost = `${btnBase} bg-gray-100 hover:bg-gray-200 border border-gray-200 text-gray-600`; + const btnAccent = `${btnBase} bg-cyan-50 hover:bg-cyan-100 border border-cyan-200 text-cyan-700`; + + return ( +
+
+

{title}

+
+ + {/* Toolbar */} +
+ {/* View controls */} + + + + + + +
+ + {/* Export controls */} + + + +
+ + {/* Mind map container */} + {renderError ? ( +
+
Render failed
+
{renderError}
+
+ ) : ( +
+
+ {tooltip && !askMenu && ( +
+ {tooltip.text} +
+ )} +
+ )} + + {askMenu && onNodeClick && ( + <> +
setAskMenu(null)} /> +
+
Ask about "{askMenu.nodeText}"
+ + {askMenu.parentText && ( + + )} +
+ + )} + +
+ {onNodeClick + ? 'Tip: Scroll to zoom, drag to pan. Click a node to ask a question about it.' + : 'Tip: Scroll to zoom, drag to pan. Click the button next to a node to expand/collapse.'} +
+
+ ); +}; diff --git a/frontend_en/src/pages/NotebookView.tsx b/frontend_en/src/pages/NotebookView.tsx index 1961f3e..f35ea5f 100644 --- a/frontend_en/src/pages/NotebookView.tsx +++ b/frontend_en/src/pages/NotebookView.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { ChevronLeft, Plus, Share2, Settings, MessageSquare, @@ -13,7 +13,7 @@ import { getApiSettings } from '../services/apiSettingsService'; import { fetchWithCache, invalidateCacheByPrefix } from '../services/clientCache'; import type { KnowledgeFile, ChatMessage, ToolType } from '../types'; import ReactMarkdown from 'react-markdown'; -import { MermaidPreview } from '../components/knowledge-base/tools/MermaidPreview'; +import { MindMapPreview } from '../components/knowledge-base/tools/MindMapPreview'; import { SettingsModal } from '../components/SettingsModal'; import DrawioInlineEditor from '../components/DrawioInlineEditor'; import { FlashcardViewer } from '../components/flashcards/FlashcardViewer'; @@ -79,6 +79,16 @@ const NotebookView = ({ notebook, onBack }: { notebook: any, onBack: () => void const chatPersistSkippedRef = React.useRef(false); const conversationIdRef = React.useRef(null); const [inputMsg, setInputMsg] = useState(''); + const handleMindmapNodeClick = useCallback((question: string) => { + setInputMsg(question); + setActiveTool('chat'); + setChatSubView('current'); + setPreviewOutput(null); + setTimeout(() => { + const input = document.querySelector('input[type="text"]'); + input?.focus(); + }, 100); + }, []); const [isChatLoading, setIsChatLoading] = useState(false); const [chatLoadingStage, setChatLoadingStage] = useState('思考中...'); @@ -3239,7 +3249,7 @@ const NotebookView = ({ notebook, onBack }: { notebook: any, onBack: () => void {toolOutput && activeTool === 'mindmap' && toolOutput.mindmap_code && (
- +
)} @@ -3755,14 +3765,14 @@ const NotebookView = ({ notebook, onBack }: { notebook: any, onBack: () => void initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} - className="absolute inset-0 glass-dark" + className="absolute inset-0 bg-black/40 backdrop-blur-sm" /> void onClick={(e) => e.stopPropagation()} > {/* Header */} -
+

{previewOutput.title}

来源:{previewOutput.sources}

@@ -3873,9 +3883,10 @@ const NotebookView = ({ notebook, onBack }: { notebook: any, onBack: () => void {previewOutput.type === 'mindmap' && previewOutput.mermaidCode && (
-
diff --git a/frontend_zh/src/components/knowledge-base/index.tsx b/frontend_zh/src/components/knowledge-base/index.tsx index 3d41c28..c739a16 100644 --- a/frontend_zh/src/components/knowledge-base/index.tsx +++ b/frontend_zh/src/components/knowledge-base/index.tsx @@ -6,7 +6,7 @@ import { UploadView } from './UploadView'; import { OutputView } from './OutputView'; import { SettingsView } from './SettingsView'; import { RightPanel } from './RightPanel'; -import { MermaidPreview } from './tools/MermaidPreview'; +import { MindMapPreview } from './tools/MindMapPreview'; import { supabase } from '../../lib/supabase'; import { useAuthStore } from '../../stores/authStore'; import { useToast } from '../../hooks/useToast'; @@ -496,7 +496,7 @@ const KnowledgeBase = () => { /> {mindmapPreviewCode ? ( - + ) : (
暂无可预览内容
)} diff --git a/frontend_zh/src/components/knowledge-base/tools/MermaidPreview.tsx b/frontend_zh/src/components/knowledge-base/tools/MermaidPreview.tsx deleted file mode 100644 index c853ded..0000000 --- a/frontend_zh/src/components/knowledge-base/tools/MermaidPreview.tsx +++ /dev/null @@ -1,305 +0,0 @@ -import { useEffect, useRef, useState } from 'react'; -import { createPortal } from 'react-dom'; -import mermaid from 'mermaid'; -import { Download, Eye, Code, Maximize2, X } from 'lucide-react'; - -interface MermaidPreviewProps { - mermaidCode: string; - title?: string; -} - -export const MermaidPreview = ({ mermaidCode, title = "思维导图预览" }: MermaidPreviewProps) => { - const mermaidRef = useRef(null); - const [showCode, setShowCode] = useState(false); - const [renderError, setRenderError] = useState(null); - const [renderedSvg, setRenderedSvg] = useState(''); - const [showModal, setShowModal] = useState(false); - const [modalSvg, setModalSvg] = useState(''); - const [zoom, setZoom] = useState(1); - const [offset, setOffset] = useState({ x: 0, y: 0 }); - const [isDragging, setIsDragging] = useState(false); - const [dragStart, setDragStart] = useState({ x: 0, y: 0 }); - const [dragOrigin, setDragOrigin] = useState({ x: 0, y: 0 }); - - useEffect(() => { - mermaid.initialize({ - startOnLoad: false, - theme: 'dark', - themeVariables: { - primaryColor: '#0ea5e9', - primaryTextColor: '#fff', - primaryBorderColor: '#0284c7', - lineColor: '#06b6d4', - secondaryColor: '#0891b2', - tertiaryColor: '#164e63', - }, - fontFamily: 'ui-sans-serif, system-ui, sans-serif', - }); - }, []); - - useEffect(() => { - const renderMermaid = async () => { - if (!mermaidCode || !mermaidRef.current) return; - - try { - setRenderError(null); - setRenderedSvg(''); - mermaidRef.current.innerHTML = ''; - - const id = `mermaid-${Date.now()}`; - const { svg } = await mermaid.render(id, mermaidCode); - setRenderedSvg(svg); - - if (mermaidRef.current) { - mermaidRef.current.innerHTML = svg; - } - } catch (error: any) { - console.error('Mermaid render error:', error); - setRenderError(error.message || 'Failed to render diagram'); - setRenderedSvg(''); - } - }; - - renderMermaid(); - }, [mermaidCode]); - - const renderSvgForExport = async () => { - if (renderedSvg) return renderedSvg; - const id = `mermaid-export-${Date.now()}`; - const { svg } = await mermaid.render(id, mermaidCode); - return svg; - }; - - const normalizeSvg = (svg: string) => { - return svg.replace(/]*?)>/i, (match, attrs) => { - let next = attrs - .replace(/\swidth="[^"]*"/i, '') - .replace(/\sheight="[^"]*"/i, ''); - - if (!/preserveAspectRatio=/i.test(next)) { - next += ' preserveAspectRatio="xMidYMid meet"'; - } - - if (/style="/i.test(next)) { - next = next.replace(/style="([^"]*)"/i, (_, style) => { - const merged = `${style}; width:100%; height:100%;`; - return `style="${merged}"`; - }); - } else { - next += ' style="width:100%; height:100%;"'; - } - - return ``; - }); - }; - - const handleDownloadSVG = async () => { - if (!mermaidCode) return; - try { - const svgData = await renderSvgForExport(); - const blob = new Blob([svgData], { type: 'image/svg+xml' }); - const url = URL.createObjectURL(blob); - const link = document.createElement('a'); - link.href = url; - link.download = `mindmap_${Date.now()}.svg`; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - URL.revokeObjectURL(url); - } catch (error) { - console.error('Download SVG failed:', error); - } - }; - - const handleDownloadCode = () => { - const blob = new Blob([mermaidCode], { type: 'text/plain' }); - const url = URL.createObjectURL(blob); - - const link = document.createElement('a'); - link.href = url; - link.download = `mindmap_${Date.now()}.mmd`; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - URL.revokeObjectURL(url); - }; - - const handleExpand = async () => { - if (!mermaidCode) return; - try { - const svgData = await renderSvgForExport(); - setModalSvg(normalizeSvg(svgData)); - setZoom(1); - setOffset({ x: 0, y: 0 }); - setShowModal(true); - } catch (error) { - console.error('Expand preview failed:', error); - } - }; - - const clampZoom = (value: number) => Math.min(5, Math.max(0.2, value)); - - const handleWheel = (e: React.WheelEvent) => { - e.preventDefault(); - const direction = e.deltaY > 0 ? 0.9 : 1.1; - setZoom(prev => clampZoom(prev * direction)); - }; - - const handleMouseDown = (e: React.MouseEvent) => { - setIsDragging(true); - setDragStart({ x: e.clientX, y: e.clientY }); - setDragOrigin(offset); - }; - - const handleMouseMove = (e: React.MouseEvent) => { - if (!isDragging) return; - const dx = e.clientX - dragStart.x; - const dy = e.clientY - dragStart.y; - setOffset({ x: dragOrigin.x + dx, y: dragOrigin.y + dy }); - }; - - const handleMouseUp = () => { - setIsDragging(false); - }; - - return ( -
-
-

{title}

-
- - - - -
-
- - {showCode ? ( -
-
Mermaid 代码:
-
-            {mermaidCode}
-          
-
- ) : ( -
- {renderError ? ( -
-
渲染失败
-
{renderError}
- -
- ) : ( -
- )} -
- )} - -
- 提示: 您可以切换查看图形或代码,也可以下载 SVG 文件或 Mermaid 代码文件 -
- - {showModal && createPortal( -
setShowModal(false)} - > -
e.stopPropagation()} - > -
-
思维导图放大预览
-
- - - - -
-
-
- {modalSvg ? ( -
-
-
- ) : ( -
暂无可预览内容
- )} -
-
-
, - document.body - )} -
- ); -}; diff --git a/frontend_zh/src/components/knowledge-base/tools/MindMapPreview.tsx b/frontend_zh/src/components/knowledge-base/tools/MindMapPreview.tsx new file mode 100644 index 0000000..fbde818 --- /dev/null +++ b/frontend_zh/src/components/knowledge-base/tools/MindMapPreview.tsx @@ -0,0 +1,302 @@ +import { useEffect, useRef, useState, useCallback } from 'react'; +import MindMap from 'simple-mind-map'; +import Export from 'simple-mind-map/src/plugins/Export.js'; +import { transformMarkdownTo } from 'simple-mind-map/src/parse/markdownTo.js'; +import { Download, Expand, Shrink, ZoomIn, ZoomOut, Maximize2, MessageSquare, FileText, Code } from 'lucide-react'; +import { mermaidToMarkdown, isMermaidMindmap, markdownToMermaid } from '../../../utils/mermaidToMarkdown'; + +MindMap.usePlugin(Export); + +interface MindMapPreviewProps { + mermaidCode: string; + title?: string; + onNodeClick?: (nodeText: string) => void; +} + +export const MindMapPreview = ({ mermaidCode, title = "思维导图预览", onNodeClick }: MindMapPreviewProps) => { + const containerRef = useRef(null); + const mindMapRef = useRef(null); + const [renderError, setRenderError] = useState(null); + const [isReady, setIsReady] = useState(false); + const [tooltip, setTooltip] = useState<{ text: string; x: number; y: number } | null>(null); + const [askMenu, setAskMenu] = useState<{ nodeText: string; parentText: string; x: number; y: number } | null>(null); + + const parseData = useCallback(() => { + if (!mermaidCode) return null; + try { + const markdown = isMermaidMindmap(mermaidCode) + ? mermaidToMarkdown(mermaidCode) + : mermaidCode; + return transformMarkdownTo(markdown); + } catch { + return null; + } + }, [mermaidCode]); + + useEffect(() => { + if (!containerRef.current || !mermaidCode) return; + + const data = parseData(); + if (!data) { + setRenderError('解析思维导图数据失败'); + return; + } + + setRenderError(null); + + if (mindMapRef.current) { + mindMapRef.current.destroy(); + mindMapRef.current = null; + setIsReady(false); + } + + try { + const mm = new MindMap({ + el: containerRef.current, + data, + theme: 'default', + layout: 'logicalStructure', + scaleRatio: 0.1, + minZoomRatio: 20, + maxZoomRatio: 500, + readonly: true, + enableFreeDrag: false, + alwaysShowExpandBtn: true, + initRootNodePosition: ['center', 'center'], + exportPaddingX: 20, + exportPaddingY: 20, + }); + + mindMapRef.current = mm; + + if (onNodeClick) { + mm.on('node_click', (node: any, e: any) => { + console.log('[MindMap] node_click fired', { node, e, nodeData: node?.nodeData, text: node?.nodeData?.data?.text }); + console.log('[MindMap] event keys:', e ? Object.keys(e) : 'null'); + const text = node?.nodeData?.data?.text; + if (!text) return; + setTooltip(null); + const parentText = node?.parent?.nodeData?.data?.text || ''; + const raw = e?.originEvent || e?.event || e; + console.log('[MindMap] raw event:', raw, 'clientX:', raw?.clientX); + const rect = containerRef.current?.getBoundingClientRect(); + if (rect && raw?.clientX != null) { + setAskMenu({ + nodeText: text, + parentText, + x: raw.clientX - rect.left, + y: raw.clientY - rect.top, + }); + } else if (rect) { + // Fallback: center of container + setAskMenu({ + nodeText: text, + parentText, + x: rect.width / 2, + y: rect.height / 2, + }); + } + }); + mm.on('node_mouseenter', (node: any, e: any) => { + const text = node?.nodeData?.data?.text; + if (text) { + const raw = e?.originEvent || e?.event || e; + const rect = containerRef.current?.getBoundingClientRect(); + if (rect && raw?.clientX != null) { + setTooltip({ + text: '点击提问', + x: raw.clientX - rect.left, + y: raw.clientY - rect.top - 36, + }); + } + } + }); + mm.on('node_mouseleave', () => { + setTooltip(null); + }); + } + + // Only fit on initial render, not on expand/collapse + let firstRender = true; + mm.on('node_tree_render_end', () => { + if (firstRender) { + firstRender = false; + setIsReady(true); + setTimeout(() => mm.view.fit(), 100); + } + }); + } catch (e: any) { + console.error('MindMap render error:', e); + setRenderError(e.message || '渲染思维导图失败'); + } + + return () => { + if (mindMapRef.current) { + mindMapRef.current.destroy(); + mindMapRef.current = null; + } + }; + }, [mermaidCode]); + + const handleExpandAll = () => { + mindMapRef.current?.execCommand('EXPAND_ALL'); + }; + + const handleCollapseAll = () => { + mindMapRef.current?.execCommand('UNEXPAND_ALL'); + }; + + const handleZoomIn = () => mindMapRef.current?.view.enlarge(); + const handleZoomOut = () => mindMapRef.current?.view.narrow(); + const handleFit = () => mindMapRef.current?.view.fit(); + + const handleDownloadPng = async () => { + if (!mindMapRef.current) return; + try { + // Save current view state + const viewState = mindMapRef.current.view.getTransformData(); + const fullData = mindMapRef.current.getData(); + // Expand all for export + mindMapRef.current.execCommand('EXPAND_ALL'); + await new Promise(r => setTimeout(r, 500)); + await mindMapRef.current.export('png', true, `mindmap_${Date.now()}`); + // Restore previous state + mindMapRef.current.setData(fullData); + await new Promise(r => setTimeout(r, 300)); + mindMapRef.current.view.setTransformData(viewState); + } catch (e) { + console.error('PNG export failed:', e); + } + }; + + const handleDownloadTxt = async () => { + if (!mindMapRef.current) return; + try { + await mindMapRef.current.export('txt', true, `mindmap_${Date.now()}`); + } catch (e) { + console.error('TXT export failed:', e); + } + }; + + const handleDownloadMermaid = () => { + const mermaid = isMermaidMindmap(mermaidCode) + ? mermaidCode + : markdownToMermaid(mermaidCode); + const blob = new Blob([mermaid], { type: 'text/plain' }); + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.download = `mindmap_${Date.now()}.mmd`; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + URL.revokeObjectURL(url); + }; + + const btnBase = "px-2.5 py-1.5 rounded-lg text-xs flex items-center gap-1.5 transition-colors"; + const btnGhost = `${btnBase} bg-gray-100 hover:bg-gray-200 border border-gray-200 text-gray-600`; + const btnAccent = `${btnBase} bg-cyan-50 hover:bg-cyan-100 border border-cyan-200 text-cyan-700`; + + return ( +
+
+

{title}

+
+ + {/* 工具栏 */} +
+ + + + + + +
+ + + + +
+ + {renderError ? ( +
+
渲染失败
+
{renderError}
+
+ ) : ( +
+
+ {tooltip && !askMenu && ( +
+ {tooltip.text} +
+ )} +
+ )} + + {/* Ask menu — rendered outside container to avoid overflow clipping */} + {askMenu && onNodeClick && ( + <> +
setAskMenu(null)} /> +
+
针对「{askMenu.nodeText}」提问
+ + {askMenu.parentText && ( + + )} +
+ + )} + +
+ {onNodeClick + ? '提示:滚轮缩放,拖拽平移。点击节点可发起提问。' + : '提示:滚轮缩放,拖拽平移。点击节点旁按钮可展开/收缩。'} +
+
+ ); +}; diff --git a/frontend_zh/src/pages/NotebookView.tsx b/frontend_zh/src/pages/NotebookView.tsx index 64c76bd..8019b3a 100644 --- a/frontend_zh/src/pages/NotebookView.tsx +++ b/frontend_zh/src/pages/NotebookView.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { ChevronLeft, Plus, Share2, Settings, MessageSquare, @@ -13,7 +13,7 @@ import { getApiSettings } from '../services/apiSettingsService'; import { fetchWithCache, invalidateCacheByPrefix } from '../services/clientCache'; import type { KnowledgeFile, ChatMessage, ToolType } from '../types'; import ReactMarkdown from 'react-markdown'; -import { MermaidPreview } from '../components/knowledge-base/tools/MermaidPreview'; +import { MindMapPreview } from '../components/knowledge-base/tools/MindMapPreview'; import { SettingsModal } from '../components/SettingsModal'; import DrawioInlineEditor from '../components/DrawioInlineEditor'; import { FlashcardViewer } from '../components/flashcards/FlashcardViewer'; @@ -175,6 +175,16 @@ const NotebookView = ({ notebook, onBack }: { notebook: any, onBack: () => void const chatPersistSkippedRef = React.useRef(false); const conversationIdRef = React.useRef(null); const [inputMsg, setInputMsg] = useState(''); + const handleMindmapNodeClick = useCallback((question: string) => { + setInputMsg(question); + setActiveTool('chat'); + setChatSubView('current'); + setPreviewOutput(null); + setTimeout(() => { + const input = document.querySelector('input[type="text"]'); + input?.focus(); + }, 100); + }, []); const [isChatLoading, setIsChatLoading] = useState(false); const [dataExtractDatasources, setDataExtractDatasources] = useState([]); const [dataExtractDatasourceId, setDataExtractDatasourceId] = useState(''); @@ -4084,7 +4094,7 @@ const NotebookView = ({ notebook, onBack }: { notebook: any, onBack: () => void {toolOutput && activeTool === 'mindmap' && toolOutput.mindmap_code && (
- +
)} @@ -4598,14 +4608,14 @@ const NotebookView = ({ notebook, onBack }: { notebook: any, onBack: () => void initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} - className="absolute inset-0 glass-dark" + className="absolute inset-0 bg-black/40 backdrop-blur-sm" /> void onClick={(e) => e.stopPropagation()} > {/* Header */} -
+

{previewOutput.title}

来源:{previewOutput.sources}

@@ -4716,9 +4726,10 @@ const NotebookView = ({ notebook, onBack }: { notebook: any, onBack: () => void {previewOutput.type === 'mindmap' && previewOutput.mermaidCode && (
-
From 57647f08f6adb252197d2a7e03cca13fb6a246d8 Mon Sep 17 00:00:00 2001 From: Anion <1005128408@qq.com> Date: Tue, 31 Mar 2026 15:35:40 +0800 Subject: [PATCH 5/6] refactor: remove hard max_depth limit from mindmap prompt Let the LLM adapt depth to content complexity instead of enforcing a fixed max_depth. The prompt structure already guides appropriate depth through its description of 4 hierarchy levels. --- workflow_engine/state.py | 2 +- workflow_engine/workflow/wf_kb_mindmap.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/workflow_engine/state.py b/workflow_engine/state.py index 676698e..5aeb279 100644 --- a/workflow_engine/state.py +++ b/workflow_engine/state.py @@ -474,7 +474,7 @@ class KBMindMapRequest(MainRequest): """ file_ids: List[str] = field(default_factory=list) # 引入层处理后的文件ID列表 mindmap_style: str = "default" # default | flowchart | tree - max_depth: int = 3 # 思维导图最大深度 + max_depth: int = 4 # 思维导图最大深度(根节点 + 一级 + 二级 + 三级要点) vector_store_base_dir: Optional[str] = None # 向量库根目录(manifest所在目录) @dataclass diff --git a/workflow_engine/workflow/wf_kb_mindmap.py b/workflow_engine/workflow/wf_kb_mindmap.py index 05552c6..1dbea9b 100644 --- a/workflow_engine/workflow/wf_kb_mindmap.py +++ b/workflow_engine/workflow/wf_kb_mindmap.py @@ -174,7 +174,6 @@ async def generate_mermaid_node(state: KBMindMapState) -> KBMindMapState: contents_str += f"=== {item['filename']} ===\n{item['content']}\n\n" language = state.request.language - max_depth = state.request.max_depth prompt = f"""请基于以下文档内容,生成一张**层级清晰、主题归纳明确、适合快速把握全文结构的思维导图**。你的目标是把文章压缩成一张"知识地图",让读者能够迅速理解这篇文章的核心主题、主要模块、关键内容,以及各部分之间的层级关系。 @@ -188,7 +187,7 @@ async def generate_mermaid_node(state: KBMindMapState) -> KBMindMapState: 当某个二级主题中存在特别重要的细节时,继续提炼 **1–3 个三级要点**(#### 四级标题),用于补充最关键的信息,例如术语、条件、指标、例子、判断依据、具体表现、限制条件、后续影响等。 -整体层级最多{max_depth}层。使用{language}语言。 +请根据内容复杂度自适应决定层级深度,不要人为限制。使用{language}语言。 整张思维导图要体现出一种**知识整理型、结构概览型、主题分解型**的风格。重点是帮助读者快速理解全文内容版图,而不是只罗列摘要句子。请让结构体现出"从总到分、由主到次、层层展开"的组织逻辑。 From f790f49cc5668c245765dc0af334569ccbd2ef15 Mon Sep 17 00:00:00 2001 From: Anion <1005128408@qq.com> Date: Tue, 31 Mar 2026 15:47:55 +0800 Subject: [PATCH 6/6] fix: refine mindmap prompt and hide redundant download button - max_depth default to 6, layer depth driven by content complexity - Remove example-heavy data instructions, keep core rule concise - Hide modal download button for mindmap type (component has its own exports) --- frontend_en/src/pages/NotebookView.tsx | 2 +- frontend_zh/src/pages/NotebookView.tsx | 2 +- workflow_engine/state.py | 2 +- workflow_engine/workflow/wf_kb_mindmap.py | 9 +++++---- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/frontend_en/src/pages/NotebookView.tsx b/frontend_en/src/pages/NotebookView.tsx index f35ea5f..88e2bff 100644 --- a/frontend_en/src/pages/NotebookView.tsx +++ b/frontend_en/src/pages/NotebookView.tsx @@ -3786,7 +3786,7 @@ const NotebookView = ({ notebook, onBack }: { notebook: any, onBack: () => void

来源:{previewOutput.sources}

- {previewOutput.url && ( + {previewOutput.url && previewOutput.type !== 'mindmap' && ( void

来源:{previewOutput.sources}

- {previewOutput.url && ( + {previewOutput.url && previewOutput.type !== 'mindmap' && ( KBMindMapState: contents_str += f"=== {item['filename']} ===\n{item['content']}\n\n" language = state.request.language + max_depth = state.request.max_depth prompt = f"""请基于以下文档内容,生成一张**层级清晰、主题归纳明确、适合快速把握全文结构的思维导图**。你的目标是把文章压缩成一张"知识地图",让读者能够迅速理解这篇文章的核心主题、主要模块、关键内容,以及各部分之间的层级关系。 @@ -185,9 +186,7 @@ async def generate_mermaid_node(state: KBMindMapState) -> KBMindMapState: 接着在每个一级主题下继续拆分 **2–4 个二级主题**(### 三级标题)。二级主题要承接上级主题,概括该部分最值得保留的核心内容,例如关键概念、主要论点、重要机制、核心步骤、代表性案例、主要证据、结果表现、应用场景、影响因素、行动建议等。 -当某个二级主题中存在特别重要的细节时,继续提炼 **1–3 个三级要点**(#### 四级标题),用于补充最关键的信息,例如术语、条件、指标、例子、判断依据、具体表现、限制条件、后续影响等。 - -请根据内容复杂度自适应决定层级深度,不要人为限制。使用{language}语言。 +需要时继续向下拆分更细的层级,整体层级最多{max_depth}层(使用 # 到 {'#' * max_depth} 表示)。层级深度由内容复杂度决定,不必强制填满所有层级,也不要人为限制在某个固定层数。使用{language}语言。 整张思维导图要体现出一种**知识整理型、结构概览型、主题分解型**的风格。重点是帮助读者快速理解全文内容版图,而不是只罗列摘要句子。请让结构体现出"从总到分、由主到次、层层展开"的组织逻辑。 @@ -201,8 +200,10 @@ async def generate_mermaid_node(state: KBMindMapState) -> KBMindMapState: 节点命名请尽量简洁而有信息量。每个节点都使用**适合放入思维导图框中的短语式表达**,让人一眼就能理解该节点要表达的重点。 +**特别注意:节点内容必须包含原文中的具体数据和关键数字。** 不要用"显著提升"、"大幅改善"等模糊表述替代具体数字。如果原文有数据,节点就必须带数据。 + 生成标准: -1. 忠实反映原文主线 +1. 忠实反映原文主线,保留关键数据和定量结果 2. 节点之间要有明确层级关系 3. 同一级节点尽量保持并列、均衡、可比较 4. 优先保留能够帮助理解全文框架的内容