markava
A Markdown superset for static site generation.
Markava
Markava is a toy markup language I created to get more familiar with parsing in OCaml. Markava is a Markdown dialect based on the CommonMark flavour which also enables simple nesting of HTML blocks.
Here is a simple example of Markava featuring all its features
# A title
::::div.container
This is a **paragraph** with `inline code`, a [link](https://example.com) and _emphasis_
within a div block, and now here comes a nested block and an inline block.
::a[href=./file.txt,download] download this example
> A blockquote
> on two lines.
- first item
- second item
- third item
1. first step
2. second step
```ocaml
let x = 1 < 2
```
---
::::figure.my-fig[id=my-fig]

::figcaption Here is a picture
::::
::::which is parsed into the following HTML
<h1>A title</h1>
<div class="container">
<p>This is a <strong>paragraph</strong> with <code>inline code</code>, a <a href="https://example.com">link</a> and <em>emphasis</em>
within a div block, and now here comes a nested block and an inline block.</p>
<p><a href="./file.txt" download>download this example</a></p>
<blockquote>
<p>A blockquote
on two lines.</p>
</blockquote>
<ul>
<li>first item</li>
<li>second item</li>
<li>third item</li>
</ul>
<ol>
<li>first step</li>
<li>second step</li>
</ol>
<pre><code class="language-ocaml">let x = 1 < 2</code></pre>
<hr />
<figure class="my-fig" id="my-fig">
<p><img alt="some picture" src="./my_picture.png" /></p>
<p><figcaption>Here is a picture</figcaption></p>
</figure>
</div>Why Markava?
As a superset of HTML, it's already easy to embed custom HTML elements in Markdown. However, when writing Markdown documents meant for direct parsing to HTML (for example in a static site generator), this can be quite tedious and confusing as the HTML markup takes more space than the content itself.
Markava aims to close that gap with its block and inline tags
::::tag
some block content
::::
and ::tag some inline contentNot only is this useful if you have to introduce some manual HTML hierarchy within your document, but it also enables you to use attributes where Markdown doesn't allow you, for example ::a[rel=noreferrer,target=_blank,href=https://mysite.com,download] mysite.
Attributes without a value are flags: [download] renders as a bare download attribute, while [href=...] renders as href="...".
Markava follows the same rules as regular Markdown: content is parsed within a node until an empty line is met. Any content that is not a tag is assumed to be generic markdown. Code blocks are handled specially to avoid affecting the rest of the document.
Block tags take their content from the lines that follow, so ::::tag needs no space after the name. Inline tags are written ::tag content: the space after the tag head is required, and the content may continue across lines until an empty line.
Supported Markdown
Markava keeps a deliberately small CommonMark core:
- ATX headings, paragraphs and thematic breaks
- emphasis, strong, inline code, links and images
- fenced code blocks with an optional language
- flat unordered and ordered lists
- single-level blockquotes
Lists are tight and a blank line ends them. Ordered list numbers are accepted but not rendered, so <ol> never carries a start attribute. A blockquote is a run of > lines that form one paragraph.
Not supported yet: nested lists, list items that span lines or contain blocks, loose lists, nested blockquotes, indented code blocks, setext headings, hard line breaks, autolinks, reference links, backslash escapes and raw HTML passthrough. Tables are not part of CommonMark.
Usage
This package contains the parser for Markava which can be used in the following way
$ markava help
Usage: markava <command> <options> ARGS
commands:
parse SOURCE OUTPUT Parse a source file into an output file.
--type md,html Whether to parse to regular Markdown or pure HTML. Defaults to HTML.
helpDevelopment
Markava is built with dune and tested with alcotest. The parser is written test-first in stages: inline AST, block AST, HTML renderer, then the end-to-end pipeline. docs/tdd-plan.md holds the pipeline, the AST, the grammar and the milestones.
opam install dune alcotest
dune exec test/test_m1_inline.exe # inline parser
dune exec test/test_m2_blocks.exe # block parser
dune exec test/test_m5_html.exe # HTML renderer
dune test # everything, CLI tests included