@qrcommunication/gigapdf-lib 0.1.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/CHANGELOG.md +192 -0
- package/README.md +54 -6
- package/dist/editor.cjs +1153 -0
- package/dist/editor.cjs.map +1 -0
- package/dist/editor.d.cts +96 -0
- package/dist/editor.d.ts +96 -0
- package/dist/editor.js +1126 -0
- package/dist/editor.js.map +1 -0
- package/dist/index.cjs +421 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +190 -4
- package/dist/index.d.ts +190 -4
- package/dist/index.js +421 -2
- package/dist/index.js.map +1 -1
- package/dist/viewer.cjs +526 -0
- package/dist/viewer.cjs.map +1 -0
- package/dist/viewer.d.cts +144 -0
- package/dist/viewer.d.ts +144 -0
- package/dist/viewer.js +501 -0
- package/dist/viewer.js.map +1 -0
- package/gigapdf.wasm +0 -0
- package/package.json +12 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,198 @@ All notable changes to `@qrcommunication/gigapdf-lib` are documented here.
|
|
|
4
4
|
The format follows [Keep a Changelog](https://keepachangelog.com/) and the
|
|
5
5
|
project adheres to [Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [0.7.0] - 2026-06-15
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Complete viewer zoom controls** (`@qrcommunication/gigapdf-lib/viewer`):
|
|
12
|
+
`fitWidth()`, `fitPage()`, `actualSize()`, `setZoom()` / `setZoomPercent()` and a
|
|
13
|
+
`zoom` getter; a toolbar **preset drop-down** (Fit width · Fit page · 50–400 %)
|
|
14
|
+
with a live `%` readout; `Ctrl`/`⌘` + mouse-wheel zoom; and a `0` keyboard
|
|
15
|
+
shortcut. A chosen **fit mode is sticky** — it re-applies when the viewport
|
|
16
|
+
resizes (via `ResizeObserver`) and when paging to a page of a different
|
|
17
|
+
orientation.
|
|
18
|
+
- **Editor rulers & margins** (`@qrcommunication/gigapdf-lib/editor`): every page
|
|
19
|
+
shows graduated **millimetre rulers** (top + left) and four **margin guides**
|
|
20
|
+
dragged **live** from handles in the ruler bands — or set via the palette's
|
|
21
|
+
`T R B L` mm fields and the `setMargins()` / `getMargins()` / `showRulers()`
|
|
22
|
+
API. Guides are drawn in page-point coordinates (on a second SVG layer) and kept
|
|
23
|
+
a constant on-screen size at any zoom.
|
|
24
|
+
|
|
25
|
+
## [0.6.0] - 2026-06-15
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- **Full page control for HTML→PDF** via `htmlRenderWith(html, fonts, options)`:
|
|
30
|
+
- **named paper sizes** — `pageSize: "A4" | "a3-landscape" | "letter" | …`
|
|
31
|
+
(ISO A0–A6, ISO B4/B5, US Letter/Legal/Tabloid/Executive; `-landscape`
|
|
32
|
+
suffix swaps the axes). `giga.pageSize(name)` resolves one to `{ w, h }`
|
|
33
|
+
points.
|
|
34
|
+
- **per-side margins** — `margin: number | { top, right, bottom, left }`.
|
|
35
|
+
- **running header & footer** — `header` / `footer` are full HTML+CSS
|
|
36
|
+
snippets painted in the page margins on every page, with `{{page}}` /
|
|
37
|
+
`{{pages}}` substitution and configurable `startPageNumber`,
|
|
38
|
+
`headerOffset` / `footerOffset`.
|
|
39
|
+
- **`htmlNeededFontsWith(html, header, footer)`** — phase-1 font discovery that
|
|
40
|
+
also scans the header/footer HTML so their Google fonts are fetched.
|
|
41
|
+
- New ABI exports: `gp_html_render_opts`, `gp_html_needed_fonts_ex`,
|
|
42
|
+
`gp_page_size`.
|
|
43
|
+
|
|
44
|
+
### Images & SVG
|
|
45
|
+
|
|
46
|
+
- **SVG → native PDF vector** via `doc.addSvg(page, src, x, y, w, h)` (ABI
|
|
47
|
+
`gp_add_svg`): shapes (`rect`/`circle`/`ellipse`/`line`/`polyline`/`polygon`),
|
|
48
|
+
`<path>` (full `d` grammar with **exact `A` arc→Bézier conversion**), `<g>`
|
|
49
|
+
groups, `transform`, `viewBox`, `fill`/`stroke`/`stroke-width`/`opacity`, and
|
|
50
|
+
**gradients** (`<linearGradient>`/`<radialGradient>` → native PDF axial/radial
|
|
51
|
+
shadings, with stops, `gradientUnits`, `gradientTransform` and `href`
|
|
52
|
+
inheritance) — crisp at any zoom, not rasterized. In the HTML renderer, inline
|
|
53
|
+
`<svg>` and `data:image/svg+xml` `<img>` sources render as native vector.
|
|
54
|
+
- **PNG transparency in the rasterizer**: `renderPage`/thumbnails now honour an
|
|
55
|
+
image's `/SMask` (soft mask) as per-pixel alpha instead of treating it as
|
|
56
|
+
opaque, so transparent PNGs composite correctly in every conversion (not just
|
|
57
|
+
HTML→PDF).
|
|
58
|
+
- **Colour emoji** (COLR v0 + CPAL): when a text run uses a colour font (e.g.
|
|
59
|
+
`font-family: "Noto Color Emoji"`), emoji are drawn as native vector colour
|
|
60
|
+
layers in the HTML renderer — crisp, and rasterized for free. **Apple `sbix`
|
|
61
|
+
bitmap emoji** are placed as PNG glyph bitmaps. Non-colour characters in the
|
|
62
|
+
run still render as text. (COLRv1 gradient glyphs and `CBDT/CBLC` strikes are
|
|
63
|
+
not yet drawn.)
|
|
64
|
+
|
|
65
|
+
### Viewer
|
|
66
|
+
|
|
67
|
+
- **`@qrcommunication/gigapdf-lib/viewer`** — a new zero-dependency browser
|
|
68
|
+
document viewer (`GigaPdfViewer`) built on the engine (no pdf.js): opens PDF,
|
|
69
|
+
Office (docx/xlsx/pptx, legacy, ODF) and HTML (auto-detected, converted
|
|
70
|
+
in-engine), renders pages with `renderPage`, **detects per-page orientation**
|
|
71
|
+
and adapts, with navigation, zoom, a thumbnail rail, keyboard control and a
|
|
72
|
+
**fullscreen presentation mode**.
|
|
73
|
+
- **`@qrcommunication/gigapdf-lib/editor`** — an interactive **editing canvas**
|
|
74
|
+
(`GigaPdfEditor`) extending the viewer: an SVG overlay per page with tools
|
|
75
|
+
(text, rectangle, ellipse, line, freehand ink, image, highlight, redaction),
|
|
76
|
+
select·move·delete, and `applyEdits()` that **bakes edits into the real PDF**
|
|
77
|
+
through the engine (then re-renders); `save()` returns the result.
|
|
78
|
+
|
|
79
|
+
### CSS
|
|
80
|
+
|
|
81
|
+
- HTML→PDF renderer gained `min-width` / `max-width`, `height` / `min-height`,
|
|
82
|
+
`box-sizing`, `text-indent` (first-line indent), `visibility: hidden`,
|
|
83
|
+
`opacity` (backgrounds/borders/text rules), and `text-decoration: line-through`
|
|
84
|
+
/ `overline`. See [`docs/HTML-CSS.md`](../docs/HTML-CSS.md).
|
|
85
|
+
|
|
86
|
+
## [0.5.0] - 2026-06-15
|
|
87
|
+
|
|
88
|
+
### Changed
|
|
89
|
+
|
|
90
|
+
- **Suspendable JavaScript VM** for `<script>` execution (`htmlRender` /
|
|
91
|
+
`runInlineScripts`). `function*` and `async` bodies now compile to a
|
|
92
|
+
resumable bytecode machine, so:
|
|
93
|
+
- **generators are truly lazy** — an infinite `while (true) { yield … }` is
|
|
94
|
+
fine, `.next(v)` feeds a value back into the suspended `yield`, and `yield*`
|
|
95
|
+
delegates lazily;
|
|
96
|
+
- **`await` yields to the event loop** with spec microtask ordering (the
|
|
97
|
+
synchronous tail runs before a deferred continuation), instead of draining
|
|
98
|
+
the queue synchronously;
|
|
99
|
+
- **full control flow** can span a `yield`/`await` — `try`/`catch`/`finally`
|
|
100
|
+
(the handler survives suspension; a rejected `await` in a `try` is caught),
|
|
101
|
+
`for…of`/`for…in`, `switch`, labelled `break`/`continue`, destructuring,
|
|
102
|
+
compound assignment, and `...spread`.
|
|
103
|
+
|
|
104
|
+
No API change — existing `htmlRender`/`runInlineScripts` calls simply behave
|
|
105
|
+
correctly for script-driven, generator/async-heavy templates. A body the VM
|
|
106
|
+
can't compile (e.g. `try`/`catch` around a `yield`/`await`) transparently
|
|
107
|
+
falls back to the previous eager/synchronous model.
|
|
108
|
+
|
|
109
|
+
## [0.4.0] - 2026-06-15
|
|
110
|
+
|
|
111
|
+
### Added
|
|
112
|
+
|
|
113
|
+
- **AcroForm field creation.** Build interactive forms from scratch — no
|
|
114
|
+
`pdf-lib`. New `GigaPdfDoc` methods, each taking a `[x0,y0,x1,y1]` rectangle
|
|
115
|
+
and an optional [`FieldStyle`](src/index.ts) (font size, text/border/background
|
|
116
|
+
colour, border width):
|
|
117
|
+
- `addTextField(page, name, rect, value?, { maxLen, multiline, password, style })`
|
|
118
|
+
- `addCheckbox(page, name, rect, checked?, { export, style })`
|
|
119
|
+
- `addRadioGroup(page, name, options: RadioOption[], { selected, style })`
|
|
120
|
+
- `addComboBox(page, name, rect, options, { selected, editable, style })`
|
|
121
|
+
- `addListBox(page, name, rect, options, { selected, multi, style })`
|
|
122
|
+
|
|
123
|
+
Every widget is given a real `/AP` appearance stream (text baseline, a vector
|
|
124
|
+
tick for checkboxes, a filled dot for radios) **and** the form is flagged
|
|
125
|
+
`NeedAppearances`, so fields display immediately and stay faithful when edited.
|
|
126
|
+
- **Advanced flexbox + real grid** in the HTML renderer:
|
|
127
|
+
- `flex-direction: column`, `justify-content` (start/center/end/space-between/
|
|
128
|
+
space-around) and per-item `flex-grow` (proportional column widths);
|
|
129
|
+
- `display: grid` with `grid-template-columns` (fixed column count; children
|
|
130
|
+
wrap into rows). `float` still maps to inline-block.
|
|
131
|
+
- **ES module syntax** is now parsed transparently by the JS engine (`import` is
|
|
132
|
+
elided, `export` declarations run as normal statements).
|
|
133
|
+
|
|
134
|
+
## [0.3.0] - 2026-06-15
|
|
135
|
+
|
|
136
|
+
### Added
|
|
137
|
+
|
|
138
|
+
- **JavaScript engine** (zero-dependency, pure Rust → WASM). A document's inline
|
|
139
|
+
`<script>`s now execute **before layout** inside `htmlRender` /
|
|
140
|
+
`htmlNeededFonts` — no Chromium/Playwright — so script-driven content renders.
|
|
141
|
+
The engine covers:
|
|
142
|
+
- Language: classes + `super`, closures, destructuring, spread, optional
|
|
143
|
+
chaining, template literals, `for…of`, generators (`function*`/`yield`,
|
|
144
|
+
eager), `async`/`await` + `Promise` (deterministic synchronous microtask
|
|
145
|
+
model), `try/catch/finally`, labelled loops, `arguments`.
|
|
146
|
+
- Built-ins: `Object`/`Array`/`String`/`Number`/`Boolean`/`Math`/`JSON`/
|
|
147
|
+
`console`/`Map`/`Set`/`RegExp` (a from-scratch backtracking regex engine)/
|
|
148
|
+
`Error`, plus `parseInt`/`parseFloat`/`setTimeout`/`queueMicrotask`.
|
|
149
|
+
- DOM bindings: `document.getElementById`/`getElementsByTagName`/
|
|
150
|
+
`querySelector(All)` (combinators `>`/`+`/`~`, attribute selectors), and on
|
|
151
|
+
elements `textContent`/`innerHTML`/`getAttribute`/`setAttribute`/
|
|
152
|
+
`appendChild`/`removeChild`/`classList`/`style`/`children`.
|
|
153
|
+
- **Page breaks** in the HTML renderer: CSS `page-break-before|after: always`,
|
|
154
|
+
`break-before|after: page`, a `<pagebreak>` element, or `class="page-break"`
|
|
155
|
+
start the following content on a new page.
|
|
156
|
+
- **CSS flexbox** (`display: flex` / `inline-flex`) — a basic equal-column row;
|
|
157
|
+
`grid` falls back to block flow and `float` to inline-block.
|
|
158
|
+
|
|
159
|
+
### Notes
|
|
160
|
+
|
|
161
|
+
- `htmlRender` / `htmlNeededFonts` are unchanged in signature — they simply run
|
|
162
|
+
the document's scripts first. No new SDK call is required.
|
|
163
|
+
|
|
164
|
+
## [0.2.0] - 2026-06-15
|
|
165
|
+
|
|
166
|
+
### Added
|
|
167
|
+
|
|
168
|
+
- Vector drawing primitives on `GigaPdfDoc`: `drawLine`, `addEllipse`,
|
|
169
|
+
`addPolygon`, and `addPath` — the latter accepts arbitrary SVG path data
|
|
170
|
+
(`M`/`L`/`H`/`V`/`C`/`S`/`Q`/`T`/`A`/`Z`, absolute & relative), converting
|
|
171
|
+
quadratic Béziers to cubics and flipping the Y axis like `pdf-lib`'s
|
|
172
|
+
`drawSvgPath`. Covers freeform/polygon/triangle shapes.
|
|
173
|
+
- `addImage`: embed PNG or JPEG rasters as image XObjects. JPEG is stored
|
|
174
|
+
losslessly via `/DCTDecode`; PNG is decoded in-engine (zero-dependency) with
|
|
175
|
+
its alpha channel honoured through a `/SMask` soft mask.
|
|
176
|
+
- `opacity` (fill + stroke alpha through a transient `/ExtGState`) on every
|
|
177
|
+
shape and image (`addRectangle`, `drawLine`, `addEllipse`, `addPolygon`,
|
|
178
|
+
`addPath`, `addImage`).
|
|
179
|
+
- `toOdp`: convert a PDF to an editable OpenDocument Presentation (`.odp`) —
|
|
180
|
+
one slide per page with positioned text boxes, pictures and shapes. This
|
|
181
|
+
completes **bidirectional ODF** (`.odt` / `.ods` / `.odp` both ways, the
|
|
182
|
+
reverse via `officeToPdf`), round-trip validated through LibreOffice Impress.
|
|
183
|
+
- **HTML → PDF rendering engine** (`htmlNeededFonts` + `htmlRender`): a
|
|
184
|
+
zero-dependency in-engine pipeline — HTML parser → CSS cascade (selectors,
|
|
185
|
+
specificity, inheritance, UA defaults) → block / inline / table layout with
|
|
186
|
+
pagination → paint — that renders HTML + CSS to PDF **without a headless
|
|
187
|
+
browser**. Text is set in **embedded Google fonts** resolved against the full
|
|
188
|
+
catalogue (real glyphs + metrics → identical or nearest match). Validated
|
|
189
|
+
end-to-end: Roboto downloaded, embedded (`emb=yes`, Identity-H) and the output
|
|
190
|
+
opens in LibreOffice. JavaScript execution is not included (a separate engine).
|
|
191
|
+
|
|
192
|
+
### Changed
|
|
193
|
+
|
|
194
|
+
- `addRectangle` gains a trailing optional `opacity` argument — backward
|
|
195
|
+
compatible (defaults to `1`).
|
|
196
|
+
|
|
197
|
+
[0.2.0]: https://github.com/qrcommunication/gigapdf-lib/releases/tag/v0.2.0
|
|
198
|
+
|
|
7
199
|
## [0.1.0] - 2026-06-14
|
|
8
200
|
|
|
9
201
|
### Added
|
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ doc.redact(1, 72, 700, 180, 14); // physically remove content in a region
|
|
|
36
36
|
doc.addHighlight(1, 72, 690, 252, 704, 0xffff00);
|
|
37
37
|
|
|
38
38
|
// Convert
|
|
39
|
-
const docx = doc.toDocx(); // also: toPptx/toOdt/toXlsx/toOds/toHtml/toText/toRtf/toPdfA
|
|
39
|
+
const docx = doc.toDocx(); // also: toPptx/toOdp/toOdt/toXlsx/toOds/toHtml/toText/toRtf/toPdfA
|
|
40
40
|
const png = doc.renderPage(1, 2); // rasterize a page
|
|
41
41
|
|
|
42
42
|
// Save
|
|
@@ -52,6 +52,27 @@ const fromHtml = giga.htmlToPdf("<h1>Hello</h1>");
|
|
|
52
52
|
const fromRtf = giga.rtfToPdf(rtfString);
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
+
### Build an interactive form (no `pdf-lib`)
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
// Coordinates are PDF user space (origin bottom-left): [x0, y0, x1, y1].
|
|
59
|
+
doc.addTextField(1, "fullname", [50, 700, 300, 720], "", { maxLen: 60 });
|
|
60
|
+
doc.addCheckbox(1, "subscribe", [50, 670, 64, 684], true, { export: "Yes" });
|
|
61
|
+
doc.addRadioGroup(1, "plan", [
|
|
62
|
+
{ export: "Basic", rect: [50, 640, 64, 654] },
|
|
63
|
+
{ export: "Pro", rect: [80, 640, 94, 654] },
|
|
64
|
+
], { selected: "Pro" });
|
|
65
|
+
doc.addComboBox(1, "country", [50, 610, 200, 626], ["FR", "US", "DE"], { selected: "FR" });
|
|
66
|
+
doc.addListBox(1, "langs", [50, 540, 200, 600], ["en", "fr", "de"], { multi: true });
|
|
67
|
+
|
|
68
|
+
// Optional per-field styling.
|
|
69
|
+
doc.addTextField(1, "vat", [50, 510, 200, 528], "", {
|
|
70
|
+
style: { fontSize: 11, color: 0x102030, border: 0x888888, background: 0xf5f5f5 },
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const filled = doc.fields(); // read them straight back: kind + value + options
|
|
74
|
+
```
|
|
75
|
+
|
|
55
76
|
### Fonts (host performs the network fetch)
|
|
56
77
|
|
|
57
78
|
```ts
|
|
@@ -84,16 +105,43 @@ Or call `GigaPdfEngine.load(bytes)` with bytes you read yourself.
|
|
|
84
105
|
`txtToPdf`/`htmlToPdf`/`rtfToPdf`/`officeToPdf`, `fontCatalog`/`fontRequestUrl`/`parseCssFontUrl`.
|
|
85
106
|
- **`GigaPdfDoc`** — text intelligence (`textRuns`, `structuredText`, `search`,
|
|
86
107
|
`ocr`, `ocrText`, `elements`, `elementAt`), editing (`replaceText`,
|
|
87
|
-
`removeElement`, `moveElement`, `duplicateElement`, `
|
|
88
|
-
|
|
108
|
+
`removeElement`, `moveElement`, `duplicateElement`, `redact`), vector drawing
|
|
109
|
+
(`addRectangle`, `drawLine`, `addEllipse`, `addPolygon`, `addPath` (SVG path),
|
|
110
|
+
`addImage` (PNG/JPEG, alpha + opacity)), pages (`rotatePage`, `deletePage`,
|
|
111
|
+
`movePage`, `appendPages`, `extractPages`, `resizePage`, `addPage`, `copyPage`,
|
|
112
|
+
`pageInfo`),
|
|
89
113
|
`renderPage`, fonts (`embedFont`, `addText`, `neededFonts`), conversions
|
|
90
|
-
(`toText/Html/Docx/Pptx/Odt/Xlsx/Ods/Rtf/PdfA`), security (`saveEncrypted`,
|
|
114
|
+
(`toText/Html/Docx/Pptx/Odp/Odt/Xlsx/Ods/Rtf/PdfA`), security (`saveEncrypted`,
|
|
91
115
|
`sign`), metadata (`getMetadata`, `setMetadata`), annotations (`addSquare`,
|
|
92
116
|
`addHighlight`, `addLineAnnotation`, `addFreeText`, `addUnderline`,
|
|
93
117
|
`addStrikeOut`, `addInk`, `addStamp`, `annotations`, `removeAnnotation`,
|
|
94
118
|
`flattenAnnotations`), links (`links`, `addUriLink`, `addGotoLink`), outline
|
|
95
|
-
(`outline`, `setOutline`),
|
|
96
|
-
`setRadio`, `setChoice`)
|
|
119
|
+
(`outline`, `setOutline`), forms — read/fill (`fields`, `setTextField`,
|
|
120
|
+
`setCheckbox`, `setRadio`, `setChoice`) **and create**
|
|
121
|
+
(`addTextField`, `addCheckbox`, `addRadioGroup`, `addComboBox`, `addListBox`,
|
|
122
|
+
each with an optional `FieldStyle`), and optional-content layers (`layers`,
|
|
123
|
+
`addLayer`, `setLayerVisibility`, `setLayerLocked`, `removeLayer`).
|
|
124
|
+
- **HTML rendering engine** (on `GigaPdfEngine`) — `htmlNeededFonts(html)`
|
|
125
|
+
returns the Google fonts to download (phase 1); `htmlRender(html, fonts,
|
|
126
|
+
pageW?, pageH?, margin?)` renders HTML + CSS to PDF with those fonts embedded
|
|
127
|
+
(phase 2). **No headless browser.** Block / inline / table / **flex**
|
|
128
|
+
(`flex-direction`, `justify-content`, `flex-grow`) / **grid**
|
|
129
|
+
(`grid-template-columns`) layout, selector cascade, pagination, and forced page
|
|
130
|
+
breaks via CSS `page-break-before|after: always` / `break-*: page` or a
|
|
131
|
+
`<pagebreak>` tag. **See the exhaustive list of supported HTML elements, CSS
|
|
132
|
+
properties, units, colours and selectors in
|
|
133
|
+
[`docs/HTML-CSS.md`](https://github.com/QrCommunication/gigapdf-lib/blob/main/docs/HTML-CSS.md).**
|
|
134
|
+
- **JavaScript** — a document's inline `<script>`s run **before layout** through
|
|
135
|
+
a built-in zero-dependency JS engine (no Chromium/Playwright), so script-driven
|
|
136
|
+
content is rendered. It covers classes + `super`, closures, destructuring,
|
|
137
|
+
`RegExp`, `Map`/`Set`, `Symbol`, `eval`/`Function`, and DOM bindings
|
|
138
|
+
(`document.getElementById`, `querySelector(All)` with `>`/`+`/`~`/`[attr]`,
|
|
139
|
+
`textContent`, `innerHTML`, `createElement`/`appendChild`, `classList`,
|
|
140
|
+
`style`). `function*`/`async` bodies compile to a **suspendable bytecode VM**,
|
|
141
|
+
so generators are **truly lazy** (infinite generators, bidirectional
|
|
142
|
+
`.next(v)`, `yield*`) and `await` **yields** with spec microtask ordering. This
|
|
143
|
+
happens automatically inside `htmlRender`/`htmlNeededFonts` — no extra call
|
|
144
|
+
needed.
|
|
97
145
|
|
|
98
146
|
Every method is fully typed. Always `close()` a document when done to free the
|
|
99
147
|
WASM handle.
|