Skip to content

ndp-software/lit-md

Repository files navigation

@ndp-software/lit-md

Literate test files that generate README.mds.

Introduction

Some projects, especially libraries, require numerous code examples. For those responsible for updating a README, or other documentation, this can be burdensome and error-prone. I've run into this before when writing a testing tool, and ran into it again when sketching out a new UI library. I wanted to write documentation with embedded code examples, but I also wanted to be sure that the examples were correct and up-to-date. This is what led me to create lit-md.

With lit-md, you write your documentation with embedded code samples. All the code samples are automatically type-checked and run through node to verify them (as tests). Every example actually works!

Key features:

  • works with Typescript or Javascript
  • supports flexible assertion methods
  • provides utilities to include shell commands and their outputs as part of your documentation. This is important if you tool has a CLI, or you just need to show how it works in the terminal.
  • fully tested with its own test suite, which also serves as documentation and examples for users

There are other tools with the same aims (see [#similar-tools]), But this combines my interest in Literate programming with a passion for TDD and excitement about Typescript. I have aimed to provide a great DX for writing documentation, with a simple syntax and powerful features that work well with-in the node ecosystem.

Documention is written in .ts (or .lit-md.ts) files, and the documentation is generated from comments and test bodies:

lit-md README.lit-md.ts > README.md

# As a convenience, "run" all the code examples as tests, or a test suite:
node --test README.lit-md.ts > README.md

# Or, you can add typechecking and do them all as one step:
lit-md --typecheck --test README.lit-md.ts > README.md

How it Works

A lit-md file contains prose in comments and examples in test bodies. At a basic level, a file is processed, and

  • comments are directly transferred into markdown, and
  • example (or test, it, spec) bodies become fenced code blocks. To make this work well, there are quite a few nuances and features to control what appears in the output and how it looks.

Basic Usage

Add @ndp-software/lit-md to your project

Then create a readme. The following is an example for a hypohetical "mathlib" project. Here's the source file:

import { describe, example } from '@ndp-software/lit-md'
import assert from 'node:assert/strict'

describe('My Project README.', () => {
// This is a really great project! 
// Adding numbers is as simple as using the "+" operator:
  example('add example', () => {
    import { add, multiply } from './maths.ts'
    const a = 1
    const b = 2
    assert.equal(add(a, b), 3)
  })  
  
  // Also supported is multiplication:
  example('multiply example', () => {
    const x = 3
    const y = 4
    assert.equal(multiply(x, y), 12)
  })
})
$ lit-md mathlib-readme.ts --out mathlib-readme.md

Output file mathlib-readme.md:

## My Project README.

This is a really great project! 
Adding numbers is as simple as using the "+" operator:
```ts
import { add, multiply } from './maths.ts'
const a = 1
const b = 2
add(a, b) // => 3
```

Also supported is multiplication:
```ts
const x = 3
const y = 4
multiply(x, y) // => 12
```

The full node assert library is supported.

For more information on CLI usage, see CLI documentation.

Shell examples

Use shellExample to include executable shell commands in the README. It verifies a 0 return code and provides flexible assertion and display options.

shellExample function

shellExample('echo "hello world"', { stdout: { display: true } })

becomes

$ echo "hello world"
hello world

For more information on the shellExample, see shellCommand documentation.

Similar tools

Credits

Conceived of and built by Andrew J. Peterson, NDP Software

Literate Programming has been a long-standing interest of mine. An earlier version of trying to solve this problem is in Test Pantry, but this is a complete re-thinking and re-implementation, with a much more robust and flexible approach. I have been inspired by many literate programming tools, but especially Knuth's original work.

Although there was some manual code changes, most of the code was Github Copilot CLI, using mostly Claude Haiku 4.5 and some Claude Sonnet 4.6. Most tasks used a plan-autopilot loop, but other approaches were used as well.

About

literate markdown generation

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors