Skip to content
LpdfDocsv0.24-r1004.10

Lpdf is pre-release. The XML schema and SDK APIs can change between releases.

Installation

Lpdf generates PDF from XML, or from code that builds the same document. One engine runs in every SDK, so the output is identical on every platform. It is compiled to WebAssembly for Node.js and the browser, and to a WASI binary for PHP, Python, and .NET.

The examples in these docs are XML, and they work in every language: pass the XML to render, as under Create PDF below. Most examples also show the same document built in code, in a tab for each language, as under Create PDF with code. The builders are the same in every language: the same elements, the same attributes under the schema’s names, and the same constants, written in each language’s own case (fontSize in Node.js and PHP, font_size in Python, FontSize in .NET).

  • Node.js 20 or later
  • No external runtime dependencies — the WASM engine is bundled in the package
Terminal window
npm install @lpdfio/lpdf
const { L } = require('@lpdfio/lpdf')
const { writeFileSync } = require('node:fs')
const xml = `<lpdf version="1">
<document size="a4" margin="48pt">
<section>
<layout>
<stack gap="m">
<text font-size="xl">Hello, world</text>
<text>This PDF was made with Lpdf.</text>
</stack>
</layout>
</section>
</document>
</lpdf>`
const engine = L.engine()
engine.render(xml).then((pdf) => writeFileSync('hello.pdf', pdf))

render returns a promise. The package is CommonJS, so load it with require: an import of @lpdfio/lpdf fails with ERR_PACKAGE_PATH_NOT_EXPORTED. To render a file, read it into a string and pass that to render.

The same document, built with L instead of written as XML. render takes either one and makes the same PDF.

const { L, NoAttr } = require('@lpdfio/lpdf')
const { writeFileSync } = require('node:fs')
const doc = L.document({ size: 'a4', margin: '48pt' }, [
L.section(NoAttr, [
L.layout(NoAttr, [
L.stack({ gap: 'm' }, [
L.text({ fontSize: 'xl' }, ['Hello, world']),
L.text(NoAttr, ['This PDF was made with Lpdf.']),
]),
]),
]),
])
const engine = L.engine()
engine.render(doc).then((pdf) => writeFileSync('hello.pdf', pdf))

The first two numbers are the Lpdf engine, and the last number counts changes to this package only. 0.22.3 runs engine 0.22. Every engine release publishes all SDKs at X.Y.0, so the same X.Y means the same engine in every language. To stay on one engine and still get package fixes, use a tilde range in package.json:

"@lpdfio/lpdf": "~0.22.0"

An image or a font that comes from a file is declared in assets with a src path. The SDK reads the file from the machine that renders the PDF, so a relative path is relative to the working directory. The engine does not fetch URLs or read data URIs. An image file the SDK cannot read is an error, and a font file it cannot read falls back to Helvetica without one. To supply the bytes yourself, call loadImage(name, bytes) or loadFont(name, bytes) on the engine and leave src out.

Asset names use lowercase letters, digits, and -, and start with a letter: logo, serif-bold.