Kinetica

Markdown

kinetica-markdown parses Markdown into an AST and renders it as Kinetica nodes — which is how this site works: every page is a .md resource, parsed on the JVM, rendered through the same ComponentScope DSL as any component, and serialized with toSafeHtml().

Usage

import io.heapy.kinetica.markdown.markdown

@UiComponent
fun ComponentScope.Article(source: String) {
    host("article") {
        markdown(source)
    }
}

Because output is ordinary nodes, markdown content composes with everything else: it can sit inside a router entry, be server-rendered, be snapshot-tested, and inherit page CSS.

Supported syntax

FeatureNotes
Headings #######h2+ get id anchors derived from their text
Paragraphs, **bold**, *italic*, code __/_ delimiters too; inline nesting supported
Links [label](href)hrefs pass the runtime's URL sanitizer — javascript: never renders
Fenced code blocks lang `server-side spans for Kotlin, JSON, HTML, and YAML; unsupported languages keep class="language-…"
Lists - / * / 1. / 1)single level, continuation lines
Blockquotes, --- rules, tablesGFM-style pipe tables
HTML comments <!-- … -->skipped entirely — these docs use them to link sections to source files
Directives ::: name argumentextension point, see below

Parsing is available standalone: parseMarkdown(source): List<MdBlock> with a small typed AST (MdHeading, MdParagraph, MdCodeBlock, MdList, MdQuote, MdTable, MdRule, MdDirective, inline MdText / MdCode / MdEmphasis / MdLink).

Directives — embedding live components

A directive line hands control back to your code mid-document:

markdown(source, MarkdownOptions(directive = { name, argument ->
    when (name) {
        "example" -> { LiveExample(argument); true }
        else -> false                       // render nothing — an unhandled directive emits no nodes
    }
}))

This page's live widgets use exactly this: the source contains ::: example counter, the site's directive hook renders a placeholder div[data-example], and a small Kinetica browser bundle mounts an interactive app into it:

Loading live example…

Live — this widget is a Kinetica app mounted in your browser.

Safety by construction

The renderer never emits raw HTML. Text becomes TextNodes (escaped by every serializer), attributes go through the same allowlist as hand-written components, and unsafe URL schemes are stripped by the runtime — a markdown document is exactly as safe as any other component tree.