Skip to content

Processing

rehype-mind-elixir integrates into the Unified processing pipeline as a Rehype plugin.

It transforms mind-elixir fenced code blocks into HTML containers. The client runtime then finds these containers and renders the corresponding Mind Elixir maps.

A typical pipeline looks like this:

Source Markdown
```mind-elixir
- ZikoJS
- Core
- Addons
```
│
▼
remark-parse
│
▼
MDAST
│
▼
remark-rehype
│
▼
HAST
│
▼
rehype-mind-elixir
│
├── Find mind-elixir code blocks
├── Split configuration and body
├── Parse YAML configuration
├── Detect body format
└── Generate Mind Elixir container
│
▼
rehype-stringify
│
▼
HTML
│
▼
rehype-mind-elixir/client
│
├── Find generated containers
├── Read body, type, and configuration
├── Parse the body
├── Create the Mind Elixir map
└── Mount the map
│
▼
Mind Elixir
│
▼
Interactive Mind Map

The process starts with a mind-elixir fenced code block:

```mind-elixir
- ZikoJS
- Core
- Addons
```

At this point, it is simply Markdown source.

remark-parse converts the Markdown into a Markdown AST (MDAST).

The fenced code block becomes a code node containing:

  • Language: mind-elixir
  • Value: the contents of the code block

remark-rehype converts the MDAST into a Hypertext AST (HAST).

The code block becomes a structure similar to:

<pre>
<code class="language-mind-elixir">
...
</code>
</pre>

rehype-mind-elixir searches the HAST tree for:

<code class="language-mind-elixir">

When a matching code block is found, the plugin:

  1. Extracts the code block contents.
  2. Splits the optional configuration from the body.
  3. Parses the configuration as YAML.
  4. Detects the body format.
  5. Generates a Mind Elixir container.

If --- is present, the first section is parsed as YAML.

height: 500px
width: 100%
direction: 2

The configuration is optional. Without it, an empty configuration object is generated.

The remaining body is passed to the body parser.

The parser identifies it as one of:

  • plain-text
  • json
  • json-like

The body is serialized according to its type so that the client runtime can process it correctly.

The original <pre> element is replaced with a container:

<div
data-mind-elixir
data-xmind-type="plain-text"
data-xmind-body="..."
data-xmind-config="..."
></div>

The plugin does not create the interactive map at this stage.

Instead, it stores the information required by the browser runtime in data-* attributes.

This keeps the Rehype transformation independent from the browser-side rendering logic.

rehype-stringify converts the resulting HAST tree into HTML.

The generated HTML contains the Mind Elixir containers but does not yet contain the rendered mind maps.

For example:

<div
data-mind-elixir
data-xmind-type="plain-text"
data-xmind-body="- ZikoJS\n - Core\n - Addons"
data-xmind-config="{}"
></div>

The browser runtime is provided by:

import "rehype-mind-elixir/client";

The runtime searches the document for elements matching:

[data-mind-elixir]

It then initializes every container that has not already been rendered.

For each container, the runtime reads:

const body = element.dataset.xmindBody;
const type = element.dataset.xmindType;
const config = element.dataset.xmindConfig;

These values correspond to the attributes generated by rehype-mind-elixir.

The data-xmind-type attribute determines how the body is converted into Mind Elixir node data.

Plain-text maps are converted using plainTextToMindNodes() from @zikojs/mind-elixir/no-css:

nodeData = plainTextToMindNodes(body);

For example:

- ZikoJS
- Core
- Addons

is converted into the corresponding Mind Elixir node structure.

JSON bodies are parsed with:

nodeData = JSON.parse(body);

JSON-like bodies are also parsed from their serialized representation:

nodeData = JSON.parse(body);

The result is the Mind Elixir node data passed to the map constructor.

If configuration data is present, the runtime parses it from data-xmind-config:

const nodeConfig = config
? JSON.parse(config)
: {};

The configuration is then combined with the default rendering options:

const map = MindMap({
height: '400px',
width: '300px',
data: nodeData,
...nodeConfig,
});

User-provided configuration therefore overrides the default height and width values when those properties are specified.

The client runtime imports MindMap from:

import {
MindMap,
plainTextToMindNodes,
} from '@zikojs/mind-elixir/no-css';

The parsed node data and configuration are passed to MindMap():

const map = MindMap({
height: '400px',
width: '300px',
data: nodeData,
...nodeConfig,
});

MindMap() creates the interactive Mind Elixir map.

The generated map is wrapped using ZikoJS:

tags
.div({}, map)
.style({
display: 'flex',
justifyContent: 'center',
border: '1px darkblue solid',
})
.mount(element);

This creates a ZikoJS <div> containing the Mind Elixir map and mounts it into the generated container.

The final structure is therefore roughly:

Generated container
│
▼
ZikoJS <div>
│
▼
MindMap(...)
│
▼
Interactive Mind Elixir map

After a container has been initialized, the runtime marks it as rendered:

element.dataset.rendered = 'true';

Before rendering a container, the runtime checks:

if (element.dataset.rendered) return;

This prevents the same container from being initialized multiple times.

The plugin and client runtime have separate responsibilities.

Runs during Markdown processing and is responsible for:

  • Finding mind-elixir blocks
  • Extracting their contents
  • Splitting configuration and body
  • Parsing YAML configuration
  • Detecting the body format
  • Generating the HTML container
  • Optionally injecting CDN resources

Runs in the browser and is responsible for:

  • Finding generated containers
  • Reading the data-* attributes
  • Parsing plain-text, JSON, and JSON-like bodies
  • Parsing the configuration
  • Creating the Mind Elixir map
  • Wrapping and mounting the map with ZikoJS
  • Preventing duplicate rendering

This separation keeps the Rehype transformation focused on document processing while the client runtime handles browser-side rendering and interactivity.