npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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

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
  • PDF
  • 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.

Legal Markdown JS Playground

Install

npm

Run without installing globally:

npx legal-md contract.md output.md

Install the package locally in a project:

npm install legal-markdown-js

Available binaries:

  • legal-md
  • legal-md-ui
  • legal-md-playground

Homebrew

Install the standalone macOS binary:

brew tap petalo/legal-markdown
brew install legal-md

After installing with Homebrew, you can use:

  • legal-md
  • legal-md ui
  • legal-md playground

Install script

curl -fsSL https://github.com/petalo/legal-markdown-js/releases/latest/download/install.sh | sh

Quick 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-md

2. Process a document

Convert a Legal Markdown file to processed Markdown:

legal-md contract.md output.md

Generate HTML, PDF, or DOCX:

legal-md contract.md --html
legal-md contract.md --pdf
legal-md contract.md --docx

l. 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 ui

Local playground

If you installed from npm or Homebrew:

legal-md-playground
# or
legal-md playground

If you are working from this repository:

npm run build:web
npm run web:serve

Useful 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

CLI 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 --stdout

Output 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 --highlight

PDF 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 weasyprint

auto resolution order is:

  1. puppeteer
  2. system-chrome
  3. weasyprint

Metadata export

legal-md contract.md --export-yaml -o metadata.yaml
legal-md contract.md --export-json -o metadata.json

Useful 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 --stdout

Programmatic 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:

  • puppeteer
  • system-chrome
  • weasyprint

Installation examples:

# Puppeteer browser install (if needed)
npx puppeteer browsers install chrome

# macOS
brew install weasyprint

# Ubuntu/Debian
sudo apt-get install -y weasyprint

Configuration

Configuration loading supports:

  • package.json (legalmd key)
  • .legalmdrc
  • .legalmdrc.yaml
  • .legalmdrc.json
  • legalmd.config.js
  • legalmd.config.ts

Useful env overrides:

  • LEGAL_MD_PDF_CONNECTOR
  • LEGAL_MD_VALIDATION_MODE
  • LOG_LEVEL
  • DEBUG
  • IMAGES_DIR
  • STYLES_DIR
  • DEFAULT_INPUT_DIR
  • DEFAULT_OUTPUT_DIR
  • ARCHIVE_DIR

Example:

LEGAL_MD_PDF_CONNECTOR=weasyprint legal-md input.md --pdf

Testing

# 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:cli

test:e2e and test:ci require both PDF paths to be available:

  • Puppeteer launchable Chrome/Chromium
  • WeasyPrint executable

Documentation

Contributing

See docs/development/contributing.md.

License

MIT. See LICENSE.

Acknowledgments

Based on the original LegalMarkdown project by Casey Kuhlman.