Liking cljdoc? Tell your friends :D

nextjournal markdown

Clojars Project Notebooks

A cross-platform clojure library for Markdown parsing and transformation.

🚧 For a richer reading experience read this readme as a clerk notebook.

Features

Try

Try it online.

Flavor

We adhere to CommonMark Spec and comply with extensions from Github flavoured Markdown. Additionally, we parse $\LaTeX$ formulas (delimited by a $ for inline rendering or $$ for display mode).

Usage

(ns hello-markdown
  (:require [nextjournal.markdown :as md]))

Parsing markdown into an AST:

(def data
  (md/parse "> et tout autour, la longue cohorte de ses personnages, avec leur histoire, leur passé, leurs légendes:
> 1. Pélage vainqueur d'Alkhamah se faisant couronner à Covadonga
> 2. La cantatrice exilée de Russie suivant Schönberg à Amsterdam
> 3. Le petit chat sourd aux yeux vairons vivant au dernier étage
> 4. ...

**Georges Perec**, _La Vie mode d'emploi_.

---
"))

#_#_=>
{:type :doc
 :content
 [{:type :blockquote,
   :content
   [{:type :paragraph,
     :content
     [{:type :text,
       :text
       "et tout autour, la longue cohorte de ses personnages, avec leur histoire, leur passé, leurs légendes:"}]}
    {:type :numbered-list,
     :content
     [{:type :list-item,
       :content
       [{:type :plain,
         :content
         [{:type :text,
           :text
           "Pélage vainqueur d'Alkhamah se faisant couronner à Covadonga"}]}]}
      {:type :list-item,
       :content
       [{:type :plain,
         :content
         [{:type :text,
           :text
           "La cantatrice exilée de Russie suivant Schönberg à Amsterdam"}]}]}
      {:type :list-item,
       :content
       [{:type :plain,
         :content
         [{:type :text,
           :text
           "Le petit chat sourd aux yeux vairons vivant au dernier étage"}]}]}
      {:type :list-item,
       :content
       [{:type :plain, :content [{:type :text, :text "..."}]}]}]}]}
  {:type :paragraph,
   :content
   [{:type :strong, :content [{:type :text, :text "Georges Perec"}]}
    {:type :text, :text ", "}
    {:type :em, :content [{:type :text, :text "La Vie mode d'emploi"}]}
    {:type :text, :text "."}]}
  {:type :ruler}]}

Hiccup rendering

To transform the above AST into hiccup syntax:

(md/->hiccup data)
#_#_=>
[:div
 [:blockquote
  [:p
   "et tout autour, la longue cohorte de ses personnages, avec leur histoire, leur passé, leurs légendes:"]
  [:ol
   [:li
    ("Pélage vainqueur d'Alkhamah se faisant couronner à Covadonga")]
   [:li
    ("La cantatrice exilée de Russie suivant Schönberg à Amsterdam")]
   [:li
    ("Le petit chat sourd aux yeux vairons vivant au dernier étage")]
   [:li ("...")]]]
 [:p [:strong "Georges Perec"] ", " [:em "La Vie mode d'emploi"] "."]
 [:hr]]

The transformation of markdown node types can be customized like this:

^{:nextjournal.clerk/viewer 'nextjournal.clerk.viewer/html-viewer}
(md/->hiccup
 (assoc md/default-hiccup-renderers
        ;; :doc specify a custom container for the whole doc
        :doc (partial md/into-hiccup [:div.viewer-markdown])
        ;; :text is funkier when it's zinc toned
        :text (fn [_ctx node] [:span {:style {:color "#71717a"}} (md/node->text node)])
        ;; :ruler gets to be funky, too
        :ruler (constantly [:hr {:style {:border "2px dashed #71717a"}}]))
 data)

HTML blocks and HTML inlines

Typically you'd want to customize the rendering of :html-inline and :html since these need to be rendered to raw strings:

(require '[hiccup2.core :as hiccup])

(def renderers
  (assoc md/default-hiccup-renderers
         :html-inline (comp hiccup/raw md/node->text)
         :html-block (comp hiccup/raw md/node->text)))

(str (hiccup/html (md/->hiccup renderers "<img src=\"...\"/>")))

#_#_=>
"<div><img src=\"...\"/></div>"

Transforming to other targets

We've built hiccup transformation in for convenience, but the same approach can be used to target more formats.

This library is one of the building blocks of Clerk where it is used for rendering literate fragments.

^{:nextjournal.clerk/viewer 'nextjournal.clerk.viewer/markdown-viewer}
data

Extensibility

We added minimal tooling for extending markdown expressions.

Can you improve this documentation? These fine people already did:
Andrea Amantini, Michiel Borkent, Martin Kavalar & Michael Glass
Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close