@treeviz/gedcom-parser 2.0.8 → 2.0.9

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.
Files changed (27) hide show
  1. package/dist/classes/index.js +382 -158
  2. package/dist/classes/indi.d.ts.map +1 -1
  3. package/dist/cli/index.js +382 -158
  4. package/dist/constants/index.js +381 -157
  5. package/dist/factories/index.js +381 -157
  6. package/dist/index.js +383 -159
  7. package/dist/kinship-translator/index.js +381 -157
  8. package/dist/kinship-translator/kinship-translator.basic.d.ts +11 -0
  9. package/dist/kinship-translator/kinship-translator.basic.d.ts.map +1 -1
  10. package/dist/kinship-translator/kinship-translator.d.ts.map +1 -1
  11. package/dist/kinship-translator/kinship-translator.de.d.ts +2 -1
  12. package/dist/kinship-translator/kinship-translator.de.d.ts.map +1 -1
  13. package/dist/kinship-translator/kinship-translator.en.d.ts +2 -1
  14. package/dist/kinship-translator/kinship-translator.en.d.ts.map +1 -1
  15. package/dist/kinship-translator/kinship-translator.es.d.ts +2 -1
  16. package/dist/kinship-translator/kinship-translator.es.d.ts.map +1 -1
  17. package/dist/kinship-translator/kinship-translator.fr.d.ts +2 -1
  18. package/dist/kinship-translator/kinship-translator.fr.d.ts.map +1 -1
  19. package/dist/kinship-translator/kinship-translator.hu.d.ts +8 -1
  20. package/dist/kinship-translator/kinship-translator.hu.d.ts.map +1 -1
  21. package/dist/kinship-translator/kinship-translator.interface.d.ts +1 -0
  22. package/dist/kinship-translator/kinship-translator.interface.d.ts.map +1 -1
  23. package/dist/kinship-translator/patterns.es.d.ts.map +1 -1
  24. package/dist/utils/cache.d.ts +14 -1
  25. package/dist/utils/cache.d.ts.map +1 -1
  26. package/dist/utils/index.js +383 -159
  27. package/package.json +1 -1
@@ -161,6 +161,135 @@ var profilePictureCache = (gedcom, key, value) => {
161
161
  const cached = caches.profilePictureCache?.[fullKey];
162
162
  return cached;
163
163
  };
