Jest Markdown Pipeline
"Nothing is better than documentation with examples. But nothing is worse than examples that don't work because the code has changed since the documentation was written." - rustbook
Example code blocks in our markdown or inline documentation comments can be useful to quickly demonstrate how one can use our software. As they are part of our living standards, each example code should be functional code that can be asserted and tested. Documentation example code should be automated, tested and linted as part of our workflow.
Initially, we were thinking of creating a md-jest
for parsing code blocks in markdown and transforming them into
jest tests. Similar to how ts-jest
transform TS to CommonJS, but using contented-processor
to transform MD files.
@eli-lim suggested we transform jest files *.test.ts
into Markdown instead. We
get the DX of writing test with Jest and IDE support (without having to support write our own runner). It is much
easier to transform comments to markdown than transform markdown to code (although not much harder, the focus here is
on the DX). Further, you get the natural flow of writing narrative and writing tests as a narrative.
This page, is written in a jest test file.
JestMarkdown.spec.ts
Comments Parsing
All comments are automatically picked up as Markdown with indent stripped. Indent are stripped using
strip-indent
, *
are also stripped. For bullet points, you should use -
and avoid using *
to prevent
unintentional stripping.
//
- Line Comment/*
- Block Comment/**
- Block Comment
This section is generated by the code snippet below.
This is a multi line with *
stripped from each line.
This is a Line Comment
This is a Block Comment
This is a Multi Line
Block Comment
without *
.
/**
* ### This section is generated by the code snippet below.
*
* This is a multi line with `*` stripped from each line.
*/
// This is a `Line Comment`
/* This is a `Block Comment` */
/* This is a `Multi Line`
`Block Comment` without `*`. */
Including Codeblocks
JestMarkdown
has the ability to "pickup" codes and add them into a codeblock. Codeblock is parsed line by line,
@contented codeblock:start
indicate the starting line and @contented codeblock:end
indicate the ending line.
Everything between will be included into a codeblock. Although not recommended, you can nest multiple
@contented codeblock
between.
'@contented codeblock:start',
'@contented codeblock:end',
it('this it statement is in a codeblock with nested codeblock', () => {
const symbols = [
// @contented codeblock:start
'@contented codeblock:start',
// @contented codeblock:end
'everything in between will be included as a TypeScript codeblock ```ts\n```',
// @contented codeblock:start
'@contented codeblock:end',
// @contented codeblock:end
];
expect(join(...symbols)).toBeDefined();
});