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

invoml

v1.0.0-alpha.5

Published

InvoML — Invoice Markup Language: parse, validate, calculate

Downloads

21

Readme

InvoML — Invoice Markup Language

A specification for AI-generated invoice documents. Deterministic math, human-readable format, international tax coverage.

npm version license CI TypeScript test vectors

InvoML is a format specification for invoice documents designed from the ground up for AI structured output and human authoring. invoml is the official TypeScript reference implementation.


The Problem

Every time an AI model generates an invoice today, it faces the same dilemma: which format?

Traditional business document formats were designed for enterprise systems, not AI. They use verbose XML with deeply nested structures — a simple invoice can require hundreds of tokens of boilerplate before the first data field appears. They handle data exchange between machines but leave human presentation entirely to the renderer — with no way for the document to carry visual intent.

The same invoice in InvoML:

{
  "$invoml": "1.0",
  "meta": { "documentType": "invoice", "number": "INV-2026-0001",
            "issueDate": "2026-03-28", "currency": "USD",
            "tax": { "label": "Tax", "rate": 10 } },
  "from": { "name": "Acme Corp", "content": "**Acme Corp**\n123 Main St" },
  "to":   { "name": "Client LLC" },
  "items": [
    { "description": "Consulting", "quantity": 10, "unitPrice": 200.00 }
  ]
}

Ad-hoc JSON doesn't solve it either: totals are pre-calculated by the model (floating-point errors, hallucinated numbers), there is no validation contract, and renderers must guess at structure.

InvoML solves all three problems. It is compact enough for token-sensitive LLM calls, carries a JSON Schema for structured output APIs, and defines deterministic calculation rules that guarantee byte-identical totals across every runtime and language.


How It Works

┌─────────────────────┐      ┌──────────────────────┐      ┌─────────────────────┐
│                     │      │                       │      │                     │
│   AI generates      │ ───▶ │  Runtime calculates   │ ───▶ │  Renderer displays  │
│   InvoML document   │      │  all arithmetic       │      │  the final invoice  │
│                     │      │                       │      │                     │
│  data only, no      │      │  arbitrary-precision  │      │  PDF, HTML, email,  │
│  pre-computed sums  │      │  decimal math         │      │  Markdown, any UI   │
│                     │      │                       │      │                     │
└─────────────────────┘      └──────────────────────┘      └─────────────────────┘

The spec separates three responsibilities that every other format conflates:

  1. Data — what the invoice says (items, parties, tax rates, discounts)
  2. Math — deterministic rules the runtime always executes (subtotals, rounding, tax cascades)
  3. Presentation — how it looks. The optional style field carries visual intent: block ordering, named templates, CSS-compatible properties. Compact enough for AI to include (18–60 tokens), expressive enough for real invoices.

AI models only produce layer 1. The runtime owns layer 2. Renderers own layer 3.


Quick Example

A minimal invoice with a single line and 10% VAT:

{
  "$invoml": "1.0",
  "meta": {
    "documentType": "invoice",
    "number": "INV-001",
    "issueDate": "2026-03-28",
    "currency": "EUR",
    "tax": { "label": "VAT", "rate": 10 }
  },
  "from": { "name": "Studio Craft", "content": "**Studio Craft**\nBerlin, Germany" },
  "to":   { "name": "Client GmbH",  "content": "**Client GmbH**\nMunich, Germany" },
  "items": [
    { "description": "Logo Design", "quantity": 1, "unitPrice": 1200.00 }
  ]
}

The runtime calculates:

| Field | Value | |--------------|-----------| | Subtotal | €1,200.00 | | VAT (10%) | €120.00 | | Total | €1,320.00 |

Numbers are computed from spec rules, never guessed by the model.

With visual intent

The same invoice, with the AI expressing how it should look:

{
  "$invoml": "1.0",
  "meta": {
    "documentType": "invoice",
    "number": "INV-001",
    "issueDate": "2026-03-28",
    "currency": "EUR",
    "tax": { "label": "VAT", "rate": 10 }
  },
  "from": { "content": "**Studio Craft**\nBerlin, Germany" },
  "to":   { "content": "**Client GmbH**\nMunich, Germany" },
  "items": [
    { "description": "Logo Design", "quantity": 1, "unitPrice": 1200.00 }
  ],
  "style": {
    "template": "modern",
    "properties": { "--accent": "#e63946", "font-family": "Georgia, serif" },
    "blocks": {
      "header": { "text-align": "center", "border-bottom": "2px solid #e63946" }
    }
  }
}

The style object adds ~30 tokens. The renderer uses it to produce a visually distinct document — centered header, serif font, red accent — while the math and data remain unchanged. Without style, the renderer applies its own defaults. This is optional: most invoices don't need it.


Reference Implementation

invoml is the official TypeScript implementation of the InvoML v1.0 specification.

npm install invoml

Parse and validate

import { parse, calculate, toMarkdown } from 'invoml'

const result = parse(jsonString)
if (!result.success) {
  console.error(result.errors)
  process.exit(1)
}

Calculate totals

const totals = calculate(result.document)

console.log(totals.subtotal)   // 1200
console.log(totals.taxTotal)   // 120
console.log(totals.total)      // 1320
console.log(totals.amountDue)  // 1320

All arithmetic uses arbitrary-precision decimal math (decimal.js). No floating-point rounding errors. Results are byte-identical across Node.js versions and operating systems.

Render to Markdown

// Attach totals to the document, then render
const doc = { ...result.document, totals }
const md = toMarkdown(doc)
// Ready for chat interfaces, email previews, plain-text pipelines

API surface

| Function | Description | |---|---| | parse(json) | Parse and type-validate a JSON string into InvoMLDocument | | calculate(doc) | Compute all totals with arbitrary-precision math | | validateSchema(value) | Validate against the JSON Schema (useful before parse) | | toJSON(doc, options?) | Serialize to JSON. Pass { compact: true } for minified output | | toMarkdown(doc) | Render as a human-readable Markdown table (reads doc.totals) | | toHTML(doc) | Render as a self-contained HTML document | | validateStyle(style, sectionNames?) | Validate a style object against normative rules | | resolveOrder(doc) | Resolve effective block rendering order for a document | | resolveStyle(doc) | Resolve the full style object with defaults applied |


Ecosystem

JSON Schema for LLM structured output

The InvoML v1.0 JSON Schema is at invoml-v1.0.schema.json. Pass it directly to any LLM structured-output API:

import schema from 'invoml/invoml-v1.0.schema.json' assert { type: 'json' }

// OpenAI structured outputs
const completion = await openai.beta.chat.completions.parse({
  model: 'gpt-4o',
  response_format: { type: 'json_schema', json_schema: { schema } },
  messages: [{ role: 'user', content: 'Generate an invoice for ...' }]
})

// Anthropic tool use
const message = await anthropic.messages.create({
  tools: [{ name: 'generate_invoice', input_schema: schema }],
  // ...
})

CLI

# Validate a document against the spec
npx invoml validate invoice.json

# Calculate and print totals
npx invoml calculate invoice.json

# Serialize to canonical JSON with computed totals
npx invoml serialize invoice.json

# Render as a self-contained HTML file
npx invoml html invoice.json > invoice.html

Test vectors for conformance

The test-vectors/ directory contains 18 canonical input/expected pairs. Any implementation claiming InvoML v1.0 conformance must pass all 18 vectors.

| # | Scenario | |---|---| | 01 | Minimal invoice (no tax) | | 02 | Basic VAT | | 03 | Multi-rate EU VAT | | 04 | Invoice-level proportional discount | | 05 | Line-level discounts | | 06 | Cascading discounts | | 07 | Compound tax (Canada GST + PST) | | 08 | Inclusive tax (Australia GST) | | 09 | Reverse charge (zero-rate VAT) | | 10 | Withholding tax | | 11 | Rounding edge case | | 12 | Zero subtotal | | 13 | Credit note | | 14 | Inclusive tax with invoice-level discount | | 15 | Compound withholding | | 16 | Error — unknown tax category | | 17 | Error — no default tax | | 18 | Proportional discount tie-breaking |


International Coverage

InvoML covers 15+ countries out of the box. The examples/ directory contains real-world documents for:

Tax models supported:

  • Flat-rate VAT/GST (UK, EU, UAE, Switzerland, New Zealand, Australia)
  • Multi-rate VAT (EU — standard 19%/7%, zero-rate, exempt within the same document)
  • Compound taxes (Canada — GST + PST calculated on different bases)
  • Inclusive taxes (Australia GST — tax embedded in the listed price)
  • Reverse charge (EU cross-border — tax shifts to buyer)
  • Withholding taxes (Nigeria, Mexico — issuer reports, buyer remits)
  • CFDI-compatible (Mexico IVA with SAT registration fields)
  • ZUGFeRD-compatible field coverage (Germany)
  • IGST/CGST/SGST model (India)
  • Consumption tax (Japan 10%)

Document types: invoices, quotes, estimates, receipts, credit notes


For AI Developers

Building an invoice generation feature? See docs/LLM-INTEGRATION.md for:

  • How to pass the InvoML schema to structured output APIs (OpenAI, Anthropic, Google)
  • System prompt patterns that produce valid InvoML reliably
  • How to validate AI output before calling calculate
  • Handling edge cases: unknown tax categories, missing currency symbols, model hallucinations

Specification

The InvoML v1.0 specification (currently Draft) lives in SPEC.md. It defines:

  • Document structure and required fields
  • Tax resolution rules (simple, full, compound, inclusive, withholding, reverse charge)
  • Discount application order (line-level before invoice-level, proportional allocation)
  • Rounding rules (half-up, currency-precision)
  • Style model: block ordering, named templates, freeform CSS-compatible properties
  • Conformance requirements for independent implementations

The invoml reference implementation is normative for any case where the spec text is ambiguous. If invoml and SPEC.md disagree, file an issue — both will be corrected.


Why InvoML?

Existing invoice standards were built for enterprise systems — they handle data exchange between machines but say nothing about how the document should look. Ad-hoc JSON handles neither reliably. InvoML covers the full pipeline: AI generates structured data with optional visual intent, the runtime computes deterministic totals, and renderers produce polished output for humans.

See docs/WHY-INVOML.md for a detailed comparison with UBL, ad-hoc JSON, and platform-specific formats.


Contributing

See CONTRIBUTING.md for development setup, test vector authoring, and the pull request process.

Implementations in other languages are welcome. Any implementation that passes all 18 test vectors and implements the arithmetic rules in SPEC.md is a conforming InvoML v1.0 implementation.


License

Apache-2.0 — see LICENSE