@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 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`, `addRectangle`, `redact`),
88
- pages (`rotatePage`, `deletePage`, `movePage`, `appendPages`, `extractPages`),
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`), and forms (`fields`, `setTextField`, `setCheckbox`,
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.