Skip to main content
ClaudeWave
Skill60 estrellas del repoactualizado 2d ago

mindmap-markmap-viewer

Turn Markdown outlines, notes, docs, or plans into an interactive mind map — a single self-contained HTML file that opens offline anywhere (markmap.js, white-on-dark, zoom/expand/export toolbar, search that keeps matches in context). Use whenever the user asks for a mind map, markmap, or concept map, wants to visualize or diagram the structure of a document or topic, summarize notes as a navigable tree, make an outline clickable or explorable, or embed such a map in Streamlit — even when they don't literally say 'mind map'.

Instalar en Claude Code
Copiar
git clone https://github.com/Jaderson-bit/mindmap-markmap-viewer ~/.claude/skills/mindmap-markmap-viewer
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# Mindmap (markmap) Skill

Render hierarchical Markdown as an interactive SVG mind map with **markmap.js**, plus three custom layers: **white-font CSS**, **expand-by-level control**, and **search that filters the tree**.

```
source.md  ──►  filter / set expand level (Python)  ──►  build_html()  ──►  vendored markmap libs (local, offline)  ──►  SVG + toolbar
 (outline)        (manipulate the text)                  (HTML + CSS)        (transform + render in the browser)          (screen)
```

Helper functions live in `scripts/render_markmap.py`; a minimal source file is in `assets/example.md`; regression tests are in `evals/`. Deeper docs: [`references/internals.md`](references/internals.md) (how the helpers work) and [`references/lessons.md`](references/lessons.md) (real-world lessons + the adversarial counter-review behind the current code).

## When to use this skill

- The user asks for a mind map, markmap, or concept map of anything.
- Hierarchical content — an outline, notes, a plan, a document's structure, a taxonomy — should become navigable, scannable, or shareable.
- A map must be sent to someone or opened with no setup: the output is one self-contained `.html` that works offline.
- A mind map should be embedded in a Streamlit app.
- An existing markmap renders blank, white-on-white, or truncated — this skill carries the known fixes (§2).

---

## 1. Source format

markmap derives hierarchy from **headings (`#`)** and **nested list items** — `-`, `*`, `+`, or numbered (`1.` / `1)`) — indented by 2 spaces per level. (Tabs work too; the filter treats one tab as one level.) A YAML frontmatter block controls behavior:

```markdown
---
markmap:
  colorFreezeLevel: 2      # freeze color from level 2 down (branches keep the parent color)
  initialExpandLevel: 2    # levels kept open; root is level 1, so 2 = root + branches (-1 = all)
  maxWidth: 380            # max node width in px (forces wrapping)
---

# Root                     <- root (level 1)
## Branch A                <- level 2
### Sub-branch A1          <- level 3
- Leaf                     <- level 4 (bullet under a level-3 heading)
  - Detail                 <- level 5 (bullet indented +2 spaces)
```

**Presets (`apply_presets`).** You don't have to hand-write the `markmap:` block — `apply_presets(src, color=None, max_width=380)` fills sensible defaults *without overriding* anything you set: `colorFreezeLevel: 2`, `maxWidth`, and an `initialExpandLevel` sized by node count (expand-all for ≤30 nodes, else level 2). Pass `color=["#7fd1ff", "#ffd479"]` for a custom palette. Any key already in your frontmatter wins, so you can set one value and let presets fill the rest.

**Content rule — term → parent / description → child.** Put the label on the node and its explanation as a *child*, not on one line. Prefer:

```markdown
- Term
  - description of the term
```
over `- Term — description`. This keeps nodes short and the tree scannable.

Node text may contain `<`, `>`, and `&` freely (`a < b`, `List<String>`, even `</div>`). `build_html` HTML-escapes the source before embedding it and the browser decodes it back, so markmap sees exactly what you wrote. (Earlier versions broke on a literal `<`; that footgun is gone — don't pre-escape to `&lt;` yourself or it shows up literally.)

---

## 2. Rendering (white font)

The renderer is: the **vendored markmap `<script>`s** (local files), an `<svg class="markmap">` plus a hidden source `<div>` holding the Markdown, a small **init script** (transform → `Markmap.create` → toolbar), and the CSS. See `build_html()` / `render_markmap()` in [`scripts/render_markmap.py`](scripts/render_markmap.py), with the rationale in [`references/internals.md`](references/internals.md).

Non-obvious points (these cost rework):
- **Offline, single self-contained file by default.** `build_html` **inlines** the vendored markmap stack (d3 + markmap-view/-lib/-toolbar, pinned exact in [`assets/vendor/`](assets/vendor/)) directly into the HTML — **no CDN, no network, and no sibling files** — so the one `.html` opens offline anywhere you move or share it. (That single-file default is the fix for maps that failed to load their libs when opened alone.) Pass `inline=False` for a smaller HTML that instead references a `vendor/` folder via `vendor="vendor"`, which must then travel beside it.
- **LaTeX math is not rendered in the offline bundle.** markmap's KaTeX support needs `window.katex`, which isn't vendored, so `$...$` / `$$...$$` show as plain text. Everything else renders fully offline.
- **Navigation toolbar** (bottom-right): zoom in/out, fit-to-window, expand-all, collapse-all, and **download as SVG / PNG**. Pass `toolbar=False` to omit it. Expand/collapse set each node's `fold` then re-render with `setData()` **and no argument** — passing data re-derives `fold` from `initialExpandLevel` and would wipe the manual fold. Export snapshots the current fold state; the SVG inlines the white-font CSS + a dark backdrop so it stands alone, and PNG rasterizes at 2× (falling back to SVG if a browser refuses to rasterize the `<foreignObject>` labels — markmap draws node text as HTML-in-SVG, not `<text>`).
- **White font is invisible without a dark background.** This is the #1 way the map "renders blank": the font is white, the surface is white, so nothing shows. A standalone `.html` opens on the browser's white default, and a Streamlit `components.html` iframe is white by default too — neither inherits the host's dark theme. So `build_html` paints its **own** dark backdrop (`background="#0e1117"` by default). Only pass `background="transparent"` when you *know* the host behind the iframe is already dark and you want a seamless blend. White font + dark background travel together — never set one without the other.
- **White font needs TWO selectors + `!important`.** markmap draws text as SVG `<text>` **and** sometimes as `<foreignObject>` (HTML inside SVG). Style both or half the labels stay dark:
  ```css
  svg.markmap te