Markdown, highlighting, and transforms
spork-site 0.1.1
Convert CommonMark into shared immutable nodes, apply structural highlighting, and transform trees post-order.
spork-site keeps parsed Markdown in the same immutable node model as authored markup. This page covers syntax highlighting, parser configuration, and post-order structural transformations.
Namespaces: require spork-site.core as site; file-loading options belong to spork-site.content.
Syntax highlighting#
Fenced Markdown code gets a language-* class during Markdown conversion. Content loading applies Pygments by default and retains the shared structure:
(def highlighted
(site.highlight-syntax
(site.render-markdown "```spork\n(+ 1 2)\n```")))
The result remains Element("pre") containing Element("code"); only Pygments' trusted, escaped span markup is represented as RawHtml. Unknown lexer names leave the original code block unchanged.
Markdown and transformations#
spork-site.markdown parses CommonMark into Fragment, Element, Text, and explicit RawHtml values, never an opaque HTML string:
(def ast (site.parse-markdown source))
(def nodes (site.markdown-ast-to-nodes ast))
(def content (site.render-markdown source))
With the default parser, inline and block HTML tokens become explicit RawHtml nodes. Surrounding text remains escaped Text. Use (site.make-markdown-parser false) to disable Markdown raw HTML.
The parser is a markdown-it-py MarkdownIt instance, so a site may enable supported extensions explicitly. For example, this enables structural pipe tables rather than treating their source as plain paragraph text:
(def parser (site.make-markdown-parser))
(parser.enable "table")
(def content (site.render-markdown-with parser source))
Pass the same parser as :parser to content.load-markdown or content.load-documents when loading files. Extensions still convert into the shared node model; they do not introduce an opaque HTML-rendering path.
transform walks a node tree depth-first and invokes a function post-order after transformed children have been installed in a fresh immutable parent:
(defn mark-heading [node]
(if (and (isinstance node site.Element)
(contains? #{"h1" "h2" "h3" "h4" "h5" "h6"} node.tag))
(site.Element node.tag
(assoc node.attrs "data-heading" true)
node.children)
node))
(def transformed (site.transform content mark-heading))
A transform may return a node, nil to remove it, a deterministic sequence to splice through a fragment, or a printable scalar to create a Text node.