gedcom-ts 2026.5.4 → 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 +24 -0
- package/README.md +76 -9
- 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/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/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 +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
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
|
+
|
|
5
29
|
## [2026.5.4] - 2026-05-24
|
|
6
30
|
|
|
7
31
|
### Added
|
package/README.md
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
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
12
|
- generate a **genealogy booklet** as PDF (`gedcom-ts/booklet`, 11 locales including RTL Arabic/Hebrew)
|
|
11
13
|
|
|
@@ -19,13 +21,14 @@ 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
34
|
- **`gedcom-ts/booklet`** — PDF livret (`pdf-lib` en peerDependency, chargé depuis `node_modules`)
|
|
@@ -367,6 +370,65 @@ await drawGedcomTsLogoOnPage(page, defaultCoverLogoOptions());
|
|
|
367
370
|
| Font preload (host) | `registerBookletPdfFontBytes`, `registerPdfFontkit`, `localeNeedsUnicodePdfFont` |
|
|
368
371
|
| Logo | `ensureBookletLogo`, `drawGedcomTsLogoOnPage`, `getGedcomTsLogoPaths`, `defaultCoverLogoOptions` |
|
|
369
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` |
|
|
431
|
+
|
|
370
432
|
## API reference
|
|
371
433
|
|
|
372
434
|
Short description and a minimal snippet for each export of **`gedcom-ts`**. For the PDF booklet, see [Genealogy booklet (PDF)](#genealogy-booklet-pdf) (`gedcom-ts/booklet`).
|
|
@@ -416,7 +478,7 @@ try {
|
|
|
416
478
|
|
|
417
479
|
#### `ReadGed`
|
|
418
480
|
|
|
419
|
-
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.
|
|
420
482
|
|
|
421
483
|
Notable members:
|
|
422
484
|
|
|
@@ -430,6 +492,7 @@ Notable members:
|
|
|
430
492
|
| `placesMap: Map<string, Place>` | City name → `Place` (first occurrence wins). |
|
|
431
493
|
| `mapFiles: Map<string, File>` | Relative path → media `File` (for ZIP imports). |
|
|
432
494
|
| `datasetVersion: GedcomDatasetVersion` | `"7.0"`, `"5.5"` or `"unknown"`. |
|
|
495
|
+
| `objeRecordsById: Map<number, ObjeRecord>` | Parsed `OBJE` records (audio, images, …) keyed by `@O{n}@`. |
|
|
433
496
|
| `preservedTopLevelRecords: string[]` | Raw blocks for partial round-trip. |
|
|
434
497
|
| `resolveIndividualPointer(raw)` | Resolves `@I12@`, `I12`, `@Homer_Simpson@`, `Homer_Simpson` to a `Person`. |
|
|
435
498
|
| `getChildrenForParent(parent)` | All children attached to a parent (via `FAMS`). |
|
|
@@ -471,6 +534,7 @@ import { ExportGedcomFile, type ReadGed } from "gedcom-ts";
|
|
|
471
534
|
function exportGed(readGed: ReadGed) {
|
|
472
535
|
new ExportGedcomFile("my-tree", readGed.persons, {
|
|
473
536
|
extraTopLevelRecords: readGed.preservedTopLevelRecords,
|
|
537
|
+
objeRecordsById: readGed.objeRecordsById,
|
|
474
538
|
headLanguageTag: "fr-FR",
|
|
475
539
|
headCopyright: "© 2026 Family Archive",
|
|
476
540
|
headDestination: "https://gedcom.io/",
|
|
@@ -499,6 +563,7 @@ Options shared by both exporters:
|
|
|
499
563
|
| Option | Effect |
|
|
500
564
|
| ---------------------- | -------------------------------------------------------------------------------------------------------- |
|
|
501
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`. |
|
|
502
567
|
| `headLanguageTag` | BCP 47 tag for `HEAD`.`LANG` (defaults to `en-US`). |
|
|
503
568
|
| `headCopyright` | One-line `1 COPR` notice. |
|
|
504
569
|
| `headDestination` | Value of `HEAD`.`DEST` (target app / URI). |
|
|
@@ -644,7 +709,7 @@ const payload = place.toGedcom7PlacPayload(); // "Paris, , Île-de-France, Franc
|
|
|
644
709
|
|
|
645
710
|
#### `MultimediaFile`, `MultimediaFiles`
|
|
646
711
|
|
|
647
|
-
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.
|
|
648
713
|
|
|
649
714
|
```ts
|
|
650
715
|
import { MultimediaFile, MultimediaFiles } from "gedcom-ts";
|
|
@@ -719,7 +784,8 @@ editDateAct(person.acts.list[0].dateAct!).setExactDate(1900, "JAN", 1);
|
|
|
719
784
|
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
720
785
|
| `editPerson(person)` / `PersonEdit` | Identity, `FAMS` / `FAMC` / `removeFams*`, `nameVariants()` / `attributes()` / `multimedia()`, bulk `clear*`, entry points to `acts()` and `notes()`. |
|
|
721
786
|
| `editActs(acts)` / `ActsEdit` | `add`, `addNew`, `insertAt`, `insertNewAt`, `replaceAt`, `removeAt`, `removeAct`, `removeLast`, `clear`, `sortByDate`, `at`, `indexOfAct`. |
|
|
722
|
-
| `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`, … |
|
|
723
789
|
| `editDateAct(dateAct)` / `DateActEdit` | `clear`, `applyGedcomPayload`, `setExactDate`, `setQualified`, `setBetween`, `setFromTo`, `setTime`, `setDatePhrase` / `appendDatePhrase`, `setVerbatimPayload`. |
|
|
724
790
|
| `editPlace(place)` / `PlaceEdit` | `setFromGedcom7Payload`, `setCity`, `setCounty`, `setState`, `setCountry`, `setPlacPhrase` / `appendPlacPhrase` / `clearPlacPhrase`, `setCoordinates` / `clearCoordinates` / `replaceCoordinateModel`, `clearStructured`. |
|
|
725
791
|
| `editNotes(notes)` / `NotesEdit` | `add`, `addNew`, `insertAt`, `insertNewAt`, `replaceAt`, `removeAt`, `removeNote`, `removeLast`, `clear`, `at`, `indexOfNote`. |
|
|
@@ -785,7 +851,7 @@ validateReadGed(readGed, {
|
|
|
785
851
|
| Export | Role |
|
|
786
852
|
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
787
853
|
| `editReadGed(readGed)` / `ReadGedEdit` | `addPerson`, `removePersonByIndi`, `preserved()` → `PreservedTopLevelEdit` (`append`, `insertAt`, `replaceAt`, `removeAt`, `clear`) on `preservedTopLevelRecords`. Low-level helpers: `addPersonToReadGed`, `removePersonFromReadGedByIndi`. |
|
|
788
|
-
| `editGedcomExportOptions(opts)` / `GedcomExportOptionsEdit` | Fluent setters for `extraTopLevelRecords`, `headLanguageTag`, `headCopyright`, `headDestination`, `headSchemaTagDefs`.
|
|
854
|
+
| `editGedcomExportOptions(opts)` / `GedcomExportOptionsEdit` | Fluent setters for `extraTopLevelRecords`, `objeRecordsById`, `headLanguageTag`, `headCopyright`, `headDestination`, `headSchemaTagDefs`. |
|
|
789
855
|
| `clonePerson(person, newIndi)` / `cloneAct(act)` / `person.clone` / `act.clone` | Deep copies for templates or undo stacks. |
|
|
790
856
|
| `nextFamilyId(persons)` | Next internal family id `F`. |
|
|
791
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`. |
|
|
@@ -832,12 +898,13 @@ const version = resolveDatasetVersion(headLines); // "7.0" | "5.5" | "unknown"
|
|
|
832
898
|
|
|
833
899
|
#### `guessMediaFormFromUri(uri)`
|
|
834
900
|
|
|
835
|
-
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.
|
|
836
902
|
|
|
837
903
|
```ts
|
|
838
|
-
import { guessMediaFormFromUri } from "gedcom-ts";
|
|
904
|
+
import { guessMediaFormFromUri, guessMediaFormFromFile } from "gedcom-ts";
|
|
839
905
|
|
|
840
|
-
guessMediaFormFromUri("
|
|
906
|
+
guessMediaFormFromUri("media/recording.webm"); // "audio/webm"
|
|
907
|
+
guessMediaFormFromFile(new File(["x"], "take.webm", { type: "audio/webm" })); // "audio/webm"
|
|
841
908
|
```
|
|
842
909
|
|
|
843
910
|
#### `extractPersonNameVariants(personLines)` / `extractIndiAttributes(personLines)`
|
|
@@ -863,7 +930,7 @@ const primary = selectPrimaryNameVariant(person.nameVariants);
|
|
|
863
930
|
|
|
864
931
|
#### `GEDCOM_LIBRARY_VERSION`
|
|
865
932
|
|
|
866
|
-
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`).
|
|
867
934
|
|
|
868
935
|
```ts
|
|
869
936
|
import { GEDCOM_LIBRARY_VERSION } from "gedcom-ts";
|