### Install Dependencies and Run Development Server Source: https://github.com/ssshooter/mind-elixir-core/blob/master/readme.md Install project dependencies using pnpm and start the development server. ```bash pnpm i pnpm dev ``` -------------------------------- ### Add Mind Elixir Core Integration Guide Source: https://github.com/ssshooter/mind-elixir-core/blob/master/readme.md Use this command to install guides for the ssshooter/mind-elixir-core project into your project. ```bash npx skills add ssshooter/mind-elixir-core ``` -------------------------------- ### Install snapdom Dependency Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/export-mindmap-image/SKILL.md Install the `@zumer/snapdom` package using npm. This is the first step to enable image export functionality. ```bash npm install @zumer/snapdom ``` -------------------------------- ### Complete Plaintext Example Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/plaintext-format/SKILL.md A comprehensive example showcasing various plaintext features including node references, styling, links, and summary nodes. ```text - Project Planning - Phase 1: Research [^phase1] - Market Analysis {"color": "#3298db"} - Competitor Study {"color": "#3298db"} - }:2 Research Summary - Phase 2: Development [^phase2] - Frontend {"color": "#2ecc71"} - Backend {"color": "#2ecc71"} - Testing {"color": "#f39c12"} - } Development Summary - Phase 3: Launch [^phase3] - Marketing - Deployment - > [^phase1] (50,0) >-Leads to-> (-50,0) [^phase2] - > [^phase2] >-Leads to-> [^phase3] ``` -------------------------------- ### Integration Example: Plaintext to Mind Elixir Initialization Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/plaintext-format/SKILL.md Demonstrates how to parse plaintext content and then use it to initialize a Mind Elixir instance. ```javascript import MindElixir from 'mind-elixir' import { plaintextToMindElixir } from 'mind-elixir/plaintextConverter' // 1. Parse plaintext const plaintext = ` - My Mind Map - Topic 1 - Subtopic 1.1 - Subtopic 1.2 - Topic 2 ` const data = plaintextToMindElixir(plaintext) // 2. Initialize Mind Elixir const mind = new MindElixir({ el: '#map', direction: MindElixir.RIGHT, }) mind.init(data) ``` -------------------------------- ### Plaintext Full Example Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/plaintext-converter.md A comprehensive example demonstrating the plaintext format, including nested nodes, reference IDs, styles, arrow connections (bidirectional and unidirectional), and summaries. ```plaintext - Root Node - Child Node 1 - Child Node 1-1 {"color": "#e87a90", "fontSize": "18px"} - Child Node 1-2 - Child Node 1-3 - }:2 Summary of first two nodes - Child Node 2 - Child Node 2-1 [^node-2-1] - Child Node 2-2 [^id2] - Child Node 2-3 - > [^node-2-1] <-Bidirectional Link-> [^id2] - Child Node 3 - Child Node 3-1 [^id3] - Child Node 3-2 [^id4] - Child Node 3-3 [^id5] {"fontFamily": "Arial", "fontWeight": "bold"} - > [^id3] >-Unidirectional Link-> [^id4] - 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 - > [^node-2-1] <-Link position is not restricted, as long as the id can be found during rendering-> [^id8] ``` -------------------------------- ### Install Mind Elixir via NPM/Yarn/PNPM Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/integrate-mind-elixir/SKILL.md Install Mind Elixir using your preferred package manager. ```bash npm i mind-elixir -S # or pnpm i mind-elixir # or yarn add mind-elixir ``` -------------------------------- ### Install Marked Library for Markdown Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/customize-markdown/SKILL.md Install the 'marked' library using npm. This is a prerequisite for integrating 'marked' into Mind Elixir for advanced markdown rendering. ```bash npm i marked ``` -------------------------------- ### Generate API Documentation Source: https://github.com/ssshooter/mind-elixir-core/blob/master/readme.md Commands to install the API extractor and generate markdown documentation. Ensure `/src/docs.ts` is maintained before generation. ```bash # Install api-extractor pnpm install -g @microsoft/api-extractor # Maintain /src/docs.ts # Generate docs pnpm doc pnpm doc:md ``` -------------------------------- ### Install Mind Elixir via NPM Source: https://github.com/ssshooter/mind-elixir-core/blob/master/readme.md Install the Mind Elixir library using NPM. This command adds the library as a project dependency. ```bash npm i mind-elixir -S ``` -------------------------------- ### Plaintext Basic Structure Example Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/plaintext-converter.md Defines the basic structure of the plaintext format using indentation to represent hierarchy. Each line starts with '- ' and indentation determines the level. ```plaintext - Root Node - Child 1 - Grandchild 1-1 - Grandchild 1-2 - Child 2 ``` -------------------------------- ### Initialize Mind Elixir and expose globally Source: https://github.com/ssshooter/mind-elixir-core/blob/master/test.html Import the MindElixir library and make it globally accessible for easy use in your application. This is useful for quick setup or debugging. ```javascript import MindElixir from '/src/index.ts' window.MindElixir = MindElixir window.E = MindElixir.E ``` -------------------------------- ### Initialize Mind Elixir with Data Source: https://github.com/ssshooter/mind-elixir-core/wiki/Breaking-Change In version 1.0.0, data should be passed to the `init()` method instead of the `options` object during initialization. Ensure all necessary plugins are installed before calling `init()`. ```javascript import MindElixir, { E } from 'mind-elixir' import example from 'mind-elixir/dist/example1' let mind = new MindElixir(options) mind.install(plugin) // install your plugin // create new map data const data = MindElixir.new('new topic') // or `example` // or the data return from `.getAllData()` mind.init(data) // <--- HERE ``` -------------------------------- ### Export Mind Map as Image Source: https://github.com/ssshooter/mind-elixir-core/blob/master/readme.md Install the `@zumer/snapdom` package to export the mind map as an image. Supports various formats like JPG. ```typescript import { snapdom } from '@zumer/snapdom' const download = async () => { const result = await snapdom(mind.nodes) await result.download({ format: 'jpg', filename: 'my-capture' }) } ``` -------------------------------- ### Plain Text Mindmap Format Example Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/streaming-mindmap/SKILL.md An example of the plain text format that Mind Elixir can parse. This format uses indentation and special characters for nodes, links, and styling. ```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] ``` -------------------------------- ### Import Mind Elixir CSS Source: https://github.com/ssshooter/mind-elixir-core/wiki/Breaking-Change Starting from version 5.0.0, the CSS file is separated from the JavaScript bundle. You must import it manually. If using a bundler with CSS support, use the provided import statement. For CDN usage, add the `@import` rule to your CSS file. ```javascript import "mind-elixir/style.css"; ``` ```css @import "https://cdn.jsdelivr.net/npm/mind-elixir@^5.0.0/dist/style.css"; ``` -------------------------------- ### Generate Main Branch Path Source: https://github.com/ssshooter/mind-elixir-core/wiki/Recipes Generates an SVG path string for a main branch. Adjusts the starting X coordinate based on the mind map's direction and root element width. ```typescript function generateMainBranch(this: MindElixirInstance, { x1, y1, x2, y2, direction }: MainLineParams) { const root = this.map.querySelector('me-root') as HTMLElement if (this.direction === SIDE) { if (direction === 'lhs') { x1 = x1 - root.offsetWidth / 8 } else { x1 = x1 + root.offsetWidth / 8 } } return `M ${x1} ${y1} V ${y2 > y1 ? y2 - 20 : y2 + 20} C ${x1} ${y2} ${x1} ${y2} ${x2 > x1 ? x1 + 20 : x1 - 20} ${y2} H ${x2}` } ``` -------------------------------- ### Get Mind Map Data Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/integrate-mind-elixir/SKILL.md Retrieve the current data of the mind map either as an object or a serialized string. ```javascript const data = mind.getData() // Returns the current data object const dataString = mind.getDataString() // Returns serialized data string ``` -------------------------------- ### Build Project and Link Locally Source: https://github.com/ssshooter/mind-elixir-core/blob/master/readme.md Build the project and link it locally for testing generated files with `dev.dist.ts`. ```bash pnpm build pnpm link ./ ``` -------------------------------- ### Initialize Mind Elixir Instance Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/integrate-mind-elixir/SKILL.md Import Mind Elixir, configure options, and initialize the mind map instance with data. ```javascript import MindElixir from 'mind-elixir' import { en } from 'mind-elixir/i18n' import 'mind-elixir/style.css' // 1. Define options let options = { el: '#map', // or HTMLDivElement direction: MindElixir.LEFT, toolBar: true, // default true keypress: true, // default true overflowHidden: false, // default false mouseSelectionButton: 0, // 0 for left button, 2 for right button, default 0 contextMenu: { locale: en, // [cn,zh_CN,zh_TW,en,ru,ja,pt,it,es,fr,ko,ro,da,fi,de,nl,nb,sv] focus: true, link: true, extend: [ { name: 'Node edit', onclick: () => { alert('extend menu') }, }, ], }, // default true before: { insertSibling(type, obj) { return true }, }, // Custom markdown parser (optional) // markdown: (text) => customMarkdownParser(text), // provide your own markdown parser function } // 2. Create instance let mind = new MindElixir(options) // 3. Initialize with data // Create new data const data = MindElixir.new('new topic') // Or use existing data passed from backend // const data = { ... } mind.init(data) ``` -------------------------------- ### Recording Operations (handleOperation) Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/undo-redo-implementation.md Outlines the workflow for recording user operations. It involves truncating history, capturing the current state as 'next', constructing a history entry, and updating the index. 'beginEdit' operations are ignored. ```plaintext 用户操作 → bus.emit('operation') → handleOperation 1. 截断 history(丢弃 currentIndex 之后的记录,分支覆盖) 2. 调用 mei.getData() 获取操作后的完整快照作为 next 3. 构造 History 条目,push 入栈 4. 更新 currentIndex 指针 ``` -------------------------------- ### Plaintext Summary Nodes Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/plaintext-format/SKILL.md Demonstrates creating summary nodes that visually group previous siblings, with options to summarize all or a specific number of preceding nodes. ```text - Root - Node 1 - Node 2 - Node 3 - } Summary of all above nodes ``` ```text - Root - Node 1 - Node 2 - Node 3 - }:2 Summary of Node 2 and Node 3 ``` -------------------------------- ### Load Mind Map from File Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/plaintext-format/SKILL.md Load a mind map from a text file using fetch and parse the content into a Mind Elixir mind map. ```javascript // Load from file const response = await fetch('/mindmaps/project.txt') const plaintext = await response.text() const data = plaintextToMindElixir(plaintext) mind.init(data) ``` -------------------------------- ### Initialize Mind Elixir with Custom Theme Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/integrate-mind-elixir/SKILL.md Configure the theme options, including color palette and CSS variables, when initializing Mind Elixir. This sets the initial visual style for the diagram. ```javascript const options = { // ... theme: { name: 'Dark', // main lines color palette palette: ['#848FA0', '#748BE9', '#D2F9FE', '#4145A5', '#789AFA', '#706CF4', '#EF987F', '#775DD5', '#FCEECF', '#DA7BC'], // overwrite css variables cssVar: { '--main-color': '#ffffff', '--main-bgcolor': '#4c4f69', '--color': '#cccccc', '--bgcolor': '#252526', '--panel-color': '255, 255, 255', '--panel-bgcolor': '45, 55, 72', }, // all variables see /src/index.less }, // ... } ``` -------------------------------- ### Plaintext Bidirectional Links Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/plaintext-format/SKILL.md Demonstrates creating bidirectional links between nodes using `[^id]` references and optional coordinate offsets for control points. ```text - Root - Node A [^id1] - Node B [^id2] - > [^id1] (10,20) <-Link Label-> (-10,-20) [^id2] ``` -------------------------------- ### Plaintext to MindElixir Conversion Process Overview Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/plaintext-converter.md Outlines the high-level steps for converting plaintext to MindElixirData: splitting lines, single-pass traversal with a stack, and post-processing arrows. ```plaintext 输入: plaintext 字符串 ↓ 按行分割 & 过滤空行 ↓ 单次遍历所有行,用栈维护层级关系 ↓ 后处理 Arrow 行(解析引用 ID 到实际节点 ID) ↓ 输出: MindElixirData ``` -------------------------------- ### Plugin Lifecycle Management and Cleanup Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/undo-redo-implementation.md Demonstrates how to manage the lifecycle of the undo/redo plugin by returning a cleanup function that removes event listeners and keydown handlers. ```typescript // 插件返回清理函数 return () => { mei.bus.removeListener('operation', handleOperation) mei.bus.removeListener('selectNodes', handleSelectNodes) mei.container.removeEventListener('keydown', handleKeyDown) } ``` -------------------------------- ### Export Mind Map as JPG or PNG Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/export-mindmap-image/SKILL.md Use the `snapdom` function to capture mind map nodes and download them as an image. Ensure `mind` is an initialized MindElixir instance. The `format` can be 'jpg' or 'png'. ```typescript import { snapdom } from '@zumer/snapdom' // Assuming `mind` is your MindElixir instance const downloadImage = async () => { // 1. Capture the nodes const result = await snapdom(mind.nodes) // 2. Download as JPG or PNG await result.download({ format: 'jpg', // or 'png' filename: 'mind-map-export', }) } ``` -------------------------------- ### Plaintext Node Styling Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/plaintext-format/SKILL.md Shows how to apply inline styles to nodes using JSON-like syntax for properties such as color, background, and fontSize. ```text - Root - Styled Node {"color": "#e87a90"} - Another Node {"color": "#3298db", "background": "#ecf0f1"} ``` -------------------------------- ### Plaintext Conversion Overall Flow Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/plaintext-converter.md Illustrates the high-level steps for converting MindElixir data to plaintext, from input to output. ```plaintext 输入: MindElixirData ↓ 构建 Plaintext 节点树 (PtTree),包含 slots 以容纳前置/后置元素 ↓ 遍历所有 Arrow 和 Summary,按关联位置插入到各个节点树对应的 slot 中 ↓ 从根节点递归遍历 PtTree,交错提取 slots 和 children 拼接多行字符串 ↓ 输出: plaintext 字符串 ``` -------------------------------- ### Plaintext Node Optional Information: Style Object Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/plaintext-converter.md Demonstrates adding a style object to a node using JSON format. Supported keys include 'color', 'fontSize', etc., and are parsed into node.style. ```plaintext - Styled Node {"color": "#e87a90", "fontSize": "18px"} ``` -------------------------------- ### Add Export Button Trigger Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/export-mindmap-image/SKILL.md Create an HTML button and attach an event listener to trigger the `downloadImage` function when clicked. This provides a user interface for exporting the mind map. ```html ``` -------------------------------- ### Plaintext Summary: All Preceding Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/plaintext-converter.md Illustrates creating a summary for all preceding sibling nodes using the '} label' format. This summarizes all nodes that have appeared before this summary line. ```plaintext - } Summary text # 概括所有已出现的兄弟节点 (Child A, B, C) ``` -------------------------------- ### Integrate Marked Library for Full Markdown Support Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/customize-markdown/SKILL.md Integrate the 'marked' library to enable full markdown rendering in Mind Elixir nodes. This approach converts markdown text into HTML using the 'marked' parser. ```javascript import { marked } from 'marked' import MindElixir from 'mind-elixir' let mind = new MindElixir({ // ... other options markdown: text => marked(text), }) ``` -------------------------------- ### Integrate Plaintext Conversion with Mind Elixir Initialization Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/plaintext-format/SKILL.md Combines plaintext parsing with Mind Elixir initialization. First, it converts plaintext to data using `plaintextToMindElixir`, then initializes a new Mind Elixir instance with the obtained data. ```javascript import MindElixir from 'mind-elixir' import { plaintextToMindElixir } from 'mind-elixir/plaintextConverter' // 1. Parse plaintext const plaintext = " - My Mind Map - Topic 1 - Subtopic 1.1 - Subtopic 1.2 - Topic 2 " const data = plaintextToMindElixir(plaintext) // 2. Initialize Mind Elixir const mind = new MindElixir({ el: '#map', direction: MindElixir.RIGHT, }) mind.init(data) ``` -------------------------------- ### Dark Theme Configuration Source: https://github.com/ssshooter/mind-elixir-core/wiki/Themes Defines the 'Dark' theme with its color palette and CSS variables. Use this to apply a dark visual style to the application. ```javascript { name: 'Dark', palette: ['#dd7878', '#ea76cb', '#8839ef', '#e64553', '#fe640b', '#df8e1d', '#40a02b', '#209fb5', '#1e66f5', '#7287fd'], cssVar: { '--main-color': '#ffffff', '--main-bgcolor': '#4c4f69', '--color': '#cccccc', '--bgcolor': '#252526', }, } ``` -------------------------------- ### Plaintext Node References (IDs) Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/plaintext-format/SKILL.md Shows how to assign custom IDs to nodes using `[^id]` syntax for cross-referencing within the plaintext format. ```text - Root - Node A [^id1] - Node B [^id2] ``` -------------------------------- ### Import Mind Elixir and Styles (NPM) Source: https://github.com/ssshooter/mind-elixir-core/blob/master/readme.md Import the Mind Elixir library and its default styles when using NPM. Ensure these imports are placed at the top of your JavaScript or TypeScript files. ```javascript import MindElixir from 'mind-elixir' import 'mind-elixir/style.css' ``` -------------------------------- ### Import Mind Elixir CSS Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/integrate-mind-elixir/SKILL.md Import the necessary CSS for Mind Elixir when using the script tag method. ```css @import 'https://cdn.jsdelivr.net/npm/mind-elixir/dist/style.css'; ``` -------------------------------- ### Handling Multiple Top-Level Nodes in Plaintext Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/plaintext-converter.md Explains how the converter handles multiple top-level nodes in the plaintext by creating a synthetic root node named 'Root' to contain them as children. ```plaintext 如果 plaintext 中有多个缩进相同的顶层节点,自动创建一个名为 `rootName`(默认 'Root')的合成根节点将它们包裹为其子节点。 ``` -------------------------------- ### Implement Simple Markdown Parsing with Regex Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/customize-markdown/SKILL.md Use this function for basic markdown formatting like bold, italic, and code. It employs simple regex replacements to convert markdown syntax to HTML tags. ```javascript let mind = new MindElixir({ // ... other options markdown: text => { // Simple regex replacements return text .replace(/\*\*(.*?)\*\*/g, '$1') .replace(/\*(.*?)\*/g, '$1') .replace(/`(.*?)`/g, '$1') }, }) ``` -------------------------------- ### Recursive Serialization (dump) Logic Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/plaintext-converter.md Outlines the recursive Depth-First Search (DFS) process for serializing the 'PtTree' structure into plaintext, interleaving node content with elements from slots. ```plaintext 对每个 PtTree 节点: 1. 输出自身节点行: - 包含自身的话题 (node.topic)。 - 如果它在原始明文中显式声明了引用 refId,或者在此次转换中被箭头连接引用过(存在于 referencedIds 中),则追加 `[^refId]`(缺省使用 UUID)。 - 如果携带 `style` 属性则追加 JSON 格式的样式。 2. 交错提取 Slots 与 Children: 用一层简单的 `for` 循环遍历所有的 Slots (从 `0` 到 `children.length`): - 取出当前 `slots[i]` 里积攒的数组,按序分别把 Arrow 格式化成 `> [^ref] ...` ,把 Summary 格式化成 `}:N label` 并输出成单行。 - (如果当前没越界)递归下降执行 `dump(tree.children[i])` 输出下一个子节点的内容。 ``` -------------------------------- ### Plaintext Node Optional Information: Combined Ref ID and Style Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/plaintext-converter.md Illustrates combining both a reference ID and a style object on a single node line. The parsing order is refId first, then style, with the remainder as the topic. ```plaintext - Node [^id1] {"fontWeight": "bold"} ``` -------------------------------- ### Implement Operation Guards Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/integrate-mind-elixir/SKILL.md Use `before` hooks to intercept and control user operations, such as performing asynchronous validation before changes are applied. ```javascript let mind = new MindElixir({ // ... other options before: { // Return true to allow, false to prevent // Supports async functions async addChild(el, obj) { try { await saveDataToDb() return true } catch (err) { return false // Operation blocked } }, // Other hooks: insertSibling, removeNode, moveNode, etc. }, }) ``` -------------------------------- ### Keyboard Shortcuts for Undo/Redo Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/undo-redo-implementation.md Notes that keyboard shortcuts for undo (Ctrl+Z) and redo (Ctrl+Shift+Z or Ctrl+Y) are bound to the 'mei.container' element. ```plaintext 键盘快捷键绑定在 `mei.container` 上:`Ctrl+Z` undo,`Ctrl+Shift+Z` / `Ctrl+Y` redo。 ``` -------------------------------- ### Plaintext Unidirectional Links Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/plaintext-format/SKILL.md Illustrates creating unidirectional links between nodes using `[^id]` references and a forward arrow syntax. ```text - Root - Node A [^id1] - Node B [^id2] - > [^id1] >-Forward Link-> [^id2] ``` -------------------------------- ### Plaintext Line Parsing Algorithm Description Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/plaintext-converter.md Describes the algorithm for parsing each line of plaintext using a stack to manage indentation and parent nodes. It details calculating indentation, parsing line content, and handling nodes, arrows, and summaries. ```plaintext 1. **计算缩进** (`getIndent`): 统计行首空格数 2. **解析行内容** (`parseLine`): 去掉 `- ` 前缀后判断类型: - 以 `>` 开头 → `arrow` 类型 - 以 `}` 开头 → `summary` 类型 - 其他 → `node` 类型(进一步提取 refId 和 style) 3. **弹栈定位父节点**: 从栈顶开始弹出所有 `indent >= 当前缩进` 的元素,栈顶即为当前行的父节点 4. **按类型处理**: - **Arrow**: 记录到 `context.arrowLines`,同时记录它所属的父节点 ID 和在子列表中的位置索引 - **Summary**: 调用 `parseSummary` 解析格式(`:N label` 或纯 `label`),根据计数确定覆盖范围 `[start, end]` - **Node**: 生成唯一 ID,创建 `NodeObj`,设置 style 和 metadata.refId(如果有),挂载到父节点的 `children` 数组,然后压入栈中 ``` -------------------------------- ### Initialize Mind Elixir Map Source: https://github.com/ssshooter/mind-elixir-core/blob/master/readme.md Initialize a Mind Elixir mind map instance within a specified HTML element. Configure options such as direction, toolbar, context menu, and custom markdown parsers. ```javascript import MindElixir from 'mind-elixir' import { en } from 'mind-elixir/i18n' import 'mind-elixir/style.css' import example from 'mind-elixir/dist/example1' let options = { el: '#map', // or HTMLDivElement direction: MindElixir.LEFT, toolBar: true, // default true keypress: true, // default true overflowHidden: false, // default false mouseSelectionButton: 0, // 0 for left button, 2 for right button, default 0 contextMenu: { locale: en, // [cn,zh_CN,zh_TW,en,ru,ja,pt,it,es,fr,ko,ro,da,fi,de,nl,nb,sv] focus: true, link: true, extend: [ { name: 'Node edit', onclick: () => { alert('extend menu') }, }, ], }, // default true before: { insertSibling(type, obj) { return true }, }, // Custom markdown parser (optional) // markdown: (text) => customMarkdownParser(text), // provide your own markdown parser function } let mind = new MindElixir(options) mind.install(plugin) // install your plugin // create new map data const data = MindElixir.new('new topic') // or `example` // or the data return from `.getData()` mind.init(data) // get a node MindElixir.E('node-id') ``` -------------------------------- ### Basic Plaintext Structure Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/plaintext-format/SKILL.md Illustrates the fundamental indentation-based syntax for representing mind map nodes and their hierarchy in plaintext. ```text - Root Node - Child Node 1 - Child Node 1-1 - Child Node 1-2 - Child Node 2 - Child Node 2-1 ``` -------------------------------- ### Implement Operation Guards in Mind Elixir Source: https://github.com/ssshooter/mind-elixir-core/blob/master/readme.md Use the 'before' option in Mind Elixir initialization to define asynchronous guards for operations like adding child nodes. These guards allow you to implement custom logic, such as saving data to a database, before an operation is finalized. ```javascript let mind = new MindElixir({ // ... before: { async addChild(el, obj) { try { await saveDataToDb() return true } catch (err) { return false } }, }, }) ``` -------------------------------- ### Plaintext Summary: Specific Count Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/plaintext-converter.md Shows how to create a summary for a specific number of preceding sibling nodes using the '}:N label' format. N indicates the count of nodes to summarize. ```plaintext - }:2 Summary text # 概括前 2 个节点 (Child B, Child C) ``` -------------------------------- ### Generate Mind Map with AI Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/plaintext-format/SKILL.md Use this prompt format to generate a mind map in plaintext using an AI. The response can then be parsed into a Mind Elixir mind map. ```javascript // Prompt example for AI const prompt = ` Generate a mind map in plaintext format about "Web Development". Use this format: - Root Topic - Subtopic 1 - Detail 1.1 - Subtopic 2 ` // Then parse the AI response const aiResponse = await callAI(prompt) const data = plaintextToMindElixir(aiResponse) mind.refresh(data) ``` -------------------------------- ### Import Mind Elixir Styles (CDN) Source: https://github.com/ssshooter/mind-elixir-core/blob/master/readme.md Import the Mind Elixir CSS styles when using the CDN script tag. Add this line to your main CSS file or within a style block in your HTML. ```css @import 'https://cdn.jsdelivr.net/npm/mind-elixir/dist/style.css'; ``` -------------------------------- ### Export and Import Mind Map Data Source: https://github.com/ssshooter/mind-elixir-core/blob/master/readme.md Export the current mind map data as a JavaScript object or a string, and import data to initialize or update the mind map. Use `getData()` for the object, `getDataString()` for a string representation, and `init()` or `refresh()` for import. ```javascript // data export const data = mind.getData() // javascript object, see src/example.js mind.getDataString() // stringify object // data import // initiate let mind = new MindElixir(options) mind.init(data) // data update mind.refresh(data) ``` -------------------------------- ### Diff Mind Map in Git Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/plaintext-format/SKILL.md The plaintext format is merge-friendly and can be easily diffed and merged using Git. ```bash # Easy to diff and merge in Git git diff mindmap.txt ``` -------------------------------- ### Core Data Structures for Undo/Redo Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/undo-redo-implementation.md Defines the key data structures used for managing history, including the history stack, current index, current data snapshot, and selected nodes. ```typescript history: History[] // 历史记录栈 currentIndex: number // 当前指针位置(-1 表示初始状态) current: MindElixirData // 当前数据快照 currentSelectedNodes // 当前选中的节点(用于记录操作上下文) ``` -------------------------------- ### Data Migration for LinkData Source: https://github.com/ssshooter/mind-elixir-core/wiki/Breaking-Change Version 4.0.0 requires migrating `linkData` to `arrows` in the content object. This script iterates through existing map documents, transforms the `linkData` structure, and updates the database. ```javascript db.maps.find({}).forEach((doc) => { if (doc.content.linkData) { doc.content.arrows = [] for (let key in doc.content.linkData) { const item = doc.content.linkData[key] doc.content.arrows.push(item) } delete doc.content.linkData db.maps.updateOne({ _id: doc._id }, { $set: { content: doc.content } }) } }) ``` -------------------------------- ### HTML Structure for Mind Map Container Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/integrate-mind-elixir/SKILL.md Define a div element to serve as the container for the mind map and apply basic styling. ```html
``` -------------------------------- ### Include Mind Elixir via Script Tag Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/integrate-mind-elixir/SKILL.md Include Mind Elixir directly in your HTML using a script tag from a CDN. ```html ``` -------------------------------- ### Redo Operation Logic Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/undo-redo-implementation.md Explains the redo operation. It increments the current index, retrieves the next history entry, refreshes the canvas with the 'next' snapshot, and restores node selection based on the operation type. ```plaintext currentIndex < history.length - 1 时: 1. currentIndex++ 2. 取 history[currentIndex] 3.mei.refresh(h.next) ← 用 next 快照完全刷新画布 4. 恢复选中状态: - 若操作是 removeNodes → 选中操作前的选中节点(因为 redo 后节点又被删了) - 否则 → 选中操作目标节点 ``` -------------------------------- ### Plaintext Node Optional Information: Reference ID Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/plaintext-converter.md Shows how to add a reference ID to a node using the '[^refId]' format. This ID can be used by Arrow lines for referencing. It is parsed into node.metadata.refId. ```plaintext - Node A [^my-ref] ``` -------------------------------- ### Safe Parsing with Error Handling Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/plaintext-format/SKILL.md Always wrap plaintext parsing in try-catch blocks to handle potential errors gracefully and return fallback data. ```javascript function safeParse(plaintext: string): MindElixirData | null { try { return plaintextToMindElixir(plaintext) } catch (error) { console.error('Parse error:', error) // Return fallback data return { nodeData: { id: 'root', topic: 'Parse Error', children: [] } } } } ``` -------------------------------- ### Tailwind CSS Compatibility Reset Source: https://github.com/ssshooter/mind-elixir-core/blob/master/index.html Resets box-sizing, borders, and styles for ::before and ::after pseudo-elements to ensure Tailwind CSS compatibility. ```css ::before, ::after { box-sizing: border-box; border-width: 0; border-style: solid; border-color: #e5e7eb; } ``` -------------------------------- ### Customize Mind Map Theme Source: https://github.com/ssshooter/mind-elixir-core/blob/master/readme.md Configure theme options including color palettes and CSS variables to customize the appearance. Mind Elixir does not automatically observe `prefers-color-scheme`, so manual theme changes are required when the system scheme changes. ```javascript const options = { // ... theme: { name: 'Dark', // main lines color palette palette: ['#848FA0', '#748BE9', '#D2F9FE', '#4145A5', '#789AFA', '#706CF4', '#EF987F', '#775DD5', '#FCEECF', '#DA7FBC'], // overwrite css variables cssVar: { '--main-color': '#ffffff', '--main-bgcolor': '#4c4f69', '--color': '#cccccc', '--bgcolor': '#252526', '--panel-color': '255, 255, 255', '--panel-bgcolor': '45, 55, 72', }, // all variables see /src/index.less }, // ... } // ... mind.changeTheme({ name: 'Latte', palette: ['#dd7878', '#ea76cb', '#8839ef', '#e64553', '#fe640b', '#df8e1d', '#40a02b', '#209fb5', '#1e66f5', '#7287fd'], cssVar: { '--main-color': '#444446', '--main-bgcolor': '#ffffff', '--color': '#777777', '--bgcolor': '#f6f6f6', }, }) ``` -------------------------------- ### Selection Restoration Symmetry Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/undo-redo-implementation.md Highlights the symmetrical logic for restoring node selections during undo and redo operations, particularly noting the distinct handling for 'removeNodes' operations. ```plaintext 操作类型 | Undo 选中 | Redo 选中 | ----------|-----------|----------- `removeNodes` | 被删节点(`currentTarget`) | 操作前选中(`currentSelected`) | 其他操作 | 操作前选中(`currentSelected`) | 操作目标(`currentTarget`) ``` -------------------------------- ### Mind Elixir Map Container Styling Source: https://github.com/ssshooter/mind-elixir-core/blob/master/index.html Styles the map containers (#map, #map2) with specific margins, height, and width for the Mind Elixir project. ```css #map, #map2 { margin-top: 50px; height: 500px; width: 800px; } ``` -------------------------------- ### Handle Mind Elixir Operations and Events Source: https://github.com/ssshooter/mind-elixir-core/blob/master/readme.md Listen for various operations and events emitted by the Mind Elixir instance using its event bus. This allows for real-time feedback on user interactions and map changes. ```javascript mind.bus.addListener('operation', operation => { console.log(operation) // return { // name: action name, // obj: target object // } // name: [insertSibling|addChild|removeNode|beginEdit|finishEdit] // obj: target // name: moveNode // obj: {from:target1,to:target2} }) mind.bus.addListener('selectNodes', nodes => { console.log(nodes) }) mind.bus.addListener('expandNode', node => { console.log('expandNode: ', node) }) ``` -------------------------------- ### Generate Sub Branch Path Source: https://github.com/ssshooter/mind-elixir-core/wiki/Recipes Generates an SVG path string for a sub branch. Handles straight lines, curves for children below parents, and curves for children above parents, with adjustable turn radii. ```typescript function generateSubBranch(this: MindElixirInstance, { pT, pL, pW, pH, cT, cL, cW, cH, direction, isFirst }: SubLineParams) { const GAP = 30 const TURNPOINT_R = 8 let y1: number if (isFirst) { y1 = pT + pH / 2 } else { y1 = pT + pH } const y2 = cT + cH let x1 = 0 let x2 = 0 let xMiddle = 0 if (direction === 'lhs') { x1 = pL + GAP x2 = cL xMiddle = cL + cW } else if (direction === 'rhs') { x1 = pL + pW - GAP x2 = cL + cW xMiddle = cL } if (y2 < y1 + 50 && y2 > y1 - 50) { // draw straight line if the distance is between +-50 return `M ${x1} ${y1} H ${xMiddle} V ${y2} H ${x2}` } else if (y2 >= y1) { // child bottom lower than parent return `M ${x1} ${y1} H ${xMiddle} V ${y2 - TURNPOINT_R} A ${TURNPOINT_R} ${TURNPOINT_R} 0 0 ${x1 > x2 ? 1 : 0} ${ x1 > x2 ? xMiddle - TURNPOINT_R : xMiddle + TURNPOINT_R } ${y2} H ${x2}` } else { // child bottom higher than parent return `M ${x1} ${y1} H ${xMiddle} V ${y2 + TURNPOINT_R} A ${TURNPOINT_R} ${TURNPOINT_R} 0 0 ${x1 > x2 ? 0 : 1} ${ x1 > x2 ? xMiddle - TURNPOINT_R : xMiddle + TURNPOINT_R } ${y2} H ${x2}` } } ``` -------------------------------- ### PtTree and Slots Data Structure Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/plaintext-converter.md Defines the core intermediate data structure 'PtTree' used during conversion, which includes nodes, children, and 'slots' for auxiliary elements like arrows and summaries. ```typescript type PtElement = { type: 'arrow'; arrow: Arrow } | { type: 'summary'; summary: Summary } class PtTree { node: NodeObj children: PtTree[] = [] slots: PtElement[][] // 长度为 children.length + 1 } ``` -------------------------------- ### Handle Mind Elixir Events Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/integrate-mind-elixir/SKILL.md Listen to various operations and events emitted by Mind Elixir using `mind.bus`. ```javascript // Listen to all operations mind.bus.addListener('operation', operation => { console.log(operation) // operation: { name: 'action_name', obj: target_object } }) // Listen to node selection mind.bus.addListener('selectNodes', nodes => { console.log(nodes) }) // Listen to node expansion mind.bus.addListener('expandNode', node => { console.log('expandNode: ', node) }) ``` -------------------------------- ### Undo Operation Logic Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/undo-redo-implementation.md Describes the process for undoing an operation. It retrieves the previous history entry, refreshes the canvas with the 'prev' snapshot, restores node selection based on the operation type, and decrements the current index. ```plaintext currentIndex > -1 时: 1. 取 history[currentIndex] 2.mei.refresh(h.prev) ← 用 prev 快照完全刷新画布 3. 恢复选中状态: - 若操作是 removeNodes → 选中被删除的节点(恢复后它们重新出现) - 否则 → 选中操作前的选中节点 4. currentIndex-- ``` -------------------------------- ### History Item Structure Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/undo-redo-implementation.md Details the fields within a 'History' entry, which include the previous and next data snapshots, the operation type, the selected nodes during the operation, and the target of the operation. ```plaintext 字段 | 说明 ------|------ `prev` | 操作前的完整数据快照 `next` | 操作后的完整数据快照 `operation` | 操作类型(如 `removeNodes`、`moveNodeIn` 等) `currentSelected` | 操作时选中的节点 ID 列表 `currentTarget` | 操作的目标对象,区分 `nodes` / `summary` / `arrow` 三种类型 ``` -------------------------------- ### Summary TypeScript Interface Definition Source: https://github.com/ssshooter/mind-elixir-core/blob/master/refs/plaintext-converter.md Defines the structure for summary objects, including the label, parent node ID, and the range of child nodes it summarizes. ```typescript interface Summary { id: string label: string // 概括文本 parent: string // 父节点 ID start: number // 起始子节点索引(0-based) end: number // 结束子节点索引(0-based) } ``` -------------------------------- ### Mind Elixir Node Data Structure Source: https://github.com/ssshooter/mind-elixir-core/blob/master/skills/integrate-mind-elixir/SKILL.md Defines the standard structure for a node object, including topic, ID, styling, expansion state, and child nodes. ```javascript const nodeData = { topic: 'node topic', id: 'bd1c24420cd2c2f5', style: { fontSize: '32', color: '#3298db', background: '#ecf0f1' }, expanded: true, parent: null, tags: ['Tag'], icons: ['😀'], hyperLink: 'https://github.com/ssshooter/mind-elixir-core', image: { url: 'https://raw.githubusercontent.com/ssshooter/mind-elixir-core/master/images/logo2.png', height: 90, width: 90, }, children: [ { topic: 'child', id: 'xxxx', // ... }, ], } ``` -------------------------------- ### Configure Markdown Support in Mind Elixir Source: https://github.com/ssshooter/mind-elixir-core/blob/master/readme.md Configure Mind Elixir to support custom markdown parsing. This can be done by omitting the markdown option (disables it), providing a custom parser function, or integrating with a markdown library like 'marked'. ```javascript // Disable markdown (default) let mind = new MindElixir({ // markdown option omitted - no markdown processing }) // Use custom markdown parser let mind = new MindElixir({ markdown: text => { // Your custom markdown implementation return text .replace(/\*\*(.*?)\*\*/g, '$1') .replace(/\*(.*?)\*/g, '$1') .replace(/`(.*?)`/g, '$1') }, }) // Use any markdown library (e.g., marked, markdown-it, etc.) import { marked } from 'marked' let mind = new MindElixir({ markdown: text => marked(text), }) ```