@treeviz/gedcom-parser 1.0.1
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/LICENSE +21 -0
- package/README.md +954 -0
- package/dist/classes/common.d.ts +87 -0
- package/dist/classes/common.d.ts.map +1 -0
- package/dist/classes/common.js +481 -0
- package/dist/classes/date.d.ts +26 -0
- package/dist/classes/date.d.ts.map +1 -0
- package/dist/classes/date.js +176 -0
- package/dist/classes/fam.d.ts +19 -0
- package/dist/classes/fam.d.ts.map +1 -0
- package/dist/classes/fam.js +38 -0
- package/dist/classes/fams.d.ts +16 -0
- package/dist/classes/fams.d.ts.map +1 -0
- package/dist/classes/fams.js +41 -0
- package/dist/classes/gedcom.d.ts +89 -0
- package/dist/classes/gedcom.d.ts.map +1 -0
- package/dist/classes/gedcom.js +421 -0
- package/dist/classes/index.d.ts +19 -0
- package/dist/classes/index.d.ts.map +1 -0
- package/dist/classes/index.js +19 -0
- package/dist/classes/indi.d.ts +298 -0
- package/dist/classes/indi.d.ts.map +1 -0
- package/dist/classes/indi.js +2049 -0
- package/dist/classes/indis.d.ts +54 -0
- package/dist/classes/indis.d.ts.map +1 -0
- package/dist/classes/indis.js +439 -0
- package/dist/classes/list.d.ts +55 -0
- package/dist/classes/list.d.ts.map +1 -0
- package/dist/classes/list.js +440 -0
- package/dist/classes/name.d.ts +20 -0
- package/dist/classes/name.d.ts.map +1 -0
- package/dist/classes/name.js +48 -0
- package/dist/classes/note.d.ts +12 -0
- package/dist/classes/note.d.ts.map +1 -0
- package/dist/classes/note.js +46 -0
- package/dist/classes/obje.d.ts +12 -0
- package/dist/classes/obje.d.ts.map +1 -0
- package/dist/classes/obje.js +81 -0
- package/dist/classes/objes.d.ts +8 -0
- package/dist/classes/objes.d.ts.map +1 -0
- package/dist/classes/objes.js +13 -0
- package/dist/classes/repo.d.ts +11 -0
- package/dist/classes/repo.d.ts.map +1 -0
- package/dist/classes/repo.js +6 -0
- package/dist/classes/repos.d.ts +8 -0
- package/dist/classes/repos.d.ts.map +1 -0
- package/dist/classes/repos.js +13 -0
- package/dist/classes/sour.d.ts +11 -0
- package/dist/classes/sour.d.ts.map +1 -0
- package/dist/classes/sour.js +6 -0
- package/dist/classes/sours.d.ts +8 -0
- package/dist/classes/sours.d.ts.map +1 -0
- package/dist/classes/sours.js +13 -0
- package/dist/classes/subm.d.ts +10 -0
- package/dist/classes/subm.d.ts.map +1 -0
- package/dist/classes/subm.js +6 -0
- package/dist/classes/subms.d.ts +8 -0
- package/dist/classes/subms.d.ts.map +1 -0
- package/dist/classes/subms.js +13 -0
- package/dist/constants/constants.d.ts +14 -0
- package/dist/constants/constants.d.ts.map +1 -0
- package/dist/constants/constants.js +13 -0
- package/dist/constants/filters.d.ts +17 -0
- package/dist/constants/filters.d.ts.map +1 -0
- package/dist/constants/filters.js +44 -0
- package/dist/constants/index.d.ts +4 -0
- package/dist/constants/index.d.ts.map +1 -0
- package/dist/constants/index.js +4 -0
- package/dist/constants/orders.d.ts +17 -0
- package/dist/constants/orders.d.ts.map +1 -0
- package/dist/constants/orders.js +240 -0
- package/dist/factories/cache-factory.d.ts +30 -0
- package/dist/factories/cache-factory.d.ts.map +1 -0
- package/dist/factories/cache-factory.js +43 -0
- package/dist/factories/date-locale-factory.d.ts +30 -0
- package/dist/factories/date-locale-factory.d.ts.map +1 -0
- package/dist/factories/date-locale-factory.js +34 -0
- package/dist/factories/i18n-factory.d.ts +40 -0
- package/dist/factories/i18n-factory.d.ts.map +1 -0
- package/dist/factories/i18n-factory.js +44 -0
- package/dist/factories/index.d.ts +5 -0
- package/dist/factories/index.d.ts.map +1 -0
- package/dist/factories/index.js +5 -0
- package/dist/factories/kinship-factory.d.ts +38 -0
- package/dist/factories/kinship-factory.d.ts.map +1 -0
- package/dist/factories/kinship-factory.js +35 -0
- package/dist/factories/place-parser-provider.d.ts +32 -0
- package/dist/factories/place-parser-provider.d.ts.map +1 -0
- package/dist/factories/place-parser-provider.js +35 -0
- package/dist/factories/place-translator-provider.d.ts +32 -0
- package/dist/factories/place-translator-provider.d.ts.map +1 -0
- package/dist/factories/place-translator-provider.js +35 -0
- package/dist/index.d.ts +78 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/interfaces/common.d.ts +43 -0
- package/dist/interfaces/common.d.ts.map +1 -0
- package/dist/interfaces/common.js +1 -0
- package/dist/interfaces/fam.d.ts +11 -0
- package/dist/interfaces/fam.d.ts.map +1 -0
- package/dist/interfaces/fam.js +1 -0
- package/dist/interfaces/fams.d.ts +9 -0
- package/dist/interfaces/fams.d.ts.map +1 -0
- package/dist/interfaces/fams.js +1 -0
- package/dist/interfaces/gedcom.d.ts +30 -0
- package/dist/interfaces/gedcom.d.ts.map +1 -0
- package/dist/interfaces/gedcom.js +1 -0
- package/dist/interfaces/index.d.ts +12 -0
- package/dist/interfaces/index.d.ts.map +1 -0
- package/dist/interfaces/index.js +1 -0
- package/dist/interfaces/indi.d.ts +109 -0
- package/dist/interfaces/indi.d.ts.map +1 -0
- package/dist/interfaces/indi.js +1 -0
- package/dist/interfaces/indis.d.ts +31 -0
- package/dist/interfaces/indis.d.ts.map +1 -0
- package/dist/interfaces/indis.js +1 -0
- package/dist/interfaces/list.d.ts +52 -0
- package/dist/interfaces/list.d.ts.map +1 -0
- package/dist/interfaces/list.js +1 -0
- package/dist/interfaces/obje.d.ts +7 -0
- package/dist/interfaces/obje.d.ts.map +1 -0
- package/dist/interfaces/obje.js +1 -0
- package/dist/interfaces/repo.d.ts +7 -0
- package/dist/interfaces/repo.d.ts.map +1 -0
- package/dist/interfaces/repo.js +1 -0
- package/dist/interfaces/sour.d.ts +7 -0
- package/dist/interfaces/sour.d.ts.map +1 -0
- package/dist/interfaces/sour.js +1 -0
- package/dist/interfaces/subm.d.ts +6 -0
- package/dist/interfaces/subm.d.ts.map +1 -0
- package/dist/interfaces/subm.js +1 -0
- package/dist/kinship-translator/index.d.ts +11 -0
- package/dist/kinship-translator/index.d.ts.map +1 -0
- package/dist/kinship-translator/index.js +10 -0
- package/dist/kinship-translator/kinship-translator.basic.d.ts +30 -0
- package/dist/kinship-translator/kinship-translator.basic.d.ts.map +1 -0
- package/dist/kinship-translator/kinship-translator.basic.js +74 -0
- package/dist/kinship-translator/kinship-translator.d.ts +26 -0
- package/dist/kinship-translator/kinship-translator.d.ts.map +1 -0
- package/dist/kinship-translator/kinship-translator.de.d.ts +18 -0
- package/dist/kinship-translator/kinship-translator.de.d.ts.map +1 -0
- package/dist/kinship-translator/kinship-translator.de.js +180 -0
- package/dist/kinship-translator/kinship-translator.en.d.ts +18 -0
- package/dist/kinship-translator/kinship-translator.en.d.ts.map +1 -0
- package/dist/kinship-translator/kinship-translator.en.js +182 -0
- package/dist/kinship-translator/kinship-translator.es.d.ts +18 -0
- package/dist/kinship-translator/kinship-translator.es.d.ts.map +1 -0
- package/dist/kinship-translator/kinship-translator.es.js +181 -0
- package/dist/kinship-translator/kinship-translator.fr.d.ts +18 -0
- package/dist/kinship-translator/kinship-translator.fr.d.ts.map +1 -0
- package/dist/kinship-translator/kinship-translator.fr.js +181 -0
- package/dist/kinship-translator/kinship-translator.hu.d.ts +19 -0
- package/dist/kinship-translator/kinship-translator.hu.d.ts.map +1 -0
- package/dist/kinship-translator/kinship-translator.hu.js +226 -0
- package/dist/kinship-translator/kinship-translator.interface.d.ts +19 -0
- package/dist/kinship-translator/kinship-translator.interface.d.ts.map +1 -0
- package/dist/kinship-translator/kinship-translator.interface.js +1 -0
- package/dist/kinship-translator/kinship-translator.js +103 -0
- package/dist/kinship-translator/patterns.de.d.ts +2 -0
- package/dist/kinship-translator/patterns.de.d.ts.map +1 -0
- package/dist/kinship-translator/patterns.de.js +14 -0
- package/dist/kinship-translator/patterns.en.d.ts +2 -0
- package/dist/kinship-translator/patterns.en.d.ts.map +1 -0
- package/dist/kinship-translator/patterns.en.js +14 -0
- package/dist/kinship-translator/patterns.es.d.ts +2 -0
- package/dist/kinship-translator/patterns.es.d.ts.map +1 -0
- package/dist/kinship-translator/patterns.es.js +14 -0
- package/dist/kinship-translator/patterns.fr.d.ts +2 -0
- package/dist/kinship-translator/patterns.fr.d.ts.map +1 -0
- package/dist/kinship-translator/patterns.fr.js +14 -0
- package/dist/kinship-translator/patterns.hu.d.ts +6 -0
- package/dist/kinship-translator/patterns.hu.d.ts.map +1 -0
- package/dist/kinship-translator/patterns.hu.js +97 -0
- package/dist/kinship-translator/translators.d.ts +6 -0
- package/dist/kinship-translator/translators.d.ts.map +1 -0
- package/dist/kinship-translator/translators.js +5 -0
- package/dist/kinship-translator/types.d.ts +9 -0
- package/dist/kinship-translator/types.d.ts.map +1 -0
- package/dist/kinship-translator/types.js +1 -0
- package/dist/structures/address.d.ts +14 -0
- package/dist/structures/address.d.ts.map +1 -0
- package/dist/structures/address.js +1 -0
- package/dist/structures/association.d.ts +13 -0
- package/dist/structures/association.d.ts.map +1 -0
- package/dist/structures/association.js +1 -0
- package/dist/structures/change-date.d.ts +8 -0
- package/dist/structures/change-date.d.ts.map +1 -0
- package/dist/structures/change-date.js +1 -0
- package/dist/structures/creation-date.d.ts +7 -0
- package/dist/structures/creation-date.d.ts.map +1 -0
- package/dist/structures/creation-date.js +1 -0
- package/dist/structures/date.d.ts +9 -0
- package/dist/structures/date.d.ts.map +1 -0
- package/dist/structures/date.js +1 -0
- package/dist/structures/event-detail-structure.d.ts +25 -0
- package/dist/structures/event-detail-structure.d.ts.map +1 -0
- package/dist/structures/event-detail-structure.js +1 -0
- package/dist/structures/family.d.ts +34 -0
- package/dist/structures/family.d.ts.map +1 -0
- package/dist/structures/family.js +1 -0
- package/dist/structures/gedcom.d.ts +60 -0
- package/dist/structures/gedcom.d.ts.map +1 -0
- package/dist/structures/gedcom.js +1 -0
- package/dist/structures/index.d.ts +25 -0
- package/dist/structures/index.d.ts.map +1 -0
- package/dist/structures/index.js +1 -0
- package/dist/structures/individual-event-detail-structure.d.ts +9 -0
- package/dist/structures/individual-event-detail-structure.d.ts.map +1 -0
- package/dist/structures/individual-event-detail-structure.js +1 -0
- package/dist/structures/individual-event-structure.d.ts +83 -0
- package/dist/structures/individual-event-structure.d.ts.map +1 -0
- package/dist/structures/individual-event-structure.js +1 -0
- package/dist/structures/individual.d.ts +40 -0
- package/dist/structures/individual.d.ts.map +1 -0
- package/dist/structures/individual.js +1 -0
- package/dist/structures/lds-ordinance-detail.d.ts +17 -0
- package/dist/structures/lds-ordinance-detail.d.ts.map +1 -0
- package/dist/structures/lds-ordinance-detail.js +1 -0
- package/dist/structures/lds-spouse-sealing.d.ts +7 -0
- package/dist/structures/lds-spouse-sealing.d.ts.map +1 -0
- package/dist/structures/lds-spouse-sealing.js +1 -0
- package/dist/structures/marriage-date.d.ts +11 -0
- package/dist/structures/marriage-date.d.ts.map +1 -0
- package/dist/structures/marriage-date.js +1 -0
- package/dist/structures/multimedia-link.d.ts +16 -0
- package/dist/structures/multimedia-link.d.ts.map +1 -0
- package/dist/structures/multimedia-link.js +1 -0
- package/dist/structures/non-event.d.ts +12 -0
- package/dist/structures/non-event.d.ts.map +1 -0
- package/dist/structures/non-event.js +1 -0
- package/dist/structures/note.d.ts +16 -0
- package/dist/structures/note.d.ts.map +1 -0
- package/dist/structures/note.js +1 -0
- package/dist/structures/personal-name-pieces.d.ts +11 -0
- package/dist/structures/personal-name-pieces.d.ts.map +1 -0
- package/dist/structures/personal-name-pieces.js +1 -0
- package/dist/structures/personal-name.d.ts +16 -0
- package/dist/structures/personal-name.d.ts.map +1 -0
- package/dist/structures/personal-name.js +1 -0
- package/dist/structures/place.d.ts +20 -0
- package/dist/structures/place.d.ts.map +1 -0
- package/dist/structures/place.js +1 -0
- package/dist/structures/repository.d.ts +6 -0
- package/dist/structures/repository.d.ts.map +1 -0
- package/dist/structures/repository.js +1 -0
- package/dist/structures/source-citation.d.ts +27 -0
- package/dist/structures/source-citation.d.ts.map +1 -0
- package/dist/structures/source-citation.js +1 -0
- package/dist/structures/source-repository-citation.d.ts +13 -0
- package/dist/structures/source-repository-citation.d.ts.map +1 -0
- package/dist/structures/source-repository-citation.js +1 -0
- package/dist/structures/source.d.ts +28 -0
- package/dist/structures/source.d.ts.map +1 -0
- package/dist/structures/source.js +1 -0
- package/dist/types/ancestry-media.d.ts +65 -0
- package/dist/types/ancestry-media.d.ts.map +1 -0
- package/dist/types/ancestry-media.js +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/settings.d.ts +12 -0
- package/dist/types/settings.d.ts.map +1 -0
- package/dist/types/settings.js +1 -0
- package/dist/types/types.d.ts +220 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/types.js +26 -0
- package/dist/utils/cache.d.ts +22 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +57 -0
- package/dist/utils/common-creator.d.ts +13 -0
- package/dist/utils/common-creator.d.ts.map +1 -0
- package/dist/utils/common-creator.js +72 -0
- package/dist/utils/date-formatter.d.ts +35 -0
- package/dist/utils/date-formatter.d.ts.map +1 -0
- package/dist/utils/date-formatter.js +207 -0
- package/dist/utils/get-all-prop.d.ts +4 -0
- package/dist/utils/get-all-prop.d.ts.map +1 -0
- package/dist/utils/get-all-prop.js +5 -0
- package/dist/utils/get-family-with.d.ts +5 -0
- package/dist/utils/get-family-with.d.ts.map +1 -0
- package/dist/utils/get-family-with.js +11 -0
- package/dist/utils/get-places.d.ts +21 -0
- package/dist/utils/get-places.d.ts.map +1 -0
- package/dist/utils/get-places.js +77 -0
- package/dist/utils/get-product-details.d.ts +4 -0
- package/dist/utils/get-product-details.d.ts.map +1 -0
- package/dist/utils/get-product-details.js +6 -0
- package/dist/utils/get-raw-size.d.ts +2 -0
- package/dist/utils/get-raw-size.d.ts.map +1 -0
- package/dist/utils/get-raw-size.js +3 -0
- package/dist/utils/index.d.ts +17 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +18 -0
- package/dist/utils/logger.d.ts +3 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +11 -0
- package/dist/utils/name-formatter.d.ts +10 -0
- package/dist/utils/name-formatter.d.ts.map +1 -0
- package/dist/utils/name-formatter.js +45 -0
- package/dist/utils/nested-group.d.ts +4 -0
- package/dist/utils/nested-group.d.ts.map +1 -0
- package/dist/utils/nested-group.js +34 -0
- package/dist/utils/ordinalize.d.ts +3 -0
- package/dist/utils/ordinalize.d.ts.map +1 -0
- package/dist/utils/ordinalize.js +104 -0
- package/dist/utils/parser.d.ts +17 -0
- package/dist/utils/parser.d.ts.map +1 -0
- package/dist/utils/parser.js +322 -0
- package/dist/utils/place-parser.d.ts +16 -0
- package/dist/utils/place-parser.d.ts.map +1 -0
- package/dist/utils/place-parser.js +46 -0
- package/dist/utils/place-translator.d.ts +6 -0
- package/dist/utils/place-translator.d.ts.map +1 -0
- package/dist/utils/place-translator.js +8 -0
- package/dist/utils/place-types.d.ts +27 -0
- package/dist/utils/place-types.d.ts.map +1 -0
- package/dist/utils/place-types.js +14 -0
- package/dist/utils/range.d.ts +19 -0
- package/dist/utils/range.d.ts.map +1 -0
- package/dist/utils/range.js +265 -0
- package/package.json +153 -0
package/README.md
ADDED
|
@@ -0,0 +1,954 @@
|
|
|
1
|
+
# @treeviz/gedcom-parser
|
|
2
|
+
|
|
3
|
+
A lightweight, pluggable GEDCOM parser library for JavaScript/TypeScript applications. Originally part of [TreeViz](https://treeviz.com), extracted as a standalone package for reusability.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🚀 **Parse GEDCOM files** - Full GEDCOM 5.5.1 support
|
|
8
|
+
- 🔌 **Pluggable Architecture** - Zero dependencies on browser-specific APIs
|
|
9
|
+
- 💾 **Optional Caching** - Provide your own cache implementation (IndexedDB, localStorage, Redis, etc.)
|
|
10
|
+
- 🌍 **Optional Place Matching** - Provide your own country/place data
|
|
11
|
+
- 🏗️ **TypeScript** - Full type definitions included
|
|
12
|
+
- 🪶 **Lightweight** - Core package has minimal dependencies
|
|
13
|
+
- 🔒 **SSR-Safe** - No-op defaults for server-side rendering
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @treeviz/gedcom-parser
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
### Basic Usage (No Plugins)
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { GedcomTree } from '@treeviz/gedcom-parser';
|
|
27
|
+
|
|
28
|
+
const gedcomContent = `0 HEAD
|
|
29
|
+
1 SOUR MyApp
|
|
30
|
+
0 @I1@ INDI
|
|
31
|
+
1 NAME John /Doe/
|
|
32
|
+
0 TRLR`;
|
|
33
|
+
|
|
34
|
+
const tree = new GedcomTree(gedcomContent);
|
|
35
|
+
const individuals = tree.indis();
|
|
36
|
+
|
|
37
|
+
individuals.forEach(indi => {
|
|
38
|
+
console.log(indi.name()); // "John Doe"
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Factory Providers
|
|
43
|
+
|
|
44
|
+
The package uses factory patterns to allow customization of core functionality. All factories are **optional** - the package provides sensible defaults.
|
|
45
|
+
|
|
46
|
+
### Available Factory Providers
|
|
47
|
+
|
|
48
|
+
#### 1. **i18n Provider** (Translation)
|
|
49
|
+
|
|
50
|
+
Provide your translation function for date formatting and other localized content.
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { setI18nProvider } from '@treeviz/gedcom-parser';
|
|
54
|
+
import i18n from './my-i18n-setup';
|
|
55
|
+
|
|
56
|
+
// Set up translation provider
|
|
57
|
+
setI18nProvider((key: string, options?: Record<string, unknown>) =>
|
|
58
|
+
i18n.t(key, options)
|
|
59
|
+
);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Default:** Returns the key as-is (no translation)
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
#### 2. **Date Locale Provider**
|
|
67
|
+
|
|
68
|
+
Provide date-fns locale for date formatting.
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import { setDateLocaleProvider } from '@treeviz/gedcom-parser';
|
|
72
|
+
import { enUS, hu, de } from 'date-fns/locale';
|
|
73
|
+
|
|
74
|
+
// Set up date locale provider
|
|
75
|
+
setDateLocaleProvider((lang: string) => {
|
|
76
|
+
switch (lang) {
|
|
77
|
+
case 'hu': return hu;
|
|
78
|
+
case 'de': return de;
|
|
79
|
+
default: return enUS;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Default:** English (en-US) locale
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
#### 3. **Place Parser Provider**
|
|
89
|
+
|
|
90
|
+
Provide custom place parsing logic for sophisticated place name recognition.
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
import { setPlaceParserProvider } from '@treeviz/gedcom-parser';
|
|
94
|
+
import type { PlaceParts } from '@treeviz/gedcom-parser';
|
|
95
|
+
|
|
96
|
+
// Custom place parser with historical place recognition
|
|
97
|
+
setPlaceParserProvider((place: string | (string | undefined)[]) => {
|
|
98
|
+
// Your sophisticated place parsing logic
|
|
99
|
+
// e.g., recognize counties, historical boundaries, etc.
|
|
100
|
+
return [{
|
|
101
|
+
leftParts: ['District'],
|
|
102
|
+
town: 'Budapest',
|
|
103
|
+
county: 'Pest',
|
|
104
|
+
country: 'Hungary'
|
|
105
|
+
}] as PlaceParts[];
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Default:** Simple comma-split parser (last part = country, second-to-last = county, rest = town)
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
#### 4. **Place Translator Provider**
|
|
114
|
+
|
|
115
|
+
Provide custom place name translation and normalization.
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
import { setPlaceTranslatorProvider } from '@treeviz/gedcom-parser';
|
|
119
|
+
|
|
120
|
+
// Custom place translator with country name translation
|
|
121
|
+
setPlaceTranslatorProvider((
|
|
122
|
+
place?: string | string[],
|
|
123
|
+
level?: number,
|
|
124
|
+
toReversed?: boolean
|
|
125
|
+
) => {
|
|
126
|
+
// Your translation logic
|
|
127
|
+
// e.g., "Magyarország" → "Hungary", "Románia" → "Romania"
|
|
128
|
+
return translatedPlace;
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Default:** Returns place name as-is (no translation)
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
#### 5. **Cache Manager Factory**
|
|
137
|
+
|
|
138
|
+
Provide your own caching implementation (IndexedDB, localStorage, Redis, etc.).
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
import { setCacheManagerFactory } from '@treeviz/gedcom-parser';
|
|
142
|
+
import type { CacheManagerFactory } from '@treeviz/gedcom-parser';
|
|
143
|
+
|
|
144
|
+
const cacheFactory: CacheManagerFactory = <T>(
|
|
145
|
+
name: string,
|
|
146
|
+
store: string,
|
|
147
|
+
type: string,
|
|
148
|
+
encrypted: boolean
|
|
149
|
+
) => {
|
|
150
|
+
// Return cache manager instance
|
|
151
|
+
return {
|
|
152
|
+
async getItem(): Promise<T | null> {
|
|
153
|
+
// Your cache get logic
|
|
154
|
+
},
|
|
155
|
+
async setItem(value: T): Promise<void> {
|
|
156
|
+
// Your cache set logic
|
|
157
|
+
},
|
|
158
|
+
async removeItem(): Promise<void> {
|
|
159
|
+
// Your cache remove logic
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
setCacheManagerFactory(cacheFactory);
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Default:** In-memory cache (suitable for Node.js, testing, or small trees)
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
#### 6. **Kinship Translator Class**
|
|
172
|
+
|
|
173
|
+
Override the kinship relationship translator.
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
import { setKinshipTranslatorClass, KinshipTranslator } from '@treeviz/gedcom-parser';
|
|
177
|
+
|
|
178
|
+
// Extend built-in translator
|
|
179
|
+
class MyCustomTranslator extends KinshipTranslator {
|
|
180
|
+
translate(showMainPerson: boolean) {
|
|
181
|
+
const result = super.translate(showMainPerson);
|
|
182
|
+
return result ? `Custom: ${result}` : result;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
setKinshipTranslatorClass(MyCustomTranslator);
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Default:** Built-in multi-language translator (EN, HU, DE, ES, FR)
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
### Complete Setup Example
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
import {
|
|
197
|
+
setI18nProvider,
|
|
198
|
+
setDateLocaleProvider,
|
|
199
|
+
setPlaceParserProvider,
|
|
200
|
+
setPlaceTranslatorProvider,
|
|
201
|
+
setCacheManagerFactory,
|
|
202
|
+
GedcomTree
|
|
203
|
+
} from '@treeviz/gedcom-parser';
|
|
204
|
+
|
|
205
|
+
// 1. Set up all factories BEFORE parsing
|
|
206
|
+
setI18nProvider((key, options) => i18n.t(key, options));
|
|
207
|
+
setDateLocaleProvider(getDateFnsLocale);
|
|
208
|
+
setPlaceParserProvider(getPlaceParts);
|
|
209
|
+
setPlaceTranslatorProvider(placeTranslator);
|
|
210
|
+
setCacheManagerFactory(cacheFactory);
|
|
211
|
+
|
|
212
|
+
// 2. Now parse GEDCOM
|
|
213
|
+
const tree = new GedcomTree(gedcomContent);
|
|
214
|
+
|
|
215
|
+
// All functionality now uses your custom implementations
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Advanced Examples
|
|
221
|
+
|
|
222
|
+
### With Caching (IndexedDB Example)
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
import { setCacheFactory, type ICacheManager } from '@treeviz/gedcom-parser';
|
|
226
|
+
import localforage from 'localforage';
|
|
227
|
+
|
|
228
|
+
// Create your cache implementation
|
|
229
|
+
class IndexedDbCache<T> implements ICacheManager<T> {
|
|
230
|
+
private store: LocalForage;
|
|
231
|
+
|
|
232
|
+
constructor(name: string, storeName: string, enc?: boolean) {
|
|
233
|
+
this.store = localforage.createInstance({ name, storeName });
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
async getItem(key: string): Promise<T | null> {
|
|
237
|
+
return this.store.getItem<T>(key);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async setItem(key: string, value: T): Promise<void> {
|
|
241
|
+
await this.store.setItem(key, value);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
clear(): void {
|
|
245
|
+
this.store.clear();
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
async clearBy(comparer: (key: string) => boolean): Promise<void> {
|
|
249
|
+
await this.store.iterate((value, key) => {
|
|
250
|
+
if (comparer(key)) {
|
|
251
|
+
this.store.removeItem(key);
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
async clearCache(): Promise<void> {
|
|
257
|
+
// Clear in-memory cache if applicable
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async getAllItems(): Promise<Record<string, () => Promise<T>>> {
|
|
261
|
+
const items: Record<string, () => Promise<T>> = {};
|
|
262
|
+
await this.store.iterate((value, key) => {
|
|
263
|
+
items[key] = async () => value as T;
|
|
264
|
+
});
|
|
265
|
+
return items;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Initialize the factory BEFORE using the parser
|
|
270
|
+
setCacheFactory((name, storeName, dataType, enc) =>
|
|
271
|
+
new IndexedDbCache(name, `${storeName}-${dataType}`, enc)
|
|
272
|
+
);
|
|
273
|
+
|
|
274
|
+
// Now caching is enabled for path calculations and relatives
|
|
275
|
+
const tree = new GedcomTree(gedcomContent);
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## API Reference
|
|
281
|
+
|
|
282
|
+
### Parser
|
|
283
|
+
|
|
284
|
+
#### `GedcomTree`
|
|
285
|
+
|
|
286
|
+
Main parser class for GEDCOM content.
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
import { GedcomTree } from '@treeviz/gedcom-parser';
|
|
290
|
+
|
|
291
|
+
const tree = new GedcomTree(gedcomContent, options?);
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
**Methods:**
|
|
295
|
+
- `indis()` - Get all individuals (Individuals collection)
|
|
296
|
+
- `fams()` - Get all families (Families collection)
|
|
297
|
+
- `sours()` - Get all sources
|
|
298
|
+
- `repos()` - Get all repositories
|
|
299
|
+
- `objes()` - Get all media objects
|
|
300
|
+
- `subms()` - Get all submitters
|
|
301
|
+
- `indi(id)` - Get individual by ID
|
|
302
|
+
- `fam(id)` - Get family by ID
|
|
303
|
+
|
|
304
|
+
**Individual Methods:**
|
|
305
|
+
- `name()` - Get formatted name
|
|
306
|
+
- `birthDate()` - Get birth date
|
|
307
|
+
- `birthPlace()` - Get birth place
|
|
308
|
+
- `deathDate()` - Get death date
|
|
309
|
+
- `deathPlace()` - Get death place
|
|
310
|
+
- `parents()` - Get parent individuals
|
|
311
|
+
- `children()` - Get children
|
|
312
|
+
- `spouses()` - Get spouses
|
|
313
|
+
- `siblings()` - Get siblings
|
|
314
|
+
- And many more...
|
|
315
|
+
|
|
316
|
+
### Cache Manager
|
|
317
|
+
|
|
318
|
+
#### `setCacheManagerFactory(factory)`
|
|
319
|
+
|
|
320
|
+
Set up caching for performance optimization.
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
import { setCacheManagerFactory, type CacheManagerFactory } from '@treeviz/gedcom-parser';
|
|
324
|
+
|
|
325
|
+
const factory: CacheManagerFactory = <T>(name: string, store: string, type: string, encrypted: boolean) => {
|
|
326
|
+
// Return your cache manager implementation
|
|
327
|
+
return {
|
|
328
|
+
async getItem(): Promise<T | null> { /* ... */ },
|
|
329
|
+
async setItem(value: T): Promise<void> { /* ... */ },
|
|
330
|
+
async removeItem(): Promise<void> { /* ... */ }
|
|
331
|
+
};
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
setCacheManagerFactory(factory);
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
**Cache Manager Interface:**
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
interface ICacheManager<T> {
|
|
341
|
+
/** Get an item from cache */
|
|
342
|
+
getItem(): Promise<T | null>;
|
|
343
|
+
|
|
344
|
+
/** Set an item in cache */
|
|
345
|
+
setItem(value: T): Promise<void>;
|
|
346
|
+
|
|
347
|
+
/** Remove item from cache */
|
|
348
|
+
removeItem(): Promise<void>;
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
**What gets cached:**
|
|
353
|
+
- Path calculations between individuals (family tree traversal)
|
|
354
|
+
- Relatives queries (all relatives at N degrees)
|
|
355
|
+
- Kinship translations
|
|
356
|
+
|
|
357
|
+
**When to use caching:**
|
|
358
|
+
- ✅ Large GEDCOM files (>10MB or >5000 individuals)
|
|
359
|
+
- ✅ Repeated path calculations
|
|
360
|
+
- ✅ Multiple relatives queries
|
|
361
|
+
- ✅ Interactive family tree applications
|
|
362
|
+
|
|
363
|
+
**When NOT to use caching:**
|
|
364
|
+
- ❌ Server-side rendering (use no-op default)
|
|
365
|
+
- ❌ Simple/small GEDCOM files
|
|
366
|
+
- ❌ Memory-constrained environments
|
|
367
|
+
- ❌ One-time parsing tasks
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
### Factory Providers API Reference
|
|
372
|
+
|
|
373
|
+
#### `setI18nProvider(provider)`
|
|
374
|
+
|
|
375
|
+
Provide translation function for localized content.
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
import { setI18nProvider, type I18nProvider } from '@treeviz/gedcom-parser';
|
|
379
|
+
|
|
380
|
+
const provider: I18nProvider = (key: string, options?: Record<string, unknown>) => {
|
|
381
|
+
// Return translated string
|
|
382
|
+
return myI18n.t(key, options);
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
setI18nProvider(provider);
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
#### `setDateLocaleProvider(provider)`
|
|
391
|
+
|
|
392
|
+
Provide date-fns locale for date formatting.
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
import { setDateLocaleProvider, type DateLocaleProvider } from '@treeviz/gedcom-parser';
|
|
396
|
+
import { enUS, hu } from 'date-fns/locale';
|
|
397
|
+
|
|
398
|
+
const provider: DateLocaleProvider = (lang: string) => {
|
|
399
|
+
return lang === 'hu' ? hu : enUS;
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
setDateLocaleProvider(provider);
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
#### `setPlaceParserProvider(provider)`
|
|
408
|
+
|
|
409
|
+
Provide custom place parsing logic.
|
|
410
|
+
|
|
411
|
+
```typescript
|
|
412
|
+
import { setPlaceParserProvider, type PlaceParserFunction } from '@treeviz/gedcom-parser';
|
|
413
|
+
|
|
414
|
+
const provider: PlaceParserFunction = (place: string | (string | undefined)[]) => {
|
|
415
|
+
// Return parsed place parts
|
|
416
|
+
return [{
|
|
417
|
+
leftParts: [],
|
|
418
|
+
town: 'Budapest',
|
|
419
|
+
county: 'Pest',
|
|
420
|
+
country: 'Hungary'
|
|
421
|
+
}];
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
setPlaceParserProvider(provider);
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
#### `setPlaceTranslatorProvider(provider)`
|
|
430
|
+
|
|
431
|
+
Provide custom place name translation.
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
import { setPlaceTranslatorProvider, type PlaceTranslatorFunction } from '@treeviz/gedcom-parser';
|
|
435
|
+
|
|
436
|
+
const provider: PlaceTranslatorFunction = (
|
|
437
|
+
place?: string | string[],
|
|
438
|
+
level?: number,
|
|
439
|
+
toReversed?: boolean
|
|
440
|
+
) => {
|
|
441
|
+
// Return translated place name
|
|
442
|
+
return translatedPlace;
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
setPlaceTranslatorProvider(provider);
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
#### `setKinshipTranslatorClass(translatorClass)`
|
|
451
|
+
|
|
452
|
+
Override the kinship relationship translator.
|
|
453
|
+
|
|
454
|
+
```typescript
|
|
455
|
+
import { setKinshipTranslatorClass, KinshipTranslator } from '@treeviz/gedcom-parser';
|
|
456
|
+
|
|
457
|
+
class MyTranslator extends KinshipTranslator {
|
|
458
|
+
translate(showMainPerson: boolean): string | undefined {
|
|
459
|
+
const result = super.translate(showMainPerson);
|
|
460
|
+
return result ? `Custom: ${result}` : result;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
setKinshipTranslatorClass(MyTranslator);
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
#### Reset Functions
|
|
470
|
+
|
|
471
|
+
All providers have corresponding reset functions to restore defaults:
|
|
472
|
+
|
|
473
|
+
```typescript
|
|
474
|
+
import {
|
|
475
|
+
resetI18nProvider,
|
|
476
|
+
resetDateLocaleProvider,
|
|
477
|
+
resetPlaceParserProvider,
|
|
478
|
+
resetPlaceTranslatorProvider,
|
|
479
|
+
resetCacheManagerFactory,
|
|
480
|
+
resetKinshipTranslatorClass
|
|
481
|
+
} from '@treeviz/gedcom-parser';
|
|
482
|
+
|
|
483
|
+
// Reset individual providers
|
|
484
|
+
resetI18nProvider();
|
|
485
|
+
resetDateLocaleProvider();
|
|
486
|
+
resetPlaceParserProvider();
|
|
487
|
+
resetPlaceTranslatorProvider();
|
|
488
|
+
resetCacheManagerFactory();
|
|
489
|
+
resetKinshipTranslatorClass();
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
---
|
|
493
|
+
|
|
494
|
+
### Country Data Provider (Deprecated)
|
|
495
|
+
|
|
496
|
+
#### `setCountryDataProvider(provider)`
|
|
497
|
+
|
|
498
|
+
⚠️ **Deprecated:** Use `setPlaceParserProvider` and `setPlaceTranslatorProvider` instead for better flexibility.
|
|
499
|
+
|
|
500
|
+
```typescript
|
|
501
|
+
import {
|
|
502
|
+
clearBy(comparer: (key: string) => boolean): Promise<void>;
|
|
503
|
+
|
|
504
|
+
/** Clear in-memory cache */
|
|
505
|
+
clearCache(): Promise<void>;
|
|
506
|
+
|
|
507
|
+
/** Get an item from cache */
|
|
508
|
+
getItem(key: string): Promise<T | null>;
|
|
509
|
+
|
|
510
|
+
/** Get all items as lazy-loaded promises */
|
|
511
|
+
getAllItems(): Promise<Record<string, () => Promise<T>>>;
|
|
512
|
+
|
|
513
|
+
/** Set an item in cache */
|
|
514
|
+
setItem(key: string, value: T): Promise<void>;
|
|
515
|
+
}
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
**What gets cached:**
|
|
519
|
+
- Path calculations between individuals (family tree traversal)
|
|
520
|
+
- Relatives queries (all relatives at N degrees)
|
|
521
|
+
|
|
522
|
+
**When to use caching:**
|
|
523
|
+
- ✅ Large GEDCOM files (>10MB or >5000 individuals)
|
|
524
|
+
- ✅ Repeated path calculations
|
|
525
|
+
- ✅ Multiple relatives queries
|
|
526
|
+
- ✅ Interactive family tree applications
|
|
527
|
+
|
|
528
|
+
**When NOT to use caching:**
|
|
529
|
+
- ❌ Server-side rendering (use no-op default)
|
|
530
|
+
- ❌ Simple/small GEDCOM files
|
|
531
|
+
- ❌ Memory-constrained environments
|
|
532
|
+
- ❌ One-time parsing tasks
|
|
533
|
+
|
|
534
|
+
### Country Data Provider
|
|
535
|
+
|
|
536
|
+
#### `setCountryDataProvider(provider)`
|
|
537
|
+
|
|
538
|
+
Set up place matching and country/town data.
|
|
539
|
+
|
|
540
|
+
```typescript
|
|
541
|
+
import {
|
|
542
|
+
setCountryDataProvider,
|
|
543
|
+
type ICountryDataProvider
|
|
544
|
+
} from '@treeviz/gedcom-parser';
|
|
545
|
+
|
|
546
|
+
const provider: ICountryDataProvider = {
|
|
547
|
+
translations: {
|
|
548
|
+
[languageCode]: { countryName: translation }
|
|
549
|
+
},
|
|
550
|
+
countries: {
|
|
551
|
+
[countryCode]: {
|
|
552
|
+
counties: { countyId: countyName },
|
|
553
|
+
towns: {
|
|
554
|
+
[year]: {
|
|
555
|
+
_source: { en: 'Source Name', hu: 'Forrás Név' },
|
|
556
|
+
_year: 1913,
|
|
557
|
+
data: { /* town data */ }
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
setCountryDataProvider(provider);
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
**Helper Functions:**
|
|
568
|
+
```typescript
|
|
569
|
+
// Get country translations for a specific language
|
|
570
|
+
getCountryTranslations(languageCode: string): CountryTranslations;
|
|
571
|
+
|
|
572
|
+
// Get country data by country code
|
|
573
|
+
getCountryData(countryCode: string): CountryData | undefined;
|
|
574
|
+
|
|
575
|
+
// List all supported countries
|
|
576
|
+
getAvailableCountries(): string[];
|
|
577
|
+
|
|
578
|
+
// List all available translations
|
|
579
|
+
getAvailableLanguages(): string[];
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
### Settings & Types
|
|
583
|
+
|
|
584
|
+
#### `Settings`
|
|
585
|
+
|
|
586
|
+
Configuration for parser behavior.
|
|
587
|
+
|
|
588
|
+
```typescript
|
|
589
|
+
import { type Settings } from '@treeviz/gedcom-parser';
|
|
590
|
+
|
|
591
|
+
interface Settings {
|
|
592
|
+
nameOrder?: NameOrder; // 'FIRST_LAST' | 'LAST_FIRST'
|
|
593
|
+
placeOrder?: PlaceOrder; // 'HIERARCHICAL' | 'REVERSE'
|
|
594
|
+
dateFormatPattern?: string; // Date format pattern
|
|
595
|
+
linkedPersons?: LinkedPersons; // How to link related personsname
|
|
596
|
+
// ... other settings
|
|
597
|
+
}
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
#### `Order`, `Filter`, `Group`
|
|
601
|
+
|
|
602
|
+
Utilities for sorting, filtering, and grouping individuals.
|
|
603
|
+
|
|
604
|
+
```typescript
|
|
605
|
+
import { type Order, type Filter, type Group } from '@treeviz/gedcom-parser';
|
|
606
|
+
|
|
607
|
+
// Order individuals by birth date
|
|
608
|
+
const byBirthDate: Order = {
|
|
609
|
+
'BIRT.DATE': {
|
|
610
|
+
direction: 'ASC',
|
|
611
|
+
getter: (value, raw) => value
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
|
|
615
|
+
// Filter individuals born after 1900
|
|
616
|
+
const bornAfter1900: Filter = {
|
|
617
|
+
'BIRT.DATE': {
|
|
618
|
+
comparer: (value) => {
|
|
619
|
+
const year = new Date(value).getFullYear();
|
|
620
|
+
return year > 1900;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
};
|
|
624
|
+
|
|
625
|
+
// Group individuals by birth place
|
|
626
|
+
const byBirthPlace: Group = {
|
|
627
|
+
'BIRT.PLAC': {
|
|
628
|
+
getter: (value) => value || 'Unknown'
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
|
|
632
|
+
// Use them
|
|
633
|
+
const individuals = tree.indis();
|
|
634
|
+
const ordered = individuals.order(byBirthDate);
|
|
635
|
+
const filtered = individuals.filter(bornAfter1900);
|
|
636
|
+
const grouped = individuals.group(byBirthPlace);
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
## Architecture
|
|
640
|
+
|
|
641
|
+
### Pluggable Design Philosophy
|
|
642
|
+
|
|
643
|
+
The package uses a **pluggable architecture** to avoid browser-specific dependencies:
|
|
644
|
+
|
|
645
|
+
```
|
|
646
|
+
┌─────────────────────────────────────┐
|
|
647
|
+
│ @treeviz/gedcom-parser (Core) │
|
|
648
|
+
│ - Pure parsing logic │
|
|
649
|
+
│ - Type definitions │
|
|
650
|
+
│ - No browser dependencies │
|
|
651
|
+
└──────────────┬──────────────────────┘
|
|
652
|
+
│
|
|
653
|
+
│ Interfaces
|
|
654
|
+
│
|
|
655
|
+
┌──────────────┴──────────────────────┐
|
|
656
|
+
│ Consumer Application │
|
|
657
|
+
│ - Provides ICacheManager │
|
|
658
|
+
│ - Provides ICountryDataProvider │
|
|
659
|
+
│ - Controls implementation │
|
|
660
|
+
└─────────────────────────────────────┘
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
**Benefits:**
|
|
664
|
+
- ✅ Works in any environment (browser, Node.js, React Native, Electron, etc.)
|
|
665
|
+
- ✅ No bundling of unused code (tree-shakeable)
|
|
666
|
+
- ✅ Consumer controls all implementation details
|
|
667
|
+
- ✅ Lightweight package size
|
|
668
|
+
- ✅ Easy to test (mock implementations)
|
|
669
|
+
- ✅ Flexible backend choices
|
|
670
|
+
|
|
671
|
+
### Performance Optimization
|
|
672
|
+
|
|
673
|
+
**Without caching:**
|
|
674
|
+
- Path between distant relatives: ~500-1000ms
|
|
675
|
+
- All relatives at 5 degrees: ~2-5 seconds
|
|
676
|
+
- Repeated queries: Same time every time
|
|
677
|
+
|
|
678
|
+
**With caching:**
|
|
679
|
+
- Path between distant relatives: ~10-50ms (10-20x faster)
|
|
680
|
+
- All relatives at 5 degrees: ~100-500ms (10-20x faster)
|
|
681
|
+
- Repeated queries: Near instant (cache hit)
|
|
682
|
+
|
|
683
|
+
**Memory usage:**
|
|
684
|
+
- Core parser: ~5-10MB for typical GEDCOM
|
|
685
|
+
- With cache: +10-50MB depending on cache size
|
|
686
|
+
- Without cache: No additional memory
|
|
687
|
+
|
|
688
|
+
## Complete Examples
|
|
689
|
+
|
|
690
|
+
### Full React Application Setup
|
|
691
|
+
|
|
692
|
+
```typescript
|
|
693
|
+
// src/utils/gedcom-init.ts
|
|
694
|
+
import {
|
|
695
|
+
setCacheFactory,
|
|
696
|
+
setCountryDataProvider,
|
|
697
|
+
type ICacheManager
|
|
698
|
+
} from '@treeviz/gedcom-parser';
|
|
699
|
+
import localforage from 'localforage';
|
|
700
|
+
|
|
701
|
+
// Import your data files
|
|
702
|
+
import huCountries from '../data/hu-countries.json';
|
|
703
|
+
import enCountries from '../data/en-countries.json';
|
|
704
|
+
import huCounties from '../data/hungary/counties.json';
|
|
705
|
+
import huTowns2020 from '../data/hungary/towns-2020.json';
|
|
706
|
+
|
|
707
|
+
// Cache implementation
|
|
708
|
+
class IndexedDbCache<T> implements ICacheManager<T> {
|
|
709
|
+
private store: LocalForage;
|
|
710
|
+
|
|
711
|
+
constructor(name: string, storeName: string, enc?: boolean) {
|
|
712
|
+
this.store = localforage.createInstance({
|
|
713
|
+
name,
|
|
714
|
+
storeName,
|
|
715
|
+
driver: localforage.INDEXEDDB
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
clear(): void {
|
|
720
|
+
this.store.clear();
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
async clearBy(comparer: (key: string) => boolean): Promise<void> {
|
|
724
|
+
await this.store.iterate((value, key) => {
|
|
725
|
+
if (comparer(key)) {
|
|
726
|
+
this.store.removeItem(key);
|
|
727
|
+
}
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
async clearCache(): Promise<void> {
|
|
732
|
+
// Optional: clear in-memory cache
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
async getItem(key: string): Promise<T | null> {
|
|
736
|
+
return this.store.getItem<T>(key);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
async getAllItems(): Promise<Record<string, () => Promise<T>>> {
|
|
740
|
+
const items: Record<string, () => Promise<T>> = {};
|
|
741
|
+
await this.store.iterate((value, key) => {
|
|
742
|
+
items[key] = async () => value as T;
|
|
743
|
+
});
|
|
744
|
+
return items;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
async setItem(key: string, value: T): Promise<void> {
|
|
748
|
+
await this.store.setItem(key, value);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
// Initialize gedcom-parser
|
|
753
|
+
export function initGedcomParser() {
|
|
754
|
+
// Set up caching
|
|
755
|
+
setCacheFactory((name, storeName, dataType, enc) =>
|
|
756
|
+
new IndexedDbCache(name, `${storeName}-${dataType}`, enc)
|
|
757
|
+
);
|
|
758
|
+
|
|
759
|
+
// Set up country data
|
|
760
|
+
setCountryDataProvider({
|
|
761
|
+
translations: {
|
|
762
|
+
hu: huCountries,
|
|
763
|
+
en: enCountries,
|
|
764
|
+
},
|
|
765
|
+
countries: {
|
|
766
|
+
HU: {
|
|
767
|
+
counties: huCounties,
|
|
768
|
+
towns: {
|
|
769
|
+
'2020': {
|
|
770
|
+
_source: { en: 'Hungary 2020', hu: 'Magyarország 2020' },
|
|
771
|
+
_year: 2020,
|
|
772
|
+
data: huTowns2020,
|
|
773
|
+
},
|
|
774
|
+
},
|
|
775
|
+
},
|
|
776
|
+
},
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// Call this in your app initialization
|
|
781
|
+
// src/index.tsx
|
|
782
|
+
import { initGedcomParser } from './utils/gedcom-init';
|
|
783
|
+
|
|
784
|
+
initGedcomParser();
|
|
785
|
+
|
|
786
|
+
// Now you can use the parser anywhere
|
|
787
|
+
import { GedcomTree } from '@treeviz/gedcom-parser';
|
|
788
|
+
|
|
789
|
+
function parseGedcom(content: string) {
|
|
790
|
+
const tree = new GedcomTree(content);
|
|
791
|
+
return tree.indis();
|
|
792
|
+
}
|
|
793
|
+
```
|
|
794
|
+
|
|
795
|
+
### Order, Filter, Group Example
|
|
796
|
+
|
|
797
|
+
```typescript
|
|
798
|
+
import { GedcomTree, type Order, type Filter, type Group } from '@treeviz/gedcom-parser';
|
|
799
|
+
|
|
800
|
+
const tree = new GedcomTree(gedcomContent);
|
|
801
|
+
const individuals = tree.indis();
|
|
802
|
+
|
|
803
|
+
// 1. Order by birth date (oldest first)
|
|
804
|
+
const byBirthDateAsc: Order = {
|
|
805
|
+
'BIRT.DATE': {
|
|
806
|
+
direction: 'ASC',
|
|
807
|
+
getter: (value) => new Date(value).getTime()
|
|
808
|
+
}
|
|
809
|
+
};
|
|
810
|
+
|
|
811
|
+
const orderedByBirth = individuals.order(byBirthDateAsc);
|
|
812
|
+
|
|
813
|
+
// 2. Filter born in 20th century
|
|
814
|
+
const born20thCentury: Filter = {
|
|
815
|
+
'BIRT.DATE': {
|
|
816
|
+
comparer: (date) => {
|
|
817
|
+
const year = new Date(date).getFullYear();
|
|
818
|
+
return year >= 1900 && year < 2000;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
};
|
|
822
|
+
|
|
823
|
+
const filtered20thCentury = individuals.filter(born20thCentury);
|
|
824
|
+
|
|
825
|
+
// 3. Group by birth place
|
|
826
|
+
const byBirthPlace: Group = {
|
|
827
|
+
'BIRT.PLAC': {
|
|
828
|
+
getter: (place) => place || 'Unknown'
|
|
829
|
+
}
|
|
830
|
+
};
|
|
831
|
+
|
|
832
|
+
const groupedByPlace = individuals.group(byBirthPlace);
|
|
833
|
+
|
|
834
|
+
// Print results
|
|
835
|
+
groupedByPlace.forEach((group, place) => {
|
|
836
|
+
console.log(`Born in ${place}:`);
|
|
837
|
+
group.forEach(indi => {
|
|
838
|
+
console.log(` - ${indi.name()}`);
|
|
839
|
+
});
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
// 4. Combine: Filter + Order + Group
|
|
843
|
+
const males born20thInBudapest = individuals
|
|
844
|
+
.filter(born20thCentury)
|
|
845
|
+
.filter({ 'BIRT.PLAC': { comparer: (place) => place?.includes('Budapest') } })
|
|
846
|
+
.filter({ 'SEX': { comparer: (sex) => sex === 'M' } })
|
|
847
|
+
.order(byBirthDateAsc);
|
|
848
|
+
```
|
|
849
|
+
|
|
850
|
+
## TypeScript Support
|
|
851
|
+
|
|
852
|
+
Full TypeScript support with complete type definitions:
|
|
853
|
+
|
|
854
|
+
```typescript
|
|
855
|
+
// Import types
|
|
856
|
+
import type {
|
|
857
|
+
// Core
|
|
858
|
+
Settings,
|
|
859
|
+
Order,
|
|
860
|
+
OrderDefinition,
|
|
861
|
+
Filter,
|
|
862
|
+
Group,
|
|
863
|
+
|
|
864
|
+
// Pluggable interfaces
|
|
865
|
+
ICacheManager,
|
|
866
|
+
CacheFactory,
|
|
867
|
+
ICountryDataProvider,
|
|
868
|
+
CountryTranslations,
|
|
869
|
+
CountryData,
|
|
870
|
+
|
|
871
|
+
// Date & Event structures
|
|
872
|
+
CommonDate,
|
|
873
|
+
IDateStructure,
|
|
874
|
+
IEventDetailStructure,
|
|
875
|
+
|
|
876
|
+
// Class interfaces
|
|
877
|
+
GedComInterface,
|
|
878
|
+
IndiInterface,
|
|
879
|
+
FamInterface,
|
|
880
|
+
|
|
881
|
+
// And many more...
|
|
882
|
+
} from '@treeviz/gedcom-parser';
|
|
883
|
+
```
|
|
884
|
+
|
|
885
|
+
## Legacy Compatibility
|
|
886
|
+
|
|
887
|
+
For backward compatibility, the package exports legacy names:
|
|
888
|
+
|
|
889
|
+
```typescript
|
|
890
|
+
// Old names (still work)
|
|
891
|
+
import {
|
|
892
|
+
setIndexedDbFactory, // ← Same as setCacheFactory
|
|
893
|
+
type IIndexedDbManager, // ← Same as ICacheManager
|
|
894
|
+
type IndexedDbFactory // ← Same as CacheFactory
|
|
895
|
+
} from '@treeviz/gedcom-parser';
|
|
896
|
+
|
|
897
|
+
// New names (recommended)
|
|
898
|
+
import {
|
|
899
|
+
setCacheFactory,
|
|
900
|
+
type ICacheManager,
|
|
901
|
+
type CacheFactory
|
|
902
|
+
} from '@treeviz/gedcom-parser';
|
|
903
|
+
```
|
|
904
|
+
|
|
905
|
+
## Browser Compatibility
|
|
906
|
+
|
|
907
|
+
- Chrome/Edge: ✅ Full support
|
|
908
|
+
- Firefox: ✅ Full support
|
|
909
|
+
- Safari: ✅ Full support
|
|
910
|
+
- IE11: ❌ Not supported (use transpilation)
|
|
911
|
+
|
|
912
|
+
## Node.js Compatibility
|
|
913
|
+
|
|
914
|
+
- Node.js 14+: ✅ Full support
|
|
915
|
+
- Recommended: Node.js 18+ (LTS)
|
|
916
|
+
|
|
917
|
+
**Note:** When using in Node.js, don't set up browser-specific plugins (IndexedDB). The package works fine with no-op defaults.
|
|
918
|
+
|
|
919
|
+
## License
|
|
920
|
+
|
|
921
|
+
MIT
|
|
922
|
+
|
|
923
|
+
## Contributing
|
|
924
|
+
|
|
925
|
+
Contributions welcome! Please open an issue or PR on GitHub.
|
|
926
|
+
|
|
927
|
+
### Development Setup
|
|
928
|
+
|
|
929
|
+
```bash
|
|
930
|
+
# Clone repository
|
|
931
|
+
git clone https://github.com/idavidka/gedcom-parser.git
|
|
932
|
+
cd gedcom-parser
|
|
933
|
+
|
|
934
|
+
# Install dependencies
|
|
935
|
+
npm install
|
|
936
|
+
|
|
937
|
+
# Build
|
|
938
|
+
npm run build
|
|
939
|
+
|
|
940
|
+
# Run tests (if available)
|
|
941
|
+
npm test
|
|
942
|
+
```
|
|
943
|
+
|
|
944
|
+
## Support
|
|
945
|
+
|
|
946
|
+
- **Issues**: [GitHub Issues](https://github.com/idavidka/gedcom-parser/issues)
|
|
947
|
+
- **Discussions**: [GitHub Discussions](https://github.com/idavidka/gedcom-parser/discussions)
|
|
948
|
+
- **Main App**: [TreeViz](https://treeviz.com)
|
|
949
|
+
|
|
950
|
+
## Credits
|
|
951
|
+
|
|
952
|
+
Originally developed as part of **TreeViz** by [@idavidka](https://github.com/idavidka).
|
|
953
|
+
|
|
954
|
+
Special thanks to all contributors and the genealogy community.
|