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

@paperjsx/json-to-docx

v0.0.1

Published

Generate Word documents from JSON

Downloads

200

Readme

@paperjsx/json-to-docx

Generating Word documents from code typically means manipulating raw OOXML XML or using heavyweight browser-based PDF-to-DOCX converters. This package takes a JSON document schema and produces a native .docx binary — no DOM, no Puppeteer, no browser required.

npm CI

Install

npm install @paperjsx/json-to-docx

Requires Node.js >= 18.

Quick Start

import { renderToDocx } from "@paperjsx/json-to-docx";
import { writeFileSync } from "node:fs";

const result = await renderToDocx({
  type: "DocxDocument",
  pageSize: "a4",
  theme: { preset: "corporate" },
  pages: [
    {
      elements: [
        { type: "heading", level: 1, text: "Annual Performance Report" },
        {
          type: "paragraph",
          text: "Revenue grew 34% year-over-year, driven by enterprise expansion in North America and APAC.",
        },
        {
          type: "table",
          style: "striped",
          rows: [
            { isHeader: true, cells: [{ text: "Region" }, { text: "Revenue" }, { text: "Growth" }] },
            { cells: [{ text: "North America" }, { text: "$5.1M" }, { text: "+28%" }] },
            { cells: [{ text: "Europe" }, { text: "$3.6M" }, { text: "+16%" }] },
            { cells: [{ text: "APAC" }, { text: "$3.5M" }, { text: "+42%" }] },
            { cells: [{ text: "LATAM" }, { text: "$1.9M" }, { text: "+35%" }] },
          ],
        },
        {
          type: "chart",
          chartType: "bar",
          series: [
            { name: "2024", dataPoints: [4000, 3100, 2500, 1400] },
            { name: "2025", dataPoints: [5100, 3600, 3500, 1900] },
          ],
          categories: ["NA", "Europe", "APAC", "LATAM"],
        },
      ],
    },
  ],
});

writeFileSync("report.docx", result.buffer);
console.log(result.stats);
// { pages: 1, elements: 4, renderTimeMs: 120 }

How It Works

Input JSON is validated against a Zod schema, adapted to a structured document model, then serialized to OOXML XML and packaged as a .docx ZIP archive. Charts are rendered via the built-in PVCE engine. Optional peer dependencies enable PDF export (pdf-lib), image optimization (sharp), and font metrics (opentype.js).

Element Types

| Type | Description | Key Properties | | --- | --- | --- | | heading | Section headings (H1-H6) | level, text, bookmark, keepWithNext | | paragraph | Rich text blocks | text or runs[] (TextRun), indent, keepLines, pageBreakBefore | | list | Bulleted or numbered lists | style (bullet/number/letter/roman), items[], nested lists | | table | Data tables | rows[], columns[], style (striped/bordered/modern/minimal/corporate), headerRepeat, colSpan/rowSpan | | image | Inline or floating images | src (HTTPS or data URI), caption, float (square/tight/behind/inFront), alignment | | chart | Editable charts | chartType, series[], categories[], legend, axes, title | | shape | Vector shapes | shapeType (rectangle/ellipse/triangle/diamond/line/arrow), fill, stroke | | codeBlock | Source code blocks | code, language, lineNumbers | | divider | Horizontal rules | style (solid/dashed/dotted/double) | | pageBreak | Explicit page boundary | — | | container | Layout wrapper | layout (vertical/horizontal/grid), children[] |

API Reference

Core Functions

| Function | Parameters | Returns | Description | | --- | --- | --- | --- | | renderToDocx | (input, options?) | Promise<DocxResult> | Render JSON to DOCX binary | | hydrateDocx | (templateBuffer, data, options?) | Promise<DocxResult> | Fill placeholders in existing DOCX | | validateDocxDocument | (input) | ValidationResult | Validate input against schema | | scanForPlaceholders | (templateBuffer) | string[] | List {{placeholder}} tokens in a DOCX template |

DocxResult

{
  buffer: Buffer;        // The .docx file
  mimeType: string;      // "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
  extension: string;     // "docx"
  stats: RenderStats;    // { pages, elements, renderTimeMs }
  warnings: DocxWarning[];
}

Render Options

| Option | Type | Default | Description | | --- | --- | --- | --- | | theme | ThemeConfig \| { preset: ThemePresetName } | Default theme | Visual theme | | onProgress | (progress: RenderProgress) => void | — | Render progress callback | | signal | AbortSignal | — | Cancellation signal |

Themes

6 built-in theme presets control fonts, colors, heading styles, and table formatting:

| Preset | Heading Font | Body Font | Accent Color | Style | | --- | --- | --- | --- | --- | | corporate | Arial | Arial | #1B365D | Clean, professional | | modern | Helvetica Neue | Helvetica Neue | #2563EB | Minimal, contemporary | | academic | Times New Roman | Times New Roman | #1A1A1A | Formal, traditional | | classic | Georgia | Georgia | #4A5568 | Serif, elegant | | minimal | Inter | Inter | #000000 | Stark, no decoration | | dark | SF Pro Display | SF Pro Text | #60A5FA | Dark background, light text |

