Skip to main content

streaming-mindmap-rendering

Implement real-time streaming mindmap rendering using Mind Elixir in web applications. Supports streaming text parsing and incremental updates.

ソース情報

リポジトリ
SSShooter/mind-elixir-core
ソースの最終更新活動
2026年2月16日 09:59
検出された SKILL.md の言語
英語
スター
3,177
フォーク
417

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
Streaming Mindmap Rendering
description
Implement real-time streaming mindmap rendering using Mind Elixir in web applications. Supports streaming text parsing and incremental updates.
# Streaming Mindmap Rendering This skill guides you through implementing a streaming mindmap renderer using `mind-elixir`. This technique allows you to display a mindmap that grows in real-time as data is generated by an AI model or fetched from a stream. ## Prerequisites - React (or any frontend framework, examples use React) - `mind-elixir` library ## 1. Install Dependencies First, ensure you have `mind-elixir` installed. ```bash npm install mind-elixir ``` ## 2. Component Structure Create a wrapper component for `mind-elixir` to handle the lifecycle and updates. ```tsx import MindElixir, { type MindElixirData, type MindElixirInstance } from 'mind-elixir' import { useEffect, useRef } from 'react' export function MindmapRenderer({ data }: { data: MindElixirData | null }) { const elRef = useRef<HTMLDivElement>(null) const meRef = useRef<MindElixirInstance | null>(null) useEffect(() => { if (!elRef.current) return meRef.current = new MindElixir({ el: elRef.current, direction: MindElixir.RIGHT, }) // Initial empty state or loading state meRef.current.init(data || { nodeData: { topic: 'Loading...', id: 'root' } }) return () => { // Cleanup if necessary } }, []) // Update effect useEffect(() => { if (meRef.current && data) { // Refresh the graph with new data meRef.current.refresh(data) } }, [data]) return <div ref={elRef} style={{ height: '500px', width: '100%' }} /> } ``` ## 3. Streaming & Parsing Logic The core of this skill is efficiently handling the stream and parsing potentially incomplete data. ### Data Formats Mind Elixir supports two main formats: 1. **JSON (Native)**: Hierarchical tree structure. Hard to stream because JSON is invalid until complete. 2. **Plain Text (Recommended for Streaming)**: Indentation-based or markdown-list-based text. Easier to parse partially. #### Plain Text Format Example ```text - Root Node - Child Node 1 - Child Node 1-1 - Child Node 1-2 - Child Node 1-3 - }:2 Summary of first two nodes - Child Node 2 - Child Node 2-1 [^id1] - Child Node 2-2 [^id2] - Child Node 2-3 {color: "#e87a90"} - > [^id1] <-Bidirectional Link-> [^id2] - Child Node 3 - Child Node 3-1 [^id3] - Child Node 3-2 [^id4] - Child Node 3-3 [^id5] - > [^id3] >-Unidirectional Link-> [^id4] - > [^id3] <-Unidirectional Link-< [^id5] - Child Node 4 - Child Node 4-1 [^id6] - Child Node 4-2 [^id7] - Child Node 4-3 [^id8] - } Summary of all previous nodes - Child Node 4-4 - > [^id1] <-Link position is not restricted, as long as the id can be found during rendering-> [^id8] ``` ### Parsing Implementation Use `mind-elixir/plaintextConverter` (or a custom parser) to convert text to the Mind Elixir JSON format. ````typescript import { plaintextToMindElixir } from 'mind-elixir/plaintextConverter' // Helper to clean Markdown code blocks if your stream includes them function cleanStreamContent(content: string): string { return content .replace(/^```[\w]*\n?/gm, '') .replace(/```$/gm, '') .trim() } // State hooks in your parent component const [mindmapData, setMindmapData] = useState<MindElixirData | null>(null) const accumulatedText = useRef('') const lastRenderTime = useRef(0) // Streaming function (Generic Example) async function startStreaming(url: string) { const response = await fetch(url) const reader = response.body?.getReader() const decoder = new TextDecoder() if (!reader) return while (true) { const { done, value } = await reader.read() if (done) break const chunk = decoder.decode(value) accumulatedText.current += chunk // Throttle updates to avoid freezing the UI const now = Date.now() if (now - lastRenderTime.current > 500) { // 500ms throttle updateMindmap() lastRenderTime.current = now } } // Final update updateMindmap() } function updateMindmap() { try { const cleanText = cleanStreamContent(accumulatedText.current) const data = plaintextToMindElixir(cleanText) setMindmapData(data) // This triggers the useEffect in MindmapRenderer } catch (e) { // Ignore parse errors from incomplete chunks console.warn('Partial parse error ignored') } } ```` ## 4. Optimization Tips - **Throttling**: Do not re-parse and re-render on every single byte. Use a throttle (e.g., 200-500ms). - **Stable Root**: Ensure the parsing logic maintains a stable root ID if possible, to prevent the whole graph from flashing. - **Scroll to Last**: To follow the generation, you can programmatically scroll to the last added node. ```typescript // Scroll to last node (inside MindmapRenderer update effect) const lastNode = findLastNode(data.nodeData) // Implement traversal to find last node if (lastNode?.id) { const nodeEle = meRef.current.findEle(lastNode.id) if (nodeEle) meRef.current.scrollIntoView(nodeEle) } ``` ## 5. Integrating with AI Prompts When generating mindmaps with LLMs, instruct the model to use the plaintext format.
GitHubで見る