@lpdfio/lpdf 0.5.0 → 0.7.0
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/LICENSE +33 -16
- package/README.md +33 -38
- package/dist/_shared.d.ts +3 -6
- package/dist/browser.js +21 -62
- package/dist/canvas.d.ts +8 -6
- package/dist/canvas.js +13 -13
- package/dist/engine.d.ts +16 -13
- package/dist/engine.js +23 -23
- package/dist/index.d.ts +9 -45
- package/dist/index.js +12 -32
- package/dist/kit-to-xml.d.ts +2 -2
- package/dist/kit.d.ts +7 -16
- package/dist/kit.js +12 -12
- package/dist/layout.d.ts +35 -34
- package/dist/layout.js +43 -43
- package/dist/pdf.d.ts +61 -0
- package/dist/pdf.js +70 -0
- package/package.json +2 -2
package/LICENSE
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Lpdf License
|
|
2
2
|
|
|
3
3
|
Copyright © 2026 Codesense LLC
|
|
4
|
+
|
|
4
5
|
License inquiries: license@lpdf.io
|
|
5
6
|
|
|
6
7
|
---
|
|
@@ -39,13 +40,11 @@ Companies and organizations whose total annual gross revenue exceeded **1,000,00
|
|
|
39
40
|
|
|
40
41
|
"Production environment" means any environment in which the Software processes real user data or supports live business operations, including staging environments accessible by end users.
|
|
41
42
|
|
|
42
|
-
Organizations whose revenue crosses the 1,000,000 USD threshold have a **90-day grace period** following the close of their fiscal year to obtain a Professional or Enterprise license. During this grace period, continued use is permitted.
|
|
43
|
-
|
|
44
43
|
### Larger Businesses
|
|
45
44
|
|
|
46
45
|
Companies and organizations whose total annual gross revenue exceeded **10,000,000 USD** in the most recent 12-month fiscal year must obtain an Enterprise License to use Lpdf in production environments.
|
|
47
46
|
|
|
48
|
-
Organizations whose revenue crosses the 10,000,000 USD threshold have a **90-day grace period** following the close of their fiscal year to obtain an Enterprise license. During this grace period, continued use under a Professional License is permitted.
|
|
47
|
+
Organizations whose revenue crosses the 10,000,000 USD threshold have a **90-day grace period** following the close of their fiscal year to obtain an Enterprise license. During this grace period, continued use under a Professional License is permitted. The licensee remains subject to the terms of their existing Professional License and does not gain Enterprise rights until an Enterprise License is obtained.
|
|
49
48
|
|
|
50
49
|
### Supporting Lpdf
|
|
51
50
|
|
|
@@ -57,17 +56,21 @@ Paid licenses directly fund the continued development, maintenance, and improvem
|
|
|
57
56
|
|
|
58
57
|
*Applies to: individuals, open-source projects, non-profit organizations, and companies with annual gross revenue under 1,000,000 USD.*
|
|
59
58
|
|
|
60
|
-
Permission is hereby granted, free of charge, to any person or qualifying organization obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
|
59
|
+
Permission is hereby granted, free of charge, to any person or qualifying organization obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
61
60
|
|
|
62
|
-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
61
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. Any redistribution of the Software must be made under the terms of this Community License and may not be sublicensed under different terms.
|
|
63
62
|
|
|
64
63
|
All modifications to the Software made by the licensee remain the intellectual property of the licensee. Codesense LLC claims no ownership over modifications unless they are voluntarily submitted as contributions to the Lpdf project under a separate Contributor License Agreement.
|
|
65
64
|
|
|
66
65
|
If your organization's annual gross revenue exceeds 1,000,000 USD, your rights under this Community License are automatically terminated upon expiration of the 90-day grace period described above, and you must obtain a Professional or Enterprise license before continuing to use Lpdf in production.
|
|
67
66
|
|
|
67
|
+
### Governing Law
|
|
68
|
+
|
|
69
|
+
This license is governed by and construed in accordance with the laws of the State of Texas, United States, without regard to its conflict of law provisions.
|
|
70
|
+
|
|
68
71
|
### Disclaimer of Warranty
|
|
69
72
|
|
|
70
|
-
THE SOFTWARE IS PROVIDED "AS IS"
|
|
73
|
+
THE SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL CODESENSE LLC OR ITS CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. IN NO EVENT SHALL CODESENSE LLC'S TOTAL CUMULATIVE LIABILITY TO ANY PARTY EXCEED THE GREATER OF (A) THE FEES PAID BY THAT PARTY TO CODESENSE LLC IN THE TWELVE MONTHS PRECEDING THE CLAIM, OR (B) ONE HUNDRED US DOLLARS (USD 100).
|
|
71
74
|
|
|
72
75
|
---
|
|
73
76
|
|
|
@@ -97,7 +100,11 @@ Upon payment, the licensee receives a perpetual license for the version of Lpdf
|
|
|
97
100
|
|
|
98
101
|
### Support
|
|
99
102
|
|
|
100
|
-
Professional License holders receive email support from Codesense LLC.
|
|
103
|
+
Professional License holders receive email support from Codesense LLC with a target response time of 3 business days for standard inquiries. Support terms are further detailed at lpdf.io/support.
|
|
104
|
+
|
|
105
|
+
### Audit
|
|
106
|
+
|
|
107
|
+
Codesense LLC may, upon 30 days' written notice and no more than once per calendar year, request a written certification from the licensee confirming their applicable license tier and annual gross revenue for the most recent fiscal year. The licensee agrees to provide such certification within 15 business days of the request.
|
|
101
108
|
|
|
102
109
|
### Ownership and Modifications
|
|
103
110
|
|
|
@@ -123,9 +130,9 @@ THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY KIND, EXPRESS OR IM
|
|
|
123
130
|
|
|
124
131
|
### Governing Law and Dispute Resolution
|
|
125
132
|
|
|
126
|
-
This license is governed by and construed in accordance with the laws of the State of
|
|
133
|
+
This license is governed by and construed in accordance with the laws of the State of Texas, United States, without regard to its conflict of law provisions.
|
|
127
134
|
|
|
128
|
-
Any dispute arising out of or relating to this license or the Software shall be resolved by binding arbitration administered by the American Arbitration Association under its Commercial Arbitration Rules. The arbitration shall take place in
|
|
135
|
+
Any dispute arising out of or relating to this license or the Software shall be resolved by binding arbitration administered by the American Arbitration Association under its Commercial Arbitration Rules. The arbitration shall take place in Plano, Texas. Judgment on the award rendered by the arbitrator may be entered in any court of competent jurisdiction.
|
|
129
136
|
|
|
130
137
|
Notwithstanding the foregoing, either party may seek injunctive or other equitable relief in any court of competent jurisdiction to prevent the actual or threatened infringement, misappropriation, or violation of a party's intellectual property rights.
|
|
131
138
|
|
|
@@ -139,16 +146,16 @@ Notwithstanding the foregoing, either party may seek injunctive or other equitab
|
|
|
139
146
|
|
|
140
147
|
Licensees agree not to make false statements of fact about Lpdf, Codesense LLC, or its contributors that are intended to cause material harm to the reputation of the project or the company. This clause does not restrict good-faith criticism, bug reports, public discussion of software deficiencies, or reviews based on the licensee's genuine experience.
|
|
141
148
|
|
|
142
|
-
License rights may not be rented, leased, or transferred to any third party.
|
|
149
|
+
License rights may not be rented, leased, or transferred to any third party, except as expressly permitted under the subsidiary grant below.
|
|
143
150
|
|
|
144
151
|
### License Grant
|
|
145
152
|
|
|
146
|
-
Subject to payment of the applicable license fee, Codesense LLC grants the licensee a non-exclusive, worldwide, royalty-free license to:
|
|
153
|
+
Subject to payment of the applicable license fee, Codesense LLC grants the licensee a non-exclusive, worldwide, royalty-free license for an unlimited number of developers within the licensee's organization to:
|
|
147
154
|
|
|
148
155
|
- Use, copy, modify, and integrate the Software into unlimited applications and projects
|
|
149
156
|
- Distribute the Software as part of compiled or packaged commercial products
|
|
150
157
|
- Deploy the Software across unlimited servers, environments, and infrastructure
|
|
151
|
-
-
|
|
158
|
+
- Extend license rights to wholly owned subsidiaries and entities in which the licensee holds more than 50% ownership or voting control ("Controlled Entities"), provided such Controlled Entities are identified to Codesense LLC upon request and remain subject to the terms of this license
|
|
152
159
|
|
|
153
160
|
### License Fees and Evaluation
|
|
154
161
|
|
|
@@ -158,11 +165,15 @@ Upon payment, the licensee receives a perpetual license for the version of Lpdf
|
|
|
158
165
|
|
|
159
166
|
### Support
|
|
160
167
|
|
|
161
|
-
Enterprise License holders receive priority support
|
|
168
|
+
Enterprise License holders receive priority support from Codesense LLC. Supported response times and escalation procedures are defined in the Enterprise Support Policy at lpdf.io/support/enterprise. Custom SLA terms may be negotiated as part of a Master Service Agreement.
|
|
162
169
|
|
|
163
170
|
### Contract
|
|
164
171
|
|
|
165
|
-
Enterprise licensees may request a Master Service Agreement (MSA) in place of the standard Terms of Service. Invoice billing is available upon request.
|
|
172
|
+
Enterprise licensees may request a Master Service Agreement (MSA) in place of the standard Terms of Service available at lpdf.io/terms. To initiate an MSA request, contact license@lpdf.io. The standard terms govern until a fully executed MSA is in place. Invoice billing is available upon request.
|
|
173
|
+
|
|
174
|
+
### Audit
|
|
175
|
+
|
|
176
|
+
Codesense LLC may, upon 30 days' written notice and no more than once per calendar year, request a written certification from the licensee confirming their applicable license tier and annual gross revenue for the most recent fiscal year, and may request a list of Controlled Entities covered under the subsidiary grant. The licensee agrees to provide such certification within 15 business days of the request. For Enterprise licensees under an MSA, audit rights may be further defined therein.
|
|
166
177
|
|
|
167
178
|
### Ownership and Modifications
|
|
168
179
|
|
|
@@ -188,8 +199,14 @@ THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY KIND, EXPRESS OR IM
|
|
|
188
199
|
|
|
189
200
|
### Governing Law and Dispute Resolution
|
|
190
201
|
|
|
191
|
-
This license is governed by and construed in accordance with the laws of the State of
|
|
202
|
+
This license is governed by and construed in accordance with the laws of the State of Texas, United States, without regard to its conflict of law provisions.
|
|
192
203
|
|
|
193
|
-
Any dispute arising out of or relating to this license or the Software shall be resolved by binding arbitration administered by the American Arbitration Association under its Commercial Arbitration Rules. The arbitration shall take place in
|
|
204
|
+
Any dispute arising out of or relating to this license or the Software shall be resolved by binding arbitration administered by the American Arbitration Association under its Commercial Arbitration Rules. The arbitration shall take place in Plano, Texas. Judgment on the award rendered by the arbitrator may be entered in any court of competent jurisdiction.
|
|
194
205
|
|
|
195
206
|
Notwithstanding the foregoing, either party may seek injunctive or other equitable relief in any court of competent jurisdiction to prevent the actual or threatened infringement, misappropriation, or violation of a party's intellectual property rights.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
For license purchases and inquiries: license@lpdf.io
|
|
211
|
+
|
|
212
|
+
Privacy Policy: lpdf.io/privacy | Terms of Service: lpdf.io/terms | Support: lpdf.io/support
|
package/README.md
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
# @lpdfio/lpdf
|
|
4
4
|
|
|
5
|
-
Node.js
|
|
5
|
+
**Node.js SDK for [Lpdf](https://lpdf.io) — PDF as Code on every platform**
|
|
6
|
+
|
|
7
|
+
You describe a document as code or XML. Lpdf renders a compact, pixel-perfect PDF — identical across platforms.
|
|
6
8
|
|
|
7
9
|
## Installation
|
|
8
10
|
|
|
@@ -13,48 +15,41 @@ npm install @lpdfio/lpdf
|
|
|
13
15
|
## Usage — Node.js
|
|
14
16
|
|
|
15
17
|
```ts
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
18
|
+
import { L, NoAttr } from 'lpdf'
|
|
19
|
+
|
|
20
|
+
const engine = L.engine()
|
|
21
|
+
|
|
22
|
+
const doc = L.document({ size: 'letter', margin: '48pt' }, [
|
|
23
|
+
L.section(NoAttr, [
|
|
24
|
+
L.layout(NoAttr, [
|
|
25
|
+
L.stack({ gap: '24pt' }, [
|
|
26
|
+
L.split(NoAttr, [
|
|
27
|
+
L.text({ fontSize: '8pt', color: '#888888' }, ['ACME CORP']),
|
|
28
|
+
L.text({ fontSize: '22pt', bold: 'true' }, ['Project Proposal']),
|
|
29
|
+
]),
|
|
30
|
+
L.divider({ thickness: 'xs' }),
|
|
31
|
+
L.text({ fontSize: '13pt', bold: 'true' }, ['Scope of Work']),
|
|
32
|
+
L.flank({ gap: '12pt', align: 'start' }, [
|
|
33
|
+
L.text({ color: '#888888', width: '24pt' }, ['01']),
|
|
34
|
+
L.text(NoAttr, ['Discovery & Research']),
|
|
35
|
+
]),
|
|
36
|
+
]),
|
|
37
|
+
]),
|
|
38
|
+
]),
|
|
39
|
+
])
|
|
40
|
+
|
|
41
|
+
const pdf = await engine.render(doc)
|
|
28
42
|
```
|
|
29
43
|
|
|
30
|
-
##
|
|
31
|
-
|
|
32
|
-
```ts
|
|
33
|
-
import { LpdfEngine } from '@lpdfio/lpdf/browser';
|
|
34
|
-
|
|
35
|
-
const engine = new LpdfEngine('');
|
|
36
|
-
|
|
37
|
-
const xml = `<stack><text>Hello, Lpdf</text></stack>`;
|
|
38
|
-
const pdf = await engine.renderPdf(xml);
|
|
44
|
+
## Requirements
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
## XML format
|
|
46
|
+
- Node.js 16+
|
|
47
|
+
- No external runtime dependencies — the WASM engine is embedded in the package.
|
|
45
48
|
|
|
46
|
-
|
|
49
|
+
## Docs
|
|
47
50
|
|
|
48
|
-
|
|
49
|
-
<stack spacing="m" padding="l">
|
|
50
|
-
<text font-size="xl" font="Montserrat-Bold">Invoice #1001</text>
|
|
51
|
-
<grid columns="2">
|
|
52
|
-
<text>Date</text> <text>2026-04-25</text>
|
|
53
|
-
<text>Due</text> <text>2026-05-25</text>
|
|
54
|
-
</grid>
|
|
55
|
-
</stack>
|
|
56
|
-
```
|
|
51
|
+
[lpdf.io/docs/js](https://lpdf.io/docs/js)
|
|
57
52
|
|
|
58
|
-
|
|
53
|
+
--
|
|
59
54
|
|
|
60
55
|
Dual-licensed: Community License (free) and Commercial License (paid). See [LICENSE](LICENSE) for full terms.
|
package/dist/_shared.d.ts
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared types used by both the Node.js and browser entry points.
|
|
3
3
|
*/
|
|
4
|
+
/** Construction-time configuration for {@link PdfEngine}. Node has no infra options. */
|
|
5
|
+
export interface EngineOptions {
|
|
6
|
+
}
|
|
4
7
|
export interface RenderOptions {
|
|
5
|
-
/**
|
|
6
|
-
* Pre-loaded font bytes for custom fonts referenced via <fonts src="…">.
|
|
7
|
-
* Keys are the font names used in the document; values are raw TTF/OTF bytes.
|
|
8
|
-
* @deprecated Pass font bytes via `LpdfEngine.loadFont()` instead.
|
|
9
|
-
*/
|
|
10
|
-
fontBytes?: Record<string, Uint8Array>;
|
|
11
8
|
/**
|
|
12
9
|
* Optional ISO 8601 creation timestamp (e.g. `"2024-06-01T12:00:00"`).
|
|
13
10
|
* When provided, written as `/CreationDate` in the PDF info dictionary.
|
package/dist/browser.js
CHANGED
|
@@ -378,63 +378,12 @@ async function __wbg_init(module_or_path) {
|
|
|
378
378
|
return __wbg_finalize_init(instance, module);
|
|
379
379
|
}
|
|
380
380
|
|
|
381
|
-
// src/kit.ts
|
|
382
|
-
function attrKey(camel) {
|
|
383
|
-
return camel.replace(/[A-Z]/g, (c) => "-" + c.toLowerCase());
|
|
384
|
-
}
|
|
385
|
-
function buildAttrs(options) {
|
|
386
|
-
const result = {};
|
|
387
|
-
for (const [key, val] of Object.entries(options)) {
|
|
388
|
-
if (val !== void 0) {
|
|
389
|
-
result[attrKey(key)] = val;
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
return result;
|
|
393
|
-
}
|
|
394
|
-
function layout(nodes = []) {
|
|
395
|
-
return { type: "layout", nodes };
|
|
396
|
-
}
|
|
397
|
-
function canvas(layers = []) {
|
|
398
|
-
return { type: "canvas", nodes: layers };
|
|
399
|
-
}
|
|
400
|
-
function section(input = {}) {
|
|
401
|
-
return {
|
|
402
|
-
type: "section",
|
|
403
|
-
attrs: buildAttrs(input.options ?? {}),
|
|
404
|
-
nodes: input.nodes ?? []
|
|
405
|
-
};
|
|
406
|
-
}
|
|
407
|
-
function document(input = {}) {
|
|
408
|
-
const { tokens, meta, ...restOpts } = input.options ?? {};
|
|
409
|
-
const attrs = {
|
|
410
|
-
...buildAttrs(restOpts)
|
|
411
|
-
};
|
|
412
|
-
if (tokens !== void 0) attrs["tokens"] = tokens;
|
|
413
|
-
if (meta !== void 0) attrs["meta"] = meta;
|
|
414
|
-
return {
|
|
415
|
-
version: 1,
|
|
416
|
-
type: "document",
|
|
417
|
-
attrs,
|
|
418
|
-
nodes: input.sections ?? []
|
|
419
|
-
};
|
|
420
|
-
}
|
|
421
|
-
var LpdfKit = Object.freeze({
|
|
422
|
-
layout,
|
|
423
|
-
canvas,
|
|
424
|
-
section,
|
|
425
|
-
document
|
|
426
|
-
});
|
|
427
|
-
|
|
428
381
|
// src/browser.ts
|
|
429
|
-
|
|
382
|
+
var NoAttr = null;
|
|
383
|
+
async function initLpdf(wasmSource, licenseKey = "") {
|
|
430
384
|
await __wbg_init(wasmSource);
|
|
431
385
|
const fontMap = /* @__PURE__ */ new Map();
|
|
432
386
|
const imageMap = /* @__PURE__ */ new Map();
|
|
433
|
-
if (initOptions.fontBytes) {
|
|
434
|
-
for (const [name, bytes] of Object.entries(initOptions.fontBytes)) {
|
|
435
|
-
fontMap.set(name, bytes);
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
387
|
return {
|
|
439
388
|
loadFont(name, bytes) {
|
|
440
389
|
fontMap.set(name, bytes);
|
|
@@ -442,27 +391,37 @@ async function initLpdf(wasmSource, licenseKey = "", initOptions = {}) {
|
|
|
442
391
|
loadImage(name, bytes) {
|
|
443
392
|
imageMap.set(name, bytes);
|
|
444
393
|
},
|
|
445
|
-
async
|
|
394
|
+
async render(input, callOptions = {}) {
|
|
446
395
|
const engine = new LpdfEngine(licenseKey);
|
|
447
396
|
for (const [name, bytes] of fontMap) {
|
|
448
397
|
engine.load_font(name, bytes);
|
|
449
398
|
}
|
|
450
|
-
if (callOptions.fontBytes) {
|
|
451
|
-
for (const [name, bytes] of Object.entries(callOptions.fontBytes)) {
|
|
452
|
-
if (!fontMap.has(name)) engine.load_font(name, bytes);
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
399
|
for (const [name, bytes] of imageMap) {
|
|
456
400
|
engine.load_image(name, bytes);
|
|
457
401
|
}
|
|
458
|
-
|
|
459
|
-
|
|
402
|
+
if (callOptions.createdOn) {
|
|
403
|
+
engine.set_created_on(callOptions.createdOn);
|
|
404
|
+
}
|
|
405
|
+
let pdf;
|
|
406
|
+
if (typeof input === "string") {
|
|
407
|
+
const dataJson = callOptions.data != null ? JSON.stringify(callOptions.data) : null;
|
|
408
|
+
pdf = engine.render_pdf(input, dataJson);
|
|
409
|
+
} else {
|
|
410
|
+
const wasmExt = engine;
|
|
411
|
+
if (typeof wasmExt.render_tree_pdf === "function") {
|
|
412
|
+
pdf = wasmExt.render_tree_pdf(JSON.stringify(input));
|
|
413
|
+
} else {
|
|
414
|
+
const mod = engine;
|
|
415
|
+
const xml = mod.constructor.kit_to_xml?.(JSON.stringify(input)) ?? "";
|
|
416
|
+
pdf = engine.render_pdf(xml, null);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
460
419
|
engine.free();
|
|
461
420
|
return pdf;
|
|
462
421
|
}
|
|
463
422
|
};
|
|
464
423
|
}
|
|
465
424
|
export {
|
|
466
|
-
|
|
425
|
+
NoAttr,
|
|
467
426
|
initLpdf
|
|
468
427
|
};
|
package/dist/canvas.d.ts
CHANGED
|
@@ -100,7 +100,9 @@ export interface LpdfCanvasImgNode {
|
|
|
100
100
|
attrs: Record<string, string>;
|
|
101
101
|
}
|
|
102
102
|
export type LpdfCanvasPrimitiveNode = LpdfCanvasRectNode | LpdfCanvasLineNode | LpdfCanvasEllipseNode | LpdfCanvasCircleNode | LpdfCanvasPathNode | LpdfCanvasTextNode | LpdfCanvasImgNode;
|
|
103
|
-
|
|
103
|
+
/** @deprecated Use {@link LayerAttr} */
|
|
104
|
+
export type CanvasLayerOptions = LayerAttr;
|
|
105
|
+
export interface LayerAttr {
|
|
104
106
|
page?: PageScope | string;
|
|
105
107
|
opacity?: number;
|
|
106
108
|
transform?: CanvasTransform;
|
|
@@ -115,17 +117,17 @@ declare function line(x1: number, y1: number, x2: number, y2: number, style?: Ca
|
|
|
115
117
|
declare function ellipse(cx: number, cy: number, rx: number, ry: number, style?: CanvasEllipseStyle): LpdfCanvasEllipseNode;
|
|
116
118
|
declare function circle(cx: number, cy: number, r: number, style?: CanvasEllipseStyle): LpdfCanvasCircleNode;
|
|
117
119
|
declare function path(d: string, style?: CanvasPathStyle): LpdfCanvasPathNode;
|
|
118
|
-
declare function
|
|
119
|
-
declare function
|
|
120
|
-
declare function layer(nodes: LpdfCanvasPrimitiveNode[]
|
|
120
|
+
declare function textAt(x: number, y: number, content: string, style?: CanvasTextStyle, runs?: CanvasRun[]): LpdfCanvasTextNode;
|
|
121
|
+
declare function imgAt(x: number, y: number, w: number, h: number, name: string): LpdfCanvasImgNode;
|
|
122
|
+
declare function layer(attrs: LayerAttr | null, nodes: LpdfCanvasPrimitiveNode[]): LpdfCanvasLayerNode;
|
|
121
123
|
export declare const LpdfCanvas: Readonly<{
|
|
122
124
|
rect: typeof rect;
|
|
123
125
|
line: typeof line;
|
|
124
126
|
ellipse: typeof ellipse;
|
|
125
127
|
circle: typeof circle;
|
|
126
128
|
path: typeof path;
|
|
127
|
-
|
|
128
|
-
|
|
129
|
+
textAt: typeof textAt;
|
|
130
|
+
imgAt: typeof imgAt;
|
|
129
131
|
layer: typeof layer;
|
|
130
132
|
}>;
|
|
131
133
|
export {};
|
package/dist/canvas.js
CHANGED
|
@@ -124,7 +124,7 @@ function path(d, style) {
|
|
|
124
124
|
attrs['line-join'] = style.lineJoin;
|
|
125
125
|
return { type: 'canvas-path', attrs };
|
|
126
126
|
}
|
|
127
|
-
function
|
|
127
|
+
function textAt(x, y, content, style, runs) {
|
|
128
128
|
const attrs = { x: String(x), y: String(y) };
|
|
129
129
|
if (style?.font !== undefined)
|
|
130
130
|
attrs['font'] = style.font;
|
|
@@ -153,21 +153,21 @@ function canvasText(x, y, content, style, runs) {
|
|
|
153
153
|
}
|
|
154
154
|
return node;
|
|
155
155
|
}
|
|
156
|
-
function
|
|
156
|
+
function imgAt(x, y, w, h, name) {
|
|
157
157
|
return {
|
|
158
158
|
type: 'canvas-img',
|
|
159
159
|
attrs: { x: String(x), y: String(y), w: String(w), h: String(h), name },
|
|
160
160
|
};
|
|
161
161
|
}
|
|
162
|
-
function layer(
|
|
163
|
-
const
|
|
164
|
-
if (
|
|
165
|
-
|
|
166
|
-
if (
|
|
167
|
-
|
|
168
|
-
if (
|
|
169
|
-
|
|
170
|
-
return { type: 'canvas-layer', attrs, nodes };
|
|
162
|
+
function layer(attrs, nodes) {
|
|
163
|
+
const a = {};
|
|
164
|
+
if (attrs?.page !== undefined)
|
|
165
|
+
a['page'] = attrs.page;
|
|
166
|
+
if (attrs?.opacity !== undefined)
|
|
167
|
+
a['opacity'] = String(attrs.opacity);
|
|
168
|
+
if (attrs?.transform !== undefined)
|
|
169
|
+
a['transform'] = attrs.transform.toString();
|
|
170
|
+
return { type: 'canvas-layer', attrs: a, nodes };
|
|
171
171
|
}
|
|
172
172
|
exports.LpdfCanvas = Object.freeze({
|
|
173
173
|
rect,
|
|
@@ -175,7 +175,7 @@ exports.LpdfCanvas = Object.freeze({
|
|
|
175
175
|
ellipse,
|
|
176
176
|
circle,
|
|
177
177
|
path,
|
|
178
|
-
|
|
179
|
-
|
|
178
|
+
textAt,
|
|
179
|
+
imgAt,
|
|
180
180
|
layer,
|
|
181
181
|
});
|
package/dist/engine.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RenderOptions } from './_shared';
|
|
2
|
-
import type {
|
|
2
|
+
import type { PdfDocument } from './kit';
|
|
3
3
|
/** Thrown when the lpdf engine returns a layout or parse error. */
|
|
4
4
|
export declare class LpdfRenderError extends Error {
|
|
5
5
|
constructor(message: string);
|
|
@@ -15,7 +15,7 @@ export interface EncryptPermissions {
|
|
|
15
15
|
assemble?: boolean;
|
|
16
16
|
print_hq?: boolean;
|
|
17
17
|
}
|
|
18
|
-
/** RC4-128 encryption options passed to {@link
|
|
18
|
+
/** RC4-128 encryption options passed to {@link PdfEngine.setEncryption}. */
|
|
19
19
|
export interface EncryptOptions {
|
|
20
20
|
/** Open password shown to readers. Empty string = no open password required. */
|
|
21
21
|
userPassword: string;
|
|
@@ -24,26 +24,29 @@ export interface EncryptOptions {
|
|
|
24
24
|
/** Permission flags applied to the document. Omitted flags default to `true`. */
|
|
25
25
|
permissions?: EncryptPermissions;
|
|
26
26
|
}
|
|
27
|
-
export declare class
|
|
28
|
-
private
|
|
29
|
-
private readonly _opts;
|
|
27
|
+
export declare class PdfEngine {
|
|
28
|
+
private _licenseKey;
|
|
30
29
|
private readonly _fonts;
|
|
31
30
|
private readonly _images;
|
|
32
31
|
private _disposed;
|
|
33
32
|
private _encrypt;
|
|
34
|
-
constructor(
|
|
33
|
+
constructor();
|
|
34
|
+
/**
|
|
35
|
+
* Set the license key. Returns `this` for chaining.
|
|
36
|
+
*/
|
|
37
|
+
setLicenseKey(key: string): this;
|
|
35
38
|
/**
|
|
36
39
|
* Register raw TTF/OTF bytes for a custom font name used in `<font src="…">`.
|
|
37
|
-
* Call before `
|
|
40
|
+
* Call before `render`. Returns `this` for chaining.
|
|
38
41
|
*/
|
|
39
42
|
loadFont(name: string, bytes: Uint8Array): this;
|
|
40
43
|
/**
|
|
41
44
|
* Register raw image bytes (PNG or JPEG) for an image name used in `<img name="…">`.
|
|
42
|
-
* Call before `
|
|
45
|
+
* Call before `render`. Returns `this` for chaining.
|
|
43
46
|
*/
|
|
44
47
|
loadImage(name: string, bytes: Uint8Array): this;
|
|
45
48
|
/**
|
|
46
|
-
* Configure RC4-128 encryption for all subsequent `
|
|
49
|
+
* Configure RC4-128 encryption for all subsequent `render` calls.
|
|
47
50
|
* Returns `this` for chaining.
|
|
48
51
|
*/
|
|
49
52
|
setEncryption(options: EncryptOptions): this;
|
|
@@ -53,7 +56,7 @@ export declare class LpdfEngine {
|
|
|
53
56
|
*/
|
|
54
57
|
clearEncryption(): this;
|
|
55
58
|
/**
|
|
56
|
-
* Release held resources. Idempotent. Subsequent `
|
|
59
|
+
* Release held resources. Idempotent. Subsequent `render` / `loadFont`
|
|
57
60
|
* calls after disposal will throw.
|
|
58
61
|
*/
|
|
59
62
|
dispose(): void;
|
|
@@ -62,9 +65,9 @@ export declare class LpdfEngine {
|
|
|
62
65
|
/**
|
|
63
66
|
* Render an lpdf XML string to PDF bytes (Node.js).
|
|
64
67
|
*/
|
|
65
|
-
|
|
68
|
+
render(input: string, callOptions?: RenderOptions): Promise<Uint8Array>;
|
|
66
69
|
/**
|
|
67
|
-
* Render
|
|
70
|
+
* Render a `PdfDocument` tree (built with `Pdf.document`) to PDF bytes (Node.js).
|
|
68
71
|
*/
|
|
69
|
-
|
|
72
|
+
render(input: PdfDocument, callOptions?: RenderOptions): Promise<Uint8Array>;
|
|
70
73
|
}
|
package/dist/engine.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.PdfEngine = exports.LpdfRenderError = void 0;
|
|
4
4
|
const node_fs_1 = require("node:fs");
|
|
5
5
|
// require() path is relative to the compiled output at dist/engine.js.
|
|
6
6
|
// In the published package, wasm-pack artifacts live in dist/wasm/.
|
|
@@ -16,18 +16,25 @@ class LpdfRenderError extends Error {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
exports.LpdfRenderError = LpdfRenderError;
|
|
19
|
-
class
|
|
20
|
-
constructor(
|
|
19
|
+
class PdfEngine {
|
|
20
|
+
constructor() {
|
|
21
|
+
this._licenseKey = '';
|
|
21
22
|
this._fonts = new Map();
|
|
22
23
|
this._images = new Map();
|
|
23
24
|
this._disposed = false;
|
|
24
25
|
this._encrypt = null;
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Set the license key. Returns `this` for chaining.
|
|
29
|
+
*/
|
|
30
|
+
setLicenseKey(key) {
|
|
31
|
+
this._throwIfDisposed();
|
|
32
|
+
this._licenseKey = key;
|
|
33
|
+
return this;
|
|
27
34
|
}
|
|
28
35
|
/**
|
|
29
36
|
* Register raw TTF/OTF bytes for a custom font name used in `<font src="…">`.
|
|
30
|
-
* Call before `
|
|
37
|
+
* Call before `render`. Returns `this` for chaining.
|
|
31
38
|
*/
|
|
32
39
|
loadFont(name, bytes) {
|
|
33
40
|
this._throwIfDisposed();
|
|
@@ -36,7 +43,7 @@ class LpdfEngine {
|
|
|
36
43
|
}
|
|
37
44
|
/**
|
|
38
45
|
* Register raw image bytes (PNG or JPEG) for an image name used in `<img name="…">`.
|
|
39
|
-
* Call before `
|
|
46
|
+
* Call before `render`. Returns `this` for chaining.
|
|
40
47
|
*/
|
|
41
48
|
loadImage(name, bytes) {
|
|
42
49
|
this._throwIfDisposed();
|
|
@@ -44,7 +51,7 @@ class LpdfEngine {
|
|
|
44
51
|
return this;
|
|
45
52
|
}
|
|
46
53
|
/**
|
|
47
|
-
* Configure RC4-128 encryption for all subsequent `
|
|
54
|
+
* Configure RC4-128 encryption for all subsequent `render` calls.
|
|
48
55
|
* Returns `this` for chaining.
|
|
49
56
|
*/
|
|
50
57
|
setEncryption(options) {
|
|
@@ -62,7 +69,7 @@ class LpdfEngine {
|
|
|
62
69
|
return this;
|
|
63
70
|
}
|
|
64
71
|
/**
|
|
65
|
-
* Release held resources. Idempotent. Subsequent `
|
|
72
|
+
* Release held resources. Idempotent. Subsequent `render` / `loadFont`
|
|
66
73
|
* calls after disposal will throw.
|
|
67
74
|
*/
|
|
68
75
|
dispose() {
|
|
@@ -71,28 +78,20 @@ class LpdfEngine {
|
|
|
71
78
|
[Symbol.dispose]() { this.dispose(); }
|
|
72
79
|
_throwIfDisposed() {
|
|
73
80
|
if (this._disposed)
|
|
74
|
-
throw new Error('
|
|
81
|
+
throw new Error('PdfEngine has been disposed.');
|
|
75
82
|
}
|
|
76
|
-
async
|
|
83
|
+
async render(input, callOptions = {}) {
|
|
77
84
|
this._throwIfDisposed();
|
|
78
|
-
// Merge fonts: instance-level loadFont() calls take precedence over the
|
|
79
|
-
// deprecated fontBytes option, which is kept for one-version compat.
|
|
80
|
-
const allFonts = new Map(this._fonts);
|
|
81
|
-
const extraBytes = { ...this._opts.fontBytes, ...callOptions.fontBytes };
|
|
82
|
-
for (const [name, bytes] of Object.entries(extraBytes)) {
|
|
83
|
-
if (!allFonts.has(name))
|
|
84
|
-
allFonts.set(name, bytes);
|
|
85
|
-
}
|
|
86
85
|
const engine = new WasmEngine(this._licenseKey);
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
engine.set_created_on(createdOn);
|
|
86
|
+
if (callOptions.createdOn) {
|
|
87
|
+
engine.set_created_on(callOptions.createdOn);
|
|
90
88
|
}
|
|
91
89
|
let pdf;
|
|
92
90
|
try {
|
|
93
91
|
if (typeof input === 'string') {
|
|
94
92
|
// XML path — auto-load fonts and images declared via src="…".
|
|
95
93
|
const xml = input;
|
|
94
|
+
const allFonts = new Map(this._fonts);
|
|
96
95
|
for (const [key, src] of extractAssetSrcs(xml, 'font')) {
|
|
97
96
|
if (!allFonts.has(key)) {
|
|
98
97
|
try {
|
|
@@ -126,6 +125,7 @@ class LpdfEngine {
|
|
|
126
125
|
else {
|
|
127
126
|
// JSON (Kit tree) path — pass JSON directly to render_tree_pdf.
|
|
128
127
|
const json = JSON.stringify(input);
|
|
128
|
+
const allFonts = new Map(this._fonts);
|
|
129
129
|
for (const [key, src] of extractFontSrcsFromJson(json)) {
|
|
130
130
|
if (!allFonts.has(key)) {
|
|
131
131
|
try {
|
|
@@ -156,7 +156,7 @@ class LpdfEngine {
|
|
|
156
156
|
return pdf;
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
|
-
exports.
|
|
159
|
+
exports.PdfEngine = PdfEngine;
|
|
160
160
|
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
161
161
|
/** Extract `ref??name → src` pairs from `<font>` or `<image>` tags in XML. */
|
|
162
162
|
function extractAssetSrcs(xml, tag) {
|