const result = await renderToDocx({
  type: "DocxDocument",
  theme: { preset: "modern" },
  pages: [/* ... */],
});

Custom themes override any preset field:

theme: {
  preset: "corporate",
  colors: { primary: "#7C3AED", accent: "#F59E0B" },
  fonts: { heading: "Montserrat", body: "Open Sans" },
}

Charts

8 chart types via the built-in PVCE (PaperJSX Visual Chart Engine):

| Type | Variants | Data Format | | --- | --- | --- | | bar | Clustered, stacked | categories[] + series[].dataPoints[] | | column | Clustered, stacked | Same as bar (vertical orientation) | | line | Standard, smooth | categories[] + series[].dataPoints[] | | area | Standard, stacked | categories[] + series[].dataPoints[] | | pie | Standard | categories[] + single series | | doughnut | Configurable hole size | categories[] + single series | | scatter | XY points | series[].dataPoints[].{x, y} | | radar | Standard, filled | categories[] + series[].dataPoints[] |

{
  type: "chart",
  chartType: "line",
  title: "Monthly Active Users",
  categories: ["Jan", "Feb", "Mar", "Apr", "May", "Jun"],
  series: [
    { name: "2024", dataPoints: [12000, 14500, 16200, 15800, 18000, 21000] },
    { name: "2025", dataPoints: [18000, 22000, 25000, 24500, 28000, 32000] },
  ],
  legend: { position: "bottom" },
  axes: {
    y: { title: "Users", numberFormat: "#,##0" },
  },
}

Template Hydration

Fill {{placeholder}} tokens in existing DOCX files:

import { hydrateDocx, scanForPlaceholders } from "@paperjsx/json-to-docx";
import { readFileSync } from "node:fs";

const template = readFileSync("contract-template.docx");

// Discover available placeholders
const placeholders = await scanForPlaceholders(template);
// ["client_name", "effective_date", "contract_value", "payment_terms"]

// Fill them
const result = await hydrateDocx(template, {
  client_name: "Acme Corporation",
  effective_date: "March 15, 2026",
  contract_value: "$240,000",
  payment_terms: "Net 30",
});

writeFileSync("contract-acme.docx", result.buffer);

Headers, Footers, and Sections

{
  type: "DocxDocument",
  headerFooter: {
    header: { text: "Confidential — Acme Corp" },
    footer: { text: "Page {{pageNumber}} of {{totalPages}}" },
  },
  pages: [
    {
      sectionBreak: "nextPage",  // "nextPage" | "continuous" | "evenPage" | "oddPage"
      elements: [/* ... */],
    },
  ],
}

Compliance Validation

Built-in validators for region-specific invoice requirements:

| Validator | Standard | Use Case | | --- | --- | --- | | validateIndiaGSTQR | India GST | QR code requirements for Indian tax invoices | | validateEUReverseCharge | EU VAT | Reverse charge notice for cross-border EU invoices | | validateBrazilianDanfe | Brazilian DANFE | Electronic invoice document formatting |

import { validateIndiaGSTQR } from "@paperjsx/json-to-docx";

const issues = validateIndiaGSTQR(invoiceData);
// [{ field: "gstin", message: "GSTIN must be 15 characters", severity: "error" }]

Secure PDF Export

Convert DOCX output to encrypted PDF (requires pdf-lib peer dependency):

import { SecurePDF } from "@paperjsx/json-to-docx";

const pdf = await SecurePDF.fromDocx(result.buffer, {
  userPassword: "reader-password",
  ownerPassword: "admin-password",
  permissions: { printing: true, copying: false, modifying: false },
});

writeFileSync("report-secured.pdf", pdf);

Peer Dependencies

| Package | Required | Purpose | | --- | --- | --- | | pdf-lib | Optional | PDF export via SecurePDF | | sharp | Optional | Image optimization and format conversion | | opentype.js | Optional | Advanced font metrics and glyph measurement |

Error Handling

import { DOCXError, isDOCXError } from "@paperjsx/json-to-docx";

try {
  await renderToDocx(input);
} catch (err) {
  if (isDOCXError(err)) {
    console.log(err.code);    // "VALIDATION_FAILED" | "RENDER_FAILED" | "MEDIA_FETCH_FAILED" | ...
    console.log(err.message); // Human-readable description
  }
}

Limitations

  • No browser runtime support. Node.js only.
  • Images referenced by URL are fetched at render time. Ensure URLs are accessible from the render environment.
  • Complex nested tables (4+ levels deep) may produce layout artifacts in some Word versions.
  • PDF export requires the optional pdf-lib peer dependency.

Documentation

paperjsx.com/docs

License

Proprietary. Requires a license key from paperjsx.com/pricing.