pretext-pdf 0.9.2 → 1.0.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/CHANGELOG.md +126 -110
- package/README.md +122 -1
- package/dist/allowed-props.d.ts +40 -0
- package/dist/allowed-props.d.ts.map +1 -0
- package/dist/allowed-props.js +130 -0
- package/dist/allowed-props.js.map +1 -0
- package/dist/assets.d.ts +4 -2
- package/dist/assets.d.ts.map +1 -1
- package/dist/assets.js +22 -1
- package/dist/assets.js.map +1 -1
- package/dist/benchmarks/corpora.d.ts +11 -0
- package/dist/benchmarks/corpora.d.ts.map +1 -0
- package/dist/benchmarks/corpora.js +228 -0
- package/dist/benchmarks/corpora.js.map +1 -0
- package/dist/builder.d.ts +10 -2
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +12 -4
- package/dist/builder.js.map +1 -1
- package/dist/element-types.d.ts +16 -0
- package/dist/element-types.d.ts.map +1 -0
- package/dist/element-types.js +16 -0
- package/dist/element-types.js.map +1 -0
- package/dist/errors.d.ts +8 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +4 -0
- package/dist/errors.js.map +1 -1
- package/dist/fonts.d.ts +2 -1
- package/dist/fonts.d.ts.map +1 -1
- package/dist/fonts.js.map +1 -1
- package/dist/index.d.ts +23 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +27 -310
- package/dist/index.js.map +1 -1
- package/dist/layout-state.d.ts +39 -0
- package/dist/layout-state.d.ts.map +1 -0
- package/dist/layout-state.js +46 -0
- package/dist/layout-state.js.map +1 -0
- package/dist/measure-blocks.d.ts +2 -1
- package/dist/measure-blocks.d.ts.map +1 -1
- package/dist/measure-blocks.js.map +1 -1
- package/dist/measure.d.ts +4 -2
- package/dist/measure.d.ts.map +1 -1
- package/dist/measure.js +15 -5
- package/dist/measure.js.map +1 -1
- package/dist/page-sizes.d.ts +1 -0
- package/dist/page-sizes.d.ts.map +1 -1
- package/dist/page-sizes.js.map +1 -1
- package/dist/paginate.d.ts +1 -1
- package/dist/paginate.d.ts.map +1 -1
- package/dist/paginate.js +11 -2
- package/dist/paginate.js.map +1 -1
- package/dist/pipeline-footnotes.d.ts +18 -0
- package/dist/pipeline-footnotes.d.ts.map +1 -0
- package/dist/pipeline-footnotes.js +98 -0
- package/dist/pipeline-footnotes.js.map +1 -0
- package/dist/pipeline-toc.d.ts +11 -0
- package/dist/pipeline-toc.d.ts.map +1 -0
- package/dist/pipeline-toc.js +28 -0
- package/dist/pipeline-toc.js.map +1 -0
- package/dist/pipeline.d.ts +24 -0
- package/dist/pipeline.d.ts.map +1 -0
- package/dist/pipeline.js +116 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/plugin-registry.d.ts +40 -0
- package/dist/plugin-registry.d.ts.map +1 -0
- package/dist/plugin-registry.js +104 -0
- package/dist/plugin-registry.js.map +1 -0
- package/dist/plugin-types.d.ts +185 -0
- package/dist/plugin-types.d.ts.map +1 -0
- package/dist/plugin-types.js +27 -0
- package/dist/plugin-types.js.map +1 -0
- package/dist/post-process.d.ts +16 -0
- package/dist/post-process.d.ts.map +1 -0
- package/dist/post-process.js +80 -0
- package/dist/post-process.js.map +1 -0
- package/dist/render-blocks.d.ts +2 -1
- package/dist/render-blocks.d.ts.map +1 -1
- package/dist/render-blocks.js.map +1 -1
- package/dist/render-extras.d.ts +2 -2
- package/dist/render-extras.d.ts.map +1 -1
- package/dist/render-extras.js.map +1 -1
- package/dist/render.d.ts +4 -2
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +23 -4
- package/dist/render.js.map +1 -1
- package/dist/types-internal.d.ts +302 -0
- package/dist/types-internal.d.ts.map +1 -0
- package/dist/types-internal.js +9 -0
- package/dist/types-internal.js.map +1 -0
- package/dist/types-public.d.ts +1031 -0
- package/dist/types-public.d.ts.map +1 -0
- package/dist/types-public.js +2 -0
- package/dist/types-public.js.map +1 -0
- package/dist/types.d.ts +6 -1224
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -1
- package/dist/validate.d.ts +6 -2
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +148 -5
- package/dist/validate.js.map +1 -1
- package/package.json +31 -23
- package/docs/screenshots/showcase-invoice.png +0 -0
- package/docs/screenshots/showcase-report.png +0 -0
- package/docs/screenshots/showcase-resume.png +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,131 @@ Format: [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/)
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [1.0.0] — 2026-05-02
|
|
11
|
+
|
|
12
|
+
First stable release. Completes the plugin extension API, closes all v1.0 gate requirements,
|
|
13
|
+
and ships a fully verified public surface with zero breaking changes from 0.9.x.
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **Plugin extension API** — Register custom element types via `RenderOptions.plugins`.
|
|
18
|
+
Each `PluginDefinition` participates in all four pipeline stages: `validate`, `loadAsset`,
|
|
19
|
+
`measure`, and `render`. Plugins are fully typed and tree-shaken from documents
|
|
20
|
+
that don't use them. See README § Custom element types (plugins) and
|
|
21
|
+
`examples/plugin-custom-element.ts` for a runnable example.
|
|
22
|
+
- **`PluginDefinition`, `PluginMeasureContext`, `PluginMeasureResult`, `PluginRenderContext`**
|
|
23
|
+
exported from `pretext-pdf` public surface (previously internal).
|
|
24
|
+
- **`PdfBuilder` and `PdfBuilderOptions`** exported from `pretext-pdf` (enables type-safe
|
|
25
|
+
builder construction in downstream code without re-declaring the interface).
|
|
26
|
+
- **`TocEntryElement`** exported from `pretext-pdf` public surface (was in the `ContentElement`
|
|
27
|
+
union but not individually importable).
|
|
28
|
+
- **`plugins` option on `createPdf()`** — `PdfBuilderOptions.plugins` threads plugins through
|
|
29
|
+
the builder's `build()` call automatically.
|
|
30
|
+
- **`Intl.Segmenter` pre-flight guard** in `render()` — throws `RENDER_FAILED` with a clear
|
|
31
|
+
message on Node.js < 16 or runtimes without full-ICU data, instead of silently producing
|
|
32
|
+
incorrect line breaks.
|
|
33
|
+
- **`PluginRenderContext.pageWidth/pageHeight/margins`** — render hooks now receive full page
|
|
34
|
+
geometry for layout calculations (page-relative positioning, bleed boxes, etc.).
|
|
35
|
+
- **`render` context Y-coordinate docs** — expanded JSDoc with multi-line text example showing
|
|
36
|
+
how to position text baselines relative to `context.y`.
|
|
37
|
+
- **Benchmark corpora manifest** and **smoke staging** tests wired into `npm test`
|
|
38
|
+
(previously orphaned). Total test count: 672.
|
|
39
|
+
- `examples/plugin-custom-element.ts` — runnable plugin example (`npm run example:plugin`).
|
|
40
|
+
|
|
41
|
+
### Fixed
|
|
42
|
+
|
|
43
|
+
- **`SIGNATURE_CERT_AND_ENCRYPTION` error code** — was declared in the `ErrorCode` union
|
|
44
|
+
but never thrown; validate.ts now uses it correctly when a document specifies both
|
|
45
|
+
signatures and encryption (previously threw a generic `VALIDATION_ERROR`).
|
|
46
|
+
- **Build break under `exactOptionalPropertyTypes: true`** — `PdfBuilder.build()` no longer
|
|
47
|
+
passes `{ plugins: undefined }` to `runPipeline` when no plugins are configured.
|
|
48
|
+
- **Plugin `validate` hook empty-string normalization** — `plugin.validate()` returning `''`
|
|
49
|
+
now correctly accepts the element (was previously treated as a rejection message).
|
|
50
|
+
- **`toc` element reaching render default arm** — `render.ts` now has an explicit
|
|
51
|
+
`case 'toc': return` guard before the default arm; TOC elements are pre-processed
|
|
52
|
+
during pagination and should never reach the renderer.
|
|
53
|
+
- **`RichLine` and `RichFragment`** demoted from `@public` to `@internal`; these are
|
|
54
|
+
implementation details of the rich-text pipeline, not intended for external use.
|
|
55
|
+
- **Sentinel value documentation** — `MeasuredBlock` comment now explicitly states that
|
|
56
|
+
`lines: []`, `fontSize: 0`, `lineHeight: 0`, `fontKey: ''` applies to spacers, tables,
|
|
57
|
+
images, hr, *and plugin blocks* — not a bug but a documented convention.
|
|
58
|
+
|
|
59
|
+
### Internal
|
|
60
|
+
|
|
61
|
+
- `src/plugin-registry.ts` (new): Pure orchestration helpers for the four plugin injection
|
|
62
|
+
points (`findPlugin`, `runPluginValidate`, `runPluginLoadAsset`, `runPluginMeasure`,
|
|
63
|
+
`runPluginRender`).
|
|
64
|
+
- `src/plugin-types.ts` (new): `PluginDefinition` interface and context/result types.
|
|
65
|
+
- `src/layout-state.ts`: `prepareLayoutState` now accepts `options?: RenderOptions` and
|
|
66
|
+
threads plugins to `stageValidate`, `stageLoadAssets`, and `stageMeasure`.
|
|
67
|
+
- `docs/V1.0-RUNBOOK.md`: Full release runbook with first-principles audit, anti-hallucination
|
|
68
|
+
protocol, verified-facts table, and phase-by-phase plan.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## [0.9.4] — 2026-05-02
|
|
73
|
+
|
|
74
|
+
Architecture hardening + API surface snapshot. No public API changes; internal
|
|
75
|
+
restructuring to eliminate circular dependencies and add drift guards before v1.0 freeze.
|
|
76
|
+
|
|
77
|
+
### Added
|
|
78
|
+
|
|
79
|
+
- **API surface snapshot** (`etc/pretext-pdf.api.md`) checked into source control as
|
|
80
|
+
the v1.0 baseline. The `api:check` CI step will fail on unintentional public-API drift.
|
|
81
|
+
- **`src/layout-state.ts`** — `prepareLayoutState()` and `summarizeLayoutState()` extracted
|
|
82
|
+
from the pipeline for testability; `layout-contract` and `hard-text-contract` tests
|
|
83
|
+
wired into `test:unit`.
|
|
84
|
+
- **`src/benchmarks/corpora.ts`** — benchmark corpus manifest (`getBenchmarkCorpora()`)
|
|
85
|
+
restored from git history; `benchmark-baseline.test.ts` wired into `test:contract`.
|
|
86
|
+
- **Drift guards** (`test/drift-guards.test.ts`) — asserts that `ELEMENT_TYPES`,
|
|
87
|
+
`ALLOWED_PROPS`, `validate.ts` cases, and `render.ts` cases all agree at test time.
|
|
88
|
+
Catches any future element-type addition that isn't plumbed through all four places.
|
|
89
|
+
- **`render.ts` default arm** — unknown element types now throw immediately instead of
|
|
90
|
+
silently producing a blank block.
|
|
91
|
+
|
|
92
|
+
### Refactored
|
|
93
|
+
|
|
94
|
+
- **Circular dependency broken**: `src/post-process.ts` extracted so `builder.ts` and
|
|
95
|
+
`index.ts` no longer form a cycle through each other.
|
|
96
|
+
- **`ELEMENT_TYPES` extracted** to `src/element-types.ts` as single source of truth;
|
|
97
|
+
re-exported from `index.ts`, imported by `validate.ts` — eliminates the previous
|
|
98
|
+
per-file string-literal duplication.
|
|
99
|
+
|
|
100
|
+
### Fixed
|
|
101
|
+
|
|
102
|
+
- `post-process.ts`: drop raw signing library error message from `SIGNATURE_FAILED`
|
|
103
|
+
to avoid leaking certificate or passphrase details in error output.
|
|
104
|
+
- `layout-state.ts`: polyfill install wrapped in try/catch; throws `CANVAS_UNAVAILABLE`
|
|
105
|
+
on failure instead of an untyped exception.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## [0.9.3] — 2026-04-23
|
|
110
|
+
|
|
111
|
+
Strict validation release. Opt-in property validation to catch unknown properties on elements and sub-structures via typo detection and precise JSONPath error reporting.
|
|
112
|
+
|
|
113
|
+
### Added
|
|
114
|
+
|
|
115
|
+
- **Strict validation mode**: Pass `{ strict: true }` to `render(doc, options)` to reject unknown properties. Non-strict mode (default) remains permissive for backwards compatibility.
|
|
116
|
+
- **`render()` options parameter**: Updated signature to `render(doc: PdfDocument, options?: RenderOptions)` where `RenderOptions = { strict?: boolean }`.
|
|
117
|
+
- **`validate()` public export**: `validate()` is now exported from `pretext-pdf` for standalone validation and testing.
|
|
118
|
+
- **Validation error details**:
|
|
119
|
+
- Unknown properties reported with Levenshtein edit-distance suggestions (distance ≤2) for typo correction.
|
|
120
|
+
- Errors include JSONPath-like paths (`content[3].table.rows[0].cells[1].align`) for precise location reporting.
|
|
121
|
+
- Error accumulation: all violations collected before throwing a single VALIDATION_ERROR with formatted multi-line message.
|
|
122
|
+
- First 20 errors shown; overflow indicator present.
|
|
123
|
+
- **Compile-time drift guards**: `src/allowed-props.ts` uses `Exact<T, Keys>` TypeScript type assertions to catch property definition drift at type-check time. If element types change, `tsc --noEmit` will error if allowed-props lists don't match.
|
|
124
|
+
- **Property allowlists**:
|
|
125
|
+
- `ALLOWED_PROPS`: 22 element types (paragraph, heading, table, image, code, list, etc.)
|
|
126
|
+
- `ALLOWED_PROPS_SUB`: 8 sub-structures (document, metadata, table-row, table-cell, list-item, inline-span, column-def, annotation)
|
|
127
|
+
|
|
128
|
+
### Internal
|
|
129
|
+
|
|
130
|
+
- `src/allowed-props.ts` (new): Central configuration for allowed properties with compile-time assertions.
|
|
131
|
+
- `src/validate.ts` (enhanced): Added `levenshteinDist()`, `closestMatch()`, `assertUnknownProps()`, and `formatErrors()` helpers; threading strict flag through `validateElement()` for nested structure validation (tables, lists, rich-paragraphs, float-groups, annotations).
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
10
135
|
## [0.9.2] — 2026-04-22
|
|
11
136
|
|
|
12
137
|
Maintenance release. Engine refresh + repo-hygiene automation. No runtime behavior changes beyond the `@chenglou/pretext` bump.
|
|
@@ -22,7 +147,7 @@ Maintenance release. Engine refresh + repo-hygiene automation. No runtime behavi
|
|
|
22
147
|
### Added
|
|
23
148
|
|
|
24
149
|
- `scripts/verify-badges.js` + CI step — compares README shields.io badge values against `package.json` dep count and `npm test` total. Fails CI on drift. Fast path via `SKIP_TEST_RUN=1` for pre-commit use.
|
|
25
|
-
-
|
|
150
|
+
- `release` job in `ci.yml` — on `v*` tag push, auto-extracts the matching `## [X.Y.Z]` section from this file and creates the GitHub release (requires publish to succeed first). Closes the "tag exists but no release page" gap that affected v0.9.1. (Note: originally shipped as `.github/workflows/release-on-tag.yml`; merged into `ci.yml` for dependency ordering in Tier 0.5.)
|
|
26
151
|
- `renovate.json` — watches dependencies, auto-merges devDependency bumps that pass CI, opens PRs (without auto-merge) for runtime, peer, and `@chenglou/pretext` engine bumps. Closes the gap that left us one release behind upstream.
|
|
27
152
|
|
|
28
153
|
### Removed
|
|
@@ -484,112 +609,3 @@ Three additive enhancements that broaden the package's surface without growing i
|
|
|
484
609
|
- Image formats: PNG, JPG, WebP
|
|
485
610
|
- Table features: custom column widths, cell padding, borders, header styling
|
|
486
611
|
- Colors: hex color codes throughout (text, backgrounds, borders)
|
|
487
|
-
|
|
488
|
-
---
|
|
489
|
-
|
|
490
|
-
## Features by Phase
|
|
491
|
-
|
|
492
|
-
| Phase | Feature | Status | Tests | Version |
|
|
493
|
-
|-------|---------|--------|-------|---------|
|
|
494
|
-
| 7A | Bookmarks / PDF Outline | ✅ Complete | 8 | 0.1.0 |
|
|
495
|
-
| 7B | Watermarks | ✅ Complete | 8 | 0.1.0 |
|
|
496
|
-
| 7C | Hyphenation | ✅ Complete | 10 | 0.1.0 |
|
|
497
|
-
| 7D | Table of Contents | ✅ Complete | 10 | 0.1.0 |
|
|
498
|
-
| 7E | SVG Support | ✅ Complete | 8 | 0.1.0 |
|
|
499
|
-
| 7F | RTL Text Support | ✅ Complete | 12 | 0.1.0 |
|
|
500
|
-
| 7G | Encryption | ✅ Complete | 7 | 0.1.0 |
|
|
501
|
-
| Integration | Feature Combinations | ✅ Complete | 6 | 0.1.0 |
|
|
502
|
-
| 6 | Advanced Features | ✅ Complete | — | 0.1.0 |
|
|
503
|
-
| 5 | Rich Text / Builder API | ✅ Complete | — | 0.1.0 |
|
|
504
|
-
| 1–4 | Core Engine | ✅ Complete | — | 0.1.0 |
|
|
505
|
-
|
|
506
|
-
---
|
|
507
|
-
|
|
508
|
-
## How to Use Examples
|
|
509
|
-
|
|
510
|
-
All Phase 7 features have working examples in the `examples/` directory. Run them with:
|
|
511
|
-
|
|
512
|
-
```bash
|
|
513
|
-
npm run example:watermark # Phase 7B — Watermarks
|
|
514
|
-
npm run example:bookmarks # Phase 7A — Bookmarks
|
|
515
|
-
npm run example:toc # Phase 7D — Table of Contents
|
|
516
|
-
npm run example:rtl # Phase 7F — RTL Text Support
|
|
517
|
-
npm run example:encryption # Phase 7G — Encryption
|
|
518
|
-
```
|
|
519
|
-
|
|
520
|
-
PDF output is written to `output/phase7-*.pdf`.
|
|
521
|
-
|
|
522
|
-
---
|
|
523
|
-
|
|
524
|
-
## Test Coverage
|
|
525
|
-
|
|
526
|
-
All phases include comprehensive test coverage:
|
|
527
|
-
|
|
528
|
-
```bash
|
|
529
|
-
npm test # Run all 75+ tests
|
|
530
|
-
npm run test:unit # Unit tests only
|
|
531
|
-
npm run test:e2e # End-to-end tests
|
|
532
|
-
npm run test:visual # Visual regression tests
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
---
|
|
536
|
-
|
|
537
|
-
## Dependencies
|
|
538
|
-
|
|
539
|
-
### Required
|
|
540
|
-
|
|
541
|
-
- `@chenglou/pretext` — Pretext text layout engine
|
|
542
|
-
- `pdf-lib` — PDF document manipulation
|
|
543
|
-
- `@fontsource/inter` — Font: Inter (bundled)
|
|
544
|
-
- `bidi-js` — Bidirectional text algorithm (Phase 7F)
|
|
545
|
-
- `hypher` — Hyphenation algorithm (Phase 7C)
|
|
546
|
-
- `hyphenation.en-us` — English hyphenation patterns (Phase 7C)
|
|
547
|
-
|
|
548
|
-
### Optional (Peer)
|
|
549
|
-
|
|
550
|
-
- `@napi-rs/canvas` — SVG rasterization (Phase 7E)
|
|
551
|
-
- `@cantoo/pdf-lib` — PDF encryption (Phase 7G)
|
|
552
|
-
|
|
553
|
-
---
|
|
554
|
-
|
|
555
|
-
## Architecture
|
|
556
|
-
|
|
557
|
-
pretext-pdf uses a modular, layered architecture:
|
|
558
|
-
|
|
559
|
-
```
|
|
560
|
-
render(doc) → validate → layout → paginate → render-pages → PDF bytes
|
|
561
|
-
```
|
|
562
|
-
|
|
563
|
-
Each phase adds features orthogonally:
|
|
564
|
-
- Phase 1–4: Core engine, pagination, typography
|
|
565
|
-
- Phase 5: Rich text and builder patterns
|
|
566
|
-
- Phase 6: Advanced layout and formatting
|
|
567
|
-
- Phase 7: Security, internationalization, accessibility
|
|
568
|
-
|
|
569
|
-
---
|
|
570
|
-
|
|
571
|
-
## Future Roadmap
|
|
572
|
-
|
|
573
|
-
Potential Phase 8+ features (not yet implemented):
|
|
574
|
-
- Hyperlinks and anchors
|
|
575
|
-
- Justified text alignment
|
|
576
|
-
- Enhanced text decorations
|
|
577
|
-
- Font subsetting for file size reduction
|
|
578
|
-
- Browser compatibility improvements
|
|
579
|
-
- Performance optimizations
|
|
580
|
-
|
|
581
|
-
---
|
|
582
|
-
|
|
583
|
-
## Contributing
|
|
584
|
-
|
|
585
|
-
pretext-pdf is actively maintained. To report issues, request features, or contribute:
|
|
586
|
-
|
|
587
|
-
1. Check existing issues on the project repo
|
|
588
|
-
2. Write failing tests first (TDD)
|
|
589
|
-
3. Submit pull requests with test coverage ≥80%
|
|
590
|
-
|
|
591
|
-
---
|
|
592
|
-
|
|
593
|
-
## License
|
|
594
|
-
|
|
595
|
-
Check LICENSE file in repository root.
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
[](https://www.npmjs.com/package/pretext-pdf)
|
|
10
10
|
[](https://github.com/Himaan1998Y/pretext-pdf/actions)
|
|
11
11
|
[](https://www.typescriptlang.org/)
|
|
12
|
-
[](#tests)
|
|
13
13
|
[](LICENSE)
|
|
14
14
|
[](#runtime-footprint)
|
|
15
15
|
|
|
@@ -34,15 +34,18 @@
|
|
|
34
34
|
- [Element catalog](#element-catalog)
|
|
35
35
|
- [Document features](#document-level-features)
|
|
36
36
|
- [API reference](#api-reference)
|
|
37
|
+
- [Strict validation](#strict-validation)
|
|
37
38
|
- [India / GST invoicing](#india--gst-invoicing)
|
|
38
39
|
- [Custom fonts](#custom-fonts)
|
|
39
40
|
- [Rich text](#rich-text)
|
|
40
41
|
- [Footnotes](#footnotes)
|
|
42
|
+
- [Custom element types (plugins)](#custom-element-types-plugins)
|
|
41
43
|
- [Examples](#examples)
|
|
42
44
|
- [Error handling](#error-handling)
|
|
43
45
|
- [Troubleshooting](#troubleshooting)
|
|
44
46
|
- [Non-goals](#non-goals)
|
|
45
47
|
- [Runtime footprint](#runtime-footprint)
|
|
48
|
+
- [Compatibility matrix](#compatibility-matrix)
|
|
46
49
|
- [Performance](#performance)
|
|
47
50
|
- [Tests](#tests)
|
|
48
51
|
- [Security](#security)
|
|
@@ -432,6 +435,47 @@ const pdf = await createPdf({ pageSize: 'A4' })
|
|
|
432
435
|
|
|
433
436
|
---
|
|
434
437
|
|
|
438
|
+
## Strict validation
|
|
439
|
+
|
|
440
|
+
By default, `render()` uses permissive validation — unknown properties are silently ignored. Enable strict mode to catch typos and ensure property names match the schema exactly:
|
|
441
|
+
|
|
442
|
+
```typescript
|
|
443
|
+
import { render } from 'pretext-pdf'
|
|
444
|
+
|
|
445
|
+
const pdf = await render(doc, { strict: true })
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
In strict mode:
|
|
449
|
+
|
|
450
|
+
- **Unknown properties are rejected** with a `VALIDATION_ERROR` that includes:
|
|
451
|
+
- Property name and location (JSONPath-like: `content[3].table.rows[0].cells[1].align`)
|
|
452
|
+
- Typo suggestions via Levenshtein distance (edit distance ≤2)
|
|
453
|
+
- All violations collected before throwing, with a 20-error cap + overflow indicator
|
|
454
|
+
|
|
455
|
+
Example error:
|
|
456
|
+
|
|
457
|
+
```
|
|
458
|
+
VALIDATION_ERROR:
|
|
459
|
+
unknown property 'fontSizee' at content[0].fontSizee (did you mean fontsize, fontSize?)
|
|
460
|
+
unknown property 'colorr' at content[1].inline.colorr (did you mean color?)
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
Strict validation is useful for:
|
|
464
|
+
- **AI agent self-correction**: LLMs can parse error messages and fix typos
|
|
465
|
+
- **Template development**: catch copy-paste errors in large documents
|
|
466
|
+
- **Type safety**: ensure your generator is emitting well-formed documents
|
|
467
|
+
|
|
468
|
+
You can also call `validate()` standalone for testing:
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
import { validate } from 'pretext-pdf'
|
|
472
|
+
|
|
473
|
+
// Throws PretextPdfError('VALIDATION_ERROR', ...) if strict check fails
|
|
474
|
+
validate(doc, { strict: true })
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
435
479
|
## India / GST invoicing
|
|
436
480
|
|
|
437
481
|
Built-in support for Indian invoice requirements:
|
|
@@ -539,6 +583,66 @@ await render({
|
|
|
539
583
|
|
|
540
584
|
---
|
|
541
585
|
|
|
586
|
+
## Custom element types (plugins)
|
|
587
|
+
|
|
588
|
+
The plugin API lets you register new element types without forking the library.
|
|
589
|
+
Each plugin definition handles one `type` string and participates in the standard
|
|
590
|
+
validate → measure → render pipeline.
|
|
591
|
+
|
|
592
|
+
```typescript
|
|
593
|
+
import { render } from 'pretext-pdf'
|
|
594
|
+
import type { PluginDefinition } from 'pretext-pdf'
|
|
595
|
+
import { rgb } from '@cantoo/pdf-lib'
|
|
596
|
+
|
|
597
|
+
const highlightBoxPlugin: PluginDefinition = {
|
|
598
|
+
type: 'highlight-box',
|
|
599
|
+
|
|
600
|
+
// Optional: reject bad elements early
|
|
601
|
+
validate(element) {
|
|
602
|
+
if (typeof element['label'] !== 'string') return '"label" must be a string'
|
|
603
|
+
},
|
|
604
|
+
|
|
605
|
+
// Required: return block height for layout/pagination
|
|
606
|
+
async measure(element) {
|
|
607
|
+
return { height: 48, spaceBefore: 8, spaceAfter: 8 }
|
|
608
|
+
},
|
|
609
|
+
|
|
610
|
+
// Required: draw onto the pdf-lib page
|
|
611
|
+
render({ element, pdfPage, x, y, width, height }) {
|
|
612
|
+
pdfPage.drawRectangle({ x, y: y - height, width, height, color: rgb(1, 0.93, 0.73) })
|
|
613
|
+
pdfPage.drawText(element['label'] as string, { x: x + 16, y: y - 30, size: 13 })
|
|
614
|
+
},
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// Pass plugins via render() options or createPdf() options
|
|
618
|
+
const pdf = await render(doc, { plugins: [highlightBoxPlugin] })
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
**How it works:**
|
|
622
|
+
|
|
623
|
+
| Hook | Stage | Required | Purpose |
|
|
624
|
+
| ---- | ----- | -------- | ------- |
|
|
625
|
+
| `validate` | 1 | No | Reject malformed custom elements; return error string or void |
|
|
626
|
+
| `loadAsset` | 2b | No | Embed a `PDFImage` (passed back as `context.pdfImage` in render) |
|
|
627
|
+
| `measure` | 3 | **Yes** | Return `height`, optional `spaceBefore`/`spaceAfter`, optional `pluginData` |
|
|
628
|
+
| `render` | 5 | **Yes** | Draw onto `context.pdfPage` using pdf-lib's drawing API |
|
|
629
|
+
|
|
630
|
+
**Y-coordinate note:** pdf-lib uses a bottom-left origin. `context.y` is the **top** edge of your block.
|
|
631
|
+
To fill the block: `drawRectangle({ x, y: y - height, width, height })`.
|
|
632
|
+
To draw the first line of text: `drawText(line, { x, y: y - fontSize })`.
|
|
633
|
+
|
|
634
|
+
**Constraints:** Plugin elements can only appear at the top level of `doc.content`.
|
|
635
|
+
They cannot be nested inside callout, blockquote, or float-group children (those
|
|
636
|
+
have hardcoded child type whitelists). Use top-level layout with spacers for positioning.
|
|
637
|
+
|
|
638
|
+
See `examples/plugin-custom-element.ts` for a full runnable example:
|
|
639
|
+
|
|
640
|
+
```bash
|
|
641
|
+
npm run example:plugin
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
---
|
|
645
|
+
|
|
542
646
|
## Examples
|
|
543
647
|
|
|
544
648
|
```bash
|
|
@@ -555,6 +659,7 @@ npm run example:assembly # Merge + assemble multiple PDFs
|
|
|
555
659
|
npm run example:inline # Super/subscript, letterSpacing, smallCaps
|
|
556
660
|
npm run example:forms # Interactive form fields
|
|
557
661
|
npm run example:callout # Callout boxes
|
|
662
|
+
npm run example:plugin # Custom element types (plugin API)
|
|
558
663
|
```
|
|
559
664
|
|
|
560
665
|
All write to `output/*.pdf`.
|
|
@@ -653,6 +758,22 @@ All other capabilities (SVG, charts, QR, barcodes, markdown, signing) are option
|
|
|
653
758
|
|
|
654
759
|
---
|
|
655
760
|
|
|
761
|
+
## Compatibility matrix
|
|
762
|
+
|
|
763
|
+
| Environment | Status | Notes |
|
|
764
|
+
| ----------- | ------ | ----- |
|
|
765
|
+
| **Node.js 18 / 20 / 22** | ✅ Confirmed | CI tests all three. Requires `@napi-rs/canvas` peer dep for SVG / chart / QR elements. |
|
|
766
|
+
| **Browser (Vite, webpack, esm.sh)** | ✅ Confirmed | Uses native `OffscreenCanvas`. No canvas peer dep needed. Bring your own font bytes via `doc.fonts` — the bundled Inter loader is Node-only. |
|
|
767
|
+
| **Bun** | ⚠️ Untested | Bun has Node.js compat mode. `@napi-rs/canvas` provides Bun builds but is untested end-to-end. |
|
|
768
|
+
| **Deno** | ⚠️ Untested | Deno's Node compat layer may work. `@napi-rs/canvas` native bindings are the unknown variable. |
|
|
769
|
+
| **AWS Lambda / serverless (Node runtime)** | ⚠️ Likely works | Node.js runtime, ESM supported. Cold-start impact from `@napi-rs/canvas` native addon if used. Elements that don't need canvas (paragraph, heading, table, list) have no native dep. |
|
|
770
|
+
| **Cloudflare Workers** | ❌ Not supported | No Node.js runtime, no native addons, no `OffscreenCanvas`. Neither the Node polyfill nor the browser path can run. |
|
|
771
|
+
| **Next.js (server components / API routes)** | ✅ Confirmed (Node path) | Runs on Node.js server side. Client-side rendering follows the browser path above. |
|
|
772
|
+
|
|
773
|
+
**Legend:** ✅ Confirmed in CI or end-to-end testing · ⚠️ Untested / likely works · ❌ Known not supported
|
|
774
|
+
|
|
775
|
+
---
|
|
776
|
+
|
|
656
777
|
## Performance
|
|
657
778
|
|
|
658
779
|
Benchmarked on Windows 11 / Node 22 / Intel i7-12th Gen. Averages over 10 runs, excluding the first cold JIT.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strict validation: allowed properties for each element and sub-structure type.
|
|
3
|
+
* Enforced at runtime by strict: true validation.
|
|
4
|
+
* Compile-time drift guards via Exact<T, Keys> ensure types stay synchronized.
|
|
5
|
+
*/
|
|
6
|
+
export declare const ALLOWED_PROPS: {
|
|
7
|
+
readonly paragraph: Set<"text" | "type" | "dir" | "fontSize" | "lineHeight" | "fontFamily" | "fontWeight" | "color" | "align" | "bgColor" | "spaceAfter" | "spaceBefore" | "keepTogether" | "underline" | "strikethrough" | "url" | "columns" | "columnGap" | "hyphenate" | "letterSpacing" | "smallCaps" | "tabularNumbers" | "annotation">;
|
|
8
|
+
readonly heading: Set<"text" | "type" | "dir" | "fontSize" | "lineHeight" | "fontFamily" | "fontWeight" | "color" | "align" | "bgColor" | "spaceAfter" | "spaceBefore" | "keepTogether" | "underline" | "strikethrough" | "url" | "hyphenate" | "letterSpacing" | "smallCaps" | "tabularNumbers" | "annotation" | "level" | "bookmark" | "anchor">;
|
|
9
|
+
readonly spacer: Set<"type" | "height">;
|
|
10
|
+
readonly table: Set<"type" | "dir" | "fontSize" | "spaceAfter" | "spaceBefore" | "columns" | "rows" | "headerRows" | "borderColor" | "borderWidth" | "headerBgColor" | "cellPaddingH" | "cellPaddingV">;
|
|
11
|
+
readonly image: Set<"type" | "align" | "spaceAfter" | "spaceBefore" | "height" | "width" | "src" | "format" | "float" | "floatWidth" | "floatGap" | "floatText" | "floatSpans" | "floatFontSize" | "floatFontFamily" | "floatColor">;
|
|
12
|
+
readonly svg: Set<"svg" | "type" | "align" | "spaceAfter" | "spaceBefore" | "height" | "width" | "src">;
|
|
13
|
+
readonly 'qr-code': Set<"type" | "align" | "spaceAfter" | "spaceBefore" | "data" | "size" | "errorCorrectionLevel" | "foreground" | "background" | "margin">;
|
|
14
|
+
readonly barcode: Set<"type" | "align" | "spaceAfter" | "spaceBefore" | "height" | "width" | "data" | "symbology" | "includeText">;
|
|
15
|
+
readonly chart: Set<"type" | "align" | "spaceAfter" | "spaceBefore" | "height" | "width" | "spec" | "caption">;
|
|
16
|
+
readonly list: Set<"type" | "fontSize" | "lineHeight" | "color" | "spaceAfter" | "spaceBefore" | "style" | "items" | "marker" | "indent" | "markerWidth" | "itemSpaceAfter" | "nestedNumberingStyle">;
|
|
17
|
+
readonly hr: Set<"type" | "color" | "spaceAfter" | "spaceBefore" | "thickness" | "spaceAbove" | "spaceBelow">;
|
|
18
|
+
readonly 'page-break': Set<"type">;
|
|
19
|
+
readonly code: Set<"text" | "language" | "type" | "dir" | "fontSize" | "lineHeight" | "fontFamily" | "color" | "bgColor" | "spaceAfter" | "spaceBefore" | "keepTogether" | "padding" | "highlightTheme">;
|
|
20
|
+
readonly 'rich-paragraph': Set<"type" | "dir" | "fontSize" | "lineHeight" | "align" | "bgColor" | "spaceAfter" | "spaceBefore" | "keepTogether" | "columns" | "columnGap" | "letterSpacing" | "smallCaps" | "tabularNumbers" | "spans">;
|
|
21
|
+
readonly blockquote: Set<"text" | "type" | "dir" | "fontSize" | "lineHeight" | "fontFamily" | "fontWeight" | "color" | "align" | "bgColor" | "spaceAfter" | "spaceBefore" | "keepTogether" | "underline" | "strikethrough" | "borderColor" | "borderWidth" | "padding" | "fontStyle" | "paddingH" | "paddingV">;
|
|
22
|
+
readonly toc: Set<"title" | "type" | "fontSize" | "fontFamily" | "spaceAfter" | "spaceBefore" | "showTitle" | "minLevel" | "maxLevel" | "titleFontSize" | "levelIndent" | "leader" | "entrySpacing">;
|
|
23
|
+
readonly 'toc-entry': Set<"text" | "type" | "fontFamily" | "fontWeight" | "level" | "levelIndent" | "leader" | "pageNumber">;
|
|
24
|
+
readonly comment: Set<"author" | "type" | "color" | "spaceAfter" | "contents" | "open">;
|
|
25
|
+
readonly 'form-field': Set<"type" | "fontSize" | "spaceAfter" | "spaceBefore" | "keepTogether" | "height" | "borderColor" | "width" | "backgroundColor" | "fieldType" | "name" | "label" | "placeholder" | "defaultValue" | "multiline" | "maxLength" | "checked" | "options" | "defaultSelected">;
|
|
26
|
+
readonly callout: Set<"content" | "title" | "type" | "dir" | "fontSize" | "lineHeight" | "fontFamily" | "fontWeight" | "color" | "spaceAfter" | "spaceBefore" | "keepTogether" | "borderColor" | "style" | "padding" | "paddingH" | "paddingV" | "backgroundColor" | "titleColor">;
|
|
27
|
+
readonly 'footnote-def': Set<"text" | "type" | "fontSize" | "fontFamily" | "spaceAfter" | "id">;
|
|
28
|
+
readonly 'float-group': Set<"image" | "content" | "type" | "spaceAfter" | "spaceBefore" | "float" | "floatWidth" | "floatGap">;
|
|
29
|
+
};
|
|
30
|
+
export declare const ALLOWED_PROPS_SUB: {
|
|
31
|
+
readonly document: Set<"header" | "footer" | "pageSize" | "margins" | "defaultFont" | "defaultFontSize" | "defaultLineHeight" | "fonts" | "watermark" | "encryption" | "signature" | "bookmarks" | "hyphenation" | "metadata" | "defaultParagraphStyle" | "sections" | "content" | "flattenForms" | "onImageLoadError" | "onFormFieldError" | "renderDate" | "allowedFileDirs">;
|
|
32
|
+
readonly metadata: Set<"title" | "author" | "subject" | "keywords" | "creator" | "language" | "producer">;
|
|
33
|
+
readonly 'column-def': Set<"align" | "width">;
|
|
34
|
+
readonly 'table-row': Set<"cells" | "isHeader">;
|
|
35
|
+
readonly 'table-cell': Set<"text" | "dir" | "fontSize" | "fontFamily" | "fontWeight" | "color" | "align" | "bgColor" | "tabularNumbers" | "colspan" | "rowspan">;
|
|
36
|
+
readonly 'list-item': Set<"text" | "dir" | "fontWeight" | "items">;
|
|
37
|
+
readonly 'inline-span': Set<"text" | "dir" | "fontSize" | "fontFamily" | "fontWeight" | "color" | "underline" | "strikethrough" | "url" | "letterSpacing" | "smallCaps" | "fontStyle" | "href" | "verticalAlign" | "footnoteRef">;
|
|
38
|
+
readonly annotation: Set<"author" | "color" | "contents" | "open">;
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=allowed-props.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"allowed-props.d.ts","sourceRoot":"","sources":["../src/allowed-props.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA8LH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;CAuBhB,CAAA;AAEV,eAAO,MAAM,iBAAiB;;;;;;;;;CASpB,CAAA"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strict validation: allowed properties for each element and sub-structure type.
|
|
3
|
+
* Enforced at runtime by strict: true validation.
|
|
4
|
+
* Compile-time drift guards via Exact<T, Keys> ensure types stay synchronized.
|
|
5
|
+
*/
|
|
6
|
+
// ─── Key arrays with compile-time assertions ──────────────────────────────────
|
|
7
|
+
const DOC_KEYS = [
|
|
8
|
+
'pageSize', 'margins', 'defaultFont', 'defaultFontSize', 'defaultLineHeight',
|
|
9
|
+
'fonts', 'header', 'footer', 'watermark', 'encryption', 'signature', 'bookmarks',
|
|
10
|
+
'hyphenation', 'metadata', 'defaultParagraphStyle', 'sections', 'content',
|
|
11
|
+
'flattenForms', 'onImageLoadError', 'onFormFieldError', 'renderDate', 'allowedFileDirs',
|
|
12
|
+
];
|
|
13
|
+
const METADATA_KEYS = ['title', 'author', 'subject', 'keywords', 'creator', 'language', 'producer'];
|
|
14
|
+
const PARAGRAPH_KEYS = [
|
|
15
|
+
'type', 'text', 'dir', 'fontSize', 'lineHeight', 'fontFamily', 'fontWeight', 'color',
|
|
16
|
+
'align', 'bgColor', 'spaceAfter', 'spaceBefore', 'keepTogether', 'underline',
|
|
17
|
+
'strikethrough', 'url', 'columns', 'columnGap', 'hyphenate', 'letterSpacing',
|
|
18
|
+
'smallCaps', 'tabularNumbers', 'annotation',
|
|
19
|
+
];
|
|
20
|
+
const HEADING_KEYS = [
|
|
21
|
+
'type', 'level', 'text', 'dir', 'fontFamily', 'fontWeight', 'fontSize', 'lineHeight',
|
|
22
|
+
'align', 'color', 'bgColor', 'spaceBefore', 'spaceAfter', 'keepTogether', 'underline',
|
|
23
|
+
'strikethrough', 'bookmark', 'hyphenate', 'url', 'anchor', 'letterSpacing', 'smallCaps',
|
|
24
|
+
'tabularNumbers', 'annotation',
|
|
25
|
+
];
|
|
26
|
+
const SPACER_KEYS = ['type', 'height'];
|
|
27
|
+
const TABLE_KEYS = [
|
|
28
|
+
'type', 'columns', 'rows', 'dir', 'headerRows', 'borderColor', 'borderWidth',
|
|
29
|
+
'headerBgColor', 'fontSize', 'cellPaddingH', 'cellPaddingV', 'spaceAfter', 'spaceBefore',
|
|
30
|
+
];
|
|
31
|
+
const COLUMN_DEF_KEYS = ['width', 'align'];
|
|
32
|
+
const TABLE_ROW_KEYS = ['cells', 'isHeader'];
|
|
33
|
+
const TABLE_CELL_KEYS = [
|
|
34
|
+
'text', 'dir', 'align', 'fontWeight', 'fontFamily', 'fontSize', 'color', 'bgColor',
|
|
35
|
+
'colspan', 'rowspan', 'tabularNumbers',
|
|
36
|
+
];
|
|
37
|
+
const IMAGE_KEYS = [
|
|
38
|
+
'type', 'src', 'format', 'width', 'height', 'align', 'spaceAfter', 'spaceBefore',
|
|
39
|
+
'float', 'floatWidth', 'floatGap', 'floatText', 'floatSpans', 'floatFontSize',
|
|
40
|
+
'floatFontFamily', 'floatColor',
|
|
41
|
+
];
|
|
42
|
+
const SVG_KEYS = ['type', 'svg', 'src', 'width', 'height', 'align', 'spaceBefore', 'spaceAfter'];
|
|
43
|
+
const QR_CODE_KEYS = [
|
|
44
|
+
'type', 'data', 'size', 'errorCorrectionLevel', 'foreground', 'background', 'margin',
|
|
45
|
+
'align', 'spaceBefore', 'spaceAfter',
|
|
46
|
+
];
|
|
47
|
+
const BARCODE_KEYS = [
|
|
48
|
+
'type', 'symbology', 'data', 'width', 'height', 'includeText', 'align', 'spaceBefore', 'spaceAfter',
|
|
49
|
+
];
|
|
50
|
+
const CHART_KEYS = ['type', 'spec', 'width', 'height', 'caption', 'align', 'spaceBefore', 'spaceAfter'];
|
|
51
|
+
const LIST_KEYS = [
|
|
52
|
+
'type', 'style', 'items', 'marker', 'indent', 'markerWidth', 'fontSize', 'lineHeight',
|
|
53
|
+
'itemSpaceAfter', 'spaceAfter', 'spaceBefore', 'color', 'nestedNumberingStyle',
|
|
54
|
+
];
|
|
55
|
+
const LIST_ITEM_KEYS = ['text', 'dir', 'fontWeight', 'items'];
|
|
56
|
+
const HR_KEYS = ['type', 'thickness', 'color', 'spaceAbove', 'spaceBelow', 'spaceBefore', 'spaceAfter'];
|
|
57
|
+
const PAGE_BREAK_KEYS = ['type'];
|
|
58
|
+
const CODE_KEYS = [
|
|
59
|
+
'type', 'text', 'dir', 'fontFamily', 'fontSize', 'lineHeight', 'bgColor', 'color',
|
|
60
|
+
'padding', 'spaceAfter', 'spaceBefore', 'keepTogether', 'language', 'highlightTheme',
|
|
61
|
+
];
|
|
62
|
+
const RICH_PARAGRAPH_KEYS = [
|
|
63
|
+
'type', 'spans', 'dir', 'fontSize', 'lineHeight', 'align', 'bgColor', 'spaceBefore',
|
|
64
|
+
'spaceAfter', 'keepTogether', 'columns', 'columnGap', 'letterSpacing', 'smallCaps',
|
|
65
|
+
'tabularNumbers',
|
|
66
|
+
];
|
|
67
|
+
const INLINE_SPAN_KEYS = [
|
|
68
|
+
'text', 'dir', 'fontFamily', 'fontWeight', 'fontStyle', 'color', 'fontSize', 'underline',
|
|
69
|
+
'strikethrough', 'url', 'href', 'verticalAlign', 'smallCaps', 'letterSpacing', 'footnoteRef',
|
|
70
|
+
];
|
|
71
|
+
const BLOCKQUOTE_KEYS = [
|
|
72
|
+
'type', 'text', 'dir', 'borderColor', 'borderWidth', 'bgColor', 'color', 'fontFamily',
|
|
73
|
+
'fontWeight', 'fontStyle', 'fontSize', 'lineHeight', 'padding', 'paddingH', 'paddingV',
|
|
74
|
+
'align', 'spaceBefore', 'spaceAfter', 'keepTogether', 'underline', 'strikethrough',
|
|
75
|
+
];
|
|
76
|
+
const CALLOUT_KEYS = [
|
|
77
|
+
'type', 'content', 'style', 'title', 'backgroundColor', 'borderColor', 'color', 'titleColor',
|
|
78
|
+
'fontFamily', 'fontWeight', 'fontSize', 'lineHeight', 'padding', 'paddingH', 'paddingV',
|
|
79
|
+
'spaceAfter', 'spaceBefore', 'keepTogether', 'dir',
|
|
80
|
+
];
|
|
81
|
+
const COMMENT_KEYS = ['type', 'contents', 'author', 'color', 'open', 'spaceAfter'];
|
|
82
|
+
const FORM_FIELD_KEYS = [
|
|
83
|
+
'type', 'fieldType', 'name', 'label', 'placeholder', 'defaultValue', 'multiline',
|
|
84
|
+
'maxLength', 'checked', 'options', 'defaultSelected', 'width', 'height', 'fontSize',
|
|
85
|
+
'borderColor', 'backgroundColor', 'spaceAfter', 'spaceBefore', 'keepTogether',
|
|
86
|
+
];
|
|
87
|
+
const FOOTNOTE_DEF_KEYS = ['type', 'id', 'text', 'fontSize', 'fontFamily', 'spaceAfter'];
|
|
88
|
+
const TOC_KEYS = [
|
|
89
|
+
'type', 'title', 'showTitle', 'minLevel', 'maxLevel', 'fontSize', 'titleFontSize',
|
|
90
|
+
'levelIndent', 'leader', 'entrySpacing', 'fontFamily', 'spaceBefore', 'spaceAfter',
|
|
91
|
+
];
|
|
92
|
+
const TOC_ENTRY_KEYS = ['type', 'text', 'pageNumber', 'level', 'levelIndent', 'leader', 'fontFamily', 'fontWeight'];
|
|
93
|
+
const FLOAT_GROUP_KEYS = ['type', 'image', 'float', 'floatWidth', 'floatGap', 'content', 'spaceBefore', 'spaceAfter'];
|
|
94
|
+
const ANNOTATION_KEYS = ['contents', 'author', 'color', 'open'];
|
|
95
|
+
// ─── Runtime Sets created from key arrays ─────────────────────────────────────
|
|
96
|
+
export const ALLOWED_PROPS = {
|
|
97
|
+
'paragraph': new Set(PARAGRAPH_KEYS),
|
|
98
|
+
'heading': new Set(HEADING_KEYS),
|
|
99
|
+
'spacer': new Set(SPACER_KEYS),
|
|
100
|
+
'table': new Set(TABLE_KEYS),
|
|
101
|
+
'image': new Set(IMAGE_KEYS),
|
|
102
|
+
'svg': new Set(SVG_KEYS),
|
|
103
|
+
'qr-code': new Set(QR_CODE_KEYS),
|
|
104
|
+
'barcode': new Set(BARCODE_KEYS),
|
|
105
|
+
'chart': new Set(CHART_KEYS),
|
|
106
|
+
'list': new Set(LIST_KEYS),
|
|
107
|
+
'hr': new Set(HR_KEYS),
|
|
108
|
+
'page-break': new Set(PAGE_BREAK_KEYS),
|
|
109
|
+
'code': new Set(CODE_KEYS),
|
|
110
|
+
'rich-paragraph': new Set(RICH_PARAGRAPH_KEYS),
|
|
111
|
+
'blockquote': new Set(BLOCKQUOTE_KEYS),
|
|
112
|
+
'toc': new Set(TOC_KEYS),
|
|
113
|
+
'toc-entry': new Set(TOC_ENTRY_KEYS),
|
|
114
|
+
'comment': new Set(COMMENT_KEYS),
|
|
115
|
+
'form-field': new Set(FORM_FIELD_KEYS),
|
|
116
|
+
'callout': new Set(CALLOUT_KEYS),
|
|
117
|
+
'footnote-def': new Set(FOOTNOTE_DEF_KEYS),
|
|
118
|
+
'float-group': new Set(FLOAT_GROUP_KEYS),
|
|
119
|
+
};
|
|
120
|
+
export const ALLOWED_PROPS_SUB = {
|
|
121
|
+
'document': new Set(DOC_KEYS),
|
|
122
|
+
'metadata': new Set(METADATA_KEYS),
|
|
123
|
+
'column-def': new Set(COLUMN_DEF_KEYS),
|
|
124
|
+
'table-row': new Set(TABLE_ROW_KEYS),
|
|
125
|
+
'table-cell': new Set(TABLE_CELL_KEYS),
|
|
126
|
+
'list-item': new Set(LIST_ITEM_KEYS),
|
|
127
|
+
'inline-span': new Set(INLINE_SPAN_KEYS),
|
|
128
|
+
'annotation': new Set(ANNOTATION_KEYS),
|
|
129
|
+
};
|
|
130
|
+
//# sourceMappingURL=allowed-props.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"allowed-props.js","sourceRoot":"","sources":["../src/allowed-props.ts"],"names":[],"mappings":"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"}
|
package/dist/assets.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { PDFDocument } from '@cantoo/pdf-lib';
|
|
2
|
-
import type { PdfDocument
|
|
2
|
+
import type { PdfDocument } from './types.js';
|
|
3
|
+
import type { ImageMap } from './types-internal.js';
|
|
4
|
+
import type { PluginDefinition } from './plugin-types.js';
|
|
3
5
|
/**
|
|
4
6
|
* Enforce allowedFileDirs: resolved absolute path must start with an allowed dir.
|
|
5
7
|
* No-op when allowedFileDirs is unset (backwards-compatible default).
|
|
@@ -26,5 +28,5 @@ export declare function assertSafeUrl(url: string, errorCode: 'IMAGE_LOAD_FAILED
|
|
|
26
28
|
* Images that fail to load (network error, file not found, unreachable URL) are
|
|
27
29
|
* logged as warnings but do not crash the document — the document renders without that image.
|
|
28
30
|
*/
|
|
29
|
-
export declare function loadImages(doc: PdfDocument, pdfDoc: PDFDocument, contentWidth: number): Promise<ImageMap>;
|
|
31
|
+
export declare function loadImages(doc: PdfDocument, pdfDoc: PDFDocument, contentWidth: number, plugins?: PluginDefinition[]): Promise<ImageMap>;
|
|
30
32
|
//# sourceMappingURL=assets.d.ts.map
|
package/dist/assets.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAyE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAyE,MAAM,YAAY,CAAA;AACpH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAEnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAKzD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAa9G;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,mBAAmB,GAAG,iBAAiB,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAiDlH;AAgSD;;;;;;;;;;;;GAYG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CA0J7I"}
|