legal-markdown-js
v4.3.0
Published
Node.js implementation of LegalMarkdown for processing legal documents with markdown and YAML - Complete feature parity with Ruby version
Maintainers
Readme
Legal Markdown JS
TypeScript/Node.js implementation of LegalMarkdown
Try it live in the hosted playground.
What It Does
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.

Install
npm
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
Homebrew
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
Install script
curl -fsSL https://github.com/petalo/legal-markdown-js/releases/latest/download/install.sh | shQuick Start
Install, 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 --docxl. Parties
Agreement with {{client}}.
l. Services
ll. Payment
Total due: ${{amount}}.
[ll. Warranty
Full warranty included.]{include_warranty}
Playground And UI
Hosted playground
Use the browser-based playground for a quick interactive test: petalo.github.io/legal-markdown-js
Interactive CLI
Launch the terminal UI:
legal-md-ui
# or
legal-md uiLocal playground
If 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=3000CLI Usage
Basic processing
# 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 --stdoutOutput formats
# 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 --highlightPDF connector selection
# 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
Metadata export
legal-md contract.md --export-yaml -o metadata.yaml
legal-md contract.md --export-json -o metadata.jsonUseful flags
legal-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 --stdoutProgrammatic API
import {
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);PDF Backends
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
Configuration 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 --pdfTesting
# 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
Documentation
- Getting Started
- CLI Reference
- Features Overview
- Output Guides
- PDF Generation
- DOCX Generation
- Configuration
- Architecture
- Development Guide
- Contributing
Contributing
See docs/development/contributing.md.
License
MIT. See LICENSE.
Acknowledgments
Based on the original LegalMarkdown project by Casey Kuhlman.