164
+ var isNonBiologicalPath = (path) => path.some(
165
+ (item) => item.relation && item.relation !== "biological" /* BIOLOGICAL */
166
+ );
167
+ var invertHop = (kinship) => {
168
+ if (kinship === "parent") {
169
+ return "child";
170
+ }
171
+ if (kinship === "child") {
172
+ return "parent";
173
+ }
174
+ return kinship;
175
+ };
176
+ var hopRelation = (from, toIndi, kinship, inherited) => {
177
+ if (kinship === "parent" || kinship === "child") {
178
+ const parent = kinship === "parent" ? toIndi : from.indi;
179
+ const child = kinship === "parent" ? from.indi : toIndi;
180
+ const currentRelation = child.getParentType(parent);
181
+ if (currentRelation && currentRelation !== "biological" /* BIOLOGICAL */) {
182
+ return currentRelation;
183
+ }
184
+ }
185
+ if (inherited && inherited !== "biological" /* BIOLOGICAL */) {
186
+ return inherited;
187
+ }
188
+ return void 0;
189
+ };
190
+ var rebuildPathFromHops = (hops, skipRelation = false) => {
191
+ if (hops.length === 0) {
192
+ return [];
193
+ }
194
+ const path = [
195
+ {
196
+ indi: hops[0].indi,
197
+ kinship: "self",
198
+ level: 0,
199
+ levelUp: 0,
200
+ levelDown: 0,
201
+ degree: 0
202
+ }
203
+ ];
204
+ for (let i = 1; i < hops.length; i++) {
205
+ const prev = path[i - 1];
206
+ const { indi, kinship } = hops[i];
207
+ const relation = skipRelation ? void 0 : hopRelation(prev, indi, kinship, prev.relation);
208
+ if (kinship === "parent") {
209
+ path.push({
210
+ indi,
211
+ kinship,
212
+ relation,
213
+ level: prev.level + 1,
214
+ levelUp: prev.levelUp + 1,
215
+ levelDown: prev.levelDown,
216
+ degree: prev.degree
217
+ });
218
+ continue;
219
+ }
220
+ if (kinship === "child") {
221
+ path.push({
222
+ indi,
223
+ kinship,
224
+ relation,
225
+ level: prev.level - 1,
226
+ levelUp: prev.levelUp,
227
+ levelDown: prev.levelDown + 1,
228
+ degree: prev.levelUp ? prev.level > 0 ? prev.levelUp - prev.level + 1 : prev.levelDown - Math.abs(prev.level) : 0
229
+ });
230
+ continue;
231
+ }
232
+ path.push({
233
+ indi,
234
+ kinship,
235
+ relation,
236
+ level: prev.level,
237
+ levelUp: prev.levelUp,
238
+ levelDown: prev.levelDown,
239
+ degree: prev.degree
240
+ });
241
+ }
242
+ return path;
243
+ };
244
+ var storePathIfBetter = (gedcom, fromId, toId, path) => {
245
+ const key = `${fromId}|${toId}`;
246
+ const existing = pathCache(gedcom, key);
247
+ if (existing && (!isNonBiologicalPath(existing) || isNonBiologicalPath(path))) {
248
+ return;
249
+ }
250
+ pathCache(gedcom, key, path);
251
+ };
252
+ var cacheDiscoveredPath = (gedcom, path) => {
253
+ const n = path.length;
254
+ if (n < 2) {
255
+ return;
256
+ }
257
+ for (let i = 0; i < n; i++) {
258
+ const fromId = path[i].indi.id;
259
+ if (!fromId) {
260
+ continue;
261
+ }
262
+ for (let j = i + 1; j < n; j++) {
263
+ const toId = path[j].indi.id;
264
+ if (!toId) {
265
+ continue;
266
+ }
267
+ const isOriginalPair = i === 0 && j === n - 1;
268
+ const isDirectHop = j === i + 1;
269
+ const slice = path.slice(i, j + 1);
270
+ const sliceMixed = isNonBiologicalPath(slice);
271
+ if (!isOriginalPair && !isDirectHop && sliceMixed) {
272
+ continue;
273
+ }
274
+ const forward = i === 0 ? slice : rebuildPathFromHops(slice, !sliceMixed);
275
+ const reverseHops = [
276
+ {
277
+ indi: slice[slice.length - 1].indi,
278
+ kinship: "self"
279
+ }
280
+ ];
281
+ for (let k = slice.length - 2; k >= 0; k--) {
282
+ reverseHops.push({
283
+ indi: slice[k].indi,
284
+ kinship: invertHop(slice[k + 1].kinship)
285
+ });
286
+ }
287
+ const reverse = rebuildPathFromHops(reverseHops, !sliceMixed);
288
+ storePathIfBetter(gedcom, fromId, toId, forward);
289
+ storePathIfBetter(gedcom, toId, fromId, reverse);
290
+ }
291
+ }
292
+ };
164
293
 
165
294
  // src/constants/constants.ts
166
295
  var REF_LINE_REG = /^0 (?:(@[_a-zA-Z0-9]*@) )?(?<type>_[_A-Z][_a-zA-Z]{2,}|_?[A-Z][a-zA-Z]{2,}) ?(?<value>.*)/gm;
