TypeScript/Node.js implementation of LegalMarkdown
Try it live in the hosted playground.
Legal Markdown JS processes legal markdown documents and can generate:
- Processed markdown
- HTML
- DOCX
Core syntax supported:
- Variables/helpers (
{{field}}, helpers, loops) - Legal headers (
l.,ll.,lll., ...) - Optional clauses (
[text]{condition}) - Cross references between sections (
|reference|) - Imports (
@import path/to/file.md)
Check the features overview document for more details.
Run without installing globally:
npx legal-md contract.md output.mdInstall the package locally in a project:
npm install legal-markdown-jsAvailable binaries:
legal-mdlegal-md-uilegal-md-playground
Install the standalone macOS binary:
brew tap petalo/legal-markdown
brew install legal-mdAfter installing with Homebrew, you can use:
legal-mdlegal-md uilegal-md playground
curl -fsSL https://github.com/petalo/legal-markdown-js/releases/latest/download/install.sh | shInstall, then run your first conversion in seconds:
1. Install
# npm
npm install legal-markdown-js
# Homebrew (macOS)
brew tap petalo/legal-markdown && brew install legal-md2. Process a document
Convert a Legal Markdown file to processed Markdown:
legal-md contract.md output.mdGenerate HTML, PDF, or DOCX:
legal-md contract.md --html
legal-md contract.md --pdf
legal-md contract.md --docxInput (contract.md) |
Output markdown | Output HTML |
|---|---|---|
|
|
|
Use the browser-based playground for a quick interactive test: petalo.github.io/legal-markdown-js
Launch the terminal UI:
legal-md-ui
# or
legal-md uiIf you installed from npm or Homebrew:
legal-md-playground
# or
legal-md playgroundIf you are working from this repository:
npm run build:web
npm run web:serveUseful variants:
# Vite dev server for playground development
npm run dev:web
# Serve an existing build on a custom port
npm run web:serve -- --port=3000# Input -> output markdown
legal-md input.md output.md
# Input -> stdout markdown
legal-md input.md --stdout
# Read from stdin
cat input.md | legal-md --stdin --stdout# HTML
legal-md input.md output.html --html
# PDF
legal-md input.md output.pdf --pdf
# DOCX
legal-md input.md output.docx --docx
# Highlighted review variants
legal-md input.md output.pdf --pdf --highlight
legal-md input.md output.docx --docx --highlight# Auto (default)
legal-md input.md output.pdf --pdf
# Force specific backend
legal-md input.md output.pdf --pdf --pdf-connector puppeteer
legal-md input.md output.pdf --pdf --pdf-connector system-chrome
legal-md input.md output.pdf --pdf --pdf-connector weasyprintauto resolution order is:
puppeteersystem-chromeweasyprint
legal-md contract.md --export-yaml -o metadata.yaml
legal-md contract.md --export-json -o metadata.jsonlegal-md contract.md --title "Master Services Agreement" --html
legal-md contract.md output.html --html --css ./styles/print.css
legal-md contract.md --enable-field-tracking --stdoutimport {
processLegalMarkdown,
generateHtml,
generatePdf,
generatePdfVersions,
generateDocx,
generateDocxVersions,
} from 'legal-markdown-js';
const source = `---\ntitle: Service Agreement\nclient: ACME\n---\n\nl. Parties\n\nAgreement with {{client}}.`;
const processed = await processLegalMarkdown(source, {
enableFieldTracking: true,
});
const html = await generateHtml(source, {
title: 'Service Agreement',
includeHighlighting: true,
});
const pdf = await generatePdf(source, './output/agreement.pdf', {
format: 'A4',
includeHighlighting: false,
pdfConnector: 'auto', // auto | puppeteer | system-chrome | weasyprint
});
const { normal, highlighted } = await generatePdfVersions(
source,
'./output/agreement.pdf',
{
format: 'Letter',
pdfConnector: 'weasyprint',
}
);
const docx = await generateDocx(source, './output/agreement.docx', {
title: 'Service Agreement',
});
const docxPair = await generateDocxVersions(source, './output/agreement.docx');
console.log(
processed.content,
html.length,
pdf.length,
normal.length,
highlighted.length
);
console.log(docx.length, docxPair.normal.length, docxPair.highlighted.length);Supported backends:
puppeteersystem-chromeweasyprint
Installation examples:
# Puppeteer browser install (if needed)
npx puppeteer browsers install chrome
# macOS
brew install weasyprint
# Ubuntu/Debian
sudo apt-get install -y weasyprintConfiguration loading supports:
package.json(legalmdkey).legalmdrc.legalmdrc.yaml.legalmdrc.jsonlegalmd.config.jslegalmd.config.ts
Useful env overrides:
LEGAL_MD_PDF_CONNECTORLEGAL_MD_VALIDATION_MODELOG_LEVELDEBUGIMAGES_DIRSTYLES_DIRDEFAULT_INPUT_DIRDEFAULT_OUTPUT_DIRARCHIVE_DIR
Example:
LEGAL_MD_PDF_CONNECTOR=weasyprint legal-md input.md --pdf# Full local suite
npm test
# CI-like run (includes PDF backend precheck)
npm run test:ci
# Backend availability check only
npm run test:pdf:backends
# Targeted suites
npm run test:unit
npm run test:integration
npm run test:e2e
npm run test:e2e:clitest:e2e and test:ci require both PDF paths to be available:
- Puppeteer launchable Chrome/Chromium
- WeasyPrint executable
- Getting Started
- CLI Reference
- Features Overview
- Output Guides
- PDF Generation
- DOCX Generation
- Configuration
- Architecture
- Development Guide
- Contributing
See docs/development/contributing.md.
MIT. See LICENSE.
Based on the original LegalMarkdown project by Casey Kuhlman.
