@treeviz/gedcom-parser 2.0.8 → 2.0.10

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 (37) hide show
  1. package/dist/classes/index.js +627 -159
  2. package/dist/classes/indi.d.ts.map +1 -1
  3. package/dist/cli/index.js +627 -159
  4. package/dist/constants/index.js +626 -158
  5. package/dist/factories/index.js +626 -158
  6. package/dist/index.js +628 -160
  7. package/dist/kinship-translator/index.d.ts +1 -0
  8. package/dist/kinship-translator/index.d.ts.map +1 -1
  9. package/dist/kinship-translator/index.js +627 -159
  10. package/dist/kinship-translator/kinship-translator.basic.d.ts +11 -0
  11. package/dist/kinship-translator/kinship-translator.basic.d.ts.map +1 -1
  12. package/dist/kinship-translator/kinship-translator.d.ts.map +1 -1
  13. package/dist/kinship-translator/kinship-translator.de.d.ts +2 -1
  14. package/dist/kinship-translator/kinship-translator.de.d.ts.map +1 -1
  15. package/dist/kinship-translator/kinship-translator.en.d.ts +2 -1
  16. package/dist/kinship-translator/kinship-translator.en.d.ts.map +1 -1
  17. package/dist/kinship-translator/kinship-translator.es.d.ts +2 -1
  18. package/dist/kinship-translator/kinship-translator.es.d.ts.map +1 -1
  19. package/dist/kinship-translator/kinship-translator.fr.d.ts +2 -1
  20. package/dist/kinship-translator/kinship-translator.fr.d.ts.map +1 -1
  21. package/dist/kinship-translator/kinship-translator.hu.d.ts +8 -1
  22. package/dist/kinship-translator/kinship-translator.hu.d.ts.map +1 -1
  23. package/dist/kinship-translator/kinship-translator.interface.d.ts +1 -0
  24. package/dist/kinship-translator/kinship-translator.interface.d.ts.map +1 -1
  25. package/dist/kinship-translator/kinship-translator.ru.d.ts +18 -0
  26. package/dist/kinship-translator/kinship-translator.ru.d.ts.map +1 -0
  27. package/dist/kinship-translator/patterns.es.d.ts.map +1 -1
  28. package/dist/kinship-translator/patterns.ru.d.ts +2 -0
  29. package/dist/kinship-translator/patterns.ru.d.ts.map +1 -0
  30. package/dist/kinship-translator/translators.d.ts +1 -0
  31. package/dist/kinship-translator/translators.d.ts.map +1 -1
  32. package/dist/kinship-translator/types.d.ts +1 -1
  33. package/dist/kinship-translator/types.d.ts.map +1 -1
  34. package/dist/utils/cache.d.ts +14 -1
  35. package/dist/utils/cache.d.ts.map +1 -1
  36. package/dist/utils/index.js +628 -160
  37. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -1101,7 +1101,8 @@ __export(translators_exports, {
1101
1101
  en: () => KinshipTranslatorEn,
1102
1102
  es: () => KinshipTranslatorEs,
1103
1103
  fr: () => KinshipTranslatorFr,
1104
- hu: () => KinshipTranslatorHU
1104
+ hu: () => KinshipTranslatorHU,
1105
+ ru: () => KinshipTranslatorRu
1105
1106
  });
1106
1107
 
1107
1108
  // src/constants/filters.ts
@@ -1258,6 +1259,135 @@ var profilePictureCache = (gedcom, key, value) => {
1258
1259
  const cached = caches.profilePictureCache?.[fullKey];
1259
1260
  return cached;
1260
1261
  };
