@paperjsx/json-to-pptx
v0.0.1
Published
Generate PowerPoint files from JSON
Maintainers
Readme
@paperjsx/json-to-pptx
Generating PowerPoint files programmatically means choosing between low-fidelity wrappers that embed static images and complex OOXML manipulation that breaks across Office versions. This package takes a JSON document tree and produces a valid .pptx with natively editable charts, Yoga flexbox layout, and OpenType text shaping.
Install
npm install @paperjsx/json-to-pptxRequires Node.js >= 18.
Quick Start
import { PaperEngine } from "@paperjsx/json-to-pptx";
import { writeFileSync } from "node:fs";
const doc = {
type: "Document",
meta: { title: "Q4 2025 Revenue Summary", author: "Finance Team" },
slides: [
{
type: "Slide",
style: { padding: 40 },
children: [
{
type: "Text",
content: "Q4 Revenue by Region",
style: { fontSize: 36, fontWeight: "bold", color: "#1E293B" },
},
{
type: "Chart",
style: { width: 800, height: 400, marginTop: 30 },
chartData: {
chartType: "bar",
barGrouping: "clustered",
categories: ["North America", "Europe", "APAC", "LATAM"],
series: [
{ name: "2024", values: [4200, 3100, 2800, 1400] },
{ name: "2025", values: [5100, 3600, 3500, 1900] },
],
legend: { position: "bottom" },
dataLabels: { showVal: true },
},
},
],
},
],
};
const buffer = await PaperEngine.render(doc);
writeFileSync("report.pptx", buffer);Output opens in PowerPoint, Google Slides, and Keynote. Charts are backed by embedded Excel data — recipients can edit values, change chart types, and reformat without any special software.
How It Works
The rendering pipeline: JSON AST passes through Zod schema validation, then Yoga WASM computes flexbox layout for every node, HarfBuzz WASM handles OpenType text shaping with Knuth-Plass line breaking, and the OOXML serializer produces spec-compliant XML. The final step packs everything into a ZIP archive (the .pptx format). Two WASM binaries ship with the package (yoga-wasm-web for layout, harfbuzzjs for typography).
Features
| Category | Details |
| --- | --- |
| Charts | 15 types: bar, line, pie, scatter, bubble, area, doughnut, radar, waterfall, stock, funnel, treemap, sunburst, histogram, box-whisker. All natively editable with embedded Excel data. Supports clustered, stacked, and percent-stacked grouping. Trendlines, error bars, dual-axis combo charts, data tables. |
| Shapes | 140+ ECMA-376 shape presets across 10 families: basic (rect, ellipse, triangle), arrows (20+), flowchart (26), callouts (15), stars, math, brackets, connectors, tabs, and custom geometry paths. |
| Layout | Yoga flexbox: flexDirection, justifyContent, alignItems, flexWrap, gap, padding, margin, position (relative/absolute), aspectRatio, min/max dimensions. Percentage and pixel units. |
| Typography | HarfBuzz OpenType shaping with Knuth-Plass line breaking. Custom font loading, auto-fit text sizing, text columns (1-16), 30+ text warp presets, RTL support, superscript/subscript, kerning. |
| Templates | Load .potx template files. Multi-master slide support, layout references, theme resolution with scheme color modifiers (tint, shade, lumMod, satMod). |
| AI Agents | Semantic interpreter compiles simplified AgentDocument JSON (designed for LLM output) into the full AST. 6 slide layout patterns, elastic pagination for long content. |
| Diagrams | 6 SmartArt-style generators: process, hierarchy, cycle, matrix, pyramid, list. Input data array, get back positioned shapes. |
| Quality | Quality reports with editability scoring (0-100), structural OOXML validation, PPTX repair, desktop PowerPoint oracle validation (optional). |
| Media | Images (base64, HTTPS, SVG), video, audio. Crop, border-radius, image effects (brightness, contrast, grayscale, duotone, blur). |
| Animations | 20+ entrance/exit/emphasis effects. Triggers: onClick, withPrevious, afterPrevious. Motion paths, build-by-paragraph. 11 slide transition types. |
| Other | Speaker notes, slide comments, header/footer, document protection, custom properties, section grouping, print settings. |
API Reference
PaperEngine
| Method | Parameters | Returns | Description |
| --- | --- | --- | --- |
| render | (doc, options?) | Promise<Buffer> | Render document to PPTX binary |
| renderStream | (doc, options?) | Promise<Readable> | Render to Node.js readable stream |
| renderWithQualityReport | (doc, previewOpts?, options?) | Promise<RenderResult> | PPTX buffer + quality analysis |
| renderWithPreviews | (doc, previewOpts?, options?) | Promise<PreviewResult> | PPTX + PNG slide previews + layout trees |
| preflight | (doc, options?) | Promise<QualityReport> | Validate without rendering (dry run) |
| validate | (buffer) | Promise<ValidationResult> | Validate existing PPTX structure |
| repair | (buffer) | Promise<Buffer> | Repair PPTX structural issues |
| validateAndRepair | (buffer) | Promise<RepairResult> | Validate then repair |
Render Options
| Option | Type | Default | Description |
| --- | --- | --- | --- |
| outputMode | "strict_editable" \| "editable_preferred" \| "visual_safe" | "editable_preferred" | Chart editability strategy |
| validationMode | "none" \| "structural" \| "desktop_async" \| "desktop_blocking" | "none" | Post-render validation level |
| repairMode | "none" \| "structural" | "none" | Auto-repair after render |
| signal | AbortSignal | — | Cancellation signal |
| onProgress | (slideIndex, total) => void | — | Per-slide progress callback |
Sub-path Exports
| Import Path | Provides | Use Case |
| --- | --- | --- |
| @paperjsx/json-to-pptx | PaperEngine, createEngine, all types | Standard usage |
| @paperjsx/json-to-pptx/engine | Engine types and methods | Engine-level customization |
| @paperjsx/json-to-pptx/interpreter | AgentDocumentSchema, compileAgentDocument, layout builders | AI agent integration |
| @paperjsx/json-to-pptx/validator | PaperDocumentSchema, PaperSlideSchema, PaperNodeSchema | Input validation |
| @paperjsx/json-to-pptx/quality | buildQualityReport, validatePptxStructure, repairPptxStructure | Quality control pipelines |
| @paperjsx/json-to-pptx/renderer | renderSlideToBuffer, renderAllSlidesToBuffers | PNG preview generation (requires @napi-rs/canvas) |
| @paperjsx/json-to-pptx/slides | PresentationSpecSchema, compilePresentationSpec, slide type schemas | Presentation spec compilation |
Semantic Interpreter (AI Agents)
The interpreter converts a simplified, LLM-friendly JSON format into the full PaperDocument AST. AI agents produce AgentDocument JSON; the compiler handles layout, styling, and chart data mapping.
import { compileAgentDocument } from "@paperjsx/json-to-pptx/interpreter";
import { PaperEngine } from "@paperjsx/json-to-pptx";
const agentDoc = {
version: "1.0",
presentationTitle: "Series B Board Update",
companyName: "Acme Corp",
accentColor: "#2563EB",
slides: [
{
pattern: "title",
content: { title: "Series B Board Update", subtitle: "Q4 2025" },
},
{
pattern: "dashboard",
content: {
title: "Key Metrics",
kpis: [
{ label: "ARR", value: "$12.4M", trend: "up", sublabel: "+34% YoY" },
{ label: "NDR", value: "118%", trend: "up" },
{ label: "Burn Multiple", value: "1.2x", trend: "down" },
],
},
},
{
pattern: "chart-focus",
content: {
title: "Revenue Growth",
chart: {
type: "line",
series: [
{ name: "Revenue", dataPoints: [2.1, 2.8, 3.4, 4.1] },
],
},
},
},
],
};
const paperDoc = compileAgentDocument(agentDoc);
const buffer = await PaperEngine.render(paperDoc);Slide Patterns
| Pattern | Layout | Best For |
| --- | --- | --- |
| title | Centered title + subtitle | Opening and section dividers |
| statement | Large statement text + supporting prose | Key takeaways |
| dashboard | KPI cards in a grid | Metrics overview |
| comparison | Side-by-side columns | Before/after, pros/cons |
| chart-focus | Full-width chart + optional title | Data-driven slides |
| bullets | Title + bullet points | Lists, agendas, summaries |
Examples
Table with Merged Cells
const slide = {
type: "Slide",
children: [
{
type: "Table",
style: { width: 800, marginTop: 40 },
tableData: {
columns: [200, 200, 200, 200],
rows: [
{
height: 40,
cells: [
{ text: "Region", style: { fontWeight: "bold", backgroundColor: "#1E293B", color: "#FFFFFF" } },
{ text: "Q1", style: { fontWeight: "bold", backgroundColor: "#1E293B", color: "#FFFFFF" } },
{ text: "Q2", style: { fontWeight: "bold", backgroundColor: "#1E293B", color: "#FFFFFF" } },
{ text: "Q3", style: { fontWeight: "bold", backgroundColor: "#1E293B", color: "#FFFFFF" } },
],
},
{
cells: [
{ text: "North America" },
{ text: "$4.2M" },
{ text: "$4.8M" },
{ text: "$5.1M" },
],
},
],
},
},
],
};Quality Report
import { PaperEngine } from "@paperjsx/json-to-pptx";
const result = await PaperEngine.renderWithQualityReport(doc);
console.log(result.qualityReport.documentVerdict);
// "native_editable" | "editable_with_constraints" | "visual_fallback" | "rejected"
console.log(result.qualityReport.editabilityScore); // 0-100
console.log(result.qualityReport.findings);
// [{ code: "CHART_FALLBACK", severity: "warning", message: "...", slideIndex: 2 }]
writeFileSync("output.pptx", result.buffer);Canvas Preview (PNG)
import { renderSlideToBuffer } from "@paperjsx/json-to-pptx/renderer";
// Requires: npm install @napi-rs/canvas
const png = await renderSlideToBuffer(doc.slides[0], {
width: 1920,
height: 1080,
scale: 2, // 2x DPI
});
writeFileSync("preview.png", png);Diagrams
import { generateDiagram } from "@paperjsx/json-to-pptx";
const orgChart = generateDiagram({
type: "hierarchy",
items: [
{ label: "CEO", children: [
{ label: "CTO", children: [{ label: "Engineering" }, { label: "DevOps" }] },
{ label: "CFO", children: [{ label: "Finance" }, { label: "Legal" }] },
]},
],
});
// orgChart is a PaperGroup node — add it to a slide's children arrayPeer Dependencies
| Package | Required | Purpose |
| --- | --- | --- |
| @napi-rs/canvas | Optional | PNG preview rendering via ./renderer sub-path |
| echarts | Optional | Advanced chart rendering |
Error Handling
All errors are PaperError instances with structured fields:
import { PaperError } from "@paperjsx/json-to-pptx";
try {
await PaperEngine.render(doc);
} catch (err) {
if (err instanceof PaperError) {
console.log(err.code); // "VALIDATION_FAILED" | "FONT_NOT_FOUND" | "RENDER_CANCELLED" | ...
console.log(err.phase); // "validation" | "layout" | "typography" | "serialization" | ...
console.log(err.slideIndex); // which slide failed (if applicable)
}
}17 error codes across 9 phases. See the documentation for the full reference.
Limitations
- Single-threaded render mutex: one render at a time per process. Use worker threads or separate processes for parallelism.
- WASM cold-start on first render (~50-100ms). Subsequent renders are faster.
- Node.js only. No browser runtime support.
- Font files must be available at render time for custom fonts. Use
loadFont()to register them.
Documentation
License
Proprietary. Requires a license key from paperjsx.com/pricing. Free trial keys available. Output is watermarked without a valid key.
For the open-source version, see @paperjsx/json-to-pptx-lite.
