markdown-ng
1 Quick start
1.1 Syntax supported
- John Gruber’s original description. 
- Enhancements controlled by the current-strict-markdown? parameter. 
1.2 Use at the command line, to generate HTML
You can run this at the command-line: Pipe in markdown and it pipes out HTML.
$ raco md I am _emph_ and I am **strong**. ^D <!DOCTYPE html> <html> <head> <meta charset="utf-8" /></head> <body> <p>I am <em>emph</em> and I am <strong>strong</strong>.</p></body></html> 
1.3 Use as a library, to generate xexprs and HTML
Use parse-markdown to convert a string? or path? to a (listof xexpr?).
You can modify the (listof xexpr?), splice it into the body element of an (html ...) wrapper, and convert to HTML text.
(require markdown-ng) 
; 1. Parse string to a list of xexprs 
(define xs (parse-markdown "I am _emph_ and I am **strong**.")) 
xs '((p () "I am " (em () "emph") " and I am " (strong () "strong") "."))
; 2. Optionally, process the xexprs somehow: ; ... nom nom nom ... ; 3. Splice them into an HTML `xexpr` and... ; 4. Convert to HTML text: 
(display-xexpr `(html () (head ()) (body () ,@xs))) 
<html>
<head></head>
<body>
<p>I am <em>emph</em> and I am <strong>strong</strong>.</p></body></html>
display-xexpr is provided as a "warm bowl of porridge" —
1.4 Use as a library, to generate "pre-Scribble"
The xexprs returned by read-markdown can also be fed to the
function xexprs->scribble-pres, which returns a Scribble
representation —
#lang racket/base (require markdown-ng markdown-ng/scrib net/sendurl racket/class racket/format racket/runtime-path scribble/base-render scribble/decode scribble/html-render) (define work-dir (find-system-path 'temp-dir)) (define (build-html-doc docs dest-file) (let* ([renderer (new (render-mixin render%) [dest-dir work-dir])] [fns (list (build-path work-dir dest-file))] [fp (send renderer traverse docs fns)] [info (send renderer collect docs fns fp)] [r-info (send renderer resolve docs fns info)]) (send renderer render docs fns r-info) (send renderer get-undefined r-info))) (define-runtime-path test.md "test/test.md") (define part (decode (xexprs->scribble-pres (with-input-from-file test.md read-markdown)))) (build-html-doc (list part) "test.html") (send-url (~a "file://" work-dir "test.html")) 
2 Notes
Originally this was implemented using a pile of regular expressions,
somewhat like how Markdown.pl works —
In October 2013 I redesigned it to be a "real" parser with a grammar, using Stephen Chang’s parsack, a monadic parser combinator library. The grammar was developed by looking first at peg-markdown and later at pandoc. For a few edge cases I found Babelmark and Babelmark2 helpful to compare result with many other implementations. The many unit tests from the old version also helped.
2.1 Links
3 API
| (require markdown-ng) | package: markdown-ng | 
The markdown-ng module provides all bindings from the markdown-ng/display-xexpr, markdown-ng/parse, and markdown-ng/toc modules.
3.1 Parsing Markdown
| (require markdown-ng/parse) | package: markdown-ng | 
procedure
(parse-markdown input [ footnote-prefix-symbol?]) → (listof xexpr?) input : (or/c path? string?) footnote-prefix-symbol? : symbol? = (gensym) 
When given a string?, parses the string as a markdown file. When given a path?, calls file->string and parses the result.
- Deletes all \r (including but not limited to \r\n). 
- Appends a \r\n to simplify whole-document processing. 
parameter
(current-strict-markdown? strict?) → void? strict? : boolean? 
= #f 
- Fenced code blocks using triple backticks ```. An optional language descriptor may follow the opening backticks. This results in the code element getting a class attribute whose value is brush: lang. 
- Inline code using single backticks may be followed by a language descriptor in square brackets. This results in the code element getting a class attribute whose value is brush: lang. 
- Heading elements get an id attribute whose value is a "slug" of the heading text. 
- Images alone in their own paragraph are nested in a in div.figure along with a p.caption element following the img. 
- "Smart" punctuation (hyphens, dashes, single and double quotes, aspostrophes, prime, ellipses). 
- Footnote definitions and references as in PHP Markdown Extra and Python-Markdown. 
- Support for math-jax expressions — - inline within \\( and \\) delimiters and display within \\[ and \\] delimiters — - resulting in script elements with type=math/tex. 
procedure
(read-markdown [footnote-prefix-symbol?]) → (listof xexpr?)
footnote-prefix-symbol? : symbol? = (gensym) 
NOTE: This function is deprecated; use parse-markdown, instead.
3.2 Building a Table of Contents
| (require markdown-ng/toc) | package: markdown-ng | 
> (toc (parse-markdown (string-join '("# 1" "## 1.1" "# 2" "## 2.1") "\n\n"))) 
'(div
((class "toc"))
(ol
(li (a ((href "#1")) "1") (ul (li (a ((href "#11")) "1.1"))))
(li (a ((href "#2")) "2") (ul (li (a ((href "#21")) "2.1"))))))
3.3 Displaying Parsed Markdown
| (require markdown-ng/display-xexpr) | package: markdown-ng | 
procedure
(display-xexpr xexpr) → any/c
xexpr : xexpr? 
procedure
(xexpr->string xexpr) → string?
xexpr : xexpr? 
3.4 Generating Pre-Scribble
| (require markdown-ng/scrib) | package: markdown-ng | 
The bindings documented in this section are not provided by the markdown-ng module.
procedure
(xexprs->scribble-pres xexprs)
→ (listof (or/c pre-part? pre-flow? pre-content?)) xexprs : (listof xexpr?) 
Although this could be generalized, currently it’s only intended to handle the subset of HTML that read-markdown returns.