@@ -3709,7 +3838,6 @@ var Indi = class extends Common {
3709
3838
  if (cache) {
3710
3839
  return cache;
3711
3840
  }
3712
- const visited = new Individuals().append(this);
3713
3841
  const mainItem = {
3714
3842
  indi: this,
3715
3843
  level: 0,
@@ -3718,129 +3846,155 @@ var Indi = class extends Common {
3718
3846
  degree: 0,
3719
3847
  kinship: "self"
3720
3848
  };
3721
- const path = [mainItem];
3849
+ const mainPath = [mainItem];
3722
3850
  if (this.id === usedIndi.id) {
3723
- return path;
3851
+ return mainPath;
3724
3852
  }
3725
- const queue = [
3726
- {
3727
- ...mainItem,
3728
- path
3729
- }
3730
- ];
3731
- let helper = 0;
3732
- while (queue.length > 0) {
3733
- if (helper++ > 1e6) {
3734
- break;
3735
- }
3736
- const {
3737
- indi,
3738
- path: path2,
3739
- kinship,
3740
- relation,
3741
- level,
3742
- levelUp,
3743
- levelDown,
3744
- degree,
3745
- breakOnNext,
3746
- breakAfterNext,
3747
- inLaw
3748
- } = queue.shift();
3749
- if (usedIndi.id === indi.id) {
3750
- if (breakOnNext) {
3751
- return void 0;
3853
+ const bfs = (biologicalOnly) => {
3854
+ const visited = new Individuals().append(this);
3855
+ const queue = [
3856
+ {
3857
+ ...mainItem,
3858
+ path: mainPath
3752
3859
  }
3753
- pathCache(this._gedcom, cacheKey, path2);
3754
- return path2;
3755
- }
3756
- visited.append(indi);
3757
- const additional = {};
3758
- if (breakOnNext || breakAfterNext) {
3759
- additional.breakOnNext = breakOnNext || breakAfterNext;
3760
- }
3761
- if (inLaw) {
3762
- additional.inLaw = inLaw;
3763
- }
3764
- if (kinship === "spouse" && breakAfterSpouse) {
3765
- if (path2.length <= 2) {
3766
- additional.inLaw = true;
3767
- } else {
3768
- additional.breakOnNext = true;
3860
+ ];
3861
+ let helper = 0;
3862
+ while (queue.length > 0) {
3863
+ if (helper++ > 1e6) {
3864
+ break;
3769
3865
  }
3770
- }
3771
- if (kinship !== "child" || !breakAfterSpouse) {
3772
- indi.getBiologicalFathers().copy().merge(indi.getBiologicalMothers()).merge(indi.getFathers().copy().merge(indi.getMothers())).forEach((relative) => {
3866
+ const {
3867
+ indi,
3868
+ path,
3869
+ kinship,
3870
+ relation,
3871
+ level,
3872
+ levelUp,
3873
+ levelDown,
3874
+ degree,
3875
+ breakOnNext,
3876
+ breakAfterNext,
3877
+ inLaw
3878
+ } = queue.shift();
3879
+ if (usedIndi.id === indi.id) {
3880
+ if (breakOnNext) {
3881
+ return void 0;
3882
+ }
3883
+ return path;
3884
+ }
3885
+ visited.append(indi);
3886
+ const additional = {};
3887
+ if (breakOnNext || breakAfterNext) {
3888
+ additional.breakOnNext = breakOnNext || breakAfterNext;
3889
+ }
3890
+ if (inLaw) {
3891
+ additional.inLaw = inLaw;
3892
+ }
3893
+ if (!biologicalOnly && kinship === "spouse" && breakAfterSpouse) {
3894
+ if (path.length <= 2) {
3895
+ additional.inLaw = true;
3896
+ } else {
3897
+ additional.breakOnNext = true;
3898
+ }
3899
+ }
3900
+ if (kinship !== "child" || !breakAfterSpouse) {
3901
+ indi.getBiologicalFathers().copy().merge(indi.getBiologicalMothers()).merge(indi.getFathers().copy().merge(indi.getMothers())).forEach((relative) => {
3902
+ if (!visited.has(relative)) {
3903
+ const currentRelation = indi.getParentType(relative);
3904
+ const isNonBiological = !!currentRelation && currentRelation !== "biological" /* BIOLOGICAL */;
3905
+ if (biologicalOnly && isNonBiological) {
3906
+ return;
3907
+ }
3908
+ if (!biologicalOnly && breakAfterNonBiological && isNonBiological) {
3909
+ additional.breakAfterNext = true;
3910
+ }
3911
+ const newItem = {
3912
+ indi: relative,
3913
+ kinship: "parent",
3914
+ relation: isNonBiological ? currentRelation : relation,
3915
+ level: level + 1,
3916
+ levelUp: levelUp + 1,
3917
+ levelDown,
3918
+ degree,
3919
+ ...additional
3920
+ };
3921
+ queue.push({
3922
+ ...newItem,
3923
+ path: [...path, newItem]
3924
+ });
3925
+ }
3926
+ });
3927
+ }
3928
+ indi.getChildren().forEach((relative) => {
3773
3929
  if (!visited.has(relative)) {
3774
- const currentRelation = indi.getParentType(relative);
3775
- if (breakAfterNonBiological && currentRelation !== "biological" /* BIOLOGICAL */) {
3930
+ const currentRelation = relative.getParentType(indi);
3931
+ const isNonBiological = !!currentRelation && currentRelation !== "biological" /* BIOLOGICAL */;
3932
+ if (biologicalOnly && isNonBiological) {
3933
+ return;
3934
+ }
3935
+ if (!biologicalOnly && breakAfterNonBiological && isNonBiological) {
3776
3936
  additional.breakAfterNext = true;
3777
3937
  }
3778
3938
  const newItem = {
3779
3939
  indi: relative,
3780
- kinship: "parent",
3781
- relation: currentRelation && currentRelation !== "biological" /* BIOLOGICAL */ ? currentRelation : relation,
3782
- level: level + 1,
3783
- levelUp: levelUp + 1,
3784
- levelDown,
3785
- degree,
3940
+ kinship: "child",
3941
+ relation: isNonBiological ? currentRelation : relation,
3942
+ level: level - 1,
3943
+ levelUp,
3944
+ levelDown: levelDown + 1,
3945
+ degree: levelUp ? level > 0 ? levelUp - level + 1 : levelDown - Math.abs(level) : 0,
3786
3946
  ...additional
3787
3947
  };
3788
3948
  queue.push({
3789
3949
  ...newItem,
3790
- path: [...path2, newItem]
3950
+ path: [...path, newItem]
3791
3951
  });
3792
3952
  }
3793
3953
  });
3794
- }
3795
- indi.getChildren().forEach((relative) => {
3796
- if (!visited.has(relative)) {
3797
- const currentRelation = relative.getParentType(indi);
3798
- if (breakAfterNonBiological && currentRelation !== "biological" /* BIOLOGICAL */) {
3799
- additional.breakAfterNext = true;
3800
- }
3801
- const newItem = {
3802
- indi: relative,
3803
- kinship: "child",
3804
- relation: currentRelation && currentRelation !== "biological" /* BIOLOGICAL */ ? currentRelation : relation,
3805
- level: level - 1,
3806
- levelUp,
3807
- levelDown: levelDown + 1,
3808
- degree: levelUp ? level > 0 ? levelUp - level + 1 : levelDown - Math.abs(level) : 0,
3809
- ...additional
3810
- };
3811
- queue.push({
3812
- ...newItem,
3813
- path: [...path2, newItem]
3814
- });
3954
+ if (biologicalOnly) {
3955
+ continue;
3815
3956
  }
3816
- });
3817
- indi.getCoParents().forEach((relative) => {
3818
- if (!visited.has(relative)) {
3819
- const currentAddition = {};
3820
- if (relation && relation !== "biological" /* BIOLOGICAL */) {
3821
- currentAddition.relation = relation;
3822
- }
3823
- if (inLaw) {
3824
- currentAddition.breakOnNext = true;
3957
+ indi.getCoParents().forEach((relative) => {
3958
+ if (!visited.has(relative)) {
3959
+ const currentAddition = {};
3960
+ if (relation && relation !== "biological" /* BIOLOGICAL */) {
3961
+ currentAddition.relation = relation;
3962
+ }
3963
+ if (inLaw) {
3964
+ currentAddition.breakOnNext = true;
3965
+ }
3966
+ const newItem = {
3967
+ indi: relative,
3968
+ kinship: "spouse",
3969
+ level,
3970
+ levelUp,
3971
+ levelDown,
3972
+ degree,
3973
+ ...additional,
3974
+ ...currentAddition
3975
+ };
3976
+ queue.push({
3977
+ ...newItem,
3978
+ path: [...path, newItem]
3979
+ });
3825
3980
  }
3826
- const newItem = {
3827
- indi: relative,
3828
- kinship: "spouse",
3829
- level,
3830
- levelUp,
3831
- levelDown,
3832
- degree,
3833
- ...additional,
3834
- ...currentAddition
3835
- };
3836
- queue.push({
3837
- ...newItem,
3838
- path: [...path2, newItem]
3839
- });
3840
- }
3841
- });
3981
+ });
3982
+ }
3983
+ return void 0;
3984
+ };
3985
+ const foundPath = bfs(false);
3986
+ const lastItem = foundPath?.[foundPath.length - 1];
3987
+ if (lastItem?.relation && lastItem.relation !== "biological" /* BIOLOGICAL */) {
3988
+ const biologicalPath = bfs(true);
3989
+ if (biologicalPath) {
3990
+ cacheDiscoveredPath(this._gedcom, biologicalPath);
3991
+ return biologicalPath;
3992
+ }
3842
3993
  }
3843
- return void 0;
3994
+ if (foundPath) {
3995
+ cacheDiscoveredPath(this._gedcom, foundPath);
3996
+ }
3997
+ return foundPath;
3844
3998
  }
3845
3999
  kinship(other, showMainPerson, lang = "en", entirePath, displayName = "givenname") {
3846
4000
  const KinshipTranslatorClass2 = getKinshipTranslatorClass();
@@ -4819,6 +4973,44 @@ var KinshipTranslatorBasic = class {
4819
4973
  }
4820
4974
  return this.pathN?.indi;
4821
4975
  }
4976
+ /**
4977
+ * True when the path goes through a common ancestor whose two children
4978
+ * (the person we came from and the person we go to) share fewer than two
4979
+ * biological parents — i.e. they are half-siblings, so every collateral
4980
+ * relative on this path is a half-aunt/half-cousin/... too.
4981
+ *
4982
+ * Direct ancestors/descendants and paths that already use a
4983
+ * step/adopted/foster edge are never half-blood.
4984
+ */
4985
+ get isHalfBlood() {
4986
+ const path = this.path;
4987
+ if (!path || path.length < 3) {
4988
+ return false;
4989
+ }
4990
+ if (path.some(
4991
+ (item) => item.relation && item.relation !== "biological" /* BIOLOGICAL */
4992
+ )) {
4993
+ return false;
4994
+ }
4995
+ let peakIndex = -1;
4996
+ for (let i = 1; i < path.length; i++) {
4997
+ if (path[i].kinship === "parent") {
4998
+ peakIndex = i;
4999
+ }
5000
+ }
5001
+ if (peakIndex <= 0 || peakIndex >= path.length - 1) {
5002
+ return false;
5003
+ }
5004
+ if (path[peakIndex + 1].kinship !== "child") {
5005
+ return false;
5006
+ }
5007
+ const siblingA = path[peakIndex - 1].indi;
5008
+ const siblingB = path[peakIndex + 1].indi;
5009
+ const parentsA = siblingA.getBiologicalParents();
5010
+ const parentsB = siblingB.getBiologicalParents();
5011
+ const inter = parentsA.intersection(parentsB);
5012
+ return inter.length === 1 && (parentsA.length > 1 || parentsB.length > 1);
5013
+ }
4822
5014
  indirect() {
4823
5015
  return "";
4824
5016
  }
@@ -4846,6 +5038,9 @@ var KinshipTranslatorBasic = class {
4846
5038
  relationType(relation) {
4847
5039
  return relation ?? "";
4848
5040
  }
5041
+ halfBlood(relation) {
5042
+ return relation ?? "";
5043
+ }
4849
5044
  of(relation) {
4850
5045
  return relation ?? "";
4851
5046
  }
@@ -5084,14 +5279,34 @@ var KinshipTranslatorHU = class extends KinshipTranslatorBasic {
5084
5279
  return `${prefix.replace(/nagy$/, "")}unoka`;
5085
5280
  }
5086
5281
  sibling() {
5087
- const parents1 = this.person1?.getBiologicalParents();
5088
- const parentsN = this.personN?.getBiologicalParents();
5089
- const inter = parents1?.intersection(parentsN);
5090
- if (!inter || inter.length < 2) {
5091
- return "f\xE9ltestv\xE9r";
5092
- }
5093
5282
  return "testv\xE9r";
5094
5283
  }
5284
+ halfBlood(relation) {
5285
+ if (!relation || !this.isHalfBlood) {
5286
+ return relation ?? "";
5287
+ }
5288
+ const [head, ...rest] = relation.split(" ");
5289
+ if (!head) {
5290
+ return relation;
5291
+ }
5292
+ const prefixed = this.prefixHalf(head);
5293
+ return [prefixed, ...rest].join(" ");
5294
+ }
5295
+ /**
5296
+ * AkH. 139: compounds of more than two members stay closed up to 6
5297
+ * syllables; longer ones are hyphenated at the main boundary. A head
5298
+ * that is already hyphenated also takes a hyphenated half- prefix.
5299
+ */
5300
+ prefixHalf(head) {
5301
+ if (head.includes("-") || !/[aáeéiíoóöőuúüű]/i.test(head)) {
5302
+ return `f\xE9l-${head}`;
5303
+ }
5304
+ const syllables = (head.match(/[aáeéiíoóöőuúüű]/gi) ?? []).length + 1;
5305
+ if (syllables > 6) {
5306
+ return `f\xE9l-${head}`;
5307
+ }
5308
+ return `f\xE9l${head}`;
5309
+ }
5095
5310
  spouse() {
5096
5311
  if (this.personN?.isMale()) {
5097
5312
  return "f\xE9rj";
@@ -5290,20 +5505,22 @@ var KinshipTranslatorEn = class extends KinshipTranslatorBasic {
5290
5505
  return `${prefix}child`;
5291
5506
  }
5292
5507
  sibling() {
5293
- const parents1 = this.person1?.getBiologicalParents();
5294
- const parentsN = this.personN?.getBiologicalParents();
5295
- const inter = parents1?.intersection(parentsN);
5296
- let prefix = "";
5297
- if (!inter || inter.length < 2) {
5298
- prefix = "half-";
5299
- }
5300
5508
  if (this.personN?.isMale()) {
5301
- return `${prefix}brother`;
5509
+ return "brother";
5302
5510
  }
5303
5511
  if (this.personN?.isFemale()) {
5304
- return `${prefix}sister`;
5512
+ return "sister";
5513
+ }
5514
+ return "sibling";
5515
+ }
5516
+ halfBlood(relation) {
5517
+ if (!relation || !this.isHalfBlood) {
5518
+ return relation ?? "";
5519
+ }
5520
+ if (relation.includes(" ")) {
5521
+ return `half ${relation}`;
5305
5522
  }
5306
- return `${prefix}sibling`;
5523
+ return `half-${relation}`;
5307
5524
  }
5308
5525
  spouse() {
5309
5526
  if (this.personN?.isMale()) {
@@ -5485,20 +5702,22 @@ var KinshipTranslatorDe = class extends KinshipTranslatorBasic {
5485
5702
  return `${prefix}kind`;
5486
5703
  }
5487
5704
  sibling() {
5488
- const parents1 = this.person1?.getBiologicalParents();
5489
- const parentsN = this.personN?.getBiologicalParents();
5490
- const inter = parents1?.intersection(parentsN);
5491
- let prefix = "";
5492
- if (!inter || inter.length < 2) {
5493
- prefix = "Halb";
5494
- }
5495
5705
  if (this.personN?.isMale()) {
5496
- return `${prefix}bruder`;
5706
+ return "bruder";
5497
5707
  }
5498
5708
  if (this.personN?.isFemale()) {
5499
- return `${prefix}schwester`;
5709
+ return "schwester";
5710
+ }
5711
+ return "geschwister";
5712
+ }
5713
+ halfBlood(relation) {
5714
+ if (!relation || !this.isHalfBlood) {
5715
+ return relation ?? "";
5716
+ }
5717
+ if (/^[A-ZÄÖÜ]/.test(relation) || /[-\s]/.test(relation)) {
5718
+ return `Halb-${relation}`;
5500
5719
  }
5501
- return `${prefix}geschwister`;
5720
+ return `Halb${relation}`;
5502
5721
  }
5503
5722
  spouse() {
5504
5723
  if (this.personN?.isMale()) {
@@ -5680,20 +5899,19 @@ var KinshipTranslatorFr = class extends KinshipTranslatorBasic {
5680
5899
  return `${prefix}enfant`;
5681
5900
  }
5682
5901
  sibling() {
5683
- const parents1 = this.person1?.getBiologicalParents();
5684
- const parentsN = this.personN?.getBiologicalParents();
5685
- const inter = parents1?.intersection(parentsN);
5686
- let prefix = "";
5687
- if (!inter || inter.length < 2) {
5688
- prefix = "demi-";
5689
- }
5690
5902
  if (this.personN?.isMale()) {
5691
- return `${prefix}fr\xE8re`;
5903
+ return "fr\xE8re";
5692
5904
  }
5693
5905
  if (this.personN?.isFemale()) {
5694
- return `${prefix}s\u0153ur`;
5906
+ return "s\u0153ur";
5695
5907
  }
5696
- return `${prefix}fr\xE8re/s\u0153ur`;
5908
+ return "fr\xE8re/s\u0153ur";
5909
+ }
5910
+ halfBlood(relation) {
5911
+ if (!relation || !this.isHalfBlood) {
5912
+ return relation ?? "";
5913
+ }
5914
+ return `demi-${relation}`;
5697
5915
  }
5698
5916
  spouse() {
5699
5917
  if (this.personN?.isMale()) {
@@ -5790,12 +6008,12 @@ var InLawsEs = {
5790
6008
  "madre del (c\xF3nyuge|esposa|esposo)": "suegra",
5791
6009
  "padre del (c\xF3nyuge|esposa|esposo)": "suegro",
5792
6010
  "padre/madre del (c\xF3nyuge|esposa|esposo)": "suegro/suegra",
5793
- "esposa de (medio )?(hermano/hermana|hermana|hermano)": "cu\xF1ada",
5794
- "esposo de (medio )?(hermano/hermana|hermana|hermano)": "cu\xF1ado",
5795
- "c\xF3nyuge de (medio )?(hermano/hermana|hermana|hermano)": "cu\xF1ado/cu\xF1ada",
5796
- "(medio )?hermana del (c\xF3nyuge|esposa|esposo)": "cu\xF1ada",
5797
- "(medio )?hermano del (c\xF3nyuge|esposa|esposo)": "cu\xF1ado",
5798
- "(medio )?hermano/hermana del (c\xF3nyuge|esposa|esposo)": "cu\xF1ado/cu\xF1ada"
6011
+ "esposa de (medio |media |medio/a )?(hermano/hermana|hermana|hermano)": "cu\xF1ada",
6012
+ "esposo de (medio |media |medio/a )?(hermano/hermana|hermana|hermano)": "cu\xF1ado",
6013
+ "c\xF3nyuge de (medio |media |medio/a )?(hermano/hermana|hermana|hermano)": "cu\xF1ado/cu\xF1ada",
6014
+ "(medio |media |medio/a )?hermana del (c\xF3nyuge|esposa|esposo)": "cu\xF1ada",
6015
+ "(medio |media |medio/a )?hermano del (c\xF3nyuge|esposa|esposo)": "cu\xF1ado",
6016
+ "(medio |media |medio/a )?hermano/hermana del (c\xF3nyuge|esposa|esposo)": "cu\xF1ado/cu\xF1ada"
5799
6017
  };
5800
6018
 
5801
6019
  // src/kinship-translator/kinship-translator.es.ts
@@ -5875,20 +6093,25 @@ var KinshipTranslatorEs = class extends KinshipTranslatorBasic {
5875
6093
  return `${prefix}hijo/hija`;
5876
6094
  }
5877
6095
  sibling() {
5878
- const parents1 = this.person1?.getBiologicalParents();
5879
- const parentsN = this.personN?.getBiologicalParents();
5880
- const inter = parents1?.intersection(parentsN);
5881
- let prefix = "";
5882
- if (!inter || inter.length < 2) {
5883
- prefix = "medio ";
5884
- }
5885
6096
  if (this.personN?.isMale()) {
5886
- return `${prefix}hermano`;
6097
+ return "hermano";
5887
6098
  }
5888
6099
  if (this.personN?.isFemale()) {
5889
- return `${prefix}hermana`;
6100
+ return "hermana";
6101
+ }
6102
+ return "hermano/hermana";
6103
+ }
6104
+ halfBlood(relation) {
6105
+ if (!relation || !this.isHalfBlood) {
6106
+ return relation ?? "";
6107
+ }
6108
+ if (this.personN?.isFemale()) {
6109
+ return `media ${relation}`;
6110
+ }
6111
+ if (this.personN?.isMale()) {
6112
+ return `medio ${relation}`;
5890
6113
  }
5891
- return `${prefix}hermano/hermana`;
6114
+ return `medio/a ${relation}`;
5892
6115
  }
5893
6116
  spouse() {
5894
6117
  if (this.personN?.isMale()) {
@@ -6070,6 +6293,7 @@ var KinshipTranslator = class {
6070
6293
  } else if (personN.level !== 0) {
6071
6294
  relation = this.removal();
6072
6295
  }
6296
+ relation = this.translator?.halfBlood(relation);
6073
6297
  relation = this.translator?.relationType(relation);
6074
6298
  if (this.translator?.isOfSpouse) {
6075
6299
  relation = this.translator?.ofSpouse(relation);
@@ -6530,7 +6754,7 @@ var isCommonDate = (value) => {
6530
6754
  // package.json
6531
6755
  var package_default = {
6532
6756
  name: "@treeviz/gedcom-parser",
6533
- version: "2.0.8"};
6757
+ version: "2.0.9"};
6534
6758
 
6535
6759
  // src/utils/get-product-details.ts
6536
6760
  var isDevelopment = () => {
@@ -7604,4 +7828,4 @@ if (isDev) {
7604
7828
  }
7605
7829
  var parser_default = GedcomTree;
7606
7830
 
7607
- export { ACCEPTED_DATE_FORMATS, ACCEPTED_DATE_FORMATS_REGEX, parser_default as GedcomTree, PlaceType, commonDateFormatter, create, dateFormatter, extractSeparationYears, extractSplitPoints, findMatchingRangeForSplitRange, fromTuple, generateSplitRanges, getAllProp, getFamilyWith, getFileExtension, getName, getPlaceParts, getPlaces, getRawSize, getVersion, hungarianOrdinalize, implemented, inRange, initializeCache, isDevelopment, isImageFormat, isIntersectedRange, isRangeContained, marriageDateFormatter, nameFormatter, notImplemented, noteDateFormatter, ordinalize, parseRangeBounds, pathCache, placeTranslator, profilePictureCache, relativesCache, resetRelativesCache, setNestedGroup, splitOverlappingRanges, splitRange };
7831
+ export { ACCEPTED_DATE_FORMATS, ACCEPTED_DATE_FORMATS_REGEX, parser_default as GedcomTree, PlaceType, cacheDiscoveredPath, commonDateFormatter, create, dateFormatter, extractSeparationYears, extractSplitPoints, findMatchingRangeForSplitRange, fromTuple, generateSplitRanges, getAllProp, getFamilyWith, getFileExtension, getName, getPlaceParts, getPlaces, getRawSize, getVersion, hungarianOrdinalize, implemented, inRange, initializeCache, isDevelopment, isImageFormat, isIntersectedRange, isRangeContained, marriageDateFormatter, nameFormatter, notImplemented, noteDateFormatter, ordinalize, parseRangeBounds, pathCache, placeTranslator, profilePictureCache, relativesCache, resetRelativesCache, setNestedGroup, splitOverlappingRanges, splitRange };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treeviz/gedcom-parser",
3
- "version": "2.0.8",
3
+ "version": "2.0.9",
4
4
  "description": "Lightweight, pluggable GEDCOM parser for JavaScript/TypeScript with optional caching and place matching. Zero browser dependencies.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",