@lupinum/nuxt-pdf 0.4.0-beta.4 → 0.4.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/CONFORMANCE.md +4 -4
- package/README.md +54 -12
- package/dist/agent/AGENTS.md +44 -0
- package/dist/agent/pages/docs/examples/supported-behavior.md +75 -0
- package/dist/agent/pages/docs/examples.md +163 -0
- package/dist/agent/pages/docs/getting-started/installation.md +75 -0
- package/dist/agent/pages/docs/getting-started/quickstart.md +126 -0
- package/dist/agent/pages/docs/getting-started.md +63 -0
- package/dist/agent/pages/docs/guides/contents-links-bookmarks.md +123 -0
- package/dist/agent/pages/docs/guides/deployment.md +118 -0
- package/dist/agent/pages/docs/guides/errors-and-debugging.md +90 -0
- package/dist/agent/pages/docs/guides/images-and-fonts.md +102 -0
- package/dist/agent/pages/docs/guides/recipes.md +258 -0
- package/dist/agent/pages/docs/guides/remote-images.md +72 -0
- package/dist/agent/pages/docs/guides/reusable-components.md +81 -0
- package/dist/agent/pages/docs/guides/standalone-node.md +107 -0
- package/dist/agent/pages/docs/guides/svg-graphics.md +165 -0
- package/dist/agent/pages/docs/guides/testing.md +119 -0
- package/dist/agent/pages/docs/learn/document-tree.md +91 -0
- package/dist/agent/pages/docs/learn/runtime-and-data.md +63 -0
- package/dist/agent/pages/docs/learn/styling-and-layout.md +79 -0
- package/dist/agent/pages/docs/learn/templates-and-registry.md +96 -0
- package/dist/agent/pages/docs/reference/composables.md +55 -0
- package/dist/agent/pages/docs/reference/define-pdf.md +96 -0
- package/dist/agent/pages/docs/reference/errors-and-limits.md +89 -0
- package/dist/agent/pages/docs/reference/module-options.md +104 -0
- package/dist/agent/pages/docs/reference/page-sizes.md +54 -0
- package/dist/agent/pages/docs/reference/primitives.md +216 -0
- package/dist/agent/pages/docs/reference/registry.md +185 -0
- package/dist/agent/pages/docs/reference/standalone.md +53 -0
- package/dist/agent/pages/docs/reference/styles.md +176 -0
- package/dist/agent/pages/docs/reference/test-utilities.md +128 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +1 -1
- package/dist/test.mjs +13 -1
- package/package.json +27 -48
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,24 @@ All notable changes to `@lupinum/nuxt-pdf` are recorded here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project adheres
|
|
5
5
|
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## 0.4.0-beta.6
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- [#68](https://github.com/lupinum-dev/nuxt-pdf/pull/68) [`11d711a`](https://github.com/lupinum-dev/nuxt-pdf/commit/11d711ac83c69d3f468fb7983a15075398fa100e) Thanks [@Mat4m0](https://github.com/Mat4m0)! - Fix `renderPdfSfc()` to use the fonts from the application's Nuxt configuration, including inherited layers, when the test passes no `fonts` option.
|
|
12
|
+
|
|
13
|
+
## 0.4.0-beta.5
|
|
14
|
+
|
|
15
|
+
[compare changes](https://github.com/lupinum-dev/nuxt-pdf/compare/v0.4.0-beta.4...0.4.0-beta.5)
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **docs:** Ship versioned package guidance ([ca81a32](https://github.com/lupinum-dev/nuxt-pdf/commit/ca81a32))
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- **deps:** Clear workspace advisories and update Vitest ([#59](https://github.com/lupinum-dev/nuxt-pdf/pull/59))
|
|
24
|
+
|
|
7
25
|
## 0.4.0-beta.4
|
|
8
26
|
|
|
9
27
|
[compare changes](https://github.com/lupinum-dev/nuxt-pdf/compare/v0.4.0-beta.3...0.4.0-beta.4)
|
package/CONFORMANCE.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# Nuxt PDF
|
|
1
|
+
# Nuxt PDF conformance
|
|
2
2
|
|
|
3
3
|
Nuxt PDF claims behavioral compatibility for a deliberately small, tested
|
|
4
4
|
corpus. It does not claim full React PDF API or test-suite compatibility.
|
|
5
5
|
|
|
6
6
|
## Version boundary
|
|
7
7
|
|
|
8
|
-
| Layer |
|
|
8
|
+
| Layer | Tested boundary |
|
|
9
9
|
|---|---|
|
|
10
10
|
| Node.js | `^22.14.0`, `^24.0.0`, or `^26.0.0` |
|
|
11
11
|
| Nuxt | `^4.4.8` |
|
|
@@ -217,7 +217,7 @@ checking.
|
|
|
217
217
|
|
|
218
218
|
### Vue and Nuxt authoring
|
|
219
219
|
|
|
220
|
-
The
|
|
220
|
+
The tests verify:
|
|
221
221
|
|
|
222
222
|
- `PdfDocument`, `PdfPage`, `PdfView`, `PdfText`, `PdfImage`, `PdfLink`, and
|
|
223
223
|
`PdfNote`;
|
|
@@ -456,7 +456,7 @@ parser, not two. Claimed:
|
|
|
456
456
|
Verified end-to-end against a real rendered template, including assertion
|
|
457
457
|
failure messages, in `test/test-utils-public.test.ts`.
|
|
458
458
|
|
|
459
|
-
## Explicitly not claimed
|
|
459
|
+
## Explicitly not claimed
|
|
460
460
|
|
|
461
461
|
- Full React PDF component, hook, browser-helper, or test-suite parity.
|
|
462
462
|
- React runtime compatibility or React-shaped dynamic callback results.
|
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
<a href="https://www.npmjs.com/package/@lupinum/nuxt-pdf"><img src="https://img.shields.io/npm/v/@lupinum/nuxt-pdf?color=00DC82" alt="npm version"></a>
|
|
23
23
|
<a href="https://github.com/lupinum-dev/nuxt-pdf/actions/workflows/ci.yml"><img src="https://github.com/lupinum-dev/nuxt-pdf/actions/workflows/ci.yml/badge.svg" alt="CI status"></a>
|
|
24
24
|
<a href="./LICENSE"><img src="https://img.shields.io/badge/license-MIT-00DC82" alt="MIT license"></a>
|
|
25
|
-
<a href="https://discord.
|
|
25
|
+
<a href="https://discord.lupinum.com"><img src="https://img.shields.io/badge/Discord-18181B?logo=discord" alt="Discord"></a>
|
|
26
26
|
<a href="https://deepwiki.com/lupinum-dev/nuxt-pdf"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
|
|
27
27
|
</p>
|
|
28
28
|
|
|
@@ -158,13 +158,58 @@ Nuxt PDF regenerates the typed `#pdf` registry whenever templates change. If
|
|
|
158
158
|
your editor still shows `#pdf` as untyped, run `nuxt prepare` once to refresh
|
|
159
159
|
the generated types.
|
|
160
160
|
|
|
161
|
+
## Agent setup
|
|
162
|
+
|
|
163
|
+
`@lupinum/nuxt-pdf` ships its documentation inside the package for coding
|
|
164
|
+
agents such as Claude Code, Codex and Cursor. The pages match the installed
|
|
165
|
+
version, so an agent does not follow the website for a different version.
|
|
166
|
+
|
|
167
|
+
To set it up, give your coding agent this task:
|
|
168
|
+
|
|
169
|
+
```text
|
|
170
|
+
Set up @lupinum/nuxt-pdf for coding agents as described under "Agent setup" in its README.
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Steps for the agent
|
|
174
|
+
|
|
175
|
+
1. Find `node_modules/@lupinum/nuxt-pdf/dist/agent/AGENTS.md`. Look in the
|
|
176
|
+
directory of the project that depends on `@lupinum/nuxt-pdf` first, then
|
|
177
|
+
in its parent directories up to the repository root (workspaces can hoist
|
|
178
|
+
packages). Read it; it lists the documentation pages.
|
|
179
|
+
2. Add the section below to the project's agent instructions: `AGENTS.md`, or
|
|
180
|
+
`CLAUDE.md` if the project has only that file. If it has neither, create
|
|
181
|
+
`AGENTS.md`. Write the path relative to the repository root, through
|
|
182
|
+
`node_modules/@lupinum/nuxt-pdf` (for example
|
|
183
|
+
`apps/web/node_modules/@lupinum/nuxt-pdf/...` in a workspace). Never write
|
|
184
|
+
a resolved path such as `node_modules/.pnpm/...`: it contains the version and
|
|
185
|
+
breaks after an upgrade. If a section for `@lupinum/nuxt-pdf` already
|
|
186
|
+
exists, leave it as it is.
|
|
187
|
+
|
|
188
|
+
Use the path you found in place of the sample path:
|
|
189
|
+
|
|
190
|
+
```md
|
|
191
|
+
## @lupinum/nuxt-pdf
|
|
192
|
+
|
|
193
|
+
Before you change code that uses @lupinum/nuxt-pdf, read
|
|
194
|
+
`node_modules/@lupinum/nuxt-pdf/dist/agent/AGENTS.md` and the pages it
|
|
195
|
+
lists. They document the installed version. Prefer them over what you
|
|
196
|
+
remember about this package and over the website.
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
3. Do not copy the documentation into the project and do not install a skill.
|
|
200
|
+
The section points into the installed package, so it stays correct after
|
|
201
|
+
every upgrade or downgrade.
|
|
202
|
+
|
|
203
|
+
If the file does not exist, the installed version has no packaged
|
|
204
|
+
documentation. Read the package README and its TypeScript types instead.
|
|
205
|
+
|
|
161
206
|
## Discord
|
|
162
207
|
|
|
163
208
|
Join the Lupinum OSS community to discuss Nuxt PDF, ask questions, and share
|
|
164
209
|
what you build.
|
|
165
210
|
|
|
166
211
|
<p align="center">
|
|
167
|
-
<a href="https://discord.
|
|
212
|
+
<a href="https://discord.lupinum.com">
|
|
168
213
|
<picture>
|
|
169
214
|
<source media="(prefers-color-scheme: dark)" srcset="docs/public/discord-dark.svg">
|
|
170
215
|
<source media="(prefers-color-scheme: light)" srcset="docs/public/discord-light.svg">
|
|
@@ -234,23 +279,20 @@ pnpm dev
|
|
|
234
279
|
pnpm verify
|
|
235
280
|
```
|
|
236
281
|
|
|
237
|
-
Use `pnpm docs:dev` to run the documentation site.
|
|
238
|
-
|
|
239
|
-
preparation.
|
|
282
|
+
Use `pnpm docs:dev` to run the documentation site. `pnpm verify` runs the same
|
|
283
|
+
checks as CI.
|
|
240
284
|
|
|
241
|
-
Read [CONTRIBUTING.md](
|
|
242
|
-
Maintainers use [MAINTAINING.md](./MAINTAINING.md) for release and recovery
|
|
243
|
-
procedures.
|
|
285
|
+
Read [CONTRIBUTING.md](.github/CONTRIBUTING.md) before you open a pull request.
|
|
244
286
|
|
|
245
287
|
## Support and security
|
|
246
288
|
|
|
247
289
|
- Read the [documentation](https://nuxt-pdf.lupinum.com).
|
|
248
|
-
- Join the [Lupinum OSS Discord](https://discord.
|
|
249
|
-
- Open a [bug report](https://github.com/lupinum-dev/nuxt-pdf/issues/new?template=bug.
|
|
290
|
+
- Join the [Lupinum OSS Discord](https://discord.lupinum.com).
|
|
291
|
+
- Open a [bug report](https://github.com/lupinum-dev/nuxt-pdf/issues/new?template=bug.yml)
|
|
250
292
|
for a reproducible defect.
|
|
251
|
-
- Open a [feature request](https://github.com/lupinum-dev/nuxt-pdf/issues/new?template=
|
|
293
|
+
- Open a [feature request](https://github.com/lupinum-dev/nuxt-pdf/issues/new?template=feature.yml)
|
|
252
294
|
before you plan a larger change.
|
|
253
|
-
- Follow [SECURITY.md](
|
|
295
|
+
- Follow [SECURITY.md](.github/SECURITY.md) for a private vulnerability report.
|
|
254
296
|
|
|
255
297
|
## License
|
|
256
298
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# @lupinum/nuxt-pdf 0.4.0-beta.6 documentation
|
|
2
|
+
|
|
3
|
+
These pages document the installed version 0.4.0-beta.6. Prefer them over what you
|
|
4
|
+
remember about this package and over the website, which may describe another version.
|
|
5
|
+
Read the pages that match the task before you write code. If they do not answer a question,
|
|
6
|
+
the user can ask in the Lupinum OSS Discord: https://discord.lupinum.com
|
|
7
|
+
|
|
8
|
+
> Author and render PDFs with Vue components in Nuxt.
|
|
9
|
+
|
|
10
|
+
## When to use
|
|
11
|
+
|
|
12
|
+
Use this site to author and render PDF documents with Nuxt PDF.
|
|
13
|
+
|
|
14
|
+
## Documentation
|
|
15
|
+
|
|
16
|
+
- [Overview](./pages/docs/getting-started.md): Decide whether Nuxt PDF fits the document you need to create.
|
|
17
|
+
- [Install Nuxt PDF](./pages/docs/getting-started/installation.md): Add server-side PDF rendering to an existing Nuxt 4 application.
|
|
18
|
+
- [Render your first PDF](./pages/docs/getting-started/quickstart.md): Create, download, and preview a small invoice in a Nuxt application.
|
|
19
|
+
- [Templates and the registry](./pages/docs/learn/templates-and-registry.md): How files under pdfs become typed server-side render functions.
|
|
20
|
+
- [The document tree](./pages/docs/learn/document-tree.md): PDF primitives, valid nesting, Vue composition, and dynamic text.
|
|
21
|
+
- [Styling and layout](./pages/docs/learn/styling-and-layout.md): The PDF style model, flex layout, units, inheritance, and shared geometry.
|
|
22
|
+
- [Runtime and data loading](./pages/docs/learn/runtime-and-data.md): Where PDF templates execute and how data enters a render.
|
|
23
|
+
- [Build reusable document components](./pages/docs/guides/reusable-components.md): Organize repeated PDF sections without creating a second component system.
|
|
24
|
+
- [Add images and fonts](./pages/docs/guides/images-and-fonts.md): Bundle local PNG, JPEG, TTF, OTF, and WOFF2 resources with a PDF template.
|
|
25
|
+
- [Configure remote images](./pages/docs/guides/remote-images.md): Admit specific HTTPS image paths and understand the request boundary.
|
|
26
|
+
- [Add links, bookmarks, and a table of contents](./pages/docs/guides/contents-links-bookmarks.md): usePdfPageNumbers, the multi-pass layout loop, convergence and maxPasses, internal links, and the bookmark outline.
|
|
27
|
+
- [Draw SVG graphics](./pages/docs/guides/svg-graphics.md): The SVG primitive set, direct presentation props, scoped definitions, SVG text, and the supported numeric boundary.
|
|
28
|
+
- [Test a PDF](./pages/docs/guides/testing.md): Assert against your own templates with a real render using @lupinum/nuxt-pdf/test, plus a realistic Vitest example.
|
|
29
|
+
- [Diagnose render failures](./pages/docs/guides/errors-and-debugging.md): Use template attribution, preview diagnostics, and exact error messages to recover from a failed render.
|
|
30
|
+
- [Deploy and operate](./pages/docs/guides/deployment.md): Size, cache, queue, and monitor PDF rendering on a tested Node target.
|
|
31
|
+
- [Production recipes](./pages/docs/guides/recipes.md): Copyable Vue patterns for invoices, statements, reports, repeating matter, and payment QR codes.
|
|
32
|
+
- [Render outside Nitro](./pages/docs/guides/standalone-node.md): Compile PDF templates once and render the generated registry in a Node worker.
|
|
33
|
+
- [Module options](./pages/docs/reference/module-options.md): Build-time configuration for registered fonts, remote images, and render budgets.
|
|
34
|
+
- [definePdf](./pages/docs/reference/define-pdf.md): The compile-time definition for render metadata, development preview data, and the multi-pass limit.
|
|
35
|
+
- [Registry and render result](./pages/docs/reference/registry.md): The typed #pdf server module, runtime dispatch, and completed render conversions.
|
|
36
|
+
- [Primitives](./pages/docs/reference/primitives.md): Prop tables for every document and SVG primitive, drawn from the shipped type definitions.
|
|
37
|
+
- [Styles](./pages/docs/reference/styles.md): Accepted style keys, values, units, inheritance, and primitive support.
|
|
38
|
+
- [Page sizes](./pages/docs/reference/page-sizes.md): Named and custom page dimensions accepted by PdfPage.
|
|
39
|
+
- [Composables](./pages/docs/reference/composables.md): The auto-imported usePdfPageNumbers map that activates multi-pass layout.
|
|
40
|
+
- [Errors and limits](./pages/docs/reference/errors-and-limits.md): Error classes, exact codes, render-budget defaults, and when each failure occurs.
|
|
41
|
+
- [Test utilities](./pages/docs/reference/test-utilities.md): The render, parse, assert, and snapshot exports of @lupinum/nuxt-pdf/test.
|
|
42
|
+
- [Standalone build and runtime](./pages/docs/reference/standalone.md): Production registry generation and Node runtime exports outside Nitro.
|
|
43
|
+
- [Example gallery](./pages/docs/examples.md): Six playground templates and the technique that each template demonstrates.
|
|
44
|
+
- [Supported behavior and limitations](./pages/docs/examples/supported-behavior.md): The public compatibility boundary and where to find its executable evidence.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Supported behavior and limitations"
|
|
3
|
+
description: "The public compatibility boundary and where to find its executable evidence."
|
|
4
|
+
url: "https://nuxt-pdf.lupinum.com/docs/examples/supported-behavior"
|
|
5
|
+
route: "/docs/examples/supported-behavior"
|
|
6
|
+
locale: "en"
|
|
7
|
+
section: "Documentation"
|
|
8
|
+
collection: "docs"
|
|
9
|
+
source: "ginko-content"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Supported behavior and limitations
|
|
13
|
+
|
|
14
|
+
> The public compatibility boundary and where to find its executable evidence.
|
|
15
|
+
|
|
16
|
+
Nuxt PDF supports the behavior listed in its public guides and reference pages
|
|
17
|
+
against exact pinned layout, font, and serialization packages. It does not claim
|
|
18
|
+
the complete React PDF API or test suite.
|
|
19
|
+
|
|
20
|
+
## Supported areas
|
|
21
|
+
|
|
22
|
+
The repository tests these user-facing areas:
|
|
23
|
+
|
|
24
|
+
- document trees, pagination, flex layout, styles, text, and raster images;
|
|
25
|
+
- local fonts and admitted local or allowlisted remote image sources;
|
|
26
|
+
- metadata, links, notes, bookmarks, and destination page numbers;
|
|
27
|
+
- SVG shapes, gradients, clip paths, transforms, and SVG text;
|
|
28
|
+
- semantic PDF inspection and raster snapshot helpers;
|
|
29
|
+
- production removal of preview routes and preview data;
|
|
30
|
+
- bounded render time, tree size, image admission, page count, and output size.
|
|
31
|
+
|
|
32
|
+
The detailed support status for scripts and fonts is in
|
|
33
|
+
[Add images and fonts](/raw/docs/guides/images-and-fonts.md). Exact primitive and style
|
|
34
|
+
support belongs to the [reference section](/raw/docs/reference/primitives.md).
|
|
35
|
+
|
|
36
|
+
## Differences from React PDF
|
|
37
|
+
|
|
38
|
+
Three behaviors differ where matching the pinned lower engine would produce a
|
|
39
|
+
wrong or unstable public result:
|
|
40
|
+
|
|
41
|
+
- A table-of-contents destination resolves to the section's first page.
|
|
42
|
+
- Dynamic page text does not inherit a `lineHeight` multiplier. Apply line
|
|
43
|
+
height to static `PdfText` instead.
|
|
44
|
+
- Explicit zero values keep SVG meaning for fill opacity, stroke width, and
|
|
45
|
+
supported gradient coordinates.
|
|
46
|
+
|
|
47
|
+
These differences have geometry or raster regression coverage.
|
|
48
|
+
|
|
49
|
+
## Outside the current boundary
|
|
50
|
+
|
|
51
|
+
Nuxt PDF does not claim:
|
|
52
|
+
|
|
53
|
+
- full React PDF API, hook, browser-helper, or runtime compatibility;
|
|
54
|
+
- Nuxt 3, Node 20, browser rendering, or edge rendering;
|
|
55
|
+
- HTML printing, browser CSS, tables, charts, forms, signing, editing, or PDF
|
|
56
|
+
merging as built-in features;
|
|
57
|
+
- tagged PDF, PDF/UA, or archival compliance profiles;
|
|
58
|
+
- byte-identical output across operating systems and viewers;
|
|
59
|
+
- authenticated remote requests, custom headers, remote fonts, or SSRF
|
|
60
|
+
protection beyond the exact-prefix allowlist;
|
|
61
|
+
- SVG image files, SVG markers, or the complete browser SVG model;
|
|
62
|
+
- multi-pass resolution of values other than destination page numbers.
|
|
63
|
+
|
|
64
|
+
## Evidence record
|
|
65
|
+
|
|
66
|
+
This page is the public summary. Maintainers and reviewers can inspect:
|
|
67
|
+
|
|
68
|
+
- [CONFORMANCE.md](https://github.com/lupinum-dev/nuxt-pdf/blob/main/CONFORMANCE.md)
|
|
69
|
+
for version pins, paired comparisons, tested fixtures, and explicit
|
|
70
|
+
non-claims;
|
|
71
|
+
- [CONTRACTS.md](https://github.com/lupinum-dev/nuxt-pdf/blob/main/src/runtime/server/engine/CONTRACTS.md)
|
|
72
|
+
for the renderer's durable engine contracts.
|
|
73
|
+
|
|
74
|
+
When the documentation and public source disagree, the source is authoritative
|
|
75
|
+
and the documentation needs a correction.
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Example gallery"
|
|
3
|
+
description: "Six playground templates and the technique that each template demonstrates."
|
|
4
|
+
url: "https://nuxt-pdf.lupinum.com/docs/examples"
|
|
5
|
+
route: "/docs/examples"
|
|
6
|
+
locale: "en"
|
|
7
|
+
section: "Documentation"
|
|
8
|
+
collection: "docs"
|
|
9
|
+
source: "ginko-content"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Example gallery
|
|
13
|
+
|
|
14
|
+
> Six playground templates and the technique that each template demonstrates.
|
|
15
|
+
|
|
16
|
+
The playground under `playground/pdfs/` ships six complete templates. Each is an
|
|
17
|
+
ordinary `.vue` single-file component discovered by the module, rendered through
|
|
18
|
+
the same registry in development and production, and covered by an end-to-end
|
|
19
|
+
rendering test. Selected visually load-bearing showcases additionally compare
|
|
20
|
+
reviewed raster baselines. Run `pnpm dev` and open `/_pdf` to browse them, or
|
|
21
|
+
read each source alongside the excerpts below.
|
|
22
|
+
|
|
23
|
+
<info icon="lucide:info">
|
|
24
|
+
`renderPdfSfc` compiles the same nested child-SFC graph as the production Nuxt
|
|
25
|
+
module. The packed-package gate exercises typed child props, a local image, and
|
|
26
|
+
multiple local font faces.
|
|
27
|
+
</info>
|
|
28
|
+
|
|
29
|
+
## At a glance
|
|
30
|
+
|
|
31
|
+
| Template | Source | Demonstrates |
|
|
32
|
+
| --- | --- | --- |
|
|
33
|
+
| Invoice | `pdfs/invoice.vue` | Typed props, computed totals, a fixed footer, dynamic page count |
|
|
34
|
+
| Report | `pdfs/report.vue` | `usePdfPageNumbers` table of contents, internal links, bookmarks |
|
|
35
|
+
| Annual report | `pdfs/annual-report.vue` | SVG bar / line / donut charts and tables drawn from Views |
|
|
36
|
+
| Certificate | `pdfs/certificate.vue` | SVG ornament craft with an engraver's border and a seal |
|
|
37
|
+
| E-book | `pdfs/ebook.vue` | `usePdfPageNumbers` with chapter-aware running matter |
|
|
38
|
+
| Menu | `pdfs/menu.vue` | Pure typography, diacritics, dotted leaders, tabular prices |
|
|
39
|
+
|
|
40
|
+
## E-book with chapter-aware running matter
|
|
41
|
+
|
|
42
|
+
_The Reed Line_ is a 21-page digest novella. It reads the resolved page map from
|
|
43
|
+
[`usePdfPageNumbers`](/raw/docs/reference/composables.md) twice: once to print a
|
|
44
|
+
Contents page with real page numbers, and once for a running foot that names the
|
|
45
|
+
**current** chapter on every page it repeats onto. The chapter is derived from
|
|
46
|
+
measured pagination, never hard-coded.
|
|
47
|
+
|
|
48
|
+
```vue [pdfs/ebook.vue]
|
|
49
|
+
const pageNumbers = usePdfPageNumbers()
|
|
50
|
+
|
|
51
|
+
// Derive the current chapter for any page from the resolved start-page map.
|
|
52
|
+
const chapterAt = (pageNumber: number): Ebook['chapters'][number] => {
|
|
53
|
+
let current = ebook.chapters[0]!
|
|
54
|
+
for (const chapter of ebook.chapters) {
|
|
55
|
+
const start = pageNumbers[chapter.id]
|
|
56
|
+
if (typeof start === 'number' && start <= pageNumber) current = chapter
|
|
57
|
+
}
|
|
58
|
+
return current
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The foot is a single `fixed` node whose `:render` closes over `chapterAt`, so one
|
|
63
|
+
callback prints the right chapter and folio on every page:
|
|
64
|
+
|
|
65
|
+
```vue [pdfs/ebook.vue]
|
|
66
|
+
<PdfText
|
|
67
|
+
fixed
|
|
68
|
+
:render="({ pageNumber }) => `${chapterAt(pageNumber).title} · ${pageNumber}`"
|
|
69
|
+
:style="footStyle"
|
|
70
|
+
/>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Annual report with SVG charts and View tables
|
|
74
|
+
|
|
75
|
+
The Fieldnote Studio annual report draws a grouped bar chart, a line chart with a
|
|
76
|
+
gradient area tint, and a donut. It uses the [SVG primitives](/raw/docs/guides/svg-graphics.md),
|
|
77
|
+
with every figure computed from one canonical `YearFigures` source. The donut
|
|
78
|
+
segments come from a pure geometry model and render as a `v-for` of paths:
|
|
79
|
+
|
|
80
|
+
```vue [pdfs/annual-report.vue]
|
|
81
|
+
<PdfSvg :viewBox="`0 0 ${donut.size} ${donut.size}`" :style="{ width: donut.size, height: donut.size }">
|
|
82
|
+
<PdfPath
|
|
83
|
+
v-for="segment in donut.segments"
|
|
84
|
+
:key="segment.id"
|
|
85
|
+
:d="segment.d"
|
|
86
|
+
:fill="segment.fill"
|
|
87
|
+
:transform="segment.transform"
|
|
88
|
+
/>
|
|
89
|
+
</PdfSvg>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The financial statement has no first-class table primitive. It uses
|
|
93
|
+
`View` rows with right-aligned tabular numerals, hairline rules above totals, and
|
|
94
|
+
parenthesised outflows. The quarter and sector breakdowns provably sum to the
|
|
95
|
+
yearly totals (asserted in the template's test).
|
|
96
|
+
|
|
97
|
+
## Certificate with SVG ornaments
|
|
98
|
+
|
|
99
|
+
The certificate is a single A4 landscape page whose decoration is drawn entirely
|
|
100
|
+
from primitives: a double-rule engraver's border with corner diamonds, and a
|
|
101
|
+
concentric seal with two rules, a 32-dot beaded coin edge, a five-point star, and a
|
|
102
|
+
single bronze `RadialGradient` used once.
|
|
103
|
+
|
|
104
|
+
```vue [pdfs/components/certificate/CertificateSeal.vue]
|
|
105
|
+
<script setup lang="ts">
|
|
106
|
+
// Evenly spaced dots in the band between the two rules.
|
|
107
|
+
const beads = Array.from({ length: 32 }, (_, index) => {
|
|
108
|
+
const angle = (index / 32) * Math.PI * 2 - Math.PI / 2
|
|
109
|
+
return { cx: 50 + 45.2 * Math.cos(angle), cy: 50 + 45.2 * Math.sin(angle) }
|
|
110
|
+
})
|
|
111
|
+
</script>
|
|
112
|
+
|
|
113
|
+
<template>
|
|
114
|
+
<PdfSvg view-box="0 0 100 100">
|
|
115
|
+
<PdfDefs>
|
|
116
|
+
<PdfRadialGradient id="seal-bronze" cx="0.5" cy="0.38" r="0.62">
|
|
117
|
+
<PdfStop offset="0" stop-color="#E7CC86" />
|
|
118
|
+
<PdfStop offset="0.55" stop-color="#C9A24B" />
|
|
119
|
+
<PdfStop offset="1" stop-color="#8A6A2F" />
|
|
120
|
+
</PdfRadialGradient>
|
|
121
|
+
</PdfDefs>
|
|
122
|
+
<PdfCircle
|
|
123
|
+
v-for="(bead, index) in beads"
|
|
124
|
+
:key="`bead-${index}`"
|
|
125
|
+
:cx="bead.cx"
|
|
126
|
+
:cy="bead.cy"
|
|
127
|
+
:r="0.75"
|
|
128
|
+
/>
|
|
129
|
+
</PdfSvg>
|
|
130
|
+
</template>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
The decorative layers are absolutely positioned, so a long recipient name wraps
|
|
134
|
+
at spaces to two centered lines and the page can never spill to a second sheet.
|
|
135
|
+
|
|
136
|
+
## Menu with typography and diacritics
|
|
137
|
+
|
|
138
|
+
The Gasthaus Alpenrose card is two A5 pages of typography without borders or
|
|
139
|
+
boxes. German dish names carry their umlauts through rendering and extraction,
|
|
140
|
+
and a flex-`1` dotted leader ties each name to a right-aligned tabular price:
|
|
141
|
+
|
|
142
|
+
```vue [pdfs/menu.vue]
|
|
143
|
+
<PdfView :style="{ alignItems: 'flex-end', flexDirection: 'row' }">
|
|
144
|
+
<PdfText :style="{ fontFamily: 'Inter', fontSize: 10, fontWeight: 600 }">
|
|
145
|
+
{{ dish.name }}
|
|
146
|
+
</PdfText>
|
|
147
|
+
<PdfView :style="{ flex: 1, marginHorizontal: 7, marginBottom: 2,
|
|
148
|
+
borderBottomWidth: 0.75, borderBottomStyle: 'dotted', borderBottomColor: leader }" />
|
|
149
|
+
<PdfText :style="{ fontFamily: 'Inter', fontSize: 10, textAlign: 'right', width: 32 }">
|
|
150
|
+
{{ formatMenuPrice(dish.price) }}
|
|
151
|
+
</PdfText>
|
|
152
|
+
</PdfView>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Prices use the locale format. For example, `9.5` becomes `9,50`. The whole card
|
|
156
|
+
is data-driven, so the `winter` scenario swaps every dish and pour without
|
|
157
|
+
touching the template.
|
|
158
|
+
|
|
159
|
+
<idea icon="lucide:lightbulb">
|
|
160
|
+
Every template ships `sampleData` and at least one named `scenario`, so the dev
|
|
161
|
+
preview at `/_pdf` can render each one without a live route. See
|
|
162
|
+
[define-pdf](/raw/docs/reference/define-pdf.md) for the definition shape.
|
|
163
|
+
</idea>
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Install Nuxt PDF"
|
|
3
|
+
description: "Add server-side PDF rendering to an existing Nuxt 4 application."
|
|
4
|
+
url: "https://nuxt-pdf.lupinum.com/docs/getting-started/installation"
|
|
5
|
+
route: "/docs/getting-started/installation"
|
|
6
|
+
locale: "en"
|
|
7
|
+
section: "Documentation"
|
|
8
|
+
collection: "docs"
|
|
9
|
+
source: "ginko-content"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Install Nuxt PDF
|
|
13
|
+
|
|
14
|
+
> Add server-side PDF rendering to an existing Nuxt 4 application.
|
|
15
|
+
|
|
16
|
+
Nuxt PDF is a Nuxt module. It does not require a separate service or CLI.
|
|
17
|
+
|
|
18
|
+
## Check the requirements
|
|
19
|
+
|
|
20
|
+
| Layer | Supported versions |
|
|
21
|
+
| --- | --- |
|
|
22
|
+
| Node.js | `^22.14.0`, `^24.0.0`, or `^26.0.0` |
|
|
23
|
+
| Nuxt | `^4.4.8` |
|
|
24
|
+
| Vue | `^3.5.0` |
|
|
25
|
+
|
|
26
|
+
Nuxt 3, Node 20, browser rendering, and edge rendering are outside the current
|
|
27
|
+
support boundary.
|
|
28
|
+
|
|
29
|
+
## Add the module
|
|
30
|
+
|
|
31
|
+
Install the package:
|
|
32
|
+
|
|
33
|
+
```bash [Terminal]
|
|
34
|
+
pnpm add @lupinum/nuxt-pdf
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Add it to `nuxt.config.ts`:
|
|
38
|
+
|
|
39
|
+
```ts [nuxt.config.ts]
|
|
40
|
+
export default defineNuxtConfig({
|
|
41
|
+
modules: ['@lupinum/nuxt-pdf'],
|
|
42
|
+
})
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Set up your coding agent
|
|
46
|
+
|
|
47
|
+
Nuxt PDF ships its documentation inside the package, so coding agents read the
|
|
48
|
+
pages that match the installed version. Give your coding agent this task:
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
Set up @lupinum/nuxt-pdf for coding agents as described under "Agent setup" in its README.
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The module now discovers Vue templates under `pdfs/`, generates the typed
|
|
55
|
+
server-only `#pdf` registry, and adds the `/_pdf` development preview.
|
|
56
|
+
|
|
57
|
+
<info icon="lucide:info">
|
|
58
|
+
If your editor does not recognize `#pdf` after installation, run
|
|
59
|
+
`pnpm nuxt prepare` once. Nuxt also refreshes the generated types when the
|
|
60
|
+
development server starts.
|
|
61
|
+
</info>
|
|
62
|
+
|
|
63
|
+
Continue with [Render your first PDF](/raw/docs/getting-started/quickstart.md).
|
|
64
|
+
|
|
65
|
+
## Add test dependencies later
|
|
66
|
+
|
|
67
|
+
The optional test entry uses `pdfjs-dist` for semantic inspection and
|
|
68
|
+
`@napi-rs/canvas` for raster comparisons. Install them only when you start
|
|
69
|
+
testing PDF output:
|
|
70
|
+
|
|
71
|
+
```bash [Terminal]
|
|
72
|
+
pnpm add -D pdfjs-dist @napi-rs/canvas
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The [testing guide](/raw/docs/guides/testing.md) shows the complete workflow.
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Render your first PDF"
|
|
3
|
+
description: "Create, download, and preview a small invoice in a Nuxt application."
|
|
4
|
+
url: "https://nuxt-pdf.lupinum.com/docs/getting-started/quickstart"
|
|
5
|
+
route: "/docs/getting-started/quickstart"
|
|
6
|
+
locale: "en"
|
|
7
|
+
section: "Documentation"
|
|
8
|
+
collection: "docs"
|
|
9
|
+
source: "ginko-content"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Render your first PDF
|
|
13
|
+
|
|
14
|
+
> Create, download, and preview a small invoice in a Nuxt application.
|
|
15
|
+
|
|
16
|
+
This tutorial starts after you [install the module](/raw/docs/getting-started/installation.md).
|
|
17
|
+
It creates one invoice from typed data and returns it from a Nitro route.
|
|
18
|
+
|
|
19
|
+
<steps>
|
|
20
|
+
### Create the invoice template
|
|
21
|
+
|
|
22
|
+
Create `pdfs/invoice.vue` at the application root:
|
|
23
|
+
|
|
24
|
+
```vue [pdfs/invoice.vue]
|
|
25
|
+
<script setup lang="ts">
|
|
26
|
+
type InvoiceProps = {
|
|
27
|
+
invoice: {
|
|
28
|
+
customer: string
|
|
29
|
+
number: string
|
|
30
|
+
total: string
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const props = defineProps<InvoiceProps>()
|
|
35
|
+
|
|
36
|
+
definePdf<InvoiceProps>({
|
|
37
|
+
title: ({ invoice }) => `Invoice ${invoice.number}`,
|
|
38
|
+
filename: ({ invoice }) => `invoice-${invoice.number}.pdf`,
|
|
39
|
+
sampleData: {
|
|
40
|
+
invoice: {
|
|
41
|
+
customer: 'Ada Lovelace',
|
|
42
|
+
number: 'INV-001',
|
|
43
|
+
total: 'EUR 1,250.00',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
})
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<template>
|
|
50
|
+
<PdfDocument>
|
|
51
|
+
<PdfPage :style="{ fontSize: 11, padding: 48 }">
|
|
52
|
+
<PdfText :style="{ fontSize: 24, marginBottom: 24 }">
|
|
53
|
+
Invoice {{ props.invoice.number }}
|
|
54
|
+
</PdfText>
|
|
55
|
+
<PdfText>{{ props.invoice.customer }}</PdfText>
|
|
56
|
+
<PdfText :style="{ marginTop: 12 }">
|
|
57
|
+
Total: {{ props.invoice.total }}
|
|
58
|
+
</PdfText>
|
|
59
|
+
</PdfPage>
|
|
60
|
+
</PdfDocument>
|
|
61
|
+
</template>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
This is the minimum authoring contract:
|
|
65
|
+
|
|
66
|
+
- Templates live under `pdfs/`.
|
|
67
|
+
- The relative filename becomes the registry key. `pdfs/invoice.vue` becomes
|
|
68
|
+
`pdf.invoice`; `pdfs/reports/monthly.vue` becomes `pdf['reports/monthly']`.
|
|
69
|
+
- Each template calls `definePdf()` exactly once.
|
|
70
|
+
- The template has one `PdfDocument` root and at least one `PdfPage`.
|
|
71
|
+
- Text belongs inside `PdfText`.
|
|
72
|
+
- Props are typed with `defineProps()` and passed to `render()`.
|
|
73
|
+
- Style keys use camelCase, such as `fontSize` and `marginBottom`.
|
|
74
|
+
- `sampleData` and preview scenarios exist only in development.
|
|
75
|
+
|
|
76
|
+
### Add a Nitro route
|
|
77
|
+
|
|
78
|
+
Create `server/api/invoice.get.ts`:
|
|
79
|
+
|
|
80
|
+
```ts [server/api/invoice.get.ts]
|
|
81
|
+
import { pdf } from '#pdf'
|
|
82
|
+
|
|
83
|
+
export default defineEventHandler(async () => {
|
|
84
|
+
const result = await pdf.invoice.render({
|
|
85
|
+
invoice: {
|
|
86
|
+
customer: 'Ada Lovelace',
|
|
87
|
+
number: 'INV-001',
|
|
88
|
+
total: 'EUR 1,250.00',
|
|
89
|
+
},
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
return result.response()
|
|
93
|
+
})
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`#pdf` is generated from the files under `pdfs/`. Its `render()` method infers
|
|
97
|
+
the props from the matching Vue template. It is available to server code only.
|
|
98
|
+
|
|
99
|
+
### Start Nuxt
|
|
100
|
+
|
|
101
|
+
Run the application's normal development command:
|
|
102
|
+
|
|
103
|
+
```bash [Terminal]
|
|
104
|
+
pnpm dev
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Download the result
|
|
108
|
+
|
|
109
|
+
Keep the development server running. In another terminal, download the PDF:
|
|
110
|
+
|
|
111
|
+
```bash [Terminal]
|
|
112
|
+
curl -o invoice.pdf http://localhost:3000/api/invoice
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Open `invoice.pdf` in a PDF viewer. The route sends `application/pdf` with the
|
|
116
|
+
filename resolved by `definePdf()`.
|
|
117
|
+
|
|
118
|
+
### Open the development preview
|
|
119
|
+
|
|
120
|
+
Open `http://localhost:3000/_pdf/invoice`. The preview uses `sampleData` and
|
|
121
|
+
shows render diagnostics. The `/_pdf` routes and preview data do not exist in a
|
|
122
|
+
production build.
|
|
123
|
+
</steps>
|
|
124
|
+
|
|
125
|
+
The next useful concepts are [templates and the registry](/raw/docs/learn/templates-and-registry.md)
|
|
126
|
+
and [the document tree](/raw/docs/learn/document-tree.md).
|