Install
$ agentstack add skill-chrisjianghp-md2mindmap-md2mindmap Open-source listing, not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged1 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Destructive filesystem operation.
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Markdown → 思维导图
将 Markdown 文档(本地或在线)的结构解析出来,生成思维导图,帮助用户一眼看清文档骨架。 支持两种输出格式(由用户选择):飞书文档(含 Mermaid mindmap 画板)、本地 HTML 文件(Markmap 交互式)、或两者都要。
两种输入模式
两种模式的产出完全一致。区别只在于 MD 内容从哪里读:
模式 A:本地 MD 文件
用户提供本地 .md 文件路径(如 ~/Documents/foo.md、./README.md),用 Read 工具读取后解析。
模式 B:在线 MD URL
用户提供一个指向 Markdown 文本的 URL,常见来源:
- GitHub raw:
https://raw.githubusercontent.com/owner/repo/branch/path/to/file.md - GitHub 普通文件页(
https://github.com/owner/repo/blob/...)→ 自动转成 raw 后再下载 - 其他直接返回 markdown 文本的 HTTP(S) 链接
用 WebFetch 或 curl 拉取原始 markdown 文本后解析。
> 不在范围内:解析飞书文档 / Notion / Confluence / 其他在线富文本系统的结构——这个 skill 只处理"纯 Markdown 文本"。
用户决策:只补问缺失的信息
读完 MD 内容、识别出标题结构之后,检查用户原始请求中是否已经明确指定了以下四个决策:Language、Depth、Format、Publish。只对缺失的决策使用 AskUserQuestion 询问;用户已经明确指定的,不要重复询问。
如果有多个缺失决策,把它们合并到一次 AskUserQuestion 调用中一起问,不要分多次问。这样既保留必要的确认,又避免用户已经说清楚时被重复打断。
决策 1:Language(语言选择)
文档源文件可能是任何语言(英文、中文、日文等)。模型有把英文文档自动翻译成中文的倾向,但用户的实际需求可能是保留原文(例如英文 README 保留英文术语更准确)。如果用户没有明确指定语言,才询问。
视为已明确指定的表达示例:
保持原文、不要翻译、用原语言、保留英文、英文原文→ 选择保持原文翻译成中文、中文输出、用中文、节点用中文→ 选择翻译为中文
缺失时询问参数:
- header:
Language(≤ 12 字) - question:
思维导图节点的文字使用哪种语言? - 选项(固定两个,不要自行扩展):
保持原文— 描述:"直接使用源文档中的文字,保留原始术语和措辞(推荐用于技术文档、专有名词、英文资料)"翻译为中文— 描述:"将节点文字翻译为简体中文,便于中文读者快速理解"
用户选择或请求中指定"保持原文"时,节点文字必须严格使用源文档中出现的字符串(包括大小写、标点),不做任何翻译、改写或归纳;摘要可以截断但不能改写。
决策 2:Depth(内容深度)
思维导图可以只展示骨架(仅标题层级),也可以在每个标题节点下附带简短摘要。骨架更紧凑、一眼看清结构;带摘要信息更丰富,但节点更多、布局更密。如果用户没有明确指定内容深度,才询问。
视为已明确指定的表达示例:
仅标题、只要标题、标题骨架、只展示结构、不要摘要、不要总结→ 选择仅标题骨架加摘要、带总结、带简短说明、包含内容总结、标题加总结→ 选择标题加简短摘要
缺失时询问参数:
- header:
Depth(≤ 12 字) - question:
思维导图包含哪些内容? - 选项(固定两个,不要自行扩展):
仅标题骨架— 描述:"只展示标题层级(h1-h6),节点紧凑,一眼看清文档结构"标题加简短摘要— 描述:"每个标题节点下附带一句话摘要(≤ 30 字),信息更丰富但节点更密集(推荐用于内容较少的文档)"
用户选择或请求中指定"仅标题骨架"时:不要生成任何摘要节点,只输出标题节点。
用户选择或请求中指定"标题加简短摘要"时:按下方「Step 1: 解析 MD 文档结构」中的摘要规则提取(首句、≤ 30 字)。
决策 3:Format(输出格式)
如果用户没有明确指定输出格式,才询问。
视为已明确指定的表达示例:
生成 HTML、到 html、本地网页、浏览器打开、Markmap、交互式网页→ 选择HTML 文件生成飞书文档、飞书画板、写到飞书、Lark doc、Feishu doc→ 选择飞书文档两者都要、同时生成 HTML 和飞书、html 和飞书都生成→ 选择两者都要
缺失时询问参数:
- header:
Format(≤ 12 字) - question:
思维导图以什么格式输出? - 选项(固定三个,不要自行扩展):
飞书文档— 描述:"创建飞书文档,思维导图嵌入文档中的 Mermaid 画板"HTML 文件— 描述:"生成本地 HTML 文件,用 Markmap 渲染交互式思维导图,支持缩放/折叠/搜索,浏览器直接打开"两者都要— 描述:"同时生成飞书文档和 HTML 文件"
决策 4:Publish(线上发布)
仅当 Format 包含 HTML 文件(即 HTML 文件 或 两者都要)时才考虑此决策;如果只生成飞书文档,则跳过 Publish。
如果用户没有明确指定是否发布到线上环境,必须询问。线上发布会把 HTML 上传到第三方托管平台,产生公开 URL;这是外向发布动作,不应默认执行。
视为已明确指定的表达示例:
不发布、只本地、不要上线、不要部署、不用线上→ 选择不发布部署到 Vercel、发布到 Vercel、上 Vercel→ 选择Vercel部署到 Netlify、发布到 Netlify、上 Netlify→ 选择NetlifyVercel 和 Netlify 都发布、两个平台都部署→ 选择两者都发布
缺失时询问参数:
- header:
Publish(≤ 12 字) - question:
HTML 思维导图是否发布到线上环境? - 选项(固定四个,不要自行扩展):
不发布— 描述:"只生成本地 HTML 文件,不上传到线上环境(默认安全选择)"Vercel— 描述:"部署到 Vercel,生成可分享的公网 URL"Netlify— 描述:"部署到 Netlify,生成可分享的公网 URL"两者都发布— 描述:"同时部署到 Vercel 和 Netlify"
默认值(仅当用户要求不要提问或上下文强烈暗示时使用)
常规情况下,缺失决策应询问。只有当用户明确说"不用问我/按默认来/直接生成",或前文同一任务已经刚刚选择过相同偏好时,才使用默认值:
- Language:保持原文
- Depth:仅标题骨架
- Format:HTML 文件
- Publish:不发布
询问时机
读完 MD 内容、识别出标题结构之后,调用 docs +create、生成 HTML 或发布线上环境之前。缺哪些问哪些;全部已明确时直接继续。
Step 1: 获取并解析 MD 文档
1.1 获取 MD 文本
| 模式 | 怎么拿到 markdown 文本 | |------|------------------------| | A 本地路径 | Read 工具直接读 | | B GitHub blob URL | 转成 raw URL(github.com/.../blob/... → raw.githubusercontent.com/.../...),再用 WebFetch 拉取 | | B GitHub raw URL | 直接 WebFetch | | B 其他 HTTP(S) MD 链接 | 直接 WebFetch;如果返回不是 markdown(HTML 渲染页),提示用户给 raw 链接 |
1.2 解析结构
提取:
- 标题层级:h1 ~ h6,保留缩进关系
- 简短摘要(仅当用户选了"标题加简短摘要"):每个标题节的第一段非空文本,截取到第一个句号/问号/感叹号为止(最长 30 字)。如果没有正文内容,则不标注摘要
解析规则:
#→ h1,##→ h2,以此类推- 忽略纯 YAML front matter(开头
---之间的内容) - 忽略代码块内(
`围起的部分)出现的"#",那些不是标题 - 标题间的正文只取第一句作为摘要,不做深度内容提取
- 摘要提取时跳过无语义装饰内容:纯图片、纯链接、徽章、Star History 图片、空链接(如
[](...))、只包含 URL 的行、语言切换链接(如中文版 | English)、目录导航链接(如安装 · 认证 · 命令) - 根节点摘要尤其要跳过顶部 badge、语言切换、目录导航,优先提取第一个真正介绍项目/文档用途的正文段落
- 如果摘要超过 30 字,显示文本截断为 30 字并加
…,但要保留完整摘要供 HTML 输出的自定义悬浮提示使用 - 如果标题本身超过 20 字,在思维导图中截断到 20 字并加
…
Step 2: 补齐用户决策
执行上面「用户决策:只补问缺失的信息」一节:
- 先从用户原始请求中识别 Language、Depth、Format、Publish 是否已经明确指定
- 对已明确的决策直接采用,不再询问
- 对缺失的决策,用一次
AskUserQuestion合并询问 - 如果 Format 不包含 HTML,则跳过 Publish 决策
- 如果所有适用决策都已明确,则跳过
AskUserQuestion,直接继续
Step 3: 根据用户选择的 Format 分支执行
分支 1:飞书文档(或两者都要)
走下方 Step 4–6(生成 Mermaid → 创建飞书文档 → 写入画板 → 交付)。
分支 2:HTML 文件(或两者都要)
走下方「HTML 输出(Markmap)」一节,生成本地 .html 文件并用 Markmap 渲染交互式思维导图。
如果 Publish 选择了 Vercel、Netlify 或 两者都发布,生成 HTML 后继续执行「线上发布」一节。
如果用户选了「两者都要」,飞书和 HTML 两个分支都执行。
飞书文档输出
Step 4: 生成 Mermaid Mindmap
将解析结果转换为 Mermaid mindmap 语法。详见下方「Mermaid Mindmap 生成规范」。 根据用户在 Step 2 的选择决定节点文字的语言和是否包含摘要。
Step 5: 创建飞书文档(含空白画板占位)
使用 lark-cli docs +create 创建文档:
lark-cli docs +create --api-version v2 --content '📋 [文件名] 结构导图
本文档由 md2mindmap 自动生成,展示原始 Markdown 文档的结构层级。
结构思维导图
'
从返回的 JSON 中提取:
data.document.url— 最终交付给用户data.document.new_blocks[0].block_token(type 为whiteboard的那条)— 画板 token,用于 Step 5 写入
> 文件名取法:模式 A 取本地路径的 basename(去 .md 后缀);模式 B 取 URL 最后一段(去 .md 后缀);若 MD 首行有 h1,可优先用 h1 文本。
Step 6: 写入思维导图到画板
lark-cli 原生支持 --input_format mermaid,无需额外工具。
cd /tmp
cat > mindmap.mmd
EOF
lark-cli whiteboard +update \
--whiteboard-token \
--input_format mermaid \
--source @./mindmap.mmd \
--overwrite --as user
> 关键:--source 必须是相对路径(如 @./mindmap.mmd)。绝对路径(如 @/tmp/mindmap.mmd)会报错。先 cd 到文件所在目录,再用 @./filename 形式引用。
Step 7: 交付(飞书)
向用户报告飞书文档 URL、节点统计。详见下方「交付规范」。
HTML 输出(Markmap)
当用户选择「HTML 文件」或「两者都要」时,生成一个自包含的 HTML 文件,用 Markmap 渲染交互式思维导图。
为什么用 Markmap 而不是 Mermaid
- Markmap 专为 Markdown → 思维导图设计,直接支持
#标题语法 - 交互式:缩放、拖拽平移、节点折叠/展开
- 零依赖 CDN 加载(d3 + markmap-view + markmap-lib),无需本地安装
- 深色/浅色主题可切换
生成步骤
Step H1: 将解析结果转回 Markdown 文本
把 Step 1 解析出的标题层级(根据 Language 和 Depth 选择后的版本)拼回 Markdown 格式,作为 Markmap 的输入。
格式要求:
- 根节点作为
#标题 - 二级标题用
##,三级用###,以此类推 - 如果用户选了「仅标题骨架」,只输出标题行
- 如果用户选了「标题加简短摘要」,不要把摘要作为普通子节点;而是把摘要嵌入对应标题节点内部,让默认只展开第一级时也能看到概要。格式如下:
``markdown ## 章节标题一句简短摘要… ``
- 摘要展示要求:清晰、克制、像副标题;避免和标题混成一行。显示文本控制在 30 字以内;如果被截断,必须在
data-full-summary属性中保留完整摘要 - 不要依赖原生
title悬浮提示;Markmap 的 SVG/foreignObject 场景下原生 title 不稳定。HTML 模板必须提供自定义 tooltip:监听.summary的mouseenter/mousemove/mouseleave,读取data-full-summary并显示浮层 - 根节点如果有摘要,显示文本应直接使用完整概要(通常是第一个真正介绍项目/文档用途的正文句子),不要截断成前几个字;但必须跳过顶部 badge、语言切换和目录导航
- 非根节点摘要显示文本控制在 30 字以内;如果被截断,通过
data-full-summary+ 自定义 tooltip 展示完整摘要 data-full-summary和摘要正文都要做 HTML 转义:&→&、`→>、"→"`- 如果保留原文,摘要也必须来自原文截断,不要改写
- 在 Markdown 顶部加入 YAML front matter 配置:
---
title: [文档标题] 结构导图
markmap:
colorFreezeLevel: 2
maxWidth: 320
initialExpandLevel: 1
---
initialExpandLevel: 1:默认只展开第一级分支,用户打开后先看到整体骨架,再点击展开细节- 如果用户明确要求全部展开,或节点数很少(...` 容器
- CDN 引用
markmap-autoloader(从 jsdelivr 加载稳定版),由 autoloader 自动渲染 html2canvasCDN:导出 PDF 时把当前思维导图 DOM 截成 PNG,再通过浏览器打印保存为 PDF
优先使用 markmap-autoloader,不要手写 new Markmap(...) 初始化。手写初始化在不同 CDN 版本和本地 file:// 打开时容易因为全局对象暴露差异导致 Chrome 空白或渲染不正常;autoloader 是官方推荐的最稳嵌入方式。
模板结构(每次生成时直接使用这个模板,替换 __MARKDOWN_CONTENT__ 和 __TITLE__):
__TITLE__ — Mindmap
* { box-sizing: border-box; }
html, body {
width: 100%; height: 100%; margin: 0; overflow: hidden;
background: #1a1a2e;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
.header {
position: fixed; top: 12px; left: 16px; z-index: 1000;
color: rgba(255,255,255,0.82);
background: rgba(255,255,255,0.08);
border: 1px solid rgba(255,255,255,0.12);
border-radius: 10px; padding: 8px 12px;
backdrop-filter: blur(10px); font-size: 14px;
}
.toolbar {
position: fixed; top: 12px; right: 16px; z-index: 1000;
display: flex; gap: 8px;
}
.toolbar button {
color: rgba(255,255,255,0.86);
background: rgba(255,255,255,0.10);
border: 1px solid rgba(255,255,255,0.16);
border-radius: 10px; padding: 8px 12px;
backdrop-filter: blur(10px); font-size: 13px;
cursor: pointer;
}
.toolbar button:hover { background: rgba(255,255,255,0.18); }
.hint {
position: fixed; bottom: 12px; left: 16px; z-index: 1000;
color: rgba(255,255,255,0.45); font-size: 12px;
background: rgba(0,0,0,0.18);
border-radius: 8px; padding: 6px 10px;
}
.markmap { width: 100vw; height: 100vh; }
.markmap > svg { width: 100%; height: 100%; display: block; }
.markmap text,
.markmap foreignObject,
.markmap foreignObject *,
.markmap .markmap-node text,
.markmap .markmap-node div,
.markmap .markmap-node span {
color: rgba(255,255,255,0.96) !important;
fill: rgba(255,255,255,0.96) !important;
-webkit-text-fill-color: rgba(255,255,255,0.96) !important;
text-shadow: 0 1px 2px rgba(0,0,0,0.35);
}
.markmap .summary {
display: block;
margin-top: 6px;
max-width: 280px;
padding: 2px 6px 2px 7px;
border-left: 2px solid rgba(125,211,252,0.75);
border-radius: 4px;
background: rgba(14,165,233,0.10);
color: rgba(186,230,253,0.88) !important;
-webkit-text-fill-color: rgba(186,230,253,0.88) !important;
font-size: 9.5px;
line-height: 1.35;
font-weight: 400;
letter-spacing: 0.01em;
white-space: normal;
text-shadow: none;
cursor: help;
}
.tooltip {
position: fixed;
z-index: 2000;
max-width: min(520px, calc(100vw - 32px));
padding: 10px 12px;
border: 1px solid rgba(125,211,252,0.35);
border-radius: 10px;
background: rgba(15,23,42,0.96);
color: rgba(255,255,255,0.94);
box-shadow: 0 12px 40px rgba(0,0,0,0.35);
font-size: 13px;
line-height: 1.55;
pointer-events: none;
opacity: 0;
transform: translateY(4px);
transition: opacity 0.12s ease, transform 0.12s ease;
}
.tooltip.visible { opacity: 1; transform: translateY(0); }
@media print {
@page { size: landscape; margin: 0; }
html, body {
background: #fff !important;
overflow: visible;
}
.header, .toolbar, .hint { display: none !important; }
.markmap { width: 100vw; height: 100vh; background: #fff !important; }
}
__TITLE__ — mindmap
导出 PDF
Drag to pan · Scroll to zoom · Click nodes to fold/unfold · Export PDF via browser print
__MARKDOWN_CONTENT__
function setupSummaryTooltip() {
const tooltip = document.getElementById('summary-tooltip');
if (!tooltip) return;
const place = (event) => {
const pad = 16;
const rect = tooltip.getBoundingClientRect();
let x = event.clientX + 14;
let y = event.clientY + 14;
if (x + rect.width > window.innerWidth - pad) x = window.innerWidth - rect.width - pad;
if (y + rect.height > window.innerHeight - pad) y = event.clientY - rect.height - 14;
tooltip.style.left = `${Math.max(pad, x)}px`;
tooltip.style.top = `${Math.max(pad, y)}px`;
};
document.addEventListener('mouseover', (event) => {
const el = event.target.closest && event.target.closest('.summary');
if (!el) return;
const text = el.getAttribute('data-full-summary') || el.textContent || '';
if (!text.trim()) return;
tooltip.textContent = text;
tooltip.classList.add('visible');
place(event);
});
document.addEventListener('mousemove', (event) => {
if (tooltip.classList.contains('visible')) place(event);
});
document.addEventListener('mouseout', (event) => {
const el = event.target.closest && event.target.closest('.summary');
if (!el) return;
tooltip.classList.remove('visible');
});
}
setTimeout(setupSummaryTooltip, 500);
function loadHtml2Canvas() {
if (window.html2canvas) return Promise.resolve(window.html2canvas);
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js';
script.onload = () => resolve(window.html2canvas);
script.onerror = () => reject(new Error('html2canvas 加载失败,请检查网络或 CDN 访问'));
document.head.appendChild(script);
});
}
async function exportPDF() {
const target = document.querySelector('.markmap');
if (!target || !target.querySelector('svg')) {
alert('思维导图还未渲染完成,请稍等 1 秒后重试');
return;
}
// Open the print window synchronously in the click handler.
// If we wait until async rendering finishes, Chrome may block it as a popup.
const printWindow = window.open('', '_blank');
if (!printWindow) {
alert('浏览器拦截了打印窗口,请允许弹窗后重试');
return;
}
printWindow.document.write(`
Preparing PDF
body{margin:0;display:grid;place-items:center;height:100vh;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;background:#1a1a2e;color:#fff}
正在生成 PDF 预览…`);
printWindow.document.close();
try {
const html2canvas = await loadHtml2Canvas();
const canvas = await html2canvas(target, {
backgroundColor: '#1a1a2e',
scale: Math.min(2, window.devicePixelRatio || 1.5),
useCORS: true,
logging: false,
width: target.clientWidth,
height: target.clientHeight,
windowWidth: document.documentElement.clientWidth,
windowHeight: document.documentElement.clientHeight,
});
const png = canvas.toDataURL('image/png');
printWindow.document.open();
printWindow.document.write(`
Mindmap PDF
@page { size: landscape; margin: 0; }
html, body { margin: 0; width: 100%; height: 100%; overflow: hidden; background: #1a1a2e; }
img { width: 100vw; height: 100vh; object-fit: contain; display: block; }
`);
printWindow.document.close();
printWindow.focus();
setTimeout(() => printWindow.print(), 500);
} catch (err) {
printWindow.document.open();
printWindow.document.write(`导出失败:${String(err && err.message || err)}\n\n请检查网络是否能访问 cdn.jsdelivr.net,或刷新页面后重试。`);
printWindow.document.close();
}
}
替换规则:
__TITLE__→ 文档标题(取源 MD 的 h1 或文件名)__MARKDOWN_CONTENT__→ Step H1 拼好的 Markdown 文本- 因为 Markdown 放在 `
中,不需要像 JS 模板字符串那样转义$或反引号;但如果 Markdown 内容里出现,需要替换为`,避免提前结束 script 标签 - 如果把摘要嵌入标题节点(
...),摘要文本和title属性都要做 HTML 转义:&→&、`→>、"→"`,避免破坏节点 HTML
Step H3: 保存并打开
将 HTML 文件保存到 /tmp/[文件名]-mindmap.html,然后用 open 命令在浏览器中打开:
open /tmp/[文件名]-mindmap.html
Step H4: 交付(HTML)
告知用户:
- 文件路径
- 交互方式:拖拽平移、滚轮缩放、点击节点折叠/展开
- 导出 PDF:点击右上角「导出 PDF」按钮,脚本会用
html2canvas把当前思维导图 DOM 截成 PNG 图片,再打开打印对话框;选择「保存为 PDF」即可。使用位图导出是为了避免 Chrome 打印 SVGforeignObject时丢失中文文字 - 文件完全自包含(除了 CDN 引用),可以复制到任何地方
示例:
✅ HTML 思维导图已生成!
📄 文件:/tmp/frontend-slides-mindmap.html
交互方式:
- 🖱 拖拽平移 | 滚轮缩放
- 点击节点折叠/展开子节点
- 右上角按钮:导出 PDF(打开浏览器打印对话框,选择"保存为 PDF")
- 零依赖,浏览器直接打开即可
线上发布
仅当用户的 Format 包含 HTML 且 Publish 不是 不发布 时执行。线上发布会生成公网 URL,属于外向发布动作;如果用户没有明确指定发布平台,必须通过 Publish 决策询问,不要默认发布。
发布前准备
把生成的 HTML 文件复制到临时目录并命名为 index.html:
rm -rf /tmp/[slug]-deploy
mkdir -p /tmp/[slug]-deploy
cp /tmp/[file]-mindmap.html /tmp/[slug]-deploy/index.html
发布到 Vercel
- 检查 Vercel CLI 和登录状态:
npx vercel --version
npx vercel whoami
- 如果未登录,引导用户运行:
! npx vercel login
等待用户完成网页登录授权后再继续。
- 部署:
cd /tmp/[slug]-deploy
npx vercel --prod --yes
- 从输出中提取并交付:
Production或AliasedURL(优先交付稳定 alias URL)- Inspect URL(可选)
发布到 Netlify
- 检查 Netlify CLI 和登录状态:
npx netlify --version
npx netlify status
- 如果未登录,引导用户运行:
! npx netlify login
等待用户完成网页登录授权后再继续。
- 部署:
npx netlify deploy --prod --dir /tmp/[slug]-deploy
- 从输出中提取并交付:
Production URLUnique deploy URL- Build logs URL(可选)
发布交付格式
示例:
✅ HTML 思维导图已生成并发布!
本地文件:/tmp/[file]-mindmap.html
Vercel:https://example.vercel.app
Netlify:https:/
…
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [chrisjianghp](https://github.com/chrisjianghp)
- **Source:** [chrisjianghp/md2mindmap](https://github.com/chrisjianghp/md2mindmap)
- **License:** MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.