@lupinum/nuxt-pdf 0.4.0-beta.2 → 0.4.0-beta.4
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/API_REPORT.md +36 -0
- package/CHANGELOG.md +37 -0
- package/CONFORMANCE.md +21 -2
- package/dist/build.d.mts +18 -0
- package/dist/build.mjs +220 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +17 -230
- package/dist/runtime/components/stubs.d.ts +22 -10
- package/dist/runtime/components/stubs.js +22 -27
- package/dist/runtime/server/assets/resolve-asset.js +2 -40
- package/dist/runtime/server/preview.js +1 -1
- package/dist/server.d.mts +4 -0
- package/dist/server.mjs +3 -0
- package/dist/shared/{nuxt-pdf.D0zmsct0.mjs → nuxt-pdf.C-E8MM_K.mjs} +10 -2
- package/dist/shared/nuxt-pdf.CjVyPF31.mjs +203 -0
- package/dist/test.mjs +1 -1
- package/package.json +22 -13
package/API_REPORT.md
CHANGED
|
@@ -260,3 +260,39 @@ declare function comparePdfSnapshot(input: PdfInput, baselineDir: string, option
|
|
|
260
260
|
export { PdfAssertionError, comparePdfSnapshot, expectPdf, loadPdfSfc, parsePdf, rasterizePdf, renderPdfSfc, renderPdfTemplate, toPdfBytes };
|
|
261
261
|
export type { ComparePdfSnapshotOptions, LinkQuery, OutlineShape, ParsedPdf, ParsedPdfLink, ParsedPdfPage, ParsedPdfTextRun, PdfExpectation, PdfInput, PdfOutlineItem, PdfPageImage, PdfSnapshotResult, RasterizePdfOptions, RenderPdfSfcOptions, RenderPdfTemplateOptions, RenderedPdfTemplate, ToContainTextOptions };
|
|
262
262
|
```
|
|
263
|
+
|
|
264
|
+
## Standalone build entry
|
|
265
|
+
|
|
266
|
+
Source: `dist/build.d.mts`
|
|
267
|
+
|
|
268
|
+
```ts
|
|
269
|
+
import { PdfFontDeclaration } from '../dist/runtime/fonts.js';
|
|
270
|
+
import { RemoteAssetOptions } from '../dist/runtime/server/assets/remote.js';
|
|
271
|
+
import { PdfLimitsOptions } from '../dist/runtime/server/render-limits.js';
|
|
272
|
+
|
|
273
|
+
interface BuildPdfRegistryOptions {
|
|
274
|
+
/** Trusted application root containing pdfs/. Not request input. */
|
|
275
|
+
rootDir: string;
|
|
276
|
+
/** Dedicated generated directory inside rootDir and outside pdfs/. */
|
|
277
|
+
outDir: string;
|
|
278
|
+
fonts?: readonly PdfFontDeclaration[];
|
|
279
|
+
limits?: PdfLimitsOptions;
|
|
280
|
+
remote?: RemoteAssetOptions;
|
|
281
|
+
}
|
|
282
|
+
/** Compile trusted templates and embed admitted resources before deployment. */
|
|
283
|
+
declare function buildPdfRegistry(options: BuildPdfRegistryOptions): Promise<void>;
|
|
284
|
+
|
|
285
|
+
export { buildPdfRegistry };
|
|
286
|
+
export type { BuildPdfRegistryOptions };
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Standalone server entry
|
|
290
|
+
|
|
291
|
+
Source: `dist/server.d.mts`
|
|
292
|
+
|
|
293
|
+
```ts
|
|
294
|
+
export { PdfRegistry, PdfRegistryEntries, createPdfRegistry, createPdfTemplate } from '../dist/runtime/server/registry.js';
|
|
295
|
+
export { NuxtPdfError, PDF_ERROR_CODES, PdfErrorCode } from '../dist/runtime/shared/errors.js';
|
|
296
|
+
export { usePdfPageNumbers } from '../dist/runtime/composables/index.js';
|
|
297
|
+
export { PdfComponentProps, PdfDefinition, PdfRenderResult, PdfTemplate } from '../dist/runtime/shared/template.js';
|
|
298
|
+
```
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,43 @@ 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.4
|
|
8
|
+
|
|
9
|
+
[compare changes](https://github.com/lupinum-dev/nuxt-pdf/compare/v0.4.0-beta.3...0.4.0-beta.4)
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **deps:** Enforce quarantine in package consumers ([#48](https://github.com/lupinum-dev/nuxt-pdf/pull/48))
|
|
14
|
+
- **assets:** Revalidate disk images across renders ([#49](https://github.com/lupinum-dev/nuxt-pdf/pull/49))
|
|
15
|
+
- **dev:** Export registered PDF component guards ([#50](https://github.com/lupinum-dev/nuxt-pdf/pull/50))
|
|
16
|
+
- **preview:** Rebuild watched templates before refreshing ([#51](https://github.com/lupinum-dev/nuxt-pdf/pull/51))
|
|
17
|
+
- **release:** Bind package evidence to its source graph ([#52](https://github.com/lupinum-dev/nuxt-pdf/pull/52))
|
|
18
|
+
|
|
19
|
+
### Maintenance
|
|
20
|
+
|
|
21
|
+
- **maintenance:** Verify PDF commands without repeated work ([#53](https://github.com/lupinum-dev/nuxt-pdf/pull/53))
|
|
22
|
+
|
|
23
|
+
### Tests
|
|
24
|
+
|
|
25
|
+
- **compatibility:** Verify declared PDF consumer versions ([#54](https://github.com/lupinum-dev/nuxt-pdf/pull/54))
|
|
26
|
+
- **assets:** Describe per-render disk validation ([#55](https://github.com/lupinum-dev/nuxt-pdf/pull/55))
|
|
27
|
+
- **production:** Tolerate fixture text whitespace ([#56](https://github.com/lupinum-dev/nuxt-pdf/pull/56))
|
|
28
|
+
|
|
29
|
+
## 0.4.0-beta.3 - 2026-09-03
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- Add a standalone registry build and Node production runtime entry. Reuse the
|
|
34
|
+
existing PDF compiler, embedded resource admission, and rendering engine.
|
|
35
|
+
- Emit backend-consumable TypeScript declarations without requiring Vue source
|
|
36
|
+
or a Vue type checker during backend compilation.
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
|
|
40
|
+
- Keep the registry documentation example compatible with strict Markdown style
|
|
41
|
+
validation and update vulnerable documentation parser dependencies.
|
|
42
|
+
- Prepare the package build export before clean-checkout type checking.
|
|
43
|
+
|
|
7
44
|
## 0.4.0-beta.2 - 2026-08-27
|
|
8
45
|
|
|
9
46
|
[compare changes](https://github.com/lupinum-dev/nuxt-pdf/compare/v0.4.0-beta.1...v0.4.0-beta.2)
|
package/CONFORMANCE.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# Nuxt PDF 0.4.0-beta.
|
|
1
|
+
# Nuxt PDF 0.4.0-beta.4 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 | 0.4.0-beta.
|
|
8
|
+
| Layer | 0.4.0-beta.4 boundary |
|
|
9
9
|
|---|---|
|
|
10
10
|
| Node.js | `^22.14.0`, `^24.0.0`, or `^26.0.0` |
|
|
11
11
|
| Nuxt | `^4.4.8` |
|
|
@@ -22,6 +22,19 @@ any of them changes.
|
|
|
22
22
|
|
|
23
23
|
## Verified corpus
|
|
24
24
|
|
|
25
|
+
### Standalone registry
|
|
26
|
+
|
|
27
|
+
`test/standalone-build.test.ts` compiles the production registry and removes
|
|
28
|
+
template, font, and image sources before rendering. It checks custom fonts,
|
|
29
|
+
Unicode, embedded images, long text, pagination, equivalent extracted content,
|
|
30
|
+
and concurrent prop isolation. Plain NodeNext TypeScript checks inferred inline
|
|
31
|
+
and imported props without Vue source. Invalid resources, output limits, failed
|
|
32
|
+
build preservation, and generated-directory ownership have focused tests.
|
|
33
|
+
|
|
34
|
+
This is local Node evidence, not a deployed Convex or serverless certification.
|
|
35
|
+
Largest-realistic-document sizing, cold/warm timing, and platform memory limits
|
|
36
|
+
remain application deployment checks. The existing Nitro path is unchanged.
|
|
37
|
+
|
|
25
38
|
### Compatibility kernel
|
|
26
39
|
|
|
27
40
|
The paired React/Vue fixture verifies:
|
|
@@ -248,6 +261,10 @@ The 0.4.0-beta.2 tests verify:
|
|
|
248
261
|
content type;
|
|
249
262
|
- development preview index, viewer, raw PDF, and named scenarios, backed by a
|
|
250
263
|
separate internal development sidecar;
|
|
264
|
+
- development guards for every global PDF component, including Nuxt
|
|
265
|
+
auto-import misuse outside a PDF template;
|
|
266
|
+
- watched template rebuilds and whole-viewer refreshes that keep the selected
|
|
267
|
+
scenario and replace document bytes with their matching diagnostics;
|
|
251
268
|
- a production Nitro route rendering through the generated registry;
|
|
252
269
|
- structural removal of `sampleData` and `scenarios` during production SFC
|
|
253
270
|
compilation, with unique fixture canaries and preview-only API tokens rejected
|
|
@@ -329,6 +346,8 @@ shows up without a restart. The tested boundary includes:
|
|
|
329
346
|
- TTF, OTF, and WOFF2 signature/extension/structure validation,
|
|
330
347
|
registration validation, source byte limits, and source-removal rendering;
|
|
331
348
|
- explicit local `pdfs/assets` and `pdfs/fonts` roots;
|
|
349
|
+
- independent image validation across roots and after same-size,
|
|
350
|
+
same-timestamp development edits;
|
|
332
351
|
- rejection of absolute paths, traversal, missing assets, ambiguous sources,
|
|
333
352
|
unsupported URLs, and symlink escapes; and
|
|
334
353
|
- font rendering after its source file is removed, and image resolution from
|
package/dist/build.d.mts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { PdfFontDeclaration } from '../dist/runtime/fonts.js';
|
|
2
|
+
import { RemoteAssetOptions } from '../dist/runtime/server/assets/remote.js';
|
|
3
|
+
import { PdfLimitsOptions } from '../dist/runtime/server/render-limits.js';
|
|
4
|
+
|
|
5
|
+
interface BuildPdfRegistryOptions {
|
|
6
|
+
/** Trusted application root containing pdfs/. Not request input. */
|
|
7
|
+
rootDir: string;
|
|
8
|
+
/** Dedicated generated directory inside rootDir and outside pdfs/. */
|
|
9
|
+
outDir: string;
|
|
10
|
+
fonts?: readonly PdfFontDeclaration[];
|
|
11
|
+
limits?: PdfLimitsOptions;
|
|
12
|
+
remote?: RemoteAssetOptions;
|
|
13
|
+
}
|
|
14
|
+
/** Compile trusted templates and embed admitted resources before deployment. */
|
|
15
|
+
declare function buildPdfRegistry(options: BuildPdfRegistryOptions): Promise<void>;
|
|
16
|
+
|
|
17
|
+
export { buildPdfRegistry };
|
|
18
|
+
export type { BuildPdfRegistryOptions };
|
package/dist/build.mjs
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { readdir, readFile, writeFile, mkdir, mkdtemp, rm, lstat, rename } from 'node:fs/promises';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
|
+
import { join, relative, dirname, resolve, isAbsolute } from 'node:path';
|
|
5
|
+
import { promisify } from 'node:util';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { build } from 'esbuild';
|
|
8
|
+
import { d as discoverPdfTemplates, a as discoverPdfImageFiles, b as bundlePdfFonts, c as compilePdfSfc } from './shared/nuxt-pdf.C-E8MM_K.mjs';
|
|
9
|
+
import ts from 'typescript';
|
|
10
|
+
import { p as preparePdfImageAssets, g as generatePdfRuntimeRegistry, a as generateAuthoringTypes, b as generatePdfRegistryTypes } from './shared/nuxt-pdf.CjVyPF31.mjs';
|
|
11
|
+
import { normalizeRemoteAssetPolicy } from '../dist/runtime/server/assets/remote.js';
|
|
12
|
+
import { normalizePdfLimits, DEFAULT_PDF_RENDER_LIMITS } from '../dist/runtime/server/render-limits.js';
|
|
13
|
+
import 'node:buffer';
|
|
14
|
+
import 'node:fs';
|
|
15
|
+
import '@vue/compiler-sfc';
|
|
16
|
+
import '@jridgewell/remapping';
|
|
17
|
+
import 'unimport';
|
|
18
|
+
import '../dist/runtime/shared/template.js';
|
|
19
|
+
import '../dist/runtime/components/stubs.js';
|
|
20
|
+
import 'ufo';
|
|
21
|
+
import '../dist/runtime/server/assets/resolve-asset.js';
|
|
22
|
+
|
|
23
|
+
async function normalizeDeclarationImports(directory) {
|
|
24
|
+
for (const file of await readdir(directory, { recursive: true })) {
|
|
25
|
+
if (!/\.d\.[cm]?ts$/.test(file)) continue;
|
|
26
|
+
const path = join(directory, file);
|
|
27
|
+
const source = ts.createSourceFile(path, await readFile(path, "utf8"), ts.ScriptTarget.Latest, true);
|
|
28
|
+
const transformed = ts.transform(source, [(context) => {
|
|
29
|
+
const visit = (node) => {
|
|
30
|
+
if (ts.isStringLiteral(node) && node.text.startsWith(".")) {
|
|
31
|
+
const parent = node.parent;
|
|
32
|
+
const isImport = ts.isImportDeclaration(parent) || ts.isExportDeclaration(parent) || ts.isLiteralTypeNode(parent) && ts.isImportTypeNode(parent.parent);
|
|
33
|
+
if (isImport && !node.text.endsWith(".json")) {
|
|
34
|
+
const module = ts.resolveModuleName(node.text, path, { moduleResolution: ts.ModuleResolutionKind.Bundler }, ts.sys).resolvedModule;
|
|
35
|
+
if (!module) throw new Error(`Cannot resolve emitted declaration import ${JSON.stringify(node.text)} from ${path}. Use a relative TypeScript source file inside rootDir.`);
|
|
36
|
+
const target = relative(dirname(path), module.resolvedFileName).replaceAll("\\", "/").replace(/\.d\.([cm]?)ts$/, ".$1js");
|
|
37
|
+
return ts.factory.createStringLiteral(target.startsWith(".") ? target : `./${target}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return ts.visitEachChild(node, visit, context);
|
|
41
|
+
};
|
|
42
|
+
return (node) => ts.visitNode(node, visit);
|
|
43
|
+
}]);
|
|
44
|
+
try {
|
|
45
|
+
await writeFile(path, ts.createPrinter().printFile(transformed.transformed[0]));
|
|
46
|
+
} finally {
|
|
47
|
+
transformed.dispose();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const runtimeImport = "@lupinum/nuxt-pdf/server";
|
|
53
|
+
const execute = promisify(execFile);
|
|
54
|
+
const ownershipMarker = ".nuxt-pdf-generated";
|
|
55
|
+
const ownershipContent = "Generated by @lupinum/nuxt-pdf/build. Do not edit.\n";
|
|
56
|
+
function contains(parent, child) {
|
|
57
|
+
const path = relative(parent, child);
|
|
58
|
+
return path === "" || path !== ".." && !path.startsWith("../") && !path.startsWith("..\\") && !isAbsolute(path);
|
|
59
|
+
}
|
|
60
|
+
async function checkOutputDirectory(outDir) {
|
|
61
|
+
const info = await lstat(outDir).catch((error) => {
|
|
62
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") return void 0;
|
|
63
|
+
throw error;
|
|
64
|
+
});
|
|
65
|
+
if (!info) return;
|
|
66
|
+
if (!info.isDirectory() || info.isSymbolicLink()) {
|
|
67
|
+
throw new TypeError("buildPdfRegistry outDir must be a directory, not a file or symlink.");
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
const marker = await readFile(join(outDir, ownershipMarker), "utf8");
|
|
71
|
+
if (marker !== ownershipContent) throw new Error("invalid ownership marker");
|
|
72
|
+
} catch (error) {
|
|
73
|
+
throw new TypeError("buildPdfRegistry refuses to replace a directory it did not generate.", { cause: error });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async function replaceOutputDirectory(staging, outDir) {
|
|
77
|
+
const parent = dirname(outDir);
|
|
78
|
+
const previousRoot = await mkdtemp(join(parent, ".nuxt-pdf-previous-"));
|
|
79
|
+
const previous = join(previousRoot, "output");
|
|
80
|
+
let removePreviousRoot = true;
|
|
81
|
+
try {
|
|
82
|
+
const exists = await lstat(outDir).then(() => true, (error) => {
|
|
83
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") return false;
|
|
84
|
+
throw error;
|
|
85
|
+
});
|
|
86
|
+
if (exists) await rename(outDir, previous);
|
|
87
|
+
try {
|
|
88
|
+
await rename(staging, outDir);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (exists) {
|
|
91
|
+
try {
|
|
92
|
+
await rename(previous, outDir);
|
|
93
|
+
} catch (restoreError) {
|
|
94
|
+
removePreviousRoot = false;
|
|
95
|
+
throw new AggregateError(
|
|
96
|
+
[error, restoreError],
|
|
97
|
+
`Failed to replace generated PDF output and restore it. The prior output remains at ${previous}.`,
|
|
98
|
+
{ cause: restoreError }
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
} finally {
|
|
105
|
+
if (removePreviousRoot) await rm(previousRoot, { recursive: true, force: true });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async function buildPdfRegistry(options) {
|
|
109
|
+
const allowed = /* @__PURE__ */ new Set(["rootDir", "outDir", "fonts", "limits", "remote"]);
|
|
110
|
+
for (const key of Object.keys(options)) {
|
|
111
|
+
if (!allowed.has(key)) throw new TypeError(`buildPdfRegistry: unsupported option ${JSON.stringify(key)}.`);
|
|
112
|
+
}
|
|
113
|
+
if (!options.rootDir?.trim() || !options.outDir?.trim()) {
|
|
114
|
+
throw new TypeError("buildPdfRegistry requires rootDir and outDir.");
|
|
115
|
+
}
|
|
116
|
+
const rootDir = resolve(options.rootDir);
|
|
117
|
+
const outDir = resolve(rootDir, options.outDir);
|
|
118
|
+
const pdfRoot = join(rootDir, "pdfs");
|
|
119
|
+
if (!contains(rootDir, outDir) || contains(pdfRoot, outDir) || contains(outDir, pdfRoot)) {
|
|
120
|
+
throw new TypeError("buildPdfRegistry outDir must be a dedicated directory inside rootDir and outside pdfs/.");
|
|
121
|
+
}
|
|
122
|
+
await checkOutputDirectory(outDir);
|
|
123
|
+
const layers = [{ rootDir }];
|
|
124
|
+
const templates = await discoverPdfTemplates(layers);
|
|
125
|
+
if (templates.length === 0) throw new TypeError("buildPdfRegistry found no templates in pdfs/.");
|
|
126
|
+
const limits = normalizePdfLimits(options.limits);
|
|
127
|
+
const [assets, fonts] = await Promise.all([
|
|
128
|
+
discoverPdfImageFiles(layers).then((images) => preparePdfImageAssets(images, limits ?? DEFAULT_PDF_RENDER_LIMITS, false)),
|
|
129
|
+
bundlePdfFonts(options.fonts ?? [], { fontRoots: [join(pdfRoot, "fonts")] })
|
|
130
|
+
]);
|
|
131
|
+
const source = generatePdfRuntimeRegistry(templates, {
|
|
132
|
+
assets,
|
|
133
|
+
fonts,
|
|
134
|
+
limits,
|
|
135
|
+
remote: normalizeRemoteAssetPolicy(options.remote),
|
|
136
|
+
runtimeImport,
|
|
137
|
+
development: false
|
|
138
|
+
});
|
|
139
|
+
const entries = new Set(templates.map((template) => template.filePath));
|
|
140
|
+
const result = await build({
|
|
141
|
+
absWorkingDir: rootDir,
|
|
142
|
+
stdin: { contents: source, resolveDir: rootDir, sourcefile: "pdf-registry.js" },
|
|
143
|
+
bundle: true,
|
|
144
|
+
packages: "external",
|
|
145
|
+
platform: "node",
|
|
146
|
+
format: "esm",
|
|
147
|
+
target: "node22",
|
|
148
|
+
tsconfigRaw: {},
|
|
149
|
+
write: false,
|
|
150
|
+
plugins: [{
|
|
151
|
+
name: "nuxt-pdf:standalone",
|
|
152
|
+
setup(builder) {
|
|
153
|
+
builder.onLoad({ filter: /\.vue$/ }, async ({ path }) => ({
|
|
154
|
+
contents: (await compilePdfSfc(await readFile(path, "utf8"), path, entries.has(path) ? "template" : "component", true, runtimeImport)).code,
|
|
155
|
+
loader: "js",
|
|
156
|
+
resolveDir: dirname(path)
|
|
157
|
+
}));
|
|
158
|
+
}
|
|
159
|
+
}]
|
|
160
|
+
});
|
|
161
|
+
const output = result.outputFiles[0];
|
|
162
|
+
if (!output) throw new Error("PDF registry compilation produced no output.");
|
|
163
|
+
await mkdir(dirname(outDir), { recursive: true });
|
|
164
|
+
const staging = await mkdtemp(join(dirname(outDir), ".nuxt-pdf-build-"));
|
|
165
|
+
try {
|
|
166
|
+
await emitDeclarations(rootDir, staging, templates);
|
|
167
|
+
await writeFile(join(staging, "index.mjs"), output.contents);
|
|
168
|
+
await writeFile(join(staging, ownershipMarker), ownershipContent);
|
|
169
|
+
await checkOutputDirectory(outDir);
|
|
170
|
+
await replaceOutputDirectory(staging, outDir);
|
|
171
|
+
} finally {
|
|
172
|
+
await rm(staging, { recursive: true, force: true });
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
async function emitDeclarations(rootDir, outDir, templates) {
|
|
176
|
+
const temporary = await mkdtemp(join(outDir, ".types-"));
|
|
177
|
+
try {
|
|
178
|
+
const globals = join(temporary, "authoring.d.ts");
|
|
179
|
+
const runtimeDirectory = join(dirname(fileURLToPath(import.meta.resolve(runtimeImport))), "runtime");
|
|
180
|
+
await writeFile(globals, generateAuthoringTypes(
|
|
181
|
+
join(runtimeDirectory, "components/index"),
|
|
182
|
+
join(runtimeDirectory, "composables/index"),
|
|
183
|
+
join(runtimeDirectory, "define-pdf")
|
|
184
|
+
));
|
|
185
|
+
const config = join(temporary, "tsconfig.json");
|
|
186
|
+
await writeFile(config, JSON.stringify({
|
|
187
|
+
compilerOptions: {
|
|
188
|
+
target: "ES2022",
|
|
189
|
+
module: "ESNext",
|
|
190
|
+
moduleResolution: "Bundler",
|
|
191
|
+
strict: true,
|
|
192
|
+
skipLibCheck: true,
|
|
193
|
+
declaration: true,
|
|
194
|
+
emitDeclarationOnly: true,
|
|
195
|
+
noEmitOnError: true,
|
|
196
|
+
rootDir,
|
|
197
|
+
declarationDir: join(outDir, "types"),
|
|
198
|
+
types: []
|
|
199
|
+
},
|
|
200
|
+
files: [...templates.map((template) => template.filePath), globals]
|
|
201
|
+
}));
|
|
202
|
+
try {
|
|
203
|
+
await execute(process.execPath, [createRequire(import.meta.url).resolve("vue-tsc/bin/vue-tsc.js"), "--project", config], { cwd: rootDir, maxBuffer: 4 * 1024 * 1024 });
|
|
204
|
+
} catch (error) {
|
|
205
|
+
const diagnostics = error instanceof Error && "stdout" in error ? String(error.stdout) : "";
|
|
206
|
+
throw new Error(`PDF template type checking failed.
|
|
207
|
+
${diagnostics}`, { cause: error });
|
|
208
|
+
}
|
|
209
|
+
await normalizeDeclarationImports(join(outDir, "types"));
|
|
210
|
+
const declarationTemplates = templates.map((template) => ({
|
|
211
|
+
...template,
|
|
212
|
+
filePath: `./types/${relative(rootDir, template.filePath).replaceAll("\\", "/")}.js`
|
|
213
|
+
}));
|
|
214
|
+
await writeFile(join(outDir, "index.d.mts"), generatePdfRegistryTypes(declarationTemplates, { runtimeImport }));
|
|
215
|
+
} finally {
|
|
216
|
+
await rm(temporary, { recursive: true, force: true });
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export { buildPdfRegistry };
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,188 +1,23 @@
|
|
|
1
1
|
import { stat } from 'node:fs/promises';
|
|
2
|
-
import { Buffer } from 'node:buffer';
|
|
3
2
|
import { join, isAbsolute, resolve, relative } from 'node:path';
|
|
4
3
|
import { defineNuxtModule, createResolver, getLayerDirectories, createIsIgnored, addServerTemplate, addTemplate, addImports, addTypeTemplate, logger, addServerHandler, addComponent } from '@nuxt/kit';
|
|
5
4
|
import { joinURL } from 'ufo';
|
|
6
|
-
import { d as discoverPdfTemplates,
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
5
|
+
import { d as discoverPdfTemplates, e as discoverPdfComponentFiles, a as discoverPdfImageFiles, b as bundlePdfFonts, f as createPdfSfcPlugin, g as classifyPdfWatchEvent } from './shared/nuxt-pdf.C-E8MM_K.mjs';
|
|
6
|
+
import { p as preparePdfImageAssets, g as generatePdfRuntimeRegistry, b as generatePdfRegistryTypes, a as generateAuthoringTypes, c as generatePdfPreviewConfig } from './shared/nuxt-pdf.CjVyPF31.mjs';
|
|
7
|
+
import * as pdfStubs from '../dist/runtime/components/stubs.js';
|
|
9
8
|
import { normalizeRemoteAssetPolicy } from '../dist/runtime/server/assets/remote.js';
|
|
10
9
|
import { normalizePdfLimits, DEFAULT_PDF_RENDER_LIMITS } from '../dist/runtime/server/render-limits.js';
|
|
10
|
+
import 'node:buffer';
|
|
11
11
|
import 'node:fs';
|
|
12
12
|
import '@vue/compiler-sfc';
|
|
13
13
|
import '@jridgewell/remapping';
|
|
14
14
|
import 'esbuild';
|
|
15
15
|
import 'unimport';
|
|
16
16
|
import '../dist/runtime/shared/template.js';
|
|
17
|
+
import '../dist/runtime/server/assets/resolve-asset.js';
|
|
17
18
|
|
|
18
|
-
const version = "0.4.0-beta.
|
|
19
|
+
const version = "0.4.0-beta.4";
|
|
19
20
|
|
|
20
|
-
const compareText = (left, right) => {
|
|
21
|
-
if (left < right) return -1;
|
|
22
|
-
if (left > right) return 1;
|
|
23
|
-
return 0;
|
|
24
|
-
};
|
|
25
|
-
const quote$1 = (value) => JSON.stringify(value);
|
|
26
|
-
const generatePdfPreviewConfig = (baseURL, buildAssetsDir) => `export const hmrClientPath = ${quote$1(joinURL(
|
|
27
|
-
baseURL.replace(/^\.\//, "/") || "/",
|
|
28
|
-
buildAssetsDir,
|
|
29
|
-
"@vite/client"
|
|
30
|
-
))}
|
|
31
|
-
`;
|
|
32
|
-
const importPath = (filePath) => filePath.replaceAll("\\", "/");
|
|
33
|
-
const runtimeOptionsSource = (options) => {
|
|
34
|
-
const assets = options.assets ?? [];
|
|
35
|
-
const fonts = options.fonts ?? [];
|
|
36
|
-
const { remote, limits } = options;
|
|
37
|
-
for (const asset of assets) {
|
|
38
|
-
if (asset.root !== void 0 === (asset.dataB64 !== void 0)) {
|
|
39
|
-
throw new TypeError(
|
|
40
|
-
`PDF image asset "${asset.key}" must declare exactly one of root or dataB64.`
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
if (assets.length === 0 && fonts.length === 0 && !remote && !limits) return [];
|
|
45
|
-
const lines = ["", "const __pdfRuntimeOptions = Object.freeze({"];
|
|
46
|
-
if (assets.length > 0) {
|
|
47
|
-
lines.push(" assets: Object.freeze({");
|
|
48
|
-
for (const asset of assets) {
|
|
49
|
-
const entry = asset.root !== void 0 ? `{ format: ${quote$1(asset.format)}, root: ${quote$1(asset.root)} }` : `{ dataB64: ${quote$1(asset.dataB64 ?? "")}, format: ${quote$1(asset.format)} }`;
|
|
50
|
-
lines.push(` ${quote$1(asset.key)}: Object.freeze(${entry}),`);
|
|
51
|
-
}
|
|
52
|
-
lines.push(" }),");
|
|
53
|
-
}
|
|
54
|
-
if (fonts.length > 0) {
|
|
55
|
-
lines.push(" fonts: Object.freeze([");
|
|
56
|
-
for (const font of fonts) {
|
|
57
|
-
lines.push(` Object.freeze(${JSON.stringify(font)}),`);
|
|
58
|
-
}
|
|
59
|
-
lines.push(" ]),");
|
|
60
|
-
}
|
|
61
|
-
if (remote) {
|
|
62
|
-
lines.push(` remote: Object.freeze(${JSON.stringify(remote)}),`);
|
|
63
|
-
}
|
|
64
|
-
if (limits) {
|
|
65
|
-
lines.push(` limits: Object.freeze(${JSON.stringify(limits)}),`);
|
|
66
|
-
}
|
|
67
|
-
lines.push("})");
|
|
68
|
-
return lines;
|
|
69
|
-
};
|
|
70
|
-
const orderedTemplates = (templates) => {
|
|
71
|
-
const result = [...templates].sort(
|
|
72
|
-
(left, right) => compareText(left.key, right.key)
|
|
73
|
-
);
|
|
74
|
-
const keys = /* @__PURE__ */ new Map();
|
|
75
|
-
for (const template of result) {
|
|
76
|
-
const duplicate = keys.get(template.key);
|
|
77
|
-
if (duplicate) {
|
|
78
|
-
throw new TypeError(
|
|
79
|
-
`Cannot generate duplicate PDF template key "${template.key}" from "${duplicate.filePath}" and "${template.filePath}".`
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
keys.set(template.key, template);
|
|
83
|
-
}
|
|
84
|
-
return result;
|
|
85
|
-
};
|
|
86
|
-
const validateOptions = (options) => {
|
|
87
|
-
if (options.runtimeImport.trim() === "") {
|
|
88
|
-
throw new TypeError("runtimeImport is required to generate the PDF registry.");
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
const generatePdfRuntimeRegistry = (templates, options) => {
|
|
92
|
-
validateOptions(options);
|
|
93
|
-
const ordered = orderedTemplates(templates);
|
|
94
|
-
const runtimeImports = options.development ? "createPdfPreviewEntry, createPdfRegistry, createPdfTemplate" : "createPdfRegistry, createPdfTemplate";
|
|
95
|
-
const lines = [
|
|
96
|
-
`import { ${runtimeImports} } from ${quote$1(options.runtimeImport)}`
|
|
97
|
-
];
|
|
98
|
-
ordered.forEach((template, index) => {
|
|
99
|
-
lines.push(
|
|
100
|
-
`import __pdfTemplate${index} from ${quote$1(importPath(template.filePath))}`
|
|
101
|
-
);
|
|
102
|
-
});
|
|
103
|
-
const runtimeOptions = runtimeOptionsSource(options);
|
|
104
|
-
lines.push(...runtimeOptions, "", "const registry = createPdfRegistry({");
|
|
105
|
-
ordered.forEach((template, index) => {
|
|
106
|
-
const file = quote$1(`pdfs/${template.relativePath}`);
|
|
107
|
-
const runtimeArgument = options.development ? runtimeOptions.length > 0 ? `, { ...__pdfRuntimeOptions, file: ${file} }` : `, { file: ${file} }` : runtimeOptions.length > 0 ? ", __pdfRuntimeOptions" : "";
|
|
108
|
-
lines.push(
|
|
109
|
-
` ${quote$1(template.key)}: createPdfTemplate(${quote$1(template.key)}, __pdfTemplate${index}${runtimeArgument}),`
|
|
110
|
-
);
|
|
111
|
-
});
|
|
112
|
-
lines.push("})");
|
|
113
|
-
if (options.development) {
|
|
114
|
-
lines.push("", "export const pdfPreview = Object.freeze({");
|
|
115
|
-
ordered.forEach((template, index) => {
|
|
116
|
-
lines.push(
|
|
117
|
-
` ${quote$1(template.key)}: createPdfPreviewEntry(registry.pdf[${quote$1(template.key)}], __pdfTemplate${index}, { file: ${quote$1(`pdfs/${template.relativePath}`)} }),`
|
|
118
|
-
);
|
|
119
|
-
});
|
|
120
|
-
lines.push("})");
|
|
121
|
-
}
|
|
122
|
-
lines.push(
|
|
123
|
-
"",
|
|
124
|
-
"export const pdf = registry.pdf",
|
|
125
|
-
"export const renderPdf = registry.renderPdf",
|
|
126
|
-
"export const getPdfTemplate = registry.getPdfTemplate",
|
|
127
|
-
"export const pdfTemplateKeys = registry.pdfTemplateKeys",
|
|
128
|
-
`export { NuxtPdfError, PDF_ERROR_CODES } from ${quote$1(options.runtimeImport)}`,
|
|
129
|
-
""
|
|
130
|
-
);
|
|
131
|
-
return lines.join("\n");
|
|
132
|
-
};
|
|
133
|
-
const generatePdfRegistryTypes = (templates, options) => {
|
|
134
|
-
validateOptions(options);
|
|
135
|
-
const ordered = orderedTemplates(templates);
|
|
136
|
-
const lines = [
|
|
137
|
-
`import type { PdfComponentProps, PdfRenderResult, PdfTemplate } from ${quote$1(options.runtimeImport)}`
|
|
138
|
-
];
|
|
139
|
-
ordered.forEach((template, index) => {
|
|
140
|
-
lines.push(
|
|
141
|
-
"",
|
|
142
|
-
`type PdfComponent${index} = typeof import(${quote$1(importPath(template.filePath))})['default']`,
|
|
143
|
-
`type PdfProps${index} = PdfComponentProps<PdfComponent${index}>`
|
|
144
|
-
);
|
|
145
|
-
});
|
|
146
|
-
lines.push("", "export declare const pdf: {");
|
|
147
|
-
ordered.forEach((template, index) => {
|
|
148
|
-
lines.push(
|
|
149
|
-
` readonly ${quote$1(template.key)}: PdfTemplate<PdfProps${index}>`
|
|
150
|
-
);
|
|
151
|
-
});
|
|
152
|
-
lines.push("}", "");
|
|
153
|
-
if (ordered.length === 0) {
|
|
154
|
-
lines.push(
|
|
155
|
-
"export declare function renderPdf(name: never, props: never): Promise<PdfRenderResult>",
|
|
156
|
-
"export declare function getPdfTemplate(name: never): never"
|
|
157
|
-
);
|
|
158
|
-
} else {
|
|
159
|
-
ordered.forEach((template, index) => {
|
|
160
|
-
lines.push(
|
|
161
|
-
`export declare function renderPdf(name: ${quote$1(template.key)}, props: PdfProps${index}): Promise<PdfRenderResult>`
|
|
162
|
-
);
|
|
163
|
-
});
|
|
164
|
-
lines.push(
|
|
165
|
-
"export declare function renderPdf(name: string, props: Record<string, unknown>, escapeHatch: { readonly unsafe: true }): Promise<PdfRenderResult>"
|
|
166
|
-
);
|
|
167
|
-
lines.push("");
|
|
168
|
-
ordered.forEach((template, index) => {
|
|
169
|
-
lines.push(
|
|
170
|
-
`export declare function getPdfTemplate(name: ${quote$1(template.key)}): PdfTemplate<PdfProps${index}>`
|
|
171
|
-
);
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
lines.push(
|
|
175
|
-
"",
|
|
176
|
-
`export declare const pdfTemplateKeys: readonly [${ordered.map((template) => quote$1(template.key)).join(", ")}]`,
|
|
177
|
-
"export type PdfTemplateKey = typeof pdfTemplateKeys[number]",
|
|
178
|
-
`export { NuxtPdfError, PDF_ERROR_CODES } from ${quote$1(options.runtimeImport)}`,
|
|
179
|
-
`export type { PdfErrorCode } from ${quote$1(options.runtimeImport)}`,
|
|
180
|
-
""
|
|
181
|
-
);
|
|
182
|
-
return lines.join("\n");
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
const quote = (value) => JSON.stringify(value);
|
|
186
21
|
const existingDirectories = async (directories) => {
|
|
187
22
|
const result = [];
|
|
188
23
|
for (const directory of directories) {
|
|
@@ -194,40 +29,6 @@ const existingDirectories = async (directories) => {
|
|
|
194
29
|
}
|
|
195
30
|
return result;
|
|
196
31
|
};
|
|
197
|
-
const generateAuthoringTypes = (componentsImport, composablesImport, definePdfImport) => `declare global {
|
|
198
|
-
const definePdf: typeof import(${quote(definePdfImport)})['definePdf']
|
|
199
|
-
const usePdfPageNumbers: typeof import(${quote(composablesImport)})['usePdfPageNumbers']
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
declare module 'vue' {
|
|
203
|
-
interface GlobalComponents {
|
|
204
|
-
PdfDocument: typeof import(${quote(componentsImport)})['PdfDocument']
|
|
205
|
-
PdfImage: typeof import(${quote(componentsImport)})['PdfImage']
|
|
206
|
-
PdfLink: typeof import(${quote(componentsImport)})['PdfLink']
|
|
207
|
-
PdfNote: typeof import(${quote(componentsImport)})['PdfNote']
|
|
208
|
-
PdfPage: typeof import(${quote(componentsImport)})['PdfPage']
|
|
209
|
-
PdfText: typeof import(${quote(componentsImport)})['PdfText']
|
|
210
|
-
PdfView: typeof import(${quote(componentsImport)})['PdfView']
|
|
211
|
-
PdfSvg: typeof import(${quote(componentsImport)})['PdfSvg']
|
|
212
|
-
PdfG: typeof import(${quote(componentsImport)})['PdfG']
|
|
213
|
-
PdfPath: typeof import(${quote(componentsImport)})['PdfPath']
|
|
214
|
-
PdfRect: typeof import(${quote(componentsImport)})['PdfRect']
|
|
215
|
-
PdfCircle: typeof import(${quote(componentsImport)})['PdfCircle']
|
|
216
|
-
PdfEllipse: typeof import(${quote(componentsImport)})['PdfEllipse']
|
|
217
|
-
PdfLine: typeof import(${quote(componentsImport)})['PdfLine']
|
|
218
|
-
PdfPolyline: typeof import(${quote(componentsImport)})['PdfPolyline']
|
|
219
|
-
PdfPolygon: typeof import(${quote(componentsImport)})['PdfPolygon']
|
|
220
|
-
PdfDefs: typeof import(${quote(componentsImport)})['PdfDefs']
|
|
221
|
-
PdfClipPath: typeof import(${quote(componentsImport)})['PdfClipPath']
|
|
222
|
-
PdfLinearGradient: typeof import(${quote(componentsImport)})['PdfLinearGradient']
|
|
223
|
-
PdfRadialGradient: typeof import(${quote(componentsImport)})['PdfRadialGradient']
|
|
224
|
-
PdfStop: typeof import(${quote(componentsImport)})['PdfStop']
|
|
225
|
-
PdfTspan: typeof import(${quote(componentsImport)})['PdfTspan']
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
export {}
|
|
230
|
-
`;
|
|
231
32
|
const module$1 = defineNuxtModule({
|
|
232
33
|
meta: {
|
|
233
34
|
name: "@lupinum/nuxt-pdf",
|
|
@@ -261,24 +62,7 @@ const module$1 = defineNuxtModule({
|
|
|
261
62
|
const limits = normalizePdfLimits(options.limits);
|
|
262
63
|
const resolvedLimits = limits ?? DEFAULT_PDF_RENDER_LIMITS;
|
|
263
64
|
const imageFiles = await discoverPdfImageFiles(layers, isIgnored);
|
|
264
|
-
const assetEntries =
|
|
265
|
-
for (const image of imageFiles) {
|
|
266
|
-
const format = pdfImageFormatFromKey(image.key);
|
|
267
|
-
if (nuxt.options.dev) {
|
|
268
|
-
assetEntries.push({ format, key: image.key, root: image.rootDir });
|
|
269
|
-
} else {
|
|
270
|
-
const loaded = await loadPdfImageAsset(image.key, {
|
|
271
|
-
roots: [image.rootDir],
|
|
272
|
-
maxBytes: resolvedLimits.maxImageBytes,
|
|
273
|
-
maxPixels: resolvedLimits.maxImagePixels
|
|
274
|
-
});
|
|
275
|
-
assetEntries.push({
|
|
276
|
-
dataB64: Buffer.from(loaded.data).toString("base64"),
|
|
277
|
-
format,
|
|
278
|
-
key: image.key
|
|
279
|
-
});
|
|
280
|
-
}
|
|
281
|
-
}
|
|
65
|
+
const assetEntries = await preparePdfImageAssets(imageFiles, resolvedLimits, nuxt.options.dev);
|
|
282
66
|
const fontRoots = await existingDirectories(
|
|
283
67
|
layers.map((layer) => join(layer.rootDir, "pdfs", "fonts"))
|
|
284
68
|
);
|
|
@@ -359,6 +143,14 @@ const module$1 = defineNuxtModule({
|
|
|
359
143
|
nuxt.hook("vite:serverCreated", (viteServer, environment) => {
|
|
360
144
|
if (environment.isClient) clientViteServer = viteServer;
|
|
361
145
|
});
|
|
146
|
+
const refreshPreview = () => clientViteServer?.ws.send({
|
|
147
|
+
type: "custom",
|
|
148
|
+
event: "nuxt-pdf:update",
|
|
149
|
+
data: {}
|
|
150
|
+
});
|
|
151
|
+
nuxt.hook("nitro:init", (nitro) => {
|
|
152
|
+
nitro.hooks.hook("dev:reload", refreshPreview);
|
|
153
|
+
});
|
|
362
154
|
nuxt.hook("builder:watch", async (event, path) => {
|
|
363
155
|
const absolutePath = isAbsolute(path) ? path : resolve(nuxt.options.srcDir, path);
|
|
364
156
|
const action = classifyPdfWatchEvent(
|
|
@@ -374,12 +166,7 @@ const module$1 = defineNuxtModule({
|
|
|
374
166
|
await nuxt.callHook("restart");
|
|
375
167
|
return;
|
|
376
168
|
}
|
|
377
|
-
if (action
|
|
378
|
-
clientViteServer?.ws.send({
|
|
379
|
-
type: "custom",
|
|
380
|
-
event: "nuxt-pdf:update",
|
|
381
|
-
data: {}
|
|
382
|
-
});
|
|
169
|
+
if (action === "refresh" && /\.(?:png|jpe?g)$/i.test(absolutePath)) refreshPreview();
|
|
383
170
|
});
|
|
384
171
|
addServerTemplate({
|
|
385
172
|
filename: "#pdf-preview-config",
|
|
@@ -398,7 +185,7 @@ const module$1 = defineNuxtModule({
|
|
|
398
185
|
view: { type: "iframe", src: joinURL(nuxt.options.app.baseURL || "/", "_pdf") }
|
|
399
186
|
});
|
|
400
187
|
});
|
|
401
|
-
for (const name of
|
|
188
|
+
for (const name of Object.keys(pdfStubs)) {
|
|
402
189
|
addComponent({
|
|
403
190
|
name,
|
|
404
191
|
export: name,
|
|
@@ -1,10 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export declare const
|
|
10
|
-
export declare const
|
|
1
|
+
export declare const PdfCircle: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
2
|
+
export declare const PdfClipPath: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
3
|
+
export declare const PdfDefs: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
4
|
+
export declare const PdfDocument: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
5
|
+
export declare const PdfEllipse: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
6
|
+
export declare const PdfG: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
7
|
+
export declare const PdfImage: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
8
|
+
export declare const PdfLine: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
9
|
+
export declare const PdfLinearGradient: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
10
|
+
export declare const PdfLink: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
11
|
+
export declare const PdfNote: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
12
|
+
export declare const PdfPage: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
13
|
+
export declare const PdfPath: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
14
|
+
export declare const PdfPolygon: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
15
|
+
export declare const PdfPolyline: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
16
|
+
export declare const PdfRadialGradient: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
17
|
+
export declare const PdfRect: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
18
|
+
export declare const PdfStop: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
19
|
+
export declare const PdfSvg: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
20
|
+
export declare const PdfText: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
21
|
+
export declare const PdfTspan: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
22
|
+
export declare const PdfView: import("vue").DefineComponent<{}, never, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -1,29 +1,5 @@
|
|
|
1
1
|
import { defineComponent } from "vue";
|
|
2
2
|
import { NuxtPdfError, PDF_ERROR_CODES } from "../shared/errors.js";
|
|
3
|
-
export const PDF_STUB_NAMES = [
|
|
4
|
-
"PdfCircle",
|
|
5
|
-
"PdfClipPath",
|
|
6
|
-
"PdfDefs",
|
|
7
|
-
"PdfDocument",
|
|
8
|
-
"PdfEllipse",
|
|
9
|
-
"PdfG",
|
|
10
|
-
"PdfImage",
|
|
11
|
-
"PdfLine",
|
|
12
|
-
"PdfLinearGradient",
|
|
13
|
-
"PdfLink",
|
|
14
|
-
"PdfNote",
|
|
15
|
-
"PdfPage",
|
|
16
|
-
"PdfPath",
|
|
17
|
-
"PdfPolygon",
|
|
18
|
-
"PdfPolyline",
|
|
19
|
-
"PdfRadialGradient",
|
|
20
|
-
"PdfRect",
|
|
21
|
-
"PdfStop",
|
|
22
|
-
"PdfSvg",
|
|
23
|
-
"PdfText",
|
|
24
|
-
"PdfTspan",
|
|
25
|
-
"PdfView"
|
|
26
|
-
];
|
|
27
3
|
const stubMessage = (name) => `<${name}> only works inside a discovered pdfs/*.vue template rendered by @lupinum/nuxt-pdf. Move this component under pdfs/, or replace it with ordinary Vue/HTML components.`;
|
|
28
4
|
const createPdfStub = (name) => defineComponent({
|
|
29
5
|
name,
|
|
@@ -32,6 +8,25 @@ const createPdfStub = (name) => defineComponent({
|
|
|
32
8
|
},
|
|
33
9
|
render: () => null
|
|
34
10
|
});
|
|
35
|
-
export const
|
|
36
|
-
|
|
37
|
-
);
|
|
11
|
+
export const PdfCircle = createPdfStub("PdfCircle");
|
|
12
|
+
export const PdfClipPath = createPdfStub("PdfClipPath");
|
|
13
|
+
export const PdfDefs = createPdfStub("PdfDefs");
|
|
14
|
+
export const PdfDocument = createPdfStub("PdfDocument");
|
|
15
|
+
export const PdfEllipse = createPdfStub("PdfEllipse");
|
|
16
|
+
export const PdfG = createPdfStub("PdfG");
|
|
17
|
+
export const PdfImage = createPdfStub("PdfImage");
|
|
18
|
+
export const PdfLine = createPdfStub("PdfLine");
|
|
19
|
+
export const PdfLinearGradient = createPdfStub("PdfLinearGradient");
|
|
20
|
+
export const PdfLink = createPdfStub("PdfLink");
|
|
21
|
+
export const PdfNote = createPdfStub("PdfNote");
|
|
22
|
+
export const PdfPage = createPdfStub("PdfPage");
|
|
23
|
+
export const PdfPath = createPdfStub("PdfPath");
|
|
24
|
+
export const PdfPolygon = createPdfStub("PdfPolygon");
|
|
25
|
+
export const PdfPolyline = createPdfStub("PdfPolyline");
|
|
26
|
+
export const PdfRadialGradient = createPdfStub("PdfRadialGradient");
|
|
27
|
+
export const PdfRect = createPdfStub("PdfRect");
|
|
28
|
+
export const PdfStop = createPdfStub("PdfStop");
|
|
29
|
+
export const PdfSvg = createPdfStub("PdfSvg");
|
|
30
|
+
export const PdfText = createPdfStub("PdfText");
|
|
31
|
+
export const PdfTspan = createPdfStub("PdfTspan");
|
|
32
|
+
export const PdfView = createPdfStub("PdfView");
|
|
@@ -276,29 +276,7 @@ export const loadPdfImageAsset = async (relativePath, options) => {
|
|
|
276
276
|
"The local PDF image was not found in a configured asset root."
|
|
277
277
|
);
|
|
278
278
|
};
|
|
279
|
-
const RESOLVED_IMAGE_CACHE_BYTES = 32 * 1024 * 1024;
|
|
280
|
-
const resolvedImageCache = /* @__PURE__ */ new Map();
|
|
281
|
-
let resolvedImageCacheBytes = 0;
|
|
282
279
|
const embeddedImageCache = /* @__PURE__ */ new WeakMap();
|
|
283
|
-
const rememberResolvedImage = (cacheKey, image) => {
|
|
284
|
-
if (resolvedImageCache.has(cacheKey)) return;
|
|
285
|
-
resolvedImageCache.set(cacheKey, image);
|
|
286
|
-
resolvedImageCacheBytes += image.data.byteLength;
|
|
287
|
-
while (resolvedImageCacheBytes > RESOLVED_IMAGE_CACHE_BYTES && resolvedImageCache.size > 1) {
|
|
288
|
-
const oldest = resolvedImageCache.keys().next().value;
|
|
289
|
-
if (oldest === void 0) break;
|
|
290
|
-
resolvedImageCacheBytes -= resolvedImageCache.get(oldest).data.byteLength;
|
|
291
|
-
resolvedImageCache.delete(oldest);
|
|
292
|
-
}
|
|
293
|
-
};
|
|
294
|
-
const cachedResolvedImage = (cacheKey) => {
|
|
295
|
-
const cached = resolvedImageCache.get(cacheKey);
|
|
296
|
-
if (!cached) return void 0;
|
|
297
|
-
return {
|
|
298
|
-
...cached,
|
|
299
|
-
data: Buffer.from(cached.data)
|
|
300
|
-
};
|
|
301
|
-
};
|
|
302
280
|
const resolveLocalImage = async (source, assets, maxBytes, maxPixels, declaredFormat) => {
|
|
303
281
|
const key = canonicalAssetKey(source);
|
|
304
282
|
const pathFormat = formatFromExtension(key);
|
|
@@ -328,8 +306,8 @@ const resolveLocalImage = async (source, assets, maxBytes, maxPixels, declaredFo
|
|
|
328
306
|
byLimits = /* @__PURE__ */ new Map();
|
|
329
307
|
embeddedImageCache.set(entry, byLimits);
|
|
330
308
|
}
|
|
331
|
-
const
|
|
332
|
-
if (
|
|
309
|
+
const cached = byLimits.get(limitsKey);
|
|
310
|
+
if (cached) return { ...cached, data: Buffer.from(cached.data) };
|
|
333
311
|
const resolved2 = validateImageBytes(
|
|
334
312
|
Buffer.from(entry.dataB64, "base64"),
|
|
335
313
|
maxBytes,
|
|
@@ -339,21 +317,6 @@ const resolveLocalImage = async (source, assets, maxBytes, maxPixels, declaredFo
|
|
|
339
317
|
byLimits.set(limitsKey, resolved2);
|
|
340
318
|
return { ...resolved2, data: Buffer.from(resolved2.data) };
|
|
341
319
|
}
|
|
342
|
-
let fileStat;
|
|
343
|
-
try {
|
|
344
|
-
fileStat = await stat(resolve(entry.root, ...key.split("/")));
|
|
345
|
-
} catch (error) {
|
|
346
|
-
if (isMissingFileError(error)) {
|
|
347
|
-
return invalid(`The local PDF image "${key}" was not found under pdfs/assets.`);
|
|
348
|
-
}
|
|
349
|
-
return invalid("The local PDF image cannot be inspected.", error);
|
|
350
|
-
}
|
|
351
|
-
if (!fileStat.isFile()) {
|
|
352
|
-
return invalid("The local PDF image is not a regular file.");
|
|
353
|
-
}
|
|
354
|
-
const cacheKey = `disk\0${key}\0${fileStat.mtimeMs}\0${fileStat.size}\0${maxBytes}\0${maxPixels}`;
|
|
355
|
-
const cached = cachedResolvedImage(cacheKey);
|
|
356
|
-
if (cached) return cached;
|
|
357
320
|
const loaded = await loadPdfImageAsset(key, {
|
|
358
321
|
roots: [entry.root],
|
|
359
322
|
maxBytes,
|
|
@@ -366,7 +329,6 @@ const resolveLocalImage = async (source, assets, maxBytes, maxPixels, declaredFo
|
|
|
366
329
|
pixels: loaded.pixels,
|
|
367
330
|
width: loaded.width
|
|
368
331
|
});
|
|
369
|
-
rememberResolvedImage(cacheKey, resolved);
|
|
370
332
|
return { ...resolved, data: Buffer.from(resolved.data) };
|
|
371
333
|
};
|
|
372
334
|
const isRemoteCandidate = (source) => /^https?:/i.test(source);
|
|
@@ -233,7 +233,7 @@ const viewerPage = async (template, props, rootPath, scenario, hmrClientPath2 =
|
|
|
233
233
|
}
|
|
234
234
|
return htmlResponse(
|
|
235
235
|
title,
|
|
236
|
-
`<header><h1>${escapeHtml(title)}</h1>${actions}</header>${nav}${body}<script type="module">import { createHotContext } from ${JSON.stringify(hmrClientPath2)};createHotContext('/_pdf').on('nuxt-pdf:update',()=>{
|
|
236
|
+
`<header><h1>${escapeHtml(title)}</h1>${actions}</header>${nav}${body}<script type="module">import { createHotContext } from ${JSON.stringify(hmrClientPath2)};createHotContext('/_pdf').on('nuxt-pdf:update',()=>{location.reload();});<\/script>`
|
|
237
237
|
);
|
|
238
238
|
};
|
|
239
239
|
export const renderPdfPreview = async (registry, request = {}) => {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { PdfRegistry, PdfRegistryEntries, createPdfRegistry, createPdfTemplate } from '../dist/runtime/server/registry.js';
|
|
2
|
+
export { NuxtPdfError, PDF_ERROR_CODES, PdfErrorCode } from '../dist/runtime/shared/errors.js';
|
|
3
|
+
export { usePdfPageNumbers } from '../dist/runtime/composables/index.js';
|
|
4
|
+
export { PdfComponentProps, PdfDefinition, PdfRenderResult, PdfTemplate } from '../dist/runtime/shared/template.js';
|
package/dist/server.mjs
ADDED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readdir, realpath, open, stat, readFile } from 'node:fs/promises';
|
|
2
2
|
import { resolve, join, relative, isAbsolute, posix, sep, dirname, extname, win32 } from 'node:path';
|
|
3
3
|
import { Buffer } from 'node:buffer';
|
|
4
|
-
import { existsSync, statSync } from 'node:fs';
|
|
4
|
+
import { existsSync, statSync, readFileSync } from 'node:fs';
|
|
5
5
|
import { parse, compileScript, compileTemplate, babelParse } from '@vue/compiler-sfc';
|
|
6
6
|
import remapping from '@jridgewell/remapping';
|
|
7
7
|
import { transform } from 'esbuild';
|
|
@@ -493,6 +493,10 @@ const bundlePdfFonts = async (declarations, options) => {
|
|
|
493
493
|
};
|
|
494
494
|
|
|
495
495
|
const authoringImportContexts = /* @__PURE__ */ new Map();
|
|
496
|
+
const compilerFileSystem = {
|
|
497
|
+
fileExists: (file) => statSync(file, { throwIfNoEntry: false })?.isFile() ?? false,
|
|
498
|
+
readFile: (file) => readFileSync(file, "utf8")
|
|
499
|
+
};
|
|
496
500
|
class PdfSfcCompileError extends Error {
|
|
497
501
|
column;
|
|
498
502
|
filename;
|
|
@@ -536,6 +540,7 @@ const createPdfSfcPlugin = (options) => ({
|
|
|
536
540
|
if (!filename) return null;
|
|
537
541
|
const kind = options.files.get(filename);
|
|
538
542
|
if (!kind) return null;
|
|
543
|
+
this.addWatchFile(filename);
|
|
539
544
|
return compilePdfSfc(
|
|
540
545
|
await readFile(filename, "utf8"),
|
|
541
546
|
filename,
|
|
@@ -882,6 +887,7 @@ function assertMetadataHoistable(source, descriptor, filename, macro) {
|
|
|
882
887
|
try {
|
|
883
888
|
const validation = parsePdfSfc(validationSource, filename);
|
|
884
889
|
compileScript(validation, {
|
|
890
|
+
fs: compilerFileSystem,
|
|
885
891
|
id: "nuxt-pdf-metadata-hoist",
|
|
886
892
|
sourceMap: false
|
|
887
893
|
});
|
|
@@ -976,6 +982,7 @@ function compileComponent(descriptor, filename, isProduction) {
|
|
|
976
982
|
if (descriptor.scriptSetup) {
|
|
977
983
|
try {
|
|
978
984
|
const result = compileScript(descriptor, {
|
|
985
|
+
fs: compilerFileSystem,
|
|
979
986
|
genDefaultAs: COMPONENT_VARIABLE,
|
|
980
987
|
id: "nuxt-pdf",
|
|
981
988
|
inlineTemplate: true,
|
|
@@ -1001,6 +1008,7 @@ function compileComponent(descriptor, filename, isProduction) {
|
|
|
1001
1008
|
if (descriptor.script) {
|
|
1002
1009
|
try {
|
|
1003
1010
|
const script = compileScript(descriptor, {
|
|
1011
|
+
fs: compilerFileSystem,
|
|
1004
1012
|
genDefaultAs: COMPONENT_VARIABLE,
|
|
1005
1013
|
id: "nuxt-pdf",
|
|
1006
1014
|
isProd: isProduction,
|
|
@@ -1171,4 +1179,4 @@ function isRecord(value) {
|
|
|
1171
1179
|
return typeof value === "object" && value !== null;
|
|
1172
1180
|
}
|
|
1173
1181
|
|
|
1174
|
-
export {
|
|
1182
|
+
export { discoverPdfImageFiles as a, bundlePdfFonts as b, compilePdfSfc as c, discoverPdfTemplates as d, discoverPdfComponentFiles as e, createPdfSfcPlugin as f, classifyPdfWatchEvent as g, templateKeyFromRelativePath as t };
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import * as pdfStubs from '../../dist/runtime/components/stubs.js';
|
|
2
|
+
import { joinURL } from 'ufo';
|
|
3
|
+
import { Buffer } from 'node:buffer';
|
|
4
|
+
import { pdfImageFormatFromKey, loadPdfImageAsset } from '../../dist/runtime/server/assets/resolve-asset.js';
|
|
5
|
+
|
|
6
|
+
const generateAuthoringTypes = (componentsImport, composablesImport, definePdfImport) => `declare global {
|
|
7
|
+
const definePdf: typeof import(${JSON.stringify(definePdfImport)})['definePdf']
|
|
8
|
+
const usePdfPageNumbers: typeof import(${JSON.stringify(composablesImport)})['usePdfPageNumbers']
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
declare module 'vue' {
|
|
12
|
+
interface GlobalComponents {
|
|
13
|
+
${Object.keys(pdfStubs).map((name) => ` ${name}: typeof import(${JSON.stringify(componentsImport)})['${name}']`).join("\n")}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export {}
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
const compareText = (left, right) => {
|
|
21
|
+
if (left < right) return -1;
|
|
22
|
+
if (left > right) return 1;
|
|
23
|
+
return 0;
|
|
24
|
+
};
|
|
25
|
+
const quote = (value) => JSON.stringify(value);
|
|
26
|
+
const generatePdfPreviewConfig = (baseURL, buildAssetsDir) => `export const hmrClientPath = ${quote(joinURL(
|
|
27
|
+
baseURL.replace(/^\.\//, "/") || "/",
|
|
28
|
+
buildAssetsDir,
|
|
29
|
+
"@vite/client"
|
|
30
|
+
))}
|
|
31
|
+
`;
|
|
32
|
+
const importPath = (filePath) => filePath.replaceAll("\\", "/");
|
|
33
|
+
const runtimeOptionsSource = (options) => {
|
|
34
|
+
const assets = options.assets ?? [];
|
|
35
|
+
const fonts = options.fonts ?? [];
|
|
36
|
+
const { remote, limits } = options;
|
|
37
|
+
for (const asset of assets) {
|
|
38
|
+
if (asset.root !== void 0 === (asset.dataB64 !== void 0)) {
|
|
39
|
+
throw new TypeError(
|
|
40
|
+
`PDF image asset "${asset.key}" must declare exactly one of root or dataB64.`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (assets.length === 0 && fonts.length === 0 && !remote && !limits) return [];
|
|
45
|
+
const lines = ["", "const __pdfRuntimeOptions = Object.freeze({"];
|
|
46
|
+
if (assets.length > 0) {
|
|
47
|
+
lines.push(" assets: Object.freeze({");
|
|
48
|
+
for (const asset of assets) {
|
|
49
|
+
const entry = asset.root !== void 0 ? `{ format: ${quote(asset.format)}, root: ${quote(asset.root)} }` : `{ dataB64: ${quote(asset.dataB64 ?? "")}, format: ${quote(asset.format)} }`;
|
|
50
|
+
lines.push(` ${quote(asset.key)}: Object.freeze(${entry}),`);
|
|
51
|
+
}
|
|
52
|
+
lines.push(" }),");
|
|
53
|
+
}
|
|
54
|
+
if (fonts.length > 0) {
|
|
55
|
+
lines.push(" fonts: Object.freeze([");
|
|
56
|
+
for (const font of fonts) {
|
|
57
|
+
lines.push(` Object.freeze(${JSON.stringify(font)}),`);
|
|
58
|
+
}
|
|
59
|
+
lines.push(" ]),");
|
|
60
|
+
}
|
|
61
|
+
if (remote) {
|
|
62
|
+
lines.push(` remote: Object.freeze(${JSON.stringify(remote)}),`);
|
|
63
|
+
}
|
|
64
|
+
if (limits) {
|
|
65
|
+
lines.push(` limits: Object.freeze(${JSON.stringify(limits)}),`);
|
|
66
|
+
}
|
|
67
|
+
lines.push("})");
|
|
68
|
+
return lines;
|
|
69
|
+
};
|
|
70
|
+
const orderedTemplates = (templates) => {
|
|
71
|
+
const result = [...templates].sort(
|
|
72
|
+
(left, right) => compareText(left.key, right.key)
|
|
73
|
+
);
|
|
74
|
+
const keys = /* @__PURE__ */ new Map();
|
|
75
|
+
for (const template of result) {
|
|
76
|
+
const duplicate = keys.get(template.key);
|
|
77
|
+
if (duplicate) {
|
|
78
|
+
throw new TypeError(
|
|
79
|
+
`Cannot generate duplicate PDF template key "${template.key}" from "${duplicate.filePath}" and "${template.filePath}".`
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
keys.set(template.key, template);
|
|
83
|
+
}
|
|
84
|
+
return result;
|
|
85
|
+
};
|
|
86
|
+
const validateOptions = (options) => {
|
|
87
|
+
if (options.runtimeImport.trim() === "") {
|
|
88
|
+
throw new TypeError("runtimeImport is required to generate the PDF registry.");
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
const generatePdfRuntimeRegistry = (templates, options) => {
|
|
92
|
+
validateOptions(options);
|
|
93
|
+
const ordered = orderedTemplates(templates);
|
|
94
|
+
const runtimeImports = options.development ? "createPdfPreviewEntry, createPdfRegistry, createPdfTemplate" : "createPdfRegistry, createPdfTemplate";
|
|
95
|
+
const lines = [
|
|
96
|
+
`import { ${runtimeImports} } from ${quote(options.runtimeImport)}`
|
|
97
|
+
];
|
|
98
|
+
ordered.forEach((template, index) => {
|
|
99
|
+
lines.push(
|
|
100
|
+
`import __pdfTemplate${index} from ${quote(importPath(template.filePath))}`
|
|
101
|
+
);
|
|
102
|
+
});
|
|
103
|
+
const runtimeOptions = runtimeOptionsSource(options);
|
|
104
|
+
lines.push(...runtimeOptions, "", "const registry = createPdfRegistry({");
|
|
105
|
+
ordered.forEach((template, index) => {
|
|
106
|
+
const file = quote(`pdfs/${template.relativePath}`);
|
|
107
|
+
const runtimeArgument = options.development ? runtimeOptions.length > 0 ? `, { ...__pdfRuntimeOptions, file: ${file} }` : `, { file: ${file} }` : runtimeOptions.length > 0 ? ", __pdfRuntimeOptions" : "";
|
|
108
|
+
lines.push(
|
|
109
|
+
` ${quote(template.key)}: createPdfTemplate(${quote(template.key)}, __pdfTemplate${index}${runtimeArgument}),`
|
|
110
|
+
);
|
|
111
|
+
});
|
|
112
|
+
lines.push("})");
|
|
113
|
+
if (options.development) {
|
|
114
|
+
lines.push("", "export const pdfPreview = Object.freeze({");
|
|
115
|
+
ordered.forEach((template, index) => {
|
|
116
|
+
lines.push(
|
|
117
|
+
` ${quote(template.key)}: createPdfPreviewEntry(registry.pdf[${quote(template.key)}], __pdfTemplate${index}, { file: ${quote(`pdfs/${template.relativePath}`)} }),`
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
lines.push("})");
|
|
121
|
+
}
|
|
122
|
+
lines.push(
|
|
123
|
+
"",
|
|
124
|
+
"export const pdf = registry.pdf",
|
|
125
|
+
"export const renderPdf = registry.renderPdf",
|
|
126
|
+
"export const getPdfTemplate = registry.getPdfTemplate",
|
|
127
|
+
"export const pdfTemplateKeys = registry.pdfTemplateKeys",
|
|
128
|
+
`export { NuxtPdfError, PDF_ERROR_CODES } from ${quote(options.runtimeImport)}`,
|
|
129
|
+
""
|
|
130
|
+
);
|
|
131
|
+
return lines.join("\n");
|
|
132
|
+
};
|
|
133
|
+
const generatePdfRegistryTypes = (templates, options) => {
|
|
134
|
+
validateOptions(options);
|
|
135
|
+
const ordered = orderedTemplates(templates);
|
|
136
|
+
const lines = [
|
|
137
|
+
`import type { PdfComponentProps, PdfRenderResult, PdfTemplate } from ${quote(options.runtimeImport)}`
|
|
138
|
+
];
|
|
139
|
+
ordered.forEach((template, index) => {
|
|
140
|
+
lines.push(
|
|
141
|
+
"",
|
|
142
|
+
`type PdfComponent${index} = typeof import(${quote(importPath(template.filePath))})['default']`,
|
|
143
|
+
`type PdfProps${index} = PdfComponentProps<PdfComponent${index}>`
|
|
144
|
+
);
|
|
145
|
+
});
|
|
146
|
+
lines.push("", "export declare const pdf: {");
|
|
147
|
+
ordered.forEach((template, index) => {
|
|
148
|
+
lines.push(
|
|
149
|
+
` readonly ${quote(template.key)}: PdfTemplate<PdfProps${index}>`
|
|
150
|
+
);
|
|
151
|
+
});
|
|
152
|
+
lines.push("}", "");
|
|
153
|
+
if (ordered.length === 0) {
|
|
154
|
+
lines.push(
|
|
155
|
+
"export declare function renderPdf(name: never, props: never): Promise<PdfRenderResult>",
|
|
156
|
+
"export declare function getPdfTemplate(name: never): never"
|
|
157
|
+
);
|
|
158
|
+
} else {
|
|
159
|
+
ordered.forEach((template, index) => {
|
|
160
|
+
lines.push(
|
|
161
|
+
`export declare function renderPdf(name: ${quote(template.key)}, props: PdfProps${index}): Promise<PdfRenderResult>`
|
|
162
|
+
);
|
|
163
|
+
});
|
|
164
|
+
lines.push(
|
|
165
|
+
"export declare function renderPdf(name: string, props: Record<string, unknown>, escapeHatch: { readonly unsafe: true }): Promise<PdfRenderResult>"
|
|
166
|
+
);
|
|
167
|
+
lines.push("");
|
|
168
|
+
ordered.forEach((template, index) => {
|
|
169
|
+
lines.push(
|
|
170
|
+
`export declare function getPdfTemplate(name: ${quote(template.key)}): PdfTemplate<PdfProps${index}>`
|
|
171
|
+
);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
lines.push(
|
|
175
|
+
"",
|
|
176
|
+
`export declare const pdfTemplateKeys: readonly [${ordered.map((template) => quote(template.key)).join(", ")}]`,
|
|
177
|
+
"export type PdfTemplateKey = typeof pdfTemplateKeys[number]",
|
|
178
|
+
`export { NuxtPdfError, PDF_ERROR_CODES } from ${quote(options.runtimeImport)}`,
|
|
179
|
+
`export type { PdfErrorCode } from ${quote(options.runtimeImport)}`,
|
|
180
|
+
""
|
|
181
|
+
);
|
|
182
|
+
return lines.join("\n");
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
async function preparePdfImageAssets(images, limits, development) {
|
|
186
|
+
const entries = [];
|
|
187
|
+
for (const image of images) {
|
|
188
|
+
const format = pdfImageFormatFromKey(image.key);
|
|
189
|
+
if (development) {
|
|
190
|
+
entries.push({ format, key: image.key, root: image.rootDir });
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
const loaded = await loadPdfImageAsset(image.key, {
|
|
194
|
+
roots: [image.rootDir],
|
|
195
|
+
maxBytes: limits.maxImageBytes,
|
|
196
|
+
maxPixels: limits.maxImagePixels
|
|
197
|
+
});
|
|
198
|
+
entries.push({ dataB64: Buffer.from(loaded.data).toString("base64"), format, key: image.key });
|
|
199
|
+
}
|
|
200
|
+
return entries;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export { generateAuthoringTypes as a, generatePdfRegistryTypes as b, generatePdfPreviewConfig as c, generatePdfRuntimeRegistry as g, preparePdfImageAssets as p };
|
package/dist/test.mjs
CHANGED
|
@@ -10,7 +10,7 @@ import { mkdir, writeFile, rm, readFile, readdir } from 'node:fs/promises';
|
|
|
10
10
|
import { resolve, dirname, join, relative, basename } from 'node:path';
|
|
11
11
|
import { pathToFileURL, fileURLToPath } from 'node:url';
|
|
12
12
|
import { build } from 'esbuild';
|
|
13
|
-
import { t as templateKeyFromRelativePath,
|
|
13
|
+
import { t as templateKeyFromRelativePath, a as discoverPdfImageFiles, b as bundlePdfFonts, c as compilePdfSfc } from './shared/nuxt-pdf.C-E8MM_K.mjs';
|
|
14
14
|
import { pdfImageFormatFromKey } from '../dist/runtime/server/assets/resolve-asset.js';
|
|
15
15
|
import '@vue/compiler-sfc';
|
|
16
16
|
import '@jridgewell/remapping';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lupinum/nuxt-pdf",
|
|
3
|
-
"version": "0.4.0-beta.
|
|
3
|
+
"version": "0.4.0-beta.4",
|
|
4
4
|
"description": "Author and render PDFs with Vue components in Nuxt",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nuxt",
|
|
@@ -30,6 +30,14 @@
|
|
|
30
30
|
"./test": {
|
|
31
31
|
"types": "./dist/test.d.mts",
|
|
32
32
|
"import": "./dist/test.mjs"
|
|
33
|
+
},
|
|
34
|
+
"./build": {
|
|
35
|
+
"types": "./dist/build.d.mts",
|
|
36
|
+
"import": "./dist/build.mjs"
|
|
37
|
+
},
|
|
38
|
+
"./server": {
|
|
39
|
+
"types": "./dist/server.d.mts",
|
|
40
|
+
"import": "./dist/server.mjs"
|
|
33
41
|
}
|
|
34
42
|
},
|
|
35
43
|
"main": "./dist/module.mjs",
|
|
@@ -68,15 +76,14 @@
|
|
|
68
76
|
"release:notes": "node scripts/write-release-notes.mjs",
|
|
69
77
|
"release:pack": "pnpm build && node scripts/check-release-artifact.mjs release-artifacts",
|
|
70
78
|
"release:prepare": "changelogen --bump --clean",
|
|
71
|
-
"release:verify": "pnpm
|
|
79
|
+
"release:verify": "pnpm check:dependencies && pnpm audit:all && pnpm check:source && node scripts/check-release-artifact.mjs release-artifacts",
|
|
72
80
|
"test:artifact": "node scripts/check-release-artifact.mjs",
|
|
73
81
|
"test:dependencies": "node scripts/check-production-dependencies.mjs",
|
|
74
|
-
"test:docs": "node scripts/check-documentation.mjs && pnpm
|
|
82
|
+
"test:docs": "node scripts/check-documentation.mjs && pnpm --dir docs check",
|
|
75
83
|
"test:package": "node scripts/check-package.mjs",
|
|
76
|
-
"test:package-metadata": "node scripts/check-api-report.mjs",
|
|
77
84
|
"test:performance": "node --expose-gc ./node_modules/vitest/vitest.mjs run --config vitest.performance.config.ts",
|
|
78
85
|
"test:prepare": "pnpm dev:prepare && nuxt prepare test/fixtures/layers",
|
|
79
|
-
"test:production": "vitest run --config vitest.production.config.ts",
|
|
86
|
+
"test:production": "pnpm build && vitest run --config vitest.production.config.ts",
|
|
80
87
|
"test:quickstart": "node scripts/test-package-quickstart.mjs",
|
|
81
88
|
"test:raster": "vitest run --config vitest.raster.config.ts",
|
|
82
89
|
"test:version-headings": "node scripts/check-version-headings.mjs",
|
|
@@ -84,10 +91,12 @@
|
|
|
84
91
|
"check:vercel": "node scripts/check-vercel-config.mjs",
|
|
85
92
|
"test:serverless": "vitest run --config vitest.serverless.config.ts",
|
|
86
93
|
"test:watch": "vitest watch",
|
|
87
|
-
"typecheck": "nuxt prepare && vue-tsc --noEmit && nuxt prepare test/fixtures/basic && vue-tsc --noEmit -p test/fixtures/basic/tsconfig.json && pnpm
|
|
94
|
+
"typecheck": "pnpm test:prepare && nuxt prepare && vue-tsc --noEmit && nuxt prepare test/fixtures/basic && vue-tsc --noEmit -p test/fixtures/basic/tsconfig.json && pnpm --dir playground exec vue-tsc --noEmit",
|
|
88
95
|
"audit:all": "pnpm audit",
|
|
89
|
-
"
|
|
90
|
-
"
|
|
96
|
+
"check:dependencies": "node scripts/check-dependency-policy.mjs",
|
|
97
|
+
"verify": "pnpm check:dependencies && pnpm audit:all && pnpm check",
|
|
98
|
+
"check": "pnpm check:source && pnpm test:artifact",
|
|
99
|
+
"check:source": "pnpm format:check && pnpm check:vercel && pnpm typecheck && pnpm test:docs && pnpm test:version-headings && pnpm test:workflows && pnpm test:dependencies && pnpm test && pnpm test:production && pnpm test:serverless && pnpm build && pnpm test:api && pnpm dev:build"
|
|
91
100
|
},
|
|
92
101
|
"dependencies": {
|
|
93
102
|
"@jridgewell/remapping": "2.3.5",
|
|
@@ -97,11 +106,13 @@
|
|
|
97
106
|
"@react-pdf/pdfkit": "5.1.1",
|
|
98
107
|
"@react-pdf/primitives": "4.3.0",
|
|
99
108
|
"@react-pdf/render": "4.5.1",
|
|
100
|
-
"@vue/compiler-sfc": "3.5.
|
|
109
|
+
"@vue/compiler-sfc": "3.5.42",
|
|
101
110
|
"esbuild": "0.28.1",
|
|
102
111
|
"h3": "1.15.11",
|
|
103
112
|
"ufo": "1.6.4",
|
|
104
|
-
"unimport": "6.3.0"
|
|
113
|
+
"unimport": "6.3.0",
|
|
114
|
+
"typescript": "~5.9.3",
|
|
115
|
+
"vue-tsc": "^3.3.3"
|
|
105
116
|
},
|
|
106
117
|
"peerDependencies": {
|
|
107
118
|
"@napi-rs/canvas": "^0.1.97",
|
|
@@ -137,10 +148,8 @@
|
|
|
137
148
|
"publint": "^0.3.21",
|
|
138
149
|
"react": "19.2.0",
|
|
139
150
|
"source-code-pro": "2.42.0",
|
|
140
|
-
"typescript": "~5.9.3",
|
|
141
151
|
"vitest": "^4.1.8",
|
|
142
|
-
"vue": "3.5.
|
|
143
|
-
"vue-tsc": "^3.3.3",
|
|
152
|
+
"vue": "3.5.42",
|
|
144
153
|
"yaml": "2.9.0"
|
|
145
154
|
}
|
|
146
155
|
}
|