Reference implementation
The markset command
One executable with four commands. It validates a document, renders it to HTML, lowers it to plain CommonMark, or prints the parsed tree. There is no build step and no configuration file.
Getting it
Running it from a clone
There is no published package yet. Clone the repository and run the entry point directly. Node 22.18 or newer is required, because the source is TypeScript that Node runs by stripping the types.
git clone https://github.com/markset-lang/markset && cd markset
npm install
node packages/cli/src/markset.ts --help
Everything below writes markset where you would type that longer path.
Commands
What each one does
markset check
Reads one or more documents and reports every diagnostic with a file, line and column. Exits with status 1 if any diagnostic is an error, which is what makes it usable in continuous integration. Add --json to get the diagnostics as structured data instead of text.
markset html
Renders a complete HTML page with the default stylesheet inlined, so the output is one self-contained file. Add --fragment for the body content alone, --theme <file> to append a theme stylesheet, and --title to set the page title.
markset downgrade
Lowers every construct to the plain CommonMark it is defined to fall back to. The output is a fixed point: downgrading it again changes nothing, and it parses with no diagnostics. This is the degradation contract, executable.
markset ast
Prints the parsed tree as JSON. The tree is mdast plus the Markset node types, so any tool in the unified ecosystem can consume it. Add --positions to keep source offsets.
A single - in place of a filename reads the document from standard input.
Options
Every flag
| Flag | Applies to | Effect |
|---|---|---|
-o, --out <path> |
all | Write to a file instead of standard output. |
--fragment |
html |
Emit the body content only, with no page shell or stylesheet. |
--css <mode> |
html |
inline inlines the default stylesheet and is the default. none omits it. Any other value is treated as a URL and linked. |
--theme <file> |
html |
Append a theme stylesheet after the default one, so it can style author classes and override tokens. See spec §6. |
--title <text> |
html |
Page title. Defaults to the first level-one heading. |
--json |
check |
Emit diagnostics as JSON rather than as lines of text. |
--positions |
ast |
Keep the position field on every node. |
-h, --help |
all | Print usage and exit. |
In practice
Three things worth knowing
-
An invalid document still renders
checkis the gate, not the renderer.htmlanddowngradereport diagnostics on standard error and then produce their output anyway, because a document with one bad directive is still mostly a document. Nothing is silently dropped. -
Validation is the point of a closed vocabulary
A misspelled
:::cardsis an error rather than a passthrough, so it fails in your editor rather than in someone's browser. Runmarkset check docs/*.mdin continuous integration and a typo cannot reach a published page. -
The downgrade is how you leave
Nothing here locks a document in.
markset downgradegives back ordinary CommonMark that any renderer on earth handles, which is the same content a viewer that has never heard of Markset would show.
See it work
markset check examples/showcase.md
markset html examples/showcase.md -o showcase.html
markset html examples/strategy-read.md --theme examples/memo.css -o memo.html
markset downgrade examples/showcase.md