gedcom-ts 2026.5.3 → 2026.6.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 +54 -0
- package/README.md +163 -29
- package/dist/booklet/booklet-date-en.d.ts +9 -0
- package/dist/booklet/booklet-date-factory.d.ts +21 -0
- package/dist/booklet/booklet-date-fr.d.ts +1 -0
- package/dist/booklet/booklet-date.d.ts +6 -0
- package/dist/booklet/booklet-estimate.d.ts +4 -3
- package/dist/booklet/booklet-gender-core.d.ts +3 -0
- package/dist/booklet/booklet-gender-data.d.ts +9 -0
- package/dist/booklet/booklet-gender.d.ts +8 -9
- package/dist/booklet/booklet-locale-helpers.d.ts +4 -0
- package/dist/booklet/booklet-locale-loader.d.ts +27 -0
- package/dist/booklet/booklet-locale-modules-source.d.ts +1 -0
- package/dist/booklet/booklet-locale-modules.d.ts +5 -0
- package/dist/booklet/booklet-locale.d.ts +15 -0
- package/dist/booklet/booklet-logo-loader.d.ts +8 -0
- package/dist/booklet/booklet-logo.d.ts +1 -5
- package/dist/booklet/booklet-messages-data.d.ts +15 -0
- package/dist/booklet/booklet-messages-types.d.ts +46 -0
- package/dist/booklet/booklet-messages.d.ts +7 -0
- package/dist/booklet/booklet-narrative-en.d.ts +10 -0
- package/dist/booklet/booklet-narrative-engine.d.ts +17 -0
- package/dist/booklet/booklet-narrative-fr.d.ts +10 -0
- package/dist/booklet/booklet-narrative-i18n.d.ts +44 -0
- package/dist/booklet/booklet-narrative-locales.d.ts +3 -0
- package/dist/booklet/booklet-narrative.d.ts +5 -8
- package/dist/booklet/booklet-pdf-bidi.d.ts +5 -0
- package/dist/booklet/booklet-pdf-content-text.d.ts +11 -0
- package/dist/booklet/booklet-pdf-font-runtime.d.ts +8 -0
- package/dist/booklet/booklet-pdf-font-runtime.node.d.ts +3 -0
- package/dist/booklet/booklet-pdf-font-sources.d.ts +6 -0
- package/dist/booklet/booklet-pdf-font.d.ts +14 -0
- package/dist/booklet/booklet-pdf-fontkit.d.ts +6 -0
- package/dist/booklet/booklet-pdf-text.d.ts +24 -0
- package/dist/booklet/booklet-pdf.d.ts +13 -0
- package/dist/booklet/booklet-person.d.ts +6 -3
- package/dist/booklet/booklet-place-en.d.ts +16 -0
- package/dist/booklet/booklet-place-factory.d.ts +28 -0
- package/dist/booklet/booklet-place.d.ts +13 -0
- package/dist/booklet/booklet-structure.d.ts +3 -2
- package/dist/booklet/booklet-timeline-canvas.d.ts +2 -9
- package/dist/booklet/booklet-timeline-loader.d.ts +6 -0
- package/dist/booklet/booklet-timeline-metrics.d.ts +8 -0
- package/dist/booklet/feature-chunks/booklet-logo-draw.d.ts +15 -0
- package/dist/booklet/feature-chunks/booklet-timeline-raster.d.ts +3 -0
- package/dist/booklet/font-chunks/booklet-font-subset-chars.d.ts +2 -0
- package/dist/booklet/font-chunks/booklet-pdf-font-bytes-ar.d.ts +2 -0
- package/dist/booklet/font-chunks/booklet-pdf-font-bytes-he.d.ts +2 -0
- package/dist/booklet/font-chunks/booklet-pdf-font-bytes-zh-ext.d.ts +2 -0
- package/dist/booklet/font-chunks/booklet-pdf-font-bytes-zh.d.ts +2 -0
- package/dist/booklet/index.d.ts +11 -3
- package/dist/booklet/locale-chunks/booklet-locale-ar.d.ts +3 -0
- package/dist/booklet/locale-chunks/booklet-locale-de.d.ts +3 -0
- package/dist/booklet/locale-chunks/booklet-locale-en.d.ts +3 -0
- package/dist/booklet/locale-chunks/booklet-locale-es.d.ts +3 -0
- package/dist/booklet/locale-chunks/booklet-locale-fr.d.ts +3 -0
- package/dist/booklet/locale-chunks/booklet-locale-he.d.ts +3 -0
- package/dist/booklet/locale-chunks/booklet-locale-it.d.ts +3 -0
- package/dist/booklet/locale-chunks/booklet-locale-nl.d.ts +3 -0
- package/dist/booklet/locale-chunks/booklet-locale-pl.d.ts +3 -0
- package/dist/booklet/locale-chunks/booklet-locale-pt.d.ts +3 -0
- package/dist/booklet/locale-chunks/booklet-locale-zh.d.ts +3 -0
- package/dist/booklet.cjs +1 -1
- package/dist/booklet.mjs +1 -1
- package/dist/commons/Act.d.ts +2 -3
- package/dist/commons/ObjeRecord.d.ts +23 -0
- package/dist/commons/Person.d.ts +2 -3
- package/dist/edit/ActEdit.d.ts +5 -0
- package/dist/edit/AudioInterviewActEdit.d.ts +35 -0
- package/dist/edit/GedcomExportOptionsEdit.d.ts +3 -0
- package/dist/edit/index.d.ts +1 -0
- package/dist/export/GEDCOM.d.ts +4 -1
- package/dist/feature-chunks/booklet-logo-draw.cjs +1 -0
- package/dist/feature-chunks/booklet-logo-draw.mjs +1 -0
- package/dist/feature-chunks/booklet-timeline-raster.cjs +1 -0
- package/dist/feature-chunks/booklet-timeline-raster.mjs +1 -0
- package/dist/font-chunks/booklet-pdf-font-bytes-ar.cjs +1 -0
- package/dist/font-chunks/booklet-pdf-font-bytes-ar.mjs +1 -0
- package/dist/font-chunks/booklet-pdf-font-bytes-he.cjs +1 -0
- package/dist/font-chunks/booklet-pdf-font-bytes-he.mjs +1 -0
- package/dist/font-chunks/booklet-pdf-font-bytes-zh-ext.cjs +1 -0
- package/dist/font-chunks/booklet-pdf-font-bytes-zh-ext.mjs +1 -0
- package/dist/font-chunks/booklet-pdf-font-bytes-zh.cjs +1 -0
- package/dist/font-chunks/booklet-pdf-font-bytes-zh.mjs +1 -0
- package/dist/import/ReadGed.d.ts +3 -1
- package/dist/import/SplitedInformations.d.ts +2 -3
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.mjs +1 -1
- package/dist/locale-chunks/booklet-locale-ar.cjs +1 -0
- package/dist/locale-chunks/booklet-locale-ar.mjs +1 -0
- package/dist/locale-chunks/booklet-locale-de.cjs +1 -0
- package/dist/locale-chunks/booklet-locale-de.mjs +1 -0
- package/dist/locale-chunks/booklet-locale-en.cjs +1 -0
- package/dist/locale-chunks/booklet-locale-en.mjs +1 -0
- package/dist/locale-chunks/booklet-locale-es.cjs +1 -0
- package/dist/locale-chunks/booklet-locale-es.mjs +1 -0
- package/dist/locale-chunks/booklet-locale-fr.cjs +1 -0
- package/dist/locale-chunks/booklet-locale-fr.mjs +1 -0
- package/dist/locale-chunks/booklet-locale-he.cjs +1 -0
- package/dist/locale-chunks/booklet-locale-he.mjs +1 -0
- package/dist/locale-chunks/booklet-locale-it.cjs +1 -0
- package/dist/locale-chunks/booklet-locale-it.mjs +1 -0
- package/dist/locale-chunks/booklet-locale-nl.cjs +1 -0
- package/dist/locale-chunks/booklet-locale-nl.mjs +1 -0
- package/dist/locale-chunks/booklet-locale-pl.cjs +1 -0
- package/dist/locale-chunks/booklet-locale-pl.mjs +1 -0
- package/dist/locale-chunks/booklet-locale-pt.cjs +1 -0
- package/dist/locale-chunks/booklet-locale-pt.mjs +1 -0
- package/dist/locale-chunks/booklet-locale-zh.cjs +1 -0
- package/dist/locale-chunks/booklet-locale-zh.mjs +1 -0
- package/dist/utils/gedcom/audioInterviewAct.d.ts +64 -0
- package/dist/utils/gedcom/formatObjeRecord.d.ts +3 -0
- package/dist/utils/gedcom/guessMediFromForm.d.ts +2 -0
- package/dist/utils/gedcom/mediaFormFromUri.d.ts +5 -1
- package/dist/utils/gedcom/parseStandaloneObje.d.ts +6 -5
- package/dist/version.d.ts +1 -1
- package/package.json +104 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,60 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes of gedcom-ts
|
|
4
4
|
|
|
5
|
+
## [2026.6.0] - 2026-06-01
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Multimédia GEDCOM 7 (`OBJE`)** : import et export complets des enregistrements `0 @O…@ OBJE` avec plusieurs `FILE`, `FORM`, `MEDI` (`AUDIO`, `PHOTO`, `VIDEO`, …), `PHRASE`, `TITL` et variantes `FILE`.`TRAN` (transcodage, WebVTT).
|
|
10
|
+
- **`ReadGed.objeRecordsById`** : map des OBJE absorbés depuis le fichier (round-trip via `GedcomExportOptions.objeRecordsById`).
|
|
11
|
+
- **Types et utilitaires OBJE** : `ObjeRecord`, `ObjeFileEntry`, `primaryObjeFileUri`, `parseStandaloneObjeBlock`, `formatObjeRecordBlock`, `guessMediFromForm`, `registerObjeRecord`.
|
|
12
|
+
- **Entretiens audio / histoire orale** : actes `EVEN` + `TYPE Interview` (ou « Oral history ») avec lien `2 OBJE`, note de transcription (`2 NOTE`) et API dédiée — `createAudioInterviewAct`, `attachAudioInterviewToAct`, `editAct(act).asAudioInterview()`, `editAudioInterviewAct`.
|
|
13
|
+
- **Détection et lecture** : `isAudioInterviewAct`, `isAudioInterviewEvenType`, `getAudioInterviewTranscription`, `getAudioInterviewMedia`, `getAudioInterviewObjeRecords`, `primaryAudioInterviewUri`, `nextObjeXrefId`.
|
|
14
|
+
- **Constantes** : `GEDCOM_7_EVEN_TYPE_AUDIO_INTERVIEW`, `GEDCOM_7_EVEN_TYPE_ORAL_HISTORY`.
|
|
15
|
+
- **`GedcomExportOptionsEdit.setObjeRecordsById`** / **`clearObjeRecordsById`**.
|
|
16
|
+
- **Tests** : `parseStandaloneObje`, `guessMediFromForm`, `audioInterviewAct`, extension des specs export / import `maximal70`.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- **Export OBJE** : émission de `MEDI` dérivé du MIME lorsque absent ; sérialisation multi-fichiers via `formatObjeRecordBlock`.
|
|
21
|
+
- **Import** : `objePayloadById` remplacé par `objeRecordsById` (`PersonGedcomImportOptions`, `ActsByExtraction`).
|
|
22
|
+
- **CI** : script `test:ci` (`build` puis `vitest run`) pour les tests qui lisent `dist/` ; `prepublishOnly` aligné.
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- **GEDZIP** : inclusion des binaires locaux liés par pointeur `OBJE` (chemins résolus depuis `sourceUri` / `relativePath`).
|
|
27
|
+
- **FORM audio** : reconnaissance de **WebM**, OGG, WAV, M4A, FLAC, etc. (`guessMediaFormFromUri`, `guessMediaFormFromFile`) ; affinage des exports `application/octet-stream` issus de l’UI.
|
|
28
|
+
|
|
29
|
+
## [2026.5.4] - 2026-05-24
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- **Livret multilingue** : traductions dédiées pour les 11 langues du site (`en`, `fr`, `de`, `nl`, `es`, `zh`, `it`, `pt`, `pl`, `ar`, `he`) — messages PDF, dates, lieux, accords de genre et récits narratifs.
|
|
34
|
+
- **RTL arabe / hébreu** : `isBookletLocaleRtl`, `bookletTextDirection`, mise en page PDF miroir ; **`bidi-js`** (réordonnancement visuel) et **`naqqash`** (formes contextuelles arabes).
|
|
35
|
+
- **Polices PDF intégrées** : Noto Sans Hebrew, Noto Sans Arabic et Noto Sans SC (subset, SIL OFL) en chunks lazy (`dist/font-chunks/`) ; chunk **`booklet-pdf-font-bytes-zh-ext`** (~1,4 MiB) si le GEDCOM contient des hanzi hors subset de base.
|
|
36
|
+
- **Rendu bi-police** : Helvetica pour le latin + Noto pour arabe / hébreu / chinois.
|
|
37
|
+
- **Architecture lazy du livret** : locales (`dist/locale-chunks/`), polices, logo SVG et frise canvas (`dist/feature-chunks/`) via `import()` — cœur `gedcom-ts/booklet` ~75 KiB minifié (~100 KiB obfusqué).
|
|
38
|
+
- **Exports TypeScript des chunks** : chaque sous-chemin `gedcom-ts/booklet/locale-chunks/*`, `font-chunks/*` et `feature-chunks/*` expose `types` + `import` / `require`.
|
|
39
|
+
- **Manifeste unique** : `scripts/booklet-chunk-manifest.mjs` alimente `build.js` et `package.json` (`npm run sync:exports` ou fin de `build:js`).
|
|
40
|
+
- **API hôte** : `registerBookletPdfFontBytes`, `registerPdfFontkit`, `ensureBookletLocale` — preload explicite des chunks (recommandé Vite/Angular).
|
|
41
|
+
- **Scripts** : `prepare:locales`, `prepare:fonts`, `sync:exports`.
|
|
42
|
+
- **Exports** : `BOOKLET_LOCALES`, `BOOKLET_RTL_LOCALES`, `isBookletLocale`, `preparePdfText`, `PdfTextOptions`, `loadBookletPdfFontBytes`, `localeNeedsUnicodePdfFont`, …
|
|
43
|
+
- **Tests** : `tests/booklet/` (i18n, RTL, polices ar/zh, bidi, chunk exports, dist imports).
|
|
44
|
+
|
|
45
|
+
### Changed
|
|
46
|
+
|
|
47
|
+
- **`pdf-lib` externalisé** : peer dependency ; `@pdf-lib/fontkit` chargé à la demande pour `zh` / `ar` / `he`.
|
|
48
|
+
- **Pipeline build livret** : esbuild → réécriture `./…-chunks/` → `gedcom-ts/booklet/…-chunks/` → obfuscation avec `reservedStrings` sur les chemins d’import dynamiques (analyse statique Vite).
|
|
49
|
+
- **`resolveBookletLocale`** : retourne la locale demandée (plus de repli silencieux vers l’anglais).
|
|
50
|
+
- **`drawGedcomTsLogoOnPage`** : async ; logo lazy (`getGedcomTsLogoPaths()`).
|
|
51
|
+
- **`ensureBookletLocale(locale)`** requis avant les APIs sync.
|
|
52
|
+
- **Frise chronologique** : titre et libellé « dates inconnues » localisés.
|
|
53
|
+
- **README** : tableau des tailles, guide d’intégration Vite/Angular.
|
|
54
|
+
|
|
55
|
+
### Fixed
|
|
56
|
+
|
|
57
|
+
- **Vite / Angular dev** : imports dynamiques relatifs pré-bundleés dans le cache deps — chemins package explicites dans `dist/booklet.mjs` + `exports` complets.
|
|
58
|
+
|
|
5
59
|
## [2026.5.3] - 2026-05-16
|
|
6
60
|
|
|
7
61
|
### Added
|
package/README.md
CHANGED
|
@@ -6,8 +6,10 @@
|
|
|
6
6
|
- work with a typed JSON model (persons, acts, dates, places, notes, media, name variants, attributes)
|
|
7
7
|
- edit the model in-place through a fluent, chainable API (`editPerson`, `editAct`, …)
|
|
8
8
|
- export data back to GEDCOM (`.ged`) or GEDZIP (`.zip`)
|
|
9
|
+
- attach **audio** and other media via GEDCOM 7 `OBJE` records (`MEDI AUDIO`, multi-`FILE`, `TRAN`)
|
|
10
|
+
- model **oral history interviews** as `EVEN` acts with `OBJE` + transcription notes
|
|
9
11
|
- geocode event places (OpenStreetMap / Nominatim) and group similar city names
|
|
10
|
-
- generate a **genealogy booklet** as PDF (`gedcom-ts/booklet`,
|
|
12
|
+
- generate a **genealogy booklet** as PDF (`gedcom-ts/booklet`, 11 locales including RTL Arabic/Hebrew)
|
|
11
13
|
|
|
12
14
|
## Live demo
|
|
13
15
|
|
|
@@ -19,16 +21,17 @@ A graphical demo showcasing the public API (import a `.ged` / `.zip`, browse the
|
|
|
19
21
|
- [Quick start](#quick-start)
|
|
20
22
|
- [Geocoding places](#geocoding-places)
|
|
21
23
|
- [Genealogy booklet (PDF)](#genealogy-booklet-pdf)
|
|
24
|
+
- [Audio and oral history (GEDCOM 7)](#audio-and-oral-history-gedcom-7)
|
|
22
25
|
- [API reference](#api-reference)
|
|
23
26
|
- [Error handling](#error-handling)
|
|
24
27
|
|
|
25
28
|
## Package
|
|
26
29
|
|
|
27
30
|
- NPM: [gedcom-ts](https://www.npmjs.com/package/gedcom-ts)
|
|
28
|
-
- Version format **CalVer** `AAAA.M.micro` (e.g. `2026.
|
|
31
|
+
- Current release **`2026.6.0`** — audio / OBJE / oral history. Version format **CalVer** `AAAA.M.micro` (e.g. `2026.6.0` = June 2026). See [CHANGELOG.md](CHANGELOG.md).
|
|
29
32
|
- Entry points:
|
|
30
33
|
- **`gedcom-ts`** — import, model, edit layer, export, geocoding
|
|
31
|
-
- **`gedcom-ts/booklet`** — PDF livret (`pdf-lib`
|
|
34
|
+
- **`gedcom-ts/booklet`** — PDF livret (`pdf-lib` en peerDependency, chargé depuis `node_modules`)
|
|
32
35
|
|
|
33
36
|
## Installation
|
|
34
37
|
|
|
@@ -36,7 +39,13 @@ A graphical demo showcasing the public API (import a `.ged` / `.zip`, browse the
|
|
|
36
39
|
npm install gedcom-ts
|
|
37
40
|
```
|
|
38
41
|
|
|
39
|
-
Both entry points come from the same package
|
|
42
|
+
Both entry points come from the same package. For the PDF booklet, **`pdf-lib` is a peer dependency** — install it in your app if you use `gedcom-ts/booklet`:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm install pdf-lib
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
For `zh` / `ar` / `he` PDF output, your bundler should also be able to resolve `@pdf-lib/fontkit` (included in `gedcom-ts` dependencies; the host app typically preloads it — see [Bundle layout](#bundle-layout) below).
|
|
40
49
|
|
|
41
50
|
## Runtime Requirements
|
|
42
51
|
|
|
@@ -193,19 +202,69 @@ The legacy callback `getCityCoordinates` is deprecated — use the flow above.
|
|
|
193
202
|
|
|
194
203
|
## Genealogy booklet (PDF)
|
|
195
204
|
|
|
196
|
-
The **`gedcom-ts/booklet`** subpath builds a printable family booklet: cover page, table of contents, chapters by generation (Sosa), family sheets, and
|
|
205
|
+
The **`gedcom-ts/booklet`** subpath builds a printable family booklet: cover page, table of contents, chapters by generation (Sosa), family sheets, and narrative text from GEDCOM acts (birth, marriage, death, …). **English is the default locale** (`DEFAULT_BOOKLET_LOCALE`). Full copy is available for **`en`**, **`fr`**, **`de`**, **`nl`**, **`es`**, **`zh`**, **`it`**, **`pt`**, **`pl`**, **`ar`**, and **`he`** (aligned with [gedcomts.com](https://gedcomts.com) UI languages). Arabic and Hebrew use **RTL layout** in the PDF (`isBookletLocaleRtl`, `bookletTextDirection`).
|
|
206
|
+
|
|
207
|
+
### Bundle layout
|
|
208
|
+
|
|
209
|
+
Code is split so the host app only downloads what it uses. Approximate sizes after minify (obfuscation adds ~25–30 KiB on `gedcom-ts/booklet`).
|
|
210
|
+
|
|
211
|
+
| Artifact | Size (typ.) | When loaded |
|
|
212
|
+
| --- | ---: | --- |
|
|
213
|
+
| `gedcom-ts` (`dist/index.mjs`) | ~180 KiB | GEDCOM import / edit / export |
|
|
214
|
+
| `gedcom-ts/booklet` (`dist/booklet.mjs`) | ~100 KiB | livret (collect, estimate, PDF) |
|
|
215
|
+
| `locale-chunks/booklet-locale-*` | 14–26 KiB | one UI language |
|
|
216
|
+
| `feature-chunks/booklet-logo-draw` | ~11 KiB | cover logo (`coverLogo !== false`) |
|
|
217
|
+
| `feature-chunks/booklet-timeline-raster` | ~3 KiB | `timelineStyle: "canvas"` |
|
|
218
|
+
| `font-chunks/booklet-pdf-font-bytes-ar` | ~43 KiB | Arabic PDF |
|
|
219
|
+
| `font-chunks/booklet-pdf-font-bytes-he` | ~13 KiB | Hebrew PDF |
|
|
220
|
+
| `font-chunks/booklet-pdf-font-bytes-zh` | ~190 KiB | Chinese PDF (base subset) |
|
|
221
|
+
| `font-chunks/booklet-pdf-font-bytes-zh-ext` | ~1.4 MiB | Chinese PDF when GEDCOM names need extra Han |
|
|
222
|
+
| `pdf-lib` (peer, not in gedcom-ts) | ~500 KiB+ | any PDF generation |
|
|
223
|
+
|
|
224
|
+
**Not bundled in gedcom-ts:** `fflate` (main entry, external), `pdf-lib` (booklet peer). **`bidi-js`** and **`naqqash`** (Arabic shaping / RTL reordering) ship inside `gedcom-ts/booklet` today.
|
|
225
|
+
|
|
226
|
+
Call **`await ensureBookletLocale(locale)`** before sync APIs. `generateGenealogyBookletPdf` preloads locale, logo, and timeline when needed.
|
|
227
|
+
|
|
228
|
+
**Lazy chunk subpaths** (for bundler preload or explicit `import()` — normal apps should use `ensureBookletLocale()` instead):
|
|
229
|
+
|
|
230
|
+
| Subpath | Role |
|
|
231
|
+
| --- | --- |
|
|
232
|
+
| `gedcom-ts/booklet/locale-chunks/booklet-locale-{en,fr,de,nl,es,zh,it,pt,pl,ar,he}` | Messages, narratives, date/place helpers per locale |
|
|
233
|
+
| `gedcom-ts/booklet/font-chunks/booklet-pdf-font-bytes-{ar,he,zh,zh-ext}` | Subset Noto font bytes |
|
|
234
|
+
| `gedcom-ts/booklet/feature-chunks/booklet-logo-draw` | Cover logo SVG paths |
|
|
235
|
+
| `gedcom-ts/booklet/feature-chunks/booklet-timeline-raster` | Canvas timeline PNG rasterizer |
|
|
236
|
+
|
|
237
|
+
Each subpath is listed in `package.json` **`exports`** with matching **`types`** (`.d.ts` under `dist/booklet/…`) and runtime (`.mjs` / `.cjs` under `dist/…`). TypeScript resolves them via `exports.types` (`moduleResolution: bundler` / `node16`). Adding a locale updates `scripts/booklet-chunk-manifest.mjs`; `npm run build:js` regenerates chunk files and syncs `exports`.
|
|
238
|
+
|
|
239
|
+
### Vite / Angular integration
|
|
240
|
+
|
|
241
|
+
1. **Lazy-load the booklet entry** — `import('gedcom-ts/booklet')` only when the user opens export / download (not on every tree page).
|
|
242
|
+
2. **Preload the UI locale** — `import('gedcom-ts/booklet/locale-chunks/booklet-locale-fr')` (or your loader) before sync APIs; then `ensureBookletLocale('fr')`.
|
|
243
|
+
3. **Unicode PDF (`zh` / `ar` / `he`)** — the host app should import font chunks explicitly and call `registerBookletPdfFontBytes` + `registerPdfFontkit` before `generateGenealogyBookletPdf` (see [gedcomts.com](https://gedcomts.com) `booklet-pdf-deps.loader.ts` for a reference pattern).
|
|
244
|
+
4. **Dev server** — exclude the main booklet bundle from Vite pre-bundling so lazy subpaths resolve via `node_modules`:
|
|
245
|
+
|
|
246
|
+
```ts
|
|
247
|
+
// vite.config.ts / angular.json (esbuild optimizeDeps)
|
|
248
|
+
optimizeDeps: {
|
|
249
|
+
exclude: ["gedcom-ts/booklet"],
|
|
250
|
+
},
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Published `dist/booklet.mjs` keeps **literal** dynamic `import('gedcom-ts/booklet/…')` strings (rewrite before obfuscation, paths reserved from string encoding) so Vite can statically analyze chunk loads.
|
|
197
254
|
|
|
198
255
|
### Workflow
|
|
199
256
|
|
|
200
257
|
1. Import with `importGedFile` (`gedcom-ts`).
|
|
201
|
-
2.
|
|
202
|
-
3.
|
|
203
|
-
4.
|
|
258
|
+
2. **`await ensureBookletLocale(locale)`** — load messages/narratives for the chosen language.
|
|
259
|
+
3. Collect persons with `collectBookletPersons` (`gedcom-ts/booklet`).
|
|
260
|
+
4. Optionally preview size with `estimateBookletSize` + `groupBookletIntoChapters`.
|
|
261
|
+
5. Build bytes with `generateGenealogyBookletPdf`, then `downloadBookletPdf` (browser).
|
|
204
262
|
|
|
205
263
|
```ts
|
|
206
264
|
import { importGedFile } from "gedcom-ts";
|
|
207
265
|
import {
|
|
208
266
|
collectBookletPersons,
|
|
267
|
+
ensureBookletLocale,
|
|
209
268
|
groupBookletIntoChapters,
|
|
210
269
|
estimateBookletSize,
|
|
211
270
|
generateGenealogyBookletPdf,
|
|
@@ -217,23 +276,27 @@ async function exportBooklet(file: File) {
|
|
|
217
276
|
const ged = await importGedFile(file);
|
|
218
277
|
const root = ged.persons[0] ?? null;
|
|
219
278
|
|
|
279
|
+
const locale = "en" as const; // BookletLocale — align with your UI language (en, fr, de, nl, es, zh, it, pt, pl, ar, he)
|
|
280
|
+
await ensureBookletLocale(locale);
|
|
281
|
+
|
|
220
282
|
const entries = collectBookletPersons({
|
|
221
283
|
ged,
|
|
222
284
|
scope: "from-reference",
|
|
223
285
|
referencePerson: root,
|
|
224
286
|
maxGeneration: 6,
|
|
287
|
+
locale,
|
|
225
288
|
});
|
|
226
289
|
|
|
227
|
-
const chapters = groupBookletIntoChapters(entries);
|
|
290
|
+
const chapters = groupBookletIntoChapters(entries, locale);
|
|
228
291
|
const families = chapters.reduce((n, ch) => n + ch.families.length, 0);
|
|
229
|
-
const size = estimateBookletSize(chapters, entries.length, families, "summary", "canvas");
|
|
292
|
+
const size = estimateBookletSize(chapters, entries.length, families, "summary", "canvas", locale);
|
|
230
293
|
console.log(size.label);
|
|
231
294
|
|
|
232
295
|
const pdf = await generateGenealogyBookletPdf(
|
|
233
296
|
entries,
|
|
234
297
|
{
|
|
235
|
-
title: "
|
|
236
|
-
scopeLabel: "
|
|
298
|
+
title: "Family booklet",
|
|
299
|
+
scopeLabel: "Ancestors and descendants",
|
|
237
300
|
personCount: entries.length,
|
|
238
301
|
referenceName: root ? personDisplayName(root) : undefined,
|
|
239
302
|
},
|
|
@@ -241,10 +304,11 @@ async function exportBooklet(file: File) {
|
|
|
241
304
|
detailLevel: "summary",
|
|
242
305
|
timelineStyle: "canvas",
|
|
243
306
|
coverLogo: true,
|
|
307
|
+
locale,
|
|
244
308
|
},
|
|
245
309
|
);
|
|
246
310
|
|
|
247
|
-
downloadBookletPdf(pdf, "
|
|
311
|
+
downloadBookletPdf(pdf, "family-booklet.pdf");
|
|
248
312
|
}
|
|
249
313
|
```
|
|
250
314
|
|
|
@@ -258,8 +322,9 @@ Use `scope: "all"` and `referencePerson: null` to include every individual in th
|
|
|
258
322
|
| `scope` | `"all"` or `"from-reference"` (Sosa from `referencePerson`) |
|
|
259
323
|
| `referencePerson` | Root person for `"from-reference"`; `null` if scope is `"all"` |
|
|
260
324
|
| `maxGeneration` | Max Sosa generation (e.g. `6`); ignored when `scope === "all"` |
|
|
325
|
+
| `locale` | `BookletLocale` (default `"en"`) — `en`, `fr`, `de`, `nl`, `es`, `zh`, `it`, `pt`, `pl`, `ar`, `he` |
|
|
261
326
|
|
|
262
|
-
Helpers: `personDisplayName`, `buildBookletPersonEntry`, `sortBookletEntries`, `bookletSexFromPerson`.
|
|
327
|
+
Helpers: `personDisplayName`, `buildBookletPersonEntry`, `sortBookletEntries`, `bookletSexFromPerson`, `DEFAULT_BOOKLET_LOCALE`, `BOOKLET_LOCALES`, `isBookletLocaleRtl`.
|
|
263
328
|
|
|
264
329
|
### `generateGenealogyBookletPdf` options
|
|
265
330
|
|
|
@@ -268,24 +333,27 @@ Helpers: `personDisplayName`, `buildBookletPersonEntry`, `sortBookletEntries`, `
|
|
|
268
333
|
| `detailLevel` | `"summary"` \| `"detailed"` | Short prose per person vs longer biographies |
|
|
269
334
|
| `timelineStyle` | `"off"` \| `"canvas"` | Generation timeline pages per chapter |
|
|
270
335
|
| `coverLogo` | `true` (default), `false`, or `DrawGedcomTsLogoOptions` | gedcom-ts vector logo on the cover |
|
|
336
|
+
| `locale` | `BookletLocale` (default `"en"`) | Narrative, chapter titles, PDF chrome, timeline legend |
|
|
337
|
+
| `unicodeFont` | `Uint8Array` (optional) | Replace bundled Noto font for `zh` / `ar` / `he` |
|
|
271
338
|
|
|
272
|
-
`BookletPdfMeta`: `title`, `scopeLabel`, `personCount`, optional `referenceName
|
|
339
|
+
`BookletPdfMeta`: `title`, `scopeLabel`, `personCount`, optional `referenceName` (usually translated in the host app).
|
|
273
340
|
|
|
274
341
|
### Cover logo
|
|
275
342
|
|
|
276
|
-
The cover draws the **gedcom-ts logo** from
|
|
343
|
+
The cover draws the **gedcom-ts logo** from lazy-loaded SVG paths (`ensureBookletLogo`, `getGedcomTsLogoPaths`, `getGedcomTsLogoViewbox`). Reuse on custom PDF pages:
|
|
277
344
|
|
|
278
345
|
```ts
|
|
279
346
|
import { PDFDocument } from "pdf-lib";
|
|
280
347
|
import {
|
|
281
348
|
drawGedcomTsLogoOnPage,
|
|
282
349
|
defaultCoverLogoOptions,
|
|
283
|
-
|
|
350
|
+
ensureBookletLogo,
|
|
284
351
|
} from "gedcom-ts/booklet";
|
|
285
352
|
|
|
286
353
|
const doc = await PDFDocument.create();
|
|
287
354
|
const page = doc.addPage();
|
|
288
|
-
|
|
355
|
+
await ensureBookletLogo();
|
|
356
|
+
await drawGedcomTsLogoOnPage(page, defaultCoverLogoOptions());
|
|
289
357
|
```
|
|
290
358
|
|
|
291
359
|
### Booklet API cheat sheet
|
|
@@ -294,11 +362,72 @@ drawGedcomTsLogoOnPage(page, defaultCoverLogoOptions());
|
|
|
294
362
|
| --- | --- |
|
|
295
363
|
| Persons for the booklet | `collectBookletPersons` |
|
|
296
364
|
| Chapters / families | `groupBookletIntoChapters`, `partnerNamesLabel` |
|
|
297
|
-
|
|
|
365
|
+
| Localized narratives (custom UI) | `buildPersonSummaryNarrative`, `buildPersonDetailedNarratives`, `buildFamilyNarrative`, `buildChapterIntroNarrative` |
|
|
298
366
|
| Page estimate | `estimateBookletSize`, `bookletSizeAdvice` |
|
|
299
367
|
| Timeline data / PNG | `buildGenerationTimeline`, `rasterizeGenerationTimelinePng` |
|
|
300
|
-
| PDF output | `generateGenealogyBookletPdf`, `downloadBookletPdf`, `toPdfText` |
|
|
301
|
-
|
|
|
368
|
+
| PDF output | `generateGenealogyBookletPdf`, `downloadBookletPdf`, `toPdfText`, `preparePdfText` |
|
|
369
|
+
| Locale helpers | `resolveBookletLocale`, `bookletLocaleToBcp47`, `bookletTextDirection`, `BOOKLET_RTL_LOCALES`, `ensureBookletLocale` |
|
|
370
|
+
| Font preload (host) | `registerBookletPdfFontBytes`, `registerPdfFontkit`, `localeNeedsUnicodePdfFont` |
|
|
371
|
+
| Logo | `ensureBookletLogo`, `drawGedcomTsLogoOnPage`, `getGedcomTsLogoPaths`, `defaultCoverLogoOptions` |
|
|
372
|
+
|
|
373
|
+
## Audio and oral history (GEDCOM 7)
|
|
374
|
+
|
|
375
|
+
Since **`2026.6.0`**, gedcom-ts models audio according to [FamilySearch GEDCOM 7](https://gedcom.io/): external files referenced by **`OBJE`** records (`FILE` + `FORM` + optional `MEDI AUDIO` + `TRAN` for alternate formats or WebVTT). Text transcriptions belong in **`NOTE`** under the event, not inside `OBJE`.
|
|
376
|
+
|
|
377
|
+
**Oral history pattern:** `1 EVEN` + `2 TYPE Interview` (or `Oral history`) + `2 OBJE @O…@` + `2 NOTE` (transcription).
|
|
378
|
+
|
|
379
|
+
```ts
|
|
380
|
+
import {
|
|
381
|
+
createAudioInterviewAct,
|
|
382
|
+
editAct,
|
|
383
|
+
ExportGedzipFile,
|
|
384
|
+
type Person,
|
|
385
|
+
type ReadGed,
|
|
386
|
+
} from "gedcom-ts";
|
|
387
|
+
|
|
388
|
+
async function addInterview(readGed: ReadGed, person: Person, mp3: File) {
|
|
389
|
+
const objeMap = new Map(readGed.objeRecordsById);
|
|
390
|
+
|
|
391
|
+
const { act, objeRecord } = createAudioInterviewAct(
|
|
392
|
+
{
|
|
393
|
+
description: "Entretien avec grand-mère",
|
|
394
|
+
participantIndis: [person.INDI],
|
|
395
|
+
ownerIndi: person.INDI,
|
|
396
|
+
audioFile: mp3,
|
|
397
|
+
transcription: "Bonjour, je m'appelle Marie…",
|
|
398
|
+
vttUri: "media/transcript.vtt", // optional FILE.TRAN on OBJE
|
|
399
|
+
},
|
|
400
|
+
readGed.persons,
|
|
401
|
+
objeMap,
|
|
402
|
+
);
|
|
403
|
+
|
|
404
|
+
person.acts.add(act);
|
|
405
|
+
if (objeRecord) {
|
|
406
|
+
objeMap.set(objeRecord.id, objeRecord);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
await new ExportGedzipFile("my-tree", readGed.persons, {
|
|
410
|
+
extraTopLevelRecords: readGed.preservedTopLevelRecords,
|
|
411
|
+
objeRecordsById: objeMap,
|
|
412
|
+
}).download();
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// enrich an existing act:
|
|
416
|
+
editAct(act)
|
|
417
|
+
.asAudioInterview(readGed.persons, objeMap)
|
|
418
|
+
.setTranscription("Suite de l'entretien…")
|
|
419
|
+
.attachAudio({ audioUri: "https://example.org/rec.mp3", ownerIndi: person.INDI });
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
| Goal | API |
|
|
423
|
+
| --- | --- |
|
|
424
|
+
| Create interview act | `createAudioInterviewAct` |
|
|
425
|
+
| Attach audio to act | `attachAudioInterviewToAct`, `editAct(act).asAudioInterview()` |
|
|
426
|
+
| Detect imported interviews | `isAudioInterviewAct`, `isAudioInterviewEvenType` |
|
|
427
|
+
| Read transcription / media | `getAudioInterviewTranscription`, `primaryAudioInterviewUri` |
|
|
428
|
+
| OBJE round-trip | `readGed.objeRecordsById` → `objeRecordsById` in export options |
|
|
429
|
+
| Low-level OBJE parse/emit | `parseStandaloneObjeBlock`, `formatObjeRecordBlock`, `guessMediFromForm` |
|
|
430
|
+
| EVEN type constants | `GEDCOM_7_EVEN_TYPE_AUDIO_INTERVIEW`, `GEDCOM_7_EVEN_TYPE_ORAL_HISTORY` |
|
|
302
431
|
|
|
303
432
|
## API reference
|
|
304
433
|
|
|
@@ -349,7 +478,7 @@ try {
|
|
|
349
478
|
|
|
350
479
|
#### `ReadGed`
|
|
351
480
|
|
|
352
|
-
Result of an import.
|
|
481
|
+
Result of an import. Standalone `0 @O…@ OBJE` blocks with at least one `FILE` are parsed into **`objeRecordsById`** (multi-file, `MEDI`, `TRAN`). Other top-level records (`REPO`, `SOUR`, `SUBM`, …) stay on `preservedTopLevelRecords` for round-trip export.
|
|
353
482
|
|
|
354
483
|
Notable members:
|
|
355
484
|
|
|
@@ -363,6 +492,7 @@ Notable members:
|
|
|
363
492
|
| `placesMap: Map<string, Place>` | City name → `Place` (first occurrence wins). |
|
|
364
493
|
| `mapFiles: Map<string, File>` | Relative path → media `File` (for ZIP imports). |
|
|
365
494
|
| `datasetVersion: GedcomDatasetVersion` | `"7.0"`, `"5.5"` or `"unknown"`. |
|
|
495
|
+
| `objeRecordsById: Map<number, ObjeRecord>` | Parsed `OBJE` records (audio, images, …) keyed by `@O{n}@`. |
|
|
366
496
|
| `preservedTopLevelRecords: string[]` | Raw blocks for partial round-trip. |
|
|
367
497
|
| `resolveIndividualPointer(raw)` | Resolves `@I12@`, `I12`, `@Homer_Simpson@`, `Homer_Simpson` to a `Person`. |
|
|
368
498
|
| `getChildrenForParent(parent)` | All children attached to a parent (via `FAMS`). |
|
|
@@ -404,6 +534,7 @@ import { ExportGedcomFile, type ReadGed } from "gedcom-ts";
|
|
|
404
534
|
function exportGed(readGed: ReadGed) {
|
|
405
535
|
new ExportGedcomFile("my-tree", readGed.persons, {
|
|
406
536
|
extraTopLevelRecords: readGed.preservedTopLevelRecords,
|
|
537
|
+
objeRecordsById: readGed.objeRecordsById,
|
|
407
538
|
headLanguageTag: "fr-FR",
|
|
408
539
|
headCopyright: "© 2026 Family Archive",
|
|
409
540
|
headDestination: "https://gedcom.io/",
|
|
@@ -432,6 +563,7 @@ Options shared by both exporters:
|
|
|
432
563
|
| Option | Effect |
|
|
433
564
|
| ---------------------- | -------------------------------------------------------------------------------------------------------- |
|
|
434
565
|
| `extraTopLevelRecords` | Raw `0 …` blocks re-emitted before `SUBM` / `TRLR` (round-trip with `readGed.preservedTopLevelRecords`). |
|
|
566
|
+
| `objeRecordsById` | Full `OBJE` records (multi-`FILE`, `MEDI AUDIO`, `TRAN`) from `readGed.objeRecordsById`. |
|
|
435
567
|
| `headLanguageTag` | BCP 47 tag for `HEAD`.`LANG` (defaults to `en-US`). |
|
|
436
568
|
| `headCopyright` | One-line `1 COPR` notice. |
|
|
437
569
|
| `headDestination` | Value of `HEAD`.`DEST` (target app / URI). |
|
|
@@ -577,7 +709,7 @@ const payload = place.toGedcom7PlacPayload(); // "Paris, , Île-de-France, Franc
|
|
|
577
709
|
|
|
578
710
|
#### `MultimediaFile`, `MultimediaFiles`
|
|
579
711
|
|
|
580
|
-
Wraps either a local `File`, an external URI (`sourceUri`) or an OBJE pointer (`objeXrefId`) so the same model can survive a GED / ZIP round-trip.
|
|
712
|
+
Wraps either a local `File`, an external URI (`sourceUri`) or an OBJE pointer (`objeXrefId`) so the same model can survive a GED / ZIP round-trip. See [Audio and oral history](#audio-and-oral-history-gedcom-7) for interview workflows.
|
|
581
713
|
|
|
582
714
|
```ts
|
|
583
715
|
import { MultimediaFile, MultimediaFiles } from "gedcom-ts";
|
|
@@ -652,7 +784,8 @@ editDateAct(person.acts.list[0].dateAct!).setExactDate(1900, "JAN", 1);
|
|
|
652
784
|
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
653
785
|
| `editPerson(person)` / `PersonEdit` | Identity, `FAMS` / `FAMC` / `removeFams*`, `nameVariants()` / `attributes()` / `multimedia()`, bulk `clear*`, entry points to `acts()` and `notes()`. |
|
|
654
786
|
| `editActs(acts)` / `ActsEdit` | `add`, `addNew`, `insertAt`, `insertNewAt`, `replaceAt`, `removeAt`, `removeAct`, `removeLast`, `clear`, `sortByDate`, `at`, `indexOfAct`. |
|
|
655
|
-
| `editAct(act)` / `ActEdit` | `setType`, `setIndis`, dates, place, EVEN fields, preserved lines, `notes()`, `multimedia()`, `clearNotes`, `clearMultimedia`.
|
|
787
|
+
| `editAct(act)` / `ActEdit` | `setType`, `setIndis`, dates, place, EVEN fields, preserved lines, `notes()`, `multimedia()`, `asAudioInterview()`, `clearNotes`, `clearMultimedia`. |
|
|
788
|
+
| `editAudioInterviewAct(act)` / `AudioInterviewActEdit` | Oral-history facade: `attachAudio`, `setTranscription`, `setDescription`, `registerPendingObje`, `isAudioInterview`, … |
|
|
656
789
|
| `editDateAct(dateAct)` / `DateActEdit` | `clear`, `applyGedcomPayload`, `setExactDate`, `setQualified`, `setBetween`, `setFromTo`, `setTime`, `setDatePhrase` / `appendDatePhrase`, `setVerbatimPayload`. |
|
|
657
790
|
| `editPlace(place)` / `PlaceEdit` | `setFromGedcom7Payload`, `setCity`, `setCounty`, `setState`, `setCountry`, `setPlacPhrase` / `appendPlacPhrase` / `clearPlacPhrase`, `setCoordinates` / `clearCoordinates` / `replaceCoordinateModel`, `clearStructured`. |
|
|
658
791
|
| `editNotes(notes)` / `NotesEdit` | `add`, `addNew`, `insertAt`, `insertNewAt`, `replaceAt`, `removeAt`, `removeNote`, `removeLast`, `clear`, `at`, `indexOfNote`. |
|
|
@@ -718,7 +851,7 @@ validateReadGed(readGed, {
|
|
|
718
851
|
| Export | Role |
|
|
719
852
|
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
720
853
|
| `editReadGed(readGed)` / `ReadGedEdit` | `addPerson`, `removePersonByIndi`, `preserved()` → `PreservedTopLevelEdit` (`append`, `insertAt`, `replaceAt`, `removeAt`, `clear`) on `preservedTopLevelRecords`. Low-level helpers: `addPersonToReadGed`, `removePersonFromReadGedByIndi`. |
|
|
721
|
-
| `editGedcomExportOptions(opts)` / `GedcomExportOptionsEdit` | Fluent setters for `extraTopLevelRecords`, `headLanguageTag`, `headCopyright`, `headDestination`, `headSchemaTagDefs`.
|
|
854
|
+
| `editGedcomExportOptions(opts)` / `GedcomExportOptionsEdit` | Fluent setters for `extraTopLevelRecords`, `objeRecordsById`, `headLanguageTag`, `headCopyright`, `headDestination`, `headSchemaTagDefs`. |
|
|
722
855
|
| `clonePerson(person, newIndi)` / `cloneAct(act)` / `person.clone` / `act.clone` | Deep copies for templates or undo stacks. |
|
|
723
856
|
| `nextFamilyId(persons)` | Next internal family id `F`. |
|
|
724
857
|
| `createMarriageFamily`, `linkChildToFamily`, `unlinkChildFromFamily`, `removeFamilyReferencesFromDataset` | Create family `F` and spouse acts; optional `{ eventTag }` (default `MARR`, also `ENGA`, banns, contract, `EVEN` + `CreateActInit`, …). See `GEDCOM_7_PAIR_UNION_EVENT_TAGS`. |
|
|
@@ -765,12 +898,13 @@ const version = resolveDatasetVersion(headLines); // "7.0" | "5.5" | "unknown"
|
|
|
765
898
|
|
|
766
899
|
#### `guessMediaFormFromUri(uri)`
|
|
767
900
|
|
|
768
|
-
Best-effort media type detection from a path/URI (
|
|
901
|
+
Best-effort media type detection from a path/URI or local `File` (`file.type` when set). Covers images, **audio** (mp3, **webm**, ogg, wav, m4a, flac, …), video, WebVTT, PDF. Used to fill `OBJE`.`FILE`.`FORM`. Pair with `guessMediFromForm` for `MEDI` (`AUDIO`, `PHOTO`, …). `refineGenericObjeForm` upgrades legacy `application/octet-stream` exports using the file extension.
|
|
769
902
|
|
|
770
903
|
```ts
|
|
771
|
-
import { guessMediaFormFromUri } from "gedcom-ts";
|
|
904
|
+
import { guessMediaFormFromUri, guessMediaFormFromFile } from "gedcom-ts";
|
|
772
905
|
|
|
773
|
-
guessMediaFormFromUri("
|
|
906
|
+
guessMediaFormFromUri("media/recording.webm"); // "audio/webm"
|
|
907
|
+
guessMediaFormFromFile(new File(["x"], "take.webm", { type: "audio/webm" })); // "audio/webm"
|
|
774
908
|
```
|
|
775
909
|
|
|
776
910
|
#### `extractPersonNameVariants(personLines)` / `extractIndiAttributes(personLines)`
|
|
@@ -796,7 +930,7 @@ const primary = selectPrimaryNameVariant(person.nameVariants);
|
|
|
796
930
|
|
|
797
931
|
#### `GEDCOM_LIBRARY_VERSION`
|
|
798
932
|
|
|
799
|
-
CalVer string written in exported `HEAD`.`SOUR`.`VERS` (same value as the npm package version, e.g. `2026.
|
|
933
|
+
CalVer string written in exported `HEAD`.`SOUR`.`VERS` (same value as the npm package version, e.g. `2026.6.0`).
|
|
800
934
|
|
|
801
935
|
```ts
|
|
802
936
|
import { GEDCOM_LIBRARY_VERSION } from "gedcom-ts";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const BOOKLET_UNKNOWN_DATE_EN = "Unknown date";
|
|
2
|
+
/** Year-only date (optional GEDCOM qualifier). */
|
|
3
|
+
export declare function isYearOnlyDate(dateLabel: string): boolean;
|
|
4
|
+
/** "on 15 March 1991", "in 1991", "about 1700", "before 1800", etc. */
|
|
5
|
+
export declare function onDate(dateLabel: string): string;
|
|
6
|
+
/** "From 1700 to 1850" or "From 15 March 1700 to 3 January 1850". */
|
|
7
|
+
export declare function lifeDateRange(from: string, to: string): string;
|
|
8
|
+
/** "was born in 1991" or "was born on 15 March 1991". */
|
|
9
|
+
export declare function seesDayOn(dateLabel: string): string;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface BookletDateConfig {
|
|
2
|
+
readonly unknownDate: string;
|
|
3
|
+
readonly onUnknown: string;
|
|
4
|
+
readonly inYear: (year: string) => string;
|
|
5
|
+
readonly beforeYear: (year: string) => string;
|
|
6
|
+
readonly afterYear: (year: string) => string;
|
|
7
|
+
readonly aboutYear: (year: string) => string;
|
|
8
|
+
readonly onFullDate: (date: string) => string;
|
|
9
|
+
readonly lifeRange: (from: string, to: string, fromIsYearOnly: boolean) => string;
|
|
10
|
+
readonly seesDayInYear: (year: string) => string;
|
|
11
|
+
readonly seesDayOnPhrase: (phrase: string) => string;
|
|
12
|
+
readonly seesDayOnFullDate: (date: string) => string;
|
|
13
|
+
}
|
|
14
|
+
export interface BookletDateModule {
|
|
15
|
+
readonly BOOKLET_UNKNOWN_DATE: string;
|
|
16
|
+
isYearOnlyDate(dateLabel: string): boolean;
|
|
17
|
+
onDate(dateLabel: string): string;
|
|
18
|
+
lifeDateRange(from: string, to: string): string;
|
|
19
|
+
seesDayOn(dateLabel: string): string;
|
|
20
|
+
}
|
|
21
|
+
export declare function createBookletDateModule(config: BookletDateConfig): BookletDateModule;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare const BOOKLET_UNKNOWN_DATE_FR = "Date inconnue";
|
|
1
2
|
/** Date réduite à une année (éventuellement avec qualificateur GEDCOM). */
|
|
2
3
|
export declare function isYearOnlyDate(dateLabel: string): boolean;
|
|
3
4
|
/** « le 15 mars 1991 », « en 1991 », « vers 1700 », « avant 1800 »… */
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { BookletLocale } from "./booklet-locale";
|
|
2
|
+
export declare function unknownDateLabel(locale?: BookletLocale): string;
|
|
3
|
+
export declare function isYearOnlyDate(dateLabel: string, locale?: BookletLocale): boolean;
|
|
4
|
+
export declare function onDate(dateLabel: string, locale?: BookletLocale): string;
|
|
5
|
+
export declare function lifeDateRange(from: string, to: string, locale?: BookletLocale): string;
|
|
6
|
+
export declare function seesDayOn(dateLabel: string, locale?: BookletLocale): string;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { BookletTimelineStyle } from './booklet-timeline';
|
|
2
2
|
import type { BookletChapter, BookletDetailLevel } from './booklet-structure';
|
|
3
|
+
import type { BookletLocale } from './booklet-locale';
|
|
3
4
|
export interface BookletSizeEstimate {
|
|
4
5
|
readonly pages: number;
|
|
5
6
|
readonly label: string;
|
|
6
7
|
}
|
|
7
8
|
/** Nombre de pages frise estimé pour un chapitre (tranches dynamiques). */
|
|
8
9
|
export declare function estimateTimelineSliceCount(rowCount: number): number;
|
|
9
|
-
/** Estimation grossière du nombre de pages pour orienter l
|
|
10
|
-
export declare function estimateBookletSize(chapters: readonly BookletChapter[], personCount: number, familyCount: number, detailLevel: BookletDetailLevel, timelineStyle?: BookletTimelineStyle): BookletSizeEstimate;
|
|
11
|
-
export declare function bookletSizeAdvice(personCount: number, detailLevel: BookletDetailLevel): string | null;
|
|
10
|
+
/** Estimation grossière du nombre de pages pour orienter l'utilisateur. */
|
|
11
|
+
export declare function estimateBookletSize(chapters: readonly BookletChapter[], personCount: number, familyCount: number, detailLevel: BookletDetailLevel, timelineStyle?: BookletTimelineStyle, locale?: BookletLocale): BookletSizeEstimate;
|
|
12
|
+
export declare function bookletSizeAdvice(personCount: number, detailLevel: BookletDetailLevel, locale?: BookletLocale): string | null;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BookletLocale } from './booklet-locale';
|
|
2
|
+
import type { BookletSex, PersonGenderWords } from './booklet-gender';
|
|
3
|
+
export interface GenderPhraseBundle {
|
|
4
|
+
readonly recensedChildren: (count: number) => string;
|
|
5
|
+
readonly otherUnions: (count: number) => string;
|
|
6
|
+
readonly usesPluralS: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare const GENDER_WORDS: Partial<Record<BookletLocale, Record<BookletSex, PersonGenderWords>>>;
|
|
9
|
+
export declare const GENDER_PHRASES: Partial<Record<BookletLocale, GenderPhraseBundle>>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { BookletLocale } from './booklet-locale';
|
|
1
2
|
/** Sexe GEDCOM exploité pour les accords du livret (M, F, U, X). */
|
|
2
3
|
export type BookletSex = 'M' | 'F' | 'U' | 'X';
|
|
3
4
|
export interface PersonGenderWords {
|
|
@@ -11,13 +12,11 @@ export interface PersonGenderWords {
|
|
|
11
12
|
readonly childOf: string;
|
|
12
13
|
readonly parentOf: string;
|
|
13
14
|
}
|
|
14
|
-
/**
|
|
15
|
-
export declare function personGenderWords(sex: BookletSex): PersonGenderWords;
|
|
16
|
-
/**
|
|
17
|
-
export declare function pluralS(count: number): string;
|
|
18
|
-
/**
|
|
15
|
+
/** Participles / role words aligned with the person's sex. U and X use neutral forms. */
|
|
16
|
+
export declare function personGenderWords(sex: BookletSex, locale?: BookletLocale): PersonGenderWords;
|
|
17
|
+
/** Plural suffix (French-style locales: 0 or 1 → singular; English: unused). */
|
|
18
|
+
export declare function pluralS(count: number, locale?: BookletLocale): string;
|
|
19
|
+
/** Singular / plural pick. */
|
|
19
20
|
export declare function pluralPick<T>(count: number, one: T, many: T): T;
|
|
20
|
-
|
|
21
|
-
export declare function
|
|
22
|
-
/** « 1 autre union citée… » / « N autres unions citées… ». */
|
|
23
|
-
export declare function otherUnionsPhrase(count: number): string;
|
|
21
|
+
export declare function recensedChildrenPhrase(count: number, locale?: BookletLocale): string;
|
|
22
|
+
export declare function otherUnionsPhrase(count: number, locale?: BookletLocale): string;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Shared place-prefix helpers for locale date/place modules. */
|
|
2
|
+
export declare function hasCountryPrefix(core: string, prefixes: readonly string[]): boolean;
|
|
3
|
+
export declare function prefixedLocation(core: string, prefixes: readonly string[], elsePrefix: string): string;
|
|
4
|
+
export declare function commaPrefixedLocation(core: string, prefixes: readonly string[], elsePrefix: string): string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { BookletDateModule } from './booklet-date-factory';
|
|
2
|
+
import type { BookletPlaceModule } from './booklet-place-factory';
|
|
3
|
+
import type { BookletSex, PersonGenderWords } from './booklet-gender';
|
|
4
|
+
import type { GenderPhraseBundle } from './booklet-gender-data';
|
|
5
|
+
import type { BookletLocale } from './booklet-locale';
|
|
6
|
+
import type { BookletMessages } from './booklet-messages-types';
|
|
7
|
+
import type { NarrativeModule } from './booklet-narrative-engine';
|
|
8
|
+
export interface BookletLocaleBundle {
|
|
9
|
+
readonly messages: BookletMessages;
|
|
10
|
+
readonly genderWords: Record<BookletSex, PersonGenderWords>;
|
|
11
|
+
readonly genderPhrases?: GenderPhraseBundle;
|
|
12
|
+
readonly dateModule: BookletDateModule;
|
|
13
|
+
readonly placeModule: BookletPlaceModule;
|
|
14
|
+
readonly narrativeModule: NarrativeModule;
|
|
15
|
+
}
|
|
16
|
+
export declare class BookletLocaleNotLoadedError extends Error {
|
|
17
|
+
constructor(locale: BookletLocale);
|
|
18
|
+
}
|
|
19
|
+
/** Clears cached locale bundles (tests). */
|
|
20
|
+
export declare function clearBookletLocaleCache(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Lazy-loads messages, gender, date/place, and narrative modules for one locale.
|
|
23
|
+
* Required before sync APIs (`getBookletMessages`, `collectBookletPersons`, …).
|
|
24
|
+
*/
|
|
25
|
+
export declare function ensureBookletLocale(locale?: BookletLocale): Promise<BookletLocale>;
|
|
26
|
+
export declare function getBookletLocaleBundle(locale: BookletLocale): BookletLocaleBundle;
|
|
27
|
+
export declare function isBookletLocaleLoaded(locale: BookletLocale): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { BookletLocale } from './booklet-locale';
|
|
2
|
+
export declare function getBookletDateModule(locale: BookletLocale): import("./booklet-date-factory").BookletDateModule;
|
|
3
|
+
export declare function getBookletPlaceModule(locale: BookletLocale): import("./booklet-place-factory").BookletPlaceModule;
|
|
4
|
+
export declare function getBookletDateModuleIfLoaded(locale?: BookletLocale): import("./booklet-date-factory").BookletDateModule;
|
|
5
|
+
export declare function getBookletPlaceModuleIfLoaded(locale?: BookletLocale): import("./booklet-place-factory").BookletPlaceModule;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Booklet narrative / PDF locales (aligned with gedcomts.com site languages). */
|
|
2
|
+
export type BookletLocale = 'en' | 'fr' | 'de' | 'nl' | 'es' | 'zh' | 'it' | 'pt' | 'pl' | 'ar' | 'he';
|
|
3
|
+
export declare const DEFAULT_BOOKLET_LOCALE: BookletLocale;
|
|
4
|
+
export declare const BOOKLET_LOCALES: readonly BookletLocale[];
|
|
5
|
+
/** Locales with full booklet copy (messages, dates, places, gender, narratives). */
|
|
6
|
+
export declare const BOOKLET_LOCALES_IMPLEMENTED: readonly BookletLocale[];
|
|
7
|
+
export declare const BOOKLET_RTL_LOCALES: readonly BookletLocale[];
|
|
8
|
+
export declare function isBookletLocale(value: string | null | undefined): value is BookletLocale;
|
|
9
|
+
export declare function resolveBookletLocale(locale?: BookletLocale): BookletLocale;
|
|
10
|
+
export declare function isBookletLocaleRtl(locale?: BookletLocale): boolean;
|
|
11
|
+
export declare function bookletTextDirection(locale?: BookletLocale): 'ltr' | 'rtl';
|
|
12
|
+
/** BCP 47 tag for `toLocaleDateString` on the PDF cover. */
|
|
13
|
+
export declare function bookletLocaleToBcp47(locale: BookletLocale): string;
|
|
14
|
+
/** `Intl.Collator` / `localeCompare` tag for chapter name ordering. */
|
|
15
|
+
export declare function bookletLocaleCompareTag(locale: BookletLocale): string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PDFPage } from 'pdf-lib';
|
|
2
|
+
import type { DrawGedcomTsLogoOptions, GedcomTsLogoLayout } from './booklet-logo';
|
|
3
|
+
export declare function clearBookletLogoCache(): void;
|
|
4
|
+
/** Loads SVG logo paths and draw helper (only when the cover logo is shown). */
|
|
5
|
+
export declare function ensureBookletLogo(): Promise<void>;
|
|
6
|
+
export declare function drawGedcomTsLogoOnPage(page: PDFPage, options?: DrawGedcomTsLogoOptions): Promise<GedcomTsLogoLayout>;
|
|
7
|
+
export declare function getGedcomTsLogoPaths(): Promise<readonly string[]>;
|
|
8
|
+
export declare function getGedcomTsLogoViewbox(): Promise<string>;
|