Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/xykong/flux-markdown/llms.txt

Use this file to discover all available pages before exploring further.

FluxMarkdown extends the core markdown-it parser with a carefully chosen set of plugins that cover common real-world Markdown dialects — GitHub Flavored Markdown, Obsidian, Pandoc exports, and more. Because FluxMarkdown is a passive viewer rather than an editor, the selection principle is to maximize compatibility with content written in other tools, not to introduce syntax that only works here.

Plugins

The base parser. Configured in buildMd() inside src/index.ts with:
new MarkdownIt({
  html: true,        // pass raw HTML through unchanged
  breaks: true,      // single newlines become <br>
  linkify: false,    // do not auto-link bare URLs
  typographer: true, // smart quotes, em-dashes, etc.
})
The html: true setting allows documents that embed raw HTML (common in GitHub READMEs) to render correctly inside the WebView.
Renders LaTeX math using KaTeX. Inline math uses single dollar signs ($E=mc^2$); display math uses double dollar signs ($$\int_0^\infty$$).
Inline: $E = mc^2$

Display:
$$
\int_0^\infty e^{-x^2} dx = \frac{\sqrt{\pi}}{2}
$$
This plugin is loaded lazily. It is dynamically imported and applied to the markdown-it instance only when the document body contains a $ or $$ pattern. Documents without math pay no loading cost.
Adds id attributes to every heading so that in-page links like [see overview](#overview) work correctly.The plugin is configured with a custom slugify function that handles CJK characters and mixed Latin/Chinese headings:
instance.use(anchor, {
  permalink: false,
  slugify: (s: string) =>
    s.toLowerCase()
     .replace(/[^\w\u4e00-\u9fa5]+/g, '-')
     .replace(/^-+|-+$/g, '')
});
The renderer also implements a five-level tolerant anchor-matching strategy to handle links generated by AI tools or third-party editors that use different slugification rules. See src/index.tsfindElementByAnchor.
Converts :emoji_name: shortcodes to Unicode characters.
:rocket: :tada: :warning:
Like KaTeX, this plugin is applied lazily — it is only wired into the markdown-it instance when the enableEmoji render option is true (the default).
Supports [^label] footnote references and definitions.
Here is a claim.[^1]

[^1]: The supporting evidence.
Renders GitHub’s > [!TYPE] alert syntax into styled callout blocks.
> [!NOTE]
> Useful information to keep in mind.

> [!WARNING]
> This action cannot be undone.

> [!TIP]
> A shortcut that saves time.
Supported types: NOTE, TIP, IMPORTANT, WARNING, CAUTION.
Wraps ==text== in <mark> elements for highlighted text.
This ==word== is highlighted.
Renders H~2~O subscript syntax.
Water is H~2~O. CO~2~ is a greenhouse gas.
Renders x^2^ superscript syntax.
E = mc^2^. The area is r^2^π.
Renders - [ ] and - [x] list items as checkboxes.
- [x] Write tests
- [ ] Update documentation
- [ ] Submit PR

Rendering pipeline

The full pipeline runs inside window.renderMarkdown in src/index.ts. Steps execute in this order:
1

YAML frontmatter extraction

extractFrontMatter(text) splits the input at the --- delimiter. If a frontmatter block is present, it is parsed with js-yaml and rendered as an HTML table (<table class="yaml-frontmatter">). The body text is passed to the next stage.
2

Feature flag evaluation

Emoji and KaTeX plugins are applied or removed from the markdown-it instance depending on the enableEmoji and enableKatex options passed by Swift. If a previously-enabled plugin needs to be disabled, rebuildMd() creates a fresh instance.
3

Outline extraction

extractOutline(md, body) parses the body text with markdown-it to extract heading tokens and builds a tree structure for the TOC panel.
4

markdown-it render

md.render(body, { baseUrl }) converts the Markdown body to an HTML string. The custom image rule resolves relative paths to local-md:// URLs. The renderToken override injects data-source-line attributes for source-line tracking.
5

Mermaid block extraction

Before writing to the DOM, code.language-mermaid blocks are replaced with <div class="mermaid"> placeholder elements. The raw diagram source is preserved as text content.
6

DOM update

The combined HTML (frontmatter table + rendered body) is written to #markdown-preview via innerHTML. RTL detection runs immediately after.
7

Diff annotation (optional)

If prevContent was provided, computeLineDiff produces a line-level diff and DiffAnimator.annotateRenderDOM annotates changed DOM nodes with CSS classes for animated highlighting.
8

Mermaid rendering

The Mermaid module is lazily imported if not yet loaded. Each .mermaid placeholder is processed: preprocessMermaidNewlines runs first, then mermaid.render() produces an SVG string that replaces the placeholder content.
9

Vega and Graphviz rendering

renderVegaDiagrams and renderGraphvizDiagrams scan the DOM for language-vega, language-vega-lite, language-dot, and language-graphviz blocks and replace them with rendered SVG output.

Mermaid newline preprocessing

Mermaid v11 does not convert \n escape sequences to line breaks inside unquoted node labels. The preprocessMermaidNewlines function in src/index.ts normalizes diagram source before passing it to mermaid.render(). It handles three cases:
// 1. Sequence diagram participants: participant U as "label\nline2"
//    → strips quotes, converts \n → <br/>

// 2. Double-quoted node labels: A["line1\nline2"]
//    → converts \n → <br/> inside the quotes

// 3. Unquoted bracket labels: A[line1\nline2], A(text\ntext), A{text\ntext}
//    → converts \n → <br/> inside the bracket
This function is exported and has comprehensive Jest test coverage in test/mermaid-newline.test.ts.

GitHub Markdown CSS

The github-markdown-css package provides the base styling that makes rendered output look like GitHub’s Markdown preview. It is imported at the top of src/index.ts:
import 'github-markdown-css/github-markdown.css';
The rendered content div carries the markdown-body class that activates these styles. Dark mode is handled by setting data-theme="dark" on <html> — the CSS package responds to this attribute. Additional style overrides live in src/styles/ and cover highlight.js themes, the TOC panel, search UI, callout blocks, print layout, and diff animations.

Extending the renderer: adding a plugin

To add a new markdown-it plugin:
1

Install the package

cd web-renderer
npm install markdown-it-your-plugin
2

Write a test first

Create test/your-plugin.test.ts and add a test that verifies the expected HTML output. See test/extended-syntax.test.ts and test/github-alerts.test.ts for examples.
3

Import and register in src/index.ts

Add the import near the existing plugin imports, then call instance.use(yourPlugin) inside buildMd():
// @ts-ignore
import yourPlugin from 'markdown-it-your-plugin';

function buildMd(): MarkdownIt {
  const instance = new MarkdownIt({ ... });
  // existing plugins...
  instance.use(yourPlugin);
  return instance;
}
4

Run tests

cd web-renderer && npm test
Plugins that inject raw HTML or attributes into the DOM increase the XSS attack surface. FluxMarkdown renders untrusted Markdown files from disk. Review any new plugin carefully before enabling it, especially if it touches html_block or html_inline token types.

Renderer overview

Architecture, tech stack, and key source files.

Testing the renderer

How to write and run Jest tests for rendering logic.

Build docs developers (and LLMs) love