@infopack/pdf-creator-app
v0.3.0
Published
A service and library for turning infopack IRNs into PDFs or raw HTML. You can run the bundled Express server or import the library directly.
Readme
PDF Creator App
A service and library for turning infopack IRNs into PDFs or raw HTML. You can run the bundled Express server or import the library directly.
HTTP usage
- Provide an IRN as
GET /single?irn=<IRN>. - Infopack files must be
.partial.html.
Library usage
Import and use the expander and PDF helpers without starting the server:
import { InfopackCollectionExpander, createPdfFromCollection } from 'pdf-creator-app'
const expander = new InfopackCollectionExpander(collectionDefinition)
await expander.expand()
const expanded = expander.get()
// Render HTML (set raw:false to get a PDF buffer)
const html = await createPdfFromCollection(collectionDefinition, {
raw: true,
templateOverrides: {
paths: { collection: './my-templates/collection.template.html' }
}
})Diff customization
createPdfDiffFromCollections now supports diffOptions for controlling diff markers and class names while keeping current behavior as default.
Defaults:
context: 'infopack'deleted.prefix: '[- 'deleted.suffix: ' -]'deleted.className: 'infopack-strike'inserted.prefix: '{+ 'inserted.suffix: ' +}'inserted.className: 'infopack-ins'
Example with custom markers/classes:
import { createPdfDiffFromCollections } from 'pdf-creator-app'
const html = await createPdfDiffFromCollections([fromCollection, toCollection], {
raw: true,
diffOptions: {
context: 'infopack',
deleted: {
prefix: '[- ',
suffix: ' -]',
className: 'my-del'
},
inserted: {
prefix: '{+ ',
suffix: ' +}',
className: 'my-ins'
}
}
})Example with red deleted text and green inserted text:
import { createPdfDiffFromCollections } from 'pdf-creator-app'
const html = await createPdfDiffFromCollections([fromCollection, toCollection], {
raw: true,
diffOptions: {
deleted: {
className: 'diff-del-red'
},
inserted: {
className: 'diff-ins-green'
}
},
templateOverrides: {
collection: `
<html>
<head>
<style>
del, ins { text-decoration: none; }
.diff-del-red { color: #c62828; text-decoration: line-through; font-weight: 600; }
.diff-ins-green { color: #2e7d32; font-weight: 600; }
</style>
</head>
<body>
{{{ partials.groups }}}
{{{ partials.toc }}}
<div class="content">{{{ content }}}</div>
</body>
</html>
`
}
})createPdfFromCollection also accepts diffOptions in its options object for API consistency with diff rendering flows. In this release, it does not change normal (non-diff) collection rendering behavior.
Templates can be overridden by changing file paths (templateOverrides.paths) or by passing template strings/functions directly on templateOverrides.
Templates and their roles
standard: Wrapper for a single infopack file (createPdfFromIrn). Should include room for content and QR code ({{qrCode}}).collection: Outer HTML for a collection; receivestitle,name,version,toc,content.toc: Builds the table of contents for a collection (getsfilesfrom the expander).file: Renders each file in a collection (receives the full content object from the expander).header/footer: Raw HTML strings printed on every PDF page. These go straight to Puppeteer’sheaderTemplate/footerTemplate, so follow Puppeteer’s rules: use<span class="pageNumber"></span>and<span class="totalPages"></span>for page numbers, and keep the total height within Puppeteer’s header/footer limits. They are not compiled with Handlebars unless you do it yourself before passing in the string.
Data available inside each template
standard(single IRN): gets everything frominfopackUrlResolverplusqrCode. Typical fields:content(HTML),meta(from.meta.json),valid,notValid,messages,url,fetchedDate,classes(if set), andqrCode(data URI for registry link).collection: receives{ title, name, version, toc, content }wheretocandcontentare rendered strings produced by the templates below.toc: receives{ files }wherefilesis the array from the collection expander. Each file item can include:kind("infopack-file"or"html-file"),collectionPath,packagePath,filePath,irn(if an infopack file),url,fetchedDate,content(HTML ifreturnContentis true),meta,valid,notValid,messages, and optionalclasses.file: receives the same file item objects astoc, so you can access any of the fields above per file.header/footer: no data injection; treated as literal HTML passed to Puppeteer. If you need Handlebars data here, compile it yourself before passing the string.
Images and assets (e.g. logos)
When you add images in templates (including header/footer), use either:
- Absolute URLs reachable from the rendering environment (e.g.
https://.../logo.png), or - Inline data URIs (
<img src="data:image/png;base64,..." />) if you need to bundle the asset.
Relative paths will not resolve from page.setContent; prefer absolute URLs or data URIs for reliable rendering.
To inline local relative images in templates (e.g. logo in header/footer), set assetsBasePath so the library can convert <img src="./..."> into data URIs in templates. Content HTML is not inlined automatically:
await createPdfFromCollection(collectionDefinition, {
assetsBasePath: './assets', // only files under this dir will be read
templateOverrides: { /* ... */ }
})Supported formats for inlining: png, jpg, jpeg, gif, svg, webp. Files outside assetsBasePath are ignored; missing files are left unchanged.
Caching
- Enabled by default: fetched infopack content and metadata are cached under
.cache/infopack(git-ignored). - TTL: 24h for URLs/IRNs containing
latest; 90 days for all other versions. - Disable or customize via
cacheoptions:
// Disable cache
await createPdfFromIrn('ns:name:version:path', { cache: { enabled: false } })
// Custom cache dir/TTL via expander in collection rendering
await createPdfFromCollection(collectionDefinition, {
expanderOptions: {
cache: { dir: './tmp/cache', ttlMs: 7 * 24 * 60 * 60 * 1000 } // 7 days for non-latest
}
})
// Render cache (final HTML) can also be cached on disk (default .cache/render)
await createPdfFromCollection(collectionDefinition, {
renderCache: { enabled: true, dir: './.cache/render' }
})Cache keys
This library uses a cache key concept to map each fetched resource to a single file on disk:
- For infopack fetches, the cache key is the full URL. The cache file name is
sha1(url).json. - For render caching, the cache key is built from all HTML-affecting render inputs: collection, template overrides, render options, and output-affecting expander options. That key payload is hashed the same way.
- Render cache is an HTML-layer cache. It does not cache final PDF buffers.
verboseandpdfOptionsare excluded from the render cache key.pdfOptionsis applied in the PDF generation step after HTML is read from render cache.assetsBasePathis also excluded from the render cache key because it is only used for header/footer asset inlining in the PDF step.- The hash keeps filenames short and filesystem-safe; no plain URLs are used as filenames.
- Each cache file stores a small JSON object with metadata (version, fetchedAt, ttlMs, type) plus the body payload.
Default paths live in lib/templates.js (defaultTemplatePaths). You can repoint files or supply inline templates:
import { createPdfFromCollection, createPdfFromIrn } from 'pdf-creator-app'
// Point to custom files
await createPdfFromCollection(collectionDefinition, {
templateOverrides: {
paths: {
collection: './my-templates/collection.template.html',
file: './my-templates/file.template.html'
}
}
})
// Inline string/function (compiled with Handlebars); header/footer are raw strings
await createPdfFromCollection(collectionDefinition, {
raw: true,
templateOverrides: {
collection: '<html><body>{{{toc}}}{{{content}}}</body></html>',
header: '<span>My header</span>',
footer: '<span>My footer</span>'
}
})
// Single IRN with custom template
await createPdfFromIrn('namespace:name:version:path', {
templateOverrides: {
standard: '<html><body>{{{content}}} {{qrCode}}</body></html>'
}
})Build
docker build . -t registry.gitlab.com/infopack/pdf-creator-app:latest
docker push registry.gitlab.com/infopack/pdf-creator-app:latestInstallation
Docker
The app is packaged as a Docker image; releases are available here.
docker run --rm --name pdf-creator-app -p 9000:9000 registry.gitlab.com/infopack/pdf-creator-app:<latest version>Release
GitLab builds and publishes the image on every tag on main. Latest images are in the container registry linked above.
Helm
To update the Helm chart, ensure helm is installed and configured, then:
cd helm/pdf-creator-app
helm --namespace infopack-pdf-creator-app upgrade pdf-creator-app .