1262
+ var isNonBiologicalPath = (path) => path.some(
1263
+ (item) => item.relation && item.relation !== "biological" /* BIOLOGICAL */
1264
+ );
1265
+ var invertHop = (kinship) => {
1266
+ if (kinship === "parent") {
1267
+ return "child";
1268
+ }
1269
+ if (kinship === "child") {
1270
+ return "parent";
1271
+ }
1272
+ return kinship;
1273
+ };
1274
+ var hopRelation = (from, toIndi, kinship, inherited) => {
1275
+ if (kinship === "parent" || kinship === "child") {
1276
+ const parent = kinship === "parent" ? toIndi : from.indi;
1277
+ const child = kinship === "parent" ? from.indi : toIndi;
1278
+ const currentRelation = child.getParentType(parent);
1279
+ if (currentRelation && currentRelation !== "biological" /* BIOLOGICAL */) {
1280
+ return currentRelation;
1281
+ }
1282
+ }
1283
+ if (inherited && inherited !== "biological" /* BIOLOGICAL */) {
1284
+ return inherited;
1285
+ }
1286
+ return void 0;
1287
+ };
1288
+ var rebuildPathFromHops = (hops, skipRelation = false) => {
1289
+ if (hops.length === 0) {
1290
+ return [];
1291
+ }
1292
+ const path = [
1293
+ {
1294
+ indi: hops[0].indi,
1295
+ kinship: "self",
1296
+ level: 0,
1297
+ levelUp: 0,
1298
+ levelDown: 0,
1299
+ degree: 0
1300
+ }
1301
+ ];
1302
+ for (let i = 1; i < hops.length; i++) {
1303
+ const prev = path[i - 1];
1304
+ const { indi, kinship } = hops[i];
1305
+ const relation = skipRelation ? void 0 : hopRelation(prev, indi, kinship, prev.relation);
1306
+ if (kinship === "parent") {
1307
+ path.push({
1308
+ indi,
1309
+ kinship,
1310
+ relation,
1311
+ level: prev.level + 1,
1312
+ levelUp: prev.levelUp + 1,
1313
+ levelDown: prev.levelDown,
1314
+ degree: prev.degree
1315
+ });
1316
+ continue;
1317
+ }
1318
+ if (kinship === "child") {
1319
+ path.push({
1320
+ indi,
1321
+ kinship,
1322
+ relation,
1323
+ level: prev.level - 1,
1324
+ levelUp: prev.levelUp,
1325
+ levelDown: prev.levelDown + 1,
1326
+ degree: prev.levelUp ? prev.level > 0 ? prev.levelUp - prev.level + 1 : prev.levelDown - Math.abs(prev.level) : 0
1327
+ });
1328
+ continue;
1329
+ }
1330
+ path.push({
1331
+ indi,
1332
+ kinship,
1333
+ relation,
1334
+ level: prev.level,
1335
+ levelUp: prev.levelUp,
1336
+ levelDown: prev.levelDown,
1337
+ degree: prev.degree
1338
+ });
1339
+ }
1340
+ return path;
1341
+ };
1342
+ var storePathIfBetter = (gedcom, fromId, toId, path) => {
1343
+ const key = `${fromId}|${toId}`;
1344
+ const existing = pathCache(gedcom, key);
1345
+ if (existing && (!isNonBiologicalPath(existing) || isNonBiologicalPath(path))) {
1346
+ return;
1347
+ }
1348
+ pathCache(gedcom, key, path);
1349
+ };
1350
+ var cacheDiscoveredPath = (gedcom, path) => {
1351
+ const n = path.length;
1352
+ if (n < 2) {
1353
+ return;
1354
+ }
1355
+ for (let i = 0; i < n; i++) {
1356
+ const fromId = path[i].indi.id;
1357
+ if (!fromId) {
1358
+ continue;
1359
+ }
1360
+ for (let j = i + 1; j < n; j++) {
1361
+ const toId = path[j].indi.id;
1362
+ if (!toId) {
1363
+ continue;
1364
+ }
1365
+ const isOriginalPair = i === 0 && j === n - 1;
1366
+ const isDirectHop = j === i + 1;
1367
+ const slice = path.slice(i, j + 1);
1368
+ const sliceMixed = isNonBiologicalPath(slice);
1369
+ if (!isOriginalPair && !isDirectHop && sliceMixed) {
1370
+ continue;
1371
+ }
1372
+ const forward = i === 0 ? slice : rebuildPathFromHops(slice, !sliceMixed);
1373
+ const reverseHops = [
1374
+ {
1375
+ indi: slice[slice.length - 1].indi,
1376
+ kinship: "self"
1377
+ }
1378
+ ];
1379
+ for (let k = slice.length - 2; k >= 0; k--) {
1380
+ reverseHops.push({
1381
+ indi: slice[k].indi,
1382
+ kinship: invertHop(slice[k + 1].kinship)
1383
+ });
1384
+ }
1385
+ const reverse = rebuildPathFromHops(reverseHops, !sliceMixed);
1386
+ storePathIfBetter(gedcom, fromId, toId, forward);
1387
+ storePathIfBetter(gedcom, toId, fromId, reverse);
1388
+ }
1389
+ }
1390
+ };
1261
1391
 
1262
1392
  // src/utils/get-all-prop.ts
1263
1393
  var getAllProp = (indi, prop) => {
@@ -2884,7 +3014,6 @@ var Indi = class extends Common {
2884
3014
  if (cache) {
2885
3015
  return cache;
2886
3016
  }
2887
- const visited = new Individuals().append(this);
2888
3017
  const mainItem = {
2889
3018
  indi: this,
2890
3019
  level: 0,
@@ -2893,129 +3022,155 @@ var Indi = class extends Common {
2893
3022
  degree: 0,
2894
3023
  kinship: "self"
2895
3024
  };
2896
- const path = [mainItem];
3025
+ const mainPath = [mainItem];
2897
3026
  if (this.id === usedIndi.id) {
2898
- return path;
3027
+ return mainPath;
2899
3028
  }
2900
- const queue = [
2901
- {
2902
- ...mainItem,
2903
- path
2904
- }
2905
- ];
2906
- let helper = 0;
2907
- while (queue.length > 0) {
2908
- if (helper++ > 1e6) {
2909
- break;
2910
- }
2911
- const {
2912
- indi,
2913
- path: path2,
2914
- kinship,
2915
- relation,
2916
- level,
2917
- levelUp,
2918
- levelDown,
2919
- degree,
2920
- breakOnNext,
2921
- breakAfterNext,
2922
- inLaw
2923
- } = queue.shift();
2924
- if (usedIndi.id === indi.id) {
2925
- if (breakOnNext) {
2926
- return void 0;
3029
+ const bfs = (biologicalOnly) => {
3030
+ const visited = new Individuals().append(this);
3031
+ const queue = [
3032
+ {
3033
+ ...mainItem,
3034
+ path: mainPath
2927
3035
  }
2928
- pathCache(this._gedcom, cacheKey, path2);
2929
- return path2;
2930
- }
2931
- visited.append(indi);
2932
- const additional = {};
2933
- if (breakOnNext || breakAfterNext) {
2934
- additional.breakOnNext = breakOnNext || breakAfterNext;
2935
- }
2936
- if (inLaw) {
2937
- additional.inLaw = inLaw;
2938
- }
2939
- if (kinship === "spouse" && breakAfterSpouse) {
2940
- if (path2.length <= 2) {
2941
- additional.inLaw = true;
2942
- } else {
2943
- additional.breakOnNext = true;
3036
+ ];
3037
+ let helper = 0;
3038
+ while (queue.length > 0) {
3039
+ if (helper++ > 1e6) {
3040
+ break;
2944
3041
  }
2945
- }
2946
- if (kinship !== "child" || !breakAfterSpouse) {
2947
- indi.getBiologicalFathers().copy().merge(indi.getBiologicalMothers()).merge(indi.getFathers().copy().merge(indi.getMothers())).forEach((relative) => {
3042
+ const {
3043
+ indi,
3044
+ path,
3045
+ kinship,
3046
+ relation,
3047
+ level,
3048
+ levelUp,
3049
+ levelDown,
3050
+ degree,
3051
+ breakOnNext,
3052
+ breakAfterNext,
3053
+ inLaw
3054
+ } = queue.shift();
3055
+ if (usedIndi.id === indi.id) {
3056
+ if (breakOnNext) {
3057
+ return void 0;
3058
+ }
3059
+ return path;
3060
+ }
3061
+ visited.append(indi);
3062
+ const additional = {};
3063
+ if (breakOnNext || breakAfterNext) {
3064
+ additional.breakOnNext = breakOnNext || breakAfterNext;
3065
+ }
3066
+ if (inLaw) {
3067
+ additional.inLaw = inLaw;
3068
+ }
3069
+ if (!biologicalOnly && kinship === "spouse" && breakAfterSpouse) {
3070
+ if (path.length <= 2) {
3071
+ additional.inLaw = true;
3072
+ } else {
3073
+ additional.breakOnNext = true;
3074
+ }
3075
+ }
3076
+ if (kinship !== "child" || !breakAfterSpouse) {
3077
+ indi.getBiologicalFathers().copy().merge(indi.getBiologicalMothers()).merge(indi.getFathers().copy().merge(indi.getMothers())).forEach((relative) => {
3078
+ if (!visited.has(relative)) {
3079
+ const currentRelation = indi.getParentType(relative);
3080
+ const isNonBiological = !!currentRelation && currentRelation !== "biological" /* BIOLOGICAL */;
3081
+ if (biologicalOnly && isNonBiological) {
3082
+ return;
3083
+ }
3084
+ if (!biologicalOnly && breakAfterNonBiological && isNonBiological) {
3085
+ additional.breakAfterNext = true;
3086
+ }
3087
+ const newItem = {
3088
+ indi: relative,
3089
+ kinship: "parent",
3090
+ relation: isNonBiological ? currentRelation : relation,
3091
+ level: level + 1,
3092
+ levelUp: levelUp + 1,
3093
+ levelDown,
3094
+ degree,
3095
+ ...additional
3096
+ };
3097
+ queue.push({
3098
+ ...newItem,
3099
+ path: [...path, newItem]
3100
+ });
3101
+ }
3102
+ });
3103
+ }
3104
+ indi.getChildren().forEach((relative) => {
2948
3105
  if (!visited.has(relative)) {
2949
- const currentRelation = indi.getParentType(relative);
2950
- if (breakAfterNonBiological && currentRelation !== "biological" /* BIOLOGICAL */) {
3106
+ const currentRelation = relative.getParentType(indi);
3107
+ const isNonBiological = !!currentRelation && currentRelation !== "biological" /* BIOLOGICAL */;
3108
+ if (biologicalOnly && isNonBiological) {
3109
+ return;
3110
+ }
3111
+ if (!biologicalOnly && breakAfterNonBiological && isNonBiological) {
2951
3112
  additional.breakAfterNext = true;
2952
3113
  }
2953
3114
  const newItem = {
2954
3115
  indi: relative,
2955
- kinship: "parent",
2956
- relation: currentRelation && currentRelation !== "biological" /* BIOLOGICAL */ ? currentRelation : relation,
2957
- level: level + 1,
2958
- levelUp: levelUp + 1,
2959
- levelDown,
2960
- degree,
3116
+ kinship: "child",
3117
+ relation: isNonBiological ? currentRelation : relation,
3118
+ level: level - 1,
3119
+ levelUp,
3120
+ levelDown: levelDown + 1,
3121
+ degree: levelUp ? level > 0 ? levelUp - level + 1 : levelDown - Math.abs(level) : 0,
2961
3122
  ...additional
2962
3123
  };
2963
3124
  queue.push({
2964
3125
  ...newItem,
2965
- path: [...path2, newItem]
3126
+ path: [...path, newItem]
2966
3127
  });
2967
3128
  }
2968
3129
  });
2969
- }
2970
- indi.getChildren().forEach((relative) => {
2971
- if (!visited.has(relative)) {
2972
- const currentRelation = relative.getParentType(indi);
2973
- if (breakAfterNonBiological && currentRelation !== "biological" /* BIOLOGICAL */) {
2974
- additional.breakAfterNext = true;
2975
- }
2976
- const newItem = {
2977
- indi: relative,
2978
- kinship: "child",
2979
- relation: currentRelation && currentRelation !== "biological" /* BIOLOGICAL */ ? currentRelation : relation,
2980
- level: level - 1,
2981
- levelUp,
2982
- levelDown: levelDown + 1,
2983
- degree: levelUp ? level > 0 ? levelUp - level + 1 : levelDown - Math.abs(level) : 0,
2984
- ...additional
2985
- };
2986
- queue.push({
2987
- ...newItem,
2988
- path: [...path2, newItem]
2989
- });
3130
+ if (biologicalOnly) {
3131
+ continue;
2990
3132
  }
2991
- });
2992
- indi.getCoParents().forEach((relative) => {
2993
- if (!visited.has(relative)) {
2994
- const currentAddition = {};
2995
- if (relation && relation !== "biological" /* BIOLOGICAL */) {
2996
- currentAddition.relation = relation;
2997
- }
2998
- if (inLaw) {
2999
- currentAddition.breakOnNext = true;
3133
+ indi.getCoParents().forEach((relative) => {
3134
+ if (!visited.has(relative)) {
3135
+ const currentAddition = {};
3136
+ if (relation && relation !== "biological" /* BIOLOGICAL */) {
3137
+ currentAddition.relation = relation;
3138
+ }
3139
+ if (inLaw) {
3140
+ currentAddition.breakOnNext = true;
3141
+ }
3142
+ const newItem = {
3143
+ indi: relative,
3144
+ kinship: "spouse",
3145
+ level,
3146
+ levelUp,
3147
+ levelDown,
3148
+ degree,
3149
+ ...additional,
3150
+ ...currentAddition
3151
+ };
3152
+ queue.push({
3153
+ ...newItem,
3154
+ path: [...path, newItem]
3155
+ });
3000
3156
  }
3001
- const newItem = {
3002
- indi: relative,
3003
- kinship: "spouse",
3004
- level,
3005
- levelUp,
3006
- levelDown,
3007
- degree,
3008
- ...additional,
3009
- ...currentAddition
3010
- };
3011
- queue.push({
3012
- ...newItem,
3013
- path: [...path2, newItem]
3014
- });
3015
- }
3016
- });
3157
+ });
3158
+ }
3159
+ return void 0;
3160
+ };
3161
+ const foundPath = bfs(false);
3162
+ const lastItem = foundPath?.[foundPath.length - 1];
3163
+ if (lastItem?.relation && lastItem.relation !== "biological" /* BIOLOGICAL */) {
3164
+ const biologicalPath = bfs(true);
3165
+ if (biologicalPath) {
3166
+ cacheDiscoveredPath(this._gedcom, biologicalPath);
3167
+ return biologicalPath;
3168
+ }
3017
3169
  }
3018
- return void 0;
3170
+ if (foundPath) {
3171
+ cacheDiscoveredPath(this._gedcom, foundPath);
3172
+ }
3173
+ return foundPath;
3019
3174
  }
3020
3175
  kinship(other, showMainPerson, lang = "en", entirePath, displayName = "givenname") {
3021
3176
  const KinshipTranslatorClass2 = getKinshipTranslatorClass();
@@ -3987,6 +4142,44 @@ var KinshipTranslatorBasic = class {
3987
4142
  }
3988
4143
  return this.pathN?.indi;
3989
4144
  }
4145
+ /**
4146
+ * True when the path goes through a common ancestor whose two children
4147
+ * (the person we came from and the person we go to) share fewer than two
4148
+ * biological parents — i.e. they are half-siblings, so every collateral
4149
+ * relative on this path is a half-aunt/half-cousin/... too.
4150
+ *
4151
+ * Direct ancestors/descendants and paths that already use a
4152
+ * step/adopted/foster edge are never half-blood.
4153
+ */
4154
+ get isHalfBlood() {
4155
+ const path = this.path;
4156
+ if (!path || path.length < 3) {
4157
+ return false;
4158
+ }
4159
+ if (path.some(
4160
+ (item) => item.relation && item.relation !== "biological" /* BIOLOGICAL */
4161
+ )) {
4162
+ return false;
4163
+ }
4164
+ let peakIndex = -1;
4165
+ for (let i = 1; i < path.length; i++) {
4166
+ if (path[i].kinship === "parent") {
4167
+ peakIndex = i;
4168
+ }
4169
+ }
4170
+ if (peakIndex <= 0 || peakIndex >= path.length - 1) {
4171
+ return false;
4172
+ }
4173
+ if (path[peakIndex + 1].kinship !== "child") {
4174
+ return false;
4175
+ }
4176
+ const siblingA = path[peakIndex - 1].indi;
4177
+ const siblingB = path[peakIndex + 1].indi;
4178
+ const parentsA = siblingA.getBiologicalParents();
4179
+ const parentsB = siblingB.getBiologicalParents();
4180
+ const inter = parentsA.intersection(parentsB);
4181
+ return inter.length === 1 && (parentsA.length > 1 || parentsB.length > 1);
4182
+ }
3990
4183
  indirect() {
3991
4184
  return "";
3992
4185
  }
@@ -4014,6 +4207,9 @@ var KinshipTranslatorBasic = class {
4014
4207
  relationType(relation) {
4015
4208
  return relation ?? "";
4016
4209
  }
4210
+ halfBlood(relation) {
4211
+ return relation ?? "";
4212
+ }
4017
4213
  of(relation) {
4018
4214
  return relation ?? "";
4019
4215
  }
@@ -4252,14 +4448,34 @@ var KinshipTranslatorHU = class extends KinshipTranslatorBasic {
4252
4448
  return `${prefix.replace(/nagy$/, "")}unoka`;
4253
4449
  }
4254
4450
  sibling() {
4255
- const parents1 = this.person1?.getBiologicalParents();
4256
- const parentsN = this.personN?.getBiologicalParents();
4257
- const inter = parents1?.intersection(parentsN);
4258
- if (!inter || inter.length < 2) {
4259
- return "f\xE9ltestv\xE9r";
4260
- }
4261
4451
  return "testv\xE9r";
4262
4452
  }
4453
+ halfBlood(relation) {
4454
+ if (!relation || !this.isHalfBlood) {
4455
+ return relation ?? "";
4456
+ }
4457
+ const [head, ...rest] = relation.split(" ");
4458
+ if (!head) {
4459
+ return relation;
4460
+ }
4461
+ const prefixed = this.prefixHalf(head);
4462
+ return [prefixed, ...rest].join(" ");
4463
+ }
4464
+ /**
4465
+ * AkH. 139: compounds of more than two members stay closed up to 6
4466
+ * syllables; longer ones are hyphenated at the main boundary. A head
4467
+ * that is already hyphenated also takes a hyphenated half- prefix.
4468
+ */
4469
+ prefixHalf(head) {
4470
+ if (head.includes("-") || !/[aáeéiíoóöőuúüű]/i.test(head)) {
4471
+ return `f\xE9l-${head}`;
4472
+ }
4473
+ const syllables = (head.match(/[aáeéiíoóöőuúüű]/gi) ?? []).length + 1;
4474
+ if (syllables > 6) {
4475
+ return `f\xE9l-${head}`;
4476
+ }
4477
+ return `f\xE9l${head}`;
4478
+ }
4263
4479
  spouse() {
4264
4480
  if (this.personN?.isMale()) {
4265
4481
  return "f\xE9rj";
@@ -4458,20 +4674,22 @@ var KinshipTranslatorEn = class extends KinshipTranslatorBasic {
4458
4674
  return `${prefix}child`;
4459
4675
  }
4460
4676
  sibling() {
4461
- const parents1 = this.person1?.getBiologicalParents();
4462
- const parentsN = this.personN?.getBiologicalParents();
4463
- const inter = parents1?.intersection(parentsN);
4464
- let prefix = "";
4465
- if (!inter || inter.length < 2) {
4466
- prefix = "half-";
4467
- }
4468
4677
  if (this.personN?.isMale()) {
4469
- return `${prefix}brother`;
4678
+ return "brother";
4470
4679
  }
4471
4680
  if (this.personN?.isFemale()) {
4472
- return `${prefix}sister`;
4681
+ return "sister";
4682
+ }
4683
+ return "sibling";
4684
+ }
4685
+ halfBlood(relation) {
4686
+ if (!relation || !this.isHalfBlood) {
4687
+ return relation ?? "";
4688
+ }
4689
+ if (relation.includes(" ")) {
4690
+ return `half ${relation}`;
4473
4691
  }
4474
- return `${prefix}sibling`;
4692
+ return `half-${relation}`;
4475
4693
  }
4476
4694
  spouse() {
4477
4695
  if (this.personN?.isMale()) {
@@ -4653,20 +4871,22 @@ var KinshipTranslatorDe = class extends KinshipTranslatorBasic {
4653
4871
  return `${prefix}kind`;
4654
4872
  }
4655
4873
  sibling() {
4656
- const parents1 = this.person1?.getBiologicalParents();
4657
- const parentsN = this.personN?.getBiologicalParents();
4658
- const inter = parents1?.intersection(parentsN);
4659
- let prefix = "";
4660
- if (!inter || inter.length < 2) {
4661
- prefix = "Halb";
4662
- }
4663
4874
  if (this.personN?.isMale()) {
4664
- return `${prefix}bruder`;
4875
+ return "bruder";
4665
4876
  }
4666
4877
  if (this.personN?.isFemale()) {
4667
- return `${prefix}schwester`;
4878
+ return "schwester";
4879
+ }
4880
+ return "geschwister";
4881
+ }
4882
+ halfBlood(relation) {
4883
+ if (!relation || !this.isHalfBlood) {
4884
+ return relation ?? "";
4885
+ }
4886
+ if (/^[A-ZÄÖÜ]/.test(relation) || /[-\s]/.test(relation)) {
4887
+ return `Halb-${relation}`;
4668
4888
  }
4669
- return `${prefix}geschwister`;
4889
+ return `Halb${relation}`;
4670
4890
  }
4671
4891
  spouse() {
4672
4892
  if (this.personN?.isMale()) {
@@ -4848,20 +5068,19 @@ var KinshipTranslatorFr = class extends KinshipTranslatorBasic {
4848
5068
  return `${prefix}enfant`;
4849
5069
  }
4850
5070
  sibling() {
4851
- const parents1 = this.person1?.getBiologicalParents();
4852
- const parentsN = this.personN?.getBiologicalParents();
4853
- const inter = parents1?.intersection(parentsN);
4854
- let prefix = "";
4855
- if (!inter || inter.length < 2) {
4856
- prefix = "demi-";
4857
- }
4858
5071
  if (this.personN?.isMale()) {
4859
- return `${prefix}fr\xE8re`;
5072
+ return "fr\xE8re";
4860
5073
  }
4861
5074
  if (this.personN?.isFemale()) {
4862
- return `${prefix}s\u0153ur`;
5075
+ return "s\u0153ur";
5076
+ }
5077
+ return "fr\xE8re/s\u0153ur";
5078
+ }
5079
+ halfBlood(relation) {
5080
+ if (!relation || !this.isHalfBlood) {
5081
+ return relation ?? "";
4863
5082
  }
4864
- return `${prefix}fr\xE8re/s\u0153ur`;
5083
+ return `demi-${relation}`;
4865
5084
  }
4866
5085
  spouse() {
4867
5086
  if (this.personN?.isMale()) {
@@ -4958,12 +5177,12 @@ var InLawsEs = {
4958
5177
  "madre del (c\xF3nyuge|esposa|esposo)": "suegra",
4959
5178
  "padre del (c\xF3nyuge|esposa|esposo)": "suegro",
4960
5179
  "padre/madre del (c\xF3nyuge|esposa|esposo)": "suegro/suegra",
4961
- "esposa de (medio )?(hermano/hermana|hermana|hermano)": "cu\xF1ada",
4962
- "esposo de (medio )?(hermano/hermana|hermana|hermano)": "cu\xF1ado",
4963
- "c\xF3nyuge de (medio )?(hermano/hermana|hermana|hermano)": "cu\xF1ado/cu\xF1ada",
4964
- "(medio )?hermana del (c\xF3nyuge|esposa|esposo)": "cu\xF1ada",
4965
- "(medio )?hermano del (c\xF3nyuge|esposa|esposo)": "cu\xF1ado",
4966
- "(medio )?hermano/hermana del (c\xF3nyuge|esposa|esposo)": "cu\xF1ado/cu\xF1ada"
5180
+ "esposa de (medio |media |medio/a )?(hermano/hermana|hermana|hermano)": "cu\xF1ada",
5181
+ "esposo de (medio |media |medio/a )?(hermano/hermana|hermana|hermano)": "cu\xF1ado",
5182
+ "c\xF3nyuge de (medio |media |medio/a )?(hermano/hermana|hermana|hermano)": "cu\xF1ado/cu\xF1ada",
5183
+ "(medio |media |medio/a )?hermana del (c\xF3nyuge|esposa|esposo)": "cu\xF1ada",
5184
+ "(medio |media |medio/a )?hermano del (c\xF3nyuge|esposa|esposo)": "cu\xF1ado",
5185
+ "(medio |media |medio/a )?hermano/hermana del (c\xF3nyuge|esposa|esposo)": "cu\xF1ado/cu\xF1ada"
4967
5186
  };
4968
5187
 
4969
5188
  // src/kinship-translator/kinship-translator.es.ts
@@ -5043,20 +5262,25 @@ var KinshipTranslatorEs = class extends KinshipTranslatorBasic {
5043
5262
  return `${prefix}hijo/hija`;
5044
5263
  }
5045
5264
  sibling() {
5046
- const parents1 = this.person1?.getBiologicalParents();
5047
- const parentsN = this.personN?.getBiologicalParents();
5048
- const inter = parents1?.intersection(parentsN);
5049
- let prefix = "";
5050
- if (!inter || inter.length < 2) {
5051
- prefix = "medio ";
5052
- }
5053
5265
  if (this.personN?.isMale()) {
5054
- return `${prefix}hermano`;
5266
+ return "hermano";
5267
+ }
5268
+ if (this.personN?.isFemale()) {
5269
+ return "hermana";
5270
+ }
5271
+ return "hermano/hermana";
5272
+ }
5273
+ halfBlood(relation) {
5274
+ if (!relation || !this.isHalfBlood) {
5275
+ return relation ?? "";
5055
5276
  }
5056
5277
  if (this.personN?.isFemale()) {
5057
- return `${prefix}hermana`;
5278
+ return `media ${relation}`;
5279
+ }
5280
+ if (this.personN?.isMale()) {
5281
+ return `medio ${relation}`;
5058
5282
  }
5059
- return `${prefix}hermano/hermana`;
5283
+ return `medio/a ${relation}`;
5060
5284
  }
5061
5285
  spouse() {
5062
5286
  if (this.personN?.isMale()) {
@@ -5145,6 +5369,249 @@ var KinshipTranslatorEs = class extends KinshipTranslatorBasic {
5145
5369
  }
5146
5370
  };
5147
5371
 
5372
+ // src/kinship-translator/patterns.ru.ts
5373
+ var InLawsRu = {
5374
+ "\u0441\u0443\u043F\u0440\u0443\u0433(?:\u0430)? (\u0440\u0435\u0431\u0451\u043D\u043A\u0430|\u0434\u043E\u0447\u0435\u0440\u0438|\u0441\u044B\u043D\u0430)": "\u0437\u044F\u0442\u044C/\u043D\u0435\u0432\u0435\u0441\u0442\u043A\u0430",
5375
+ "\u0436\u0435\u043D\u0430 (\u0440\u0435\u0431\u0451\u043D\u043A\u0430|\u0434\u043E\u0447\u0435\u0440\u0438|\u0441\u044B\u043D\u0430)": "\u043D\u0435\u0432\u0435\u0441\u0442\u043A\u0430",
5376
+ "\u043C\u0443\u0436 (\u0440\u0435\u0431\u0451\u043D\u043A\u0430|\u0434\u043E\u0447\u0435\u0440\u0438|\u0441\u044B\u043D\u0430)": "\u0437\u044F\u0442\u044C",
5377
+ "\u043C\u0430\u0442\u044C (\u0441\u0443\u043F\u0440\u0443\u0433\u0430|\u0436\u0435\u043D\u044B|\u043C\u0443\u0436\u0430)": "\u0442\u0451\u0449\u0430",
5378
+ "\u043E\u0442\u0435\u0446 (\u0441\u0443\u043F\u0440\u0443\u0433\u0430|\u0436\u0435\u043D\u044B|\u043C\u0443\u0436\u0430)": "\u0442\u0435\u0441\u0442\u044C",
5379
+ "\u0440\u043E\u0434\u0438\u0442\u0435\u043B\u044C (\u0441\u0443\u043F\u0440\u0443\u0433\u0430|\u0436\u0435\u043D\u044B|\u043C\u0443\u0436\u0430)": "\u0442\u0435\u0441\u0442\u044C/\u0442\u0451\u0449\u0430",
5380
+ "\u0436\u0435\u043D\u0430 (\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?(\u0431\u0440\u0430\u0442\u0430|\u0441\u0435\u0441\u0442\u0440\u044B|\u0441\u0438\u0431\u043B\u0438\u043D\u0433\u0430)": "\u043D\u0435\u0432\u0435\u0441\u0442\u043A\u0430",
5381
+ "\u043C\u0443\u0436 (\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?(\u0431\u0440\u0430\u0442\u0430|\u0441\u0435\u0441\u0442\u0440\u044B|\u0441\u0438\u0431\u043B\u0438\u043D\u0433\u0430)": "\u0437\u044F\u0442\u044C",
5382
+ "\u0441\u0443\u043F\u0440\u0443\u0433(?:\u0430)? (\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?(\u0431\u0440\u0430\u0442\u0430|\u0441\u0435\u0441\u0442\u0440\u044B|\u0441\u0438\u0431\u043B\u0438\u043D\u0433\u0430)": "\u0437\u044F\u0442\u044C/\u043D\u0435\u0432\u0435\u0441\u0442\u043A\u0430",
5383
+ "(\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?\u0441\u0435\u0441\u0442\u0440\u0430 (\u0441\u0443\u043F\u0440\u0443\u0433\u0430|\u0436\u0435\u043D\u044B|\u043C\u0443\u0436\u0430)": "\u0437\u043E\u043B\u043E\u0432\u043A\u0430",
5384
+ "(\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?\u0431\u0440\u0430\u0442 (\u0441\u0443\u043F\u0440\u0443\u0433\u0430|\u0436\u0435\u043D\u044B|\u043C\u0443\u0436\u0430)": "\u0448\u0443\u0440\u0438\u043D",
5385
+ "(\u0441\u0432\u043E\u0434\u043D(?:\u044B\u0439|\u0430\u044F) )?\u0441\u0438\u0431\u043B\u0438\u043D\u0433 (\u0441\u0443\u043F\u0440\u0443\u0433\u0430|\u0436\u0435\u043D\u044B|\u043C\u0443\u0436\u0430)": "\u0448\u0443\u0440\u0438\u043D/\u0437\u043E\u043B\u043E\u0432\u043A\u0430"
5386
+ };
5387
+
5388
+ // src/kinship-translator/kinship-translator.ru.ts
5389
+ var GENITIVE = {
5390
+ \u0441\u044B\u043D: "\u0441\u044B\u043D\u0430",
5391
+ \u0434\u043E\u0447\u044C: "\u0434\u043E\u0447\u0435\u0440\u0438",
5392
+ \u0440\u0435\u0431\u0451\u043D\u043E\u043A: "\u0440\u0435\u0431\u0451\u043D\u043A\u0430",
5393
+ \u0431\u0440\u0430\u0442: "\u0431\u0440\u0430\u0442\u0430",
5394
+ \u0441\u0435\u0441\u0442\u0440\u0430: "\u0441\u0435\u0441\u0442\u0440\u044B",
5395
+ \u0441\u0438\u0431\u043B\u0438\u043D\u0433: "\u0441\u0438\u0431\u043B\u0438\u043D\u0433\u0430",
5396
+ \u043E\u0442\u0435\u0446: "\u043E\u0442\u0446\u0430",
5397
+ \u043C\u0430\u0442\u044C: "\u043C\u0430\u0442\u0435\u0440\u0438",
5398
+ \u0440\u043E\u0434\u0438\u0442\u0435\u043B\u044C: "\u0440\u043E\u0434\u0438\u0442\u0435\u043B\u044F",
5399
+ \u043C\u0443\u0436: "\u043C\u0443\u0436\u0430",
5400
+ \u0436\u0435\u043D\u0430: "\u0436\u0435\u043D\u044B",
5401
+ \u0441\u0443\u043F\u0440\u0443\u0433: "\u0441\u0443\u043F\u0440\u0443\u0433\u0430",
5402
+ \u0441\u0443\u043F\u0440\u0443\u0433\u0430: "\u0441\u0443\u043F\u0440\u0443\u0433\u0438"
5403
+ };
5404
+ var toGenitive = (word) => GENITIVE[word] ?? word;
5405
+ var cousinWord = (degree, sex) => {
5406
+ const stem = degree <= 1 ? "\u0434\u0432\u043E\u044E\u0440\u043E\u0434\u043D" : degree === 2 ? "\u0442\u0440\u043E\u044E\u0440\u043E\u0434\u043D" : degree === 3 ? "\u0447\u0435\u0442\u0432\u0435\u0440\u043E\u044E\u0440\u043E\u0434\u043D" : `${degree + 1}-\u044E\u0440\u043E\u0434\u043D`;
5407
+ if (sex === "m") {
5408
+ return `${stem}\u044B\u0439 \u0431\u0440\u0430\u0442`;
5409
+ }
5410
+ if (sex === "f") {
5411
+ return `${stem}\u0430\u044F \u0441\u0435\u0441\u0442\u0440\u0430`;
5412
+ }
5413
+ return `${stem}\u044B\u0439 \u0431\u0440\u0430\u0442/\u0441\u0435\u0441\u0442\u0440\u0430`;
5414
+ };
5415
+ var praRepeat = (count) => count > 0 ? "\u043F\u0440\u0430".repeat(count) : "";
5416
+ var sexOf = (person) => {
5417
+ if (person?.isMale?.()) {
5418
+ return "m";
5419
+ }
5420
+ if (person?.isFemale?.()) {
5421
+ return "f";
5422
+ }
5423
+ return "n";
5424
+ };
5425
+ var KinshipTranslatorRu = class extends KinshipTranslatorBasic {
5426
+ indirect() {
5427
+ let degree = Math.abs(this.pathN?.degree ?? 0);
5428
+ if (degree > 0) {
5429
+ degree = degree - 1;
5430
+ }
5431
+ return cousinWord(degree, sexOf(this.personN));
5432
+ }
5433
+ removal() {
5434
+ const level = this.pathN?.level ?? 0;
5435
+ let degree = Math.abs(this.pathN?.degree ?? 0);
5436
+ if (degree > 0) {
5437
+ degree = degree - 1;
5438
+ }
5439
+ if (!degree) {
5440
+ return level < 0 ? this.nibling() : this.auncle();
5441
+ }
5442
+ const removed = Math.abs(level);
5443
+ return `${cousinWord(degree, sexOf(this.personN))} (${removed}\xD7 \u0447\u0435\u0440\u0435\u0437 \u043F\u043E\u043A\u043E\u043B\u0435\u043D\u0438\u0435)`;
5444
+ }
5445
+ auncle() {
5446
+ const level = Math.abs(this.pathN?.level ?? 0);
5447
+ const pra = praRepeat(Math.max(0, level - 2));
5448
+ const sex = sexOf(this.personN);
5449
+ if (sex === "m") {
5450
+ return `${pra}\u0434\u044F\u0434\u044F`;
5451
+ }
5452
+ if (sex === "f") {
5453
+ return `${pra}\u0442\u0451\u0442\u044F`;
5454
+ }
5455
+ return `${pra}\u0434\u044F\u0434\u044F/\u0442\u0451\u0442\u044F`;
5456
+ }
5457
+ nibling() {
5458
+ const level = Math.abs(this.pathN?.level ?? 0);
5459
+ const pra = praRepeat(Math.max(0, level - 2));
5460
+ const sex = sexOf(this.personN);
5461
+ if (sex === "m") {
5462
+ return `${pra}\u043F\u043B\u0435\u043C\u044F\u043D\u043D\u0438\u043A`;
5463
+ }
5464
+ if (sex === "f") {
5465
+ return `${pra}\u043F\u043B\u0435\u043C\u044F\u043D\u043D\u0438\u0446\u0430`;
5466
+ }
5467
+ return `${pra}\u043F\u043B\u0435\u043C\u044F\u043D\u043D\u0438\u043A/\u043F\u043B\u0435\u043C\u044F\u043D\u043D\u0438\u0446\u0430`;
5468
+ }
5469
+ parent() {
5470
+ const level = Math.abs(this.pathN?.level ?? 0);
5471
+ const sex = sexOf(this.personN);
5472
+ if (level <= 1) {
5473
+ if (sex === "m") {
5474
+ return "\u043E\u0442\u0435\u0446";
5475
+ }
5476
+ if (sex === "f") {
5477
+ return "\u043C\u0430\u0442\u044C";
5478
+ }
5479
+ return "\u0440\u043E\u0434\u0438\u0442\u0435\u043B\u044C";
5480
+ }
5481
+ if (level === 2) {
5482
+ if (sex === "m") {
5483
+ return "\u0434\u0435\u0434";
5484
+ }
5485
+ if (sex === "f") {
5486
+ return "\u0431\u0430\u0431\u0443\u0448\u043A\u0430";
5487
+ }
5488
+ return "\u0434\u0435\u0434/\u0431\u0430\u0431\u0443\u0448\u043A\u0430";
5489
+ }
5490
+ const pra = praRepeat(level - 2);
5491
+ if (sex === "m") {
5492
+ return `${pra}\u0434\u0435\u0434`;
5493
+ }
5494
+ if (sex === "f") {
5495
+ return `${pra}\u0431\u0430\u0431\u0443\u0448\u043A\u0430`;
5496
+ }
5497
+ return `${pra}\u0434\u0435\u0434/\u0431\u0430\u0431\u0443\u0448\u043A\u0430`;
5498
+ }
5499
+ child() {
5500
+ const level = Math.abs(this.pathN?.level ?? 0);
5501
+ const sex = sexOf(this.personN);
5502
+ if (level <= 1) {
5503
+ if (sex === "m") {
5504
+ return "\u0441\u044B\u043D";
5505
+ }
5506
+ if (sex === "f") {
5507
+ return "\u0434\u043E\u0447\u044C";
5508
+ }
5509
+ return "\u0440\u0435\u0431\u0451\u043D\u043E\u043A";
5510
+ }
5511
+ if (level === 2) {
5512
+ if (sex === "m") {
5513
+ return "\u0432\u043D\u0443\u043A";
5514
+ }
5515
+ if (sex === "f") {
5516
+ return "\u0432\u043D\u0443\u0447\u043A\u0430";
5517
+ }
5518
+ return "\u0432\u043D\u0443\u043A/\u0432\u043D\u0443\u0447\u043A\u0430";
5519
+ }
5520
+ const pra = praRepeat(level - 2);
5521
+ if (sex === "m") {
5522
+ return `${pra}\u0432\u043D\u0443\u043A`;
5523
+ }
5524
+ if (sex === "f") {
5525
+ return `${pra}\u0432\u043D\u0443\u0447\u043A\u0430`;
5526
+ }
5527
+ return `${pra}\u0432\u043D\u0443\u043A/\u0432\u043D\u0443\u0447\u043A\u0430`;
5528
+ }
5529
+ sibling() {
5530
+ const sex = sexOf(this.personN);
5531
+ if (sex === "m") {
5532
+ return "\u0431\u0440\u0430\u0442";
5533
+ }
5534
+ if (sex === "f") {
5535
+ return "\u0441\u0435\u0441\u0442\u0440\u0430";
5536
+ }
5537
+ return "\u0441\u0438\u0431\u043B\u0438\u043D\u0433";
5538
+ }
5539
+ halfBlood(relation) {
5540
+ if (!relation || !this.isHalfBlood) {
5541
+ return relation ?? "";
5542
+ }
5543
+ if (/сестра|дочь|мать|тётя|бабушка|жена|племянница|внучка/.test(
5544
+ relation
5545
+ )) {
5546
+ return `\u0441\u0432\u043E\u0434\u043D\u0430\u044F ${relation}`;
5547
+ }
5548
+ return `\u0441\u0432\u043E\u0434\u043D\u044B\u0439 ${relation}`;
5549
+ }
5550
+ spouse() {
5551
+ const sex = sexOf(this.personN);
5552
+ if (sex === "m") {
5553
+ return "\u043C\u0443\u0436";
5554
+ }
5555
+ if (sex === "f") {
5556
+ return "\u0436\u0435\u043D\u0430";
5557
+ }
5558
+ return "\u0441\u0443\u043F\u0440\u0443\u0433";
5559
+ }
5560
+ ofSpouse(relation) {
5561
+ if (!relation) {
5562
+ return "";
5563
+ }
5564
+ const spouse = this.path?.[1].indi;
5565
+ const sex = sexOf(spouse);
5566
+ const spouseType = sex === "m" ? "\u043C\u0443\u0436" : sex === "f" ? "\u0436\u0435\u043D\u0430" : "\u0441\u0443\u043F\u0440\u0443\u0433";
5567
+ return `${relation} ${toGenitive(spouseType)}`;
5568
+ }
5569
+ spouseOf(relation) {
5570
+ if (!relation) {
5571
+ return "";
5572
+ }
5573
+ const spouse = this.path?.[this.path.length - 1].indi;
5574
+ const sex = sexOf(spouse);
5575
+ const spouseType = sex === "m" ? "\u043C\u0443\u0436" : sex === "f" ? "\u0436\u0435\u043D\u0430" : "\u0441\u0443\u043F\u0440\u0443\u0433";
5576
+ return `${spouseType} ${toGenitive(relation)}`;
5577
+ }
5578
+ of(relation) {
5579
+ const formattedName = nameFormatter(this.path?.[0]?.indi, {
5580
+ nameOrder: "first-last"
5581
+ });
5582
+ let name = formattedName.inOrder.filter(Boolean).join(" ");
5583
+ if (this.displayName === "none") {
5584
+ name = "";
5585
+ } else if (this.displayName === "givenname") {
5586
+ name = formattedName.givenname;
5587
+ } else if (this.displayName === "surname") {
5588
+ name = `${formattedName.surname}`;
5589
+ }
5590
+ if (!name || !relation) {
5591
+ return relation ?? "";
5592
+ }
5593
+ return `${name}: ${relation}`;
5594
+ }
5595
+ inLaw(relation) {
5596
+ let inLawRelation = relation;
5597
+ Object.keys(InLawsRu).find((pattern) => {
5598
+ const regex = new RegExp(`^${pattern}$`);
5599
+ if (relation?.match(regex)) {
5600
+ inLawRelation = InLawsRu[pattern];
5601
+ return true;
5602
+ }
5603
+ return false;
5604
+ });
5605
+ return inLawRelation ?? "";
5606
+ }
5607
+ relationType(relation) {
5608
+ if (!relation || !this.pathN?.relation) {
5609
+ return relation ?? "";
5610
+ }
5611
+ return `${this.pathN.relation} ${relation}`;
5612
+ }
5613
+ };
5614
+
5148
5615
  // src/kinship-translator/kinship-translator.ts
5149
5616
  var KinshipTranslator = class {
5150
5617
  constructor(person1, person2, lang = "en", entirePath, displayName = "givenname") {
@@ -5238,6 +5705,7 @@ var KinshipTranslator = class {
5238
5705
  } else if (personN.level !== 0) {
5239
5706
  relation = this.removal();
5240
5707
  }
5708
+ relation = this.translator?.halfBlood(relation);
5241
5709
  relation = this.translator?.relationType(relation);
5242
5710
  if (this.translator?.isOfSpouse) {
5243
5711
  relation = this.translator?.ofSpouse(relation);
@@ -6288,7 +6756,7 @@ var Families = class _Families extends List {
6288
6756
 
6289
6757
  // package.json
6290
6758
  var package_default = {
6291
- version: "2.0.8"};
6759
+ version: "2.0.10"};
6292
6760
 
6293
6761
  // src/utils/get-product-details.ts
6294
6762
  var isDevelopment = () => {