-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathget.js
233 lines (218 loc) · 8.3 KB
/
get.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
/** @module get retrieve selected GEDCOM records */
/** @author Coert Vonk <MY.NAME@gmail.com> */
var value = require('./value.js');
function _id2typeName(id) {
if (id) {
const types = ["FAM", "INDI", "SOUR", "REPO", "NOTE"];
for (let type of types) {
if (type[0] == id[1]) {
return type;
}
}
}
throw "Unsupported id format (" + id + ")";
}
function _fieldValue(i18n, gedcom, obj, refs, fields) {
let ret = "";
if (obj && fields) {
const field = fields.split('.').slice(-1)[0]; // last entry separated by '.'
const [type, format] = field.split(':');
if (obj) {
switch (type) {
case 'NAME': ret += value.name(obj, format); break;
case 'SEX': ret += value.sex(i18n, obj, format); break;
case 'BIRT':
case 'BAPM':
case 'DEAT':
case 'MARR': ret += module.exports.byTemplate(i18n, gedcom, obj[0], refs, '[DATE:' + format + ']| in [PLAC]'); break;
case 'PLAC': ret += value.place(obj, format); break;
case 'DATE': ret += value.date(i18n, obj, format); break;
default: if (obj[0]) ret += obj[0].value;
}
}
if (refs && ret.length) {
ret += refs.add(i18n, gedcom, obj[0] && obj[0].SOUR);
}
}
return ret;
}
function _trimmedI18n(i18n, s) {
if (s) {
const middleStart = s.length - s.replace(/^[^\w]+/, '').length;
let middleEnd = s.replace(/[^\w]+$/, '').length;
if (middleEnd <= middleStart) middleEnd = middleStart; // in case theer are no letters
const pre = s.substring(0, middleStart);
let middle = s.substring(middleStart, middleEnd);
const post = s.substring(middleEnd, s.length);
//console.log(s + '|' + pre + '|' + middle + '|' + post + '|');
if (middle.length) {
middle = i18n.__(middle);
}
return pre + middle + post;
}
return s;
}
module.exports = {
/**
* Returns the object from parsed GEDCOM file 'e' that matches the identifier 'id'. For
* example, for id '@F1@' it will return the element of the array e.FAM where
* e.FAM[].id == id.
*
* @param {Object} e parsed GEDCOM file
* @param {String} id identifier, for example '@F1@'
* @returns {Object} the requested object, or undefined if not found
*/
byId: function (gedcom, id) {
if (gedcom && id) {
const typeName = _id2typeName(id);
for (let element of gedcom[typeName]) {
if (element.id == id) {
return element;
}
}
} else {
throw "parameter missing"
}
},
/**
* Returns the child object of 'obj' specified by 'fields'.
*
* @param {Object} e parsed GEDCOM file
* @param {Object} obj object within the parsed GEDCOM file
* @param {String} selector dot-separated field names, such as 'FAMS.WIFE.NAME'
* @returns {Object} the requested object, or undefined if not found
*/
byName: function(gedcom, obj, selector) {
if (gedcom && obj && selector) {
var fields = selector.split('.');
let field = fields.shift(); // take first el from array
field = field.split(':')[0]; // remove :format
obj = this.resolveIndirects(gedcom, obj);
if (fields.length == 0) {
obj = obj[field];
if (!(obj instanceof Array)) {
obj = [obj];
}
for (let idx in obj) {
obj[idx] = this.resolveIndirects(gedcom, obj[idx]);
}
return obj;
}
if (!obj[field]) {
//throw 'selector (' + selector + ') fails at field (' + field + ')';
return;
}
if (obj[field].length > 1) {
throw 'selector (' + selector + ') diverges at field (' + field + ')';
}
return this.byName(gedcom, obj[field], fields.join('.')); // recursive call
}
},
/**
* Returns the spouse for individual 'indi' who is the other spouse in family 'fams'
*
* @param {Object} e parsed GEDCOM file
* @param {Object} fams object containing GEDCOM FAM record
* @param {Object} indi object of the individual whose spouse we're looking for
* @returns {Object} the requested object, or undefined if not found
*/
spouse: function(i18n, gedcom, fams, indi) {
if (i18n, gedcom && fams && indi) {
const husbIds = this.byName(gedcom, fams, 'HUSB');
const wifeIds = this.byName(gedcom, fams, 'WIFE');
if (husbIds && husbIds[0] && wifeIds && wifeIds[0]) {
if (husbIds[0].id == indi.id) {
return this.byId(gedcom, wifeIds[0].id);
}
return this.byId(gedcom, husbIds[0].id);
}
}
},
byTemplate: function (i18n, gedcom, obj, refs, templatesStr, fnc) {
let ret = "";
if (obj && templatesStr) {
const templates = templatesStr.split('|');
for (let template of templates) {
let pre, fieldName, post;
[pre, fieldName, post] = template.split(/\[|\]/);
if (fieldName) {
const oo = module.exports.byName(gedcom, obj, fieldName);
if (oo && oo[0]) {
const text = _fieldValue(gedcom, oo, refs, fieldName);
if (text.length) {
ret += i18n.__(pre) + text + i18n.__(post);
}
}
} else {
ret += pre;
}
}
if (ret && fnc) {
ret = fnc(ret);
}
}
return ret;
},
sourceTitle: function(i18n, gedcom, id) {
let ret = '';
if (id) {
let s = module.exports.byId(gedcom, id);
if (s && s.TITL) {
ret += s.TITL.value;
if (s.REPO) {
let r = module.exports.byId(gedcom, s.REPO.id);
if (r && r.NAME) {
ret += ' ' + i18n.__('accessed via') + ' ' + r.NAME.value + '.';
}
}
//ret += NL;
}
}
return ret;
},
lifeSpan: function(i18n, gedcom, indi, refs) {
let ret = '';
if (gedcom && indi) {
let birth = module.exports.byTemplate(i18n, gedcom, indi, refs, '[BIRT.DATE:year]');
if (!birth.length) birth = module.exports.byTemplate(i18n, gedcom, indi, refs, '[BAPM.DATE:year]');
const death = module.exports.byTemplate(i18n, gedcom, indi, refs, '[DEAT.DATE:year]');
if (birth.length || death.length) {
ret += ' (';
if (birth.length) {
ret += birth.replace('~ ', '~').replace('< ', '<').replace('> ', '>');
}
ret += '-';
if (death.length) {
ret += death.replace('~ ', '~').replace('< ', '<').replace('> ', '>');
}
ret += ')';
}
}
return ret;
},
resolveIndirects: function(gedcom, obj) {
if (gedcom && obj) {
let lastId = undefined; // to stop self-reference loop
// can't just go by Object.keys(obj).length == 1, 'cause occational there are additional fields (such as _FREL or _MREL in CHIL)
while (obj.id != lastId) {
lastId = obj.id;
obj = module.exports.byId(gedcom, obj.id);
}
return obj;
}
},
naturalFamily: function(indi, fams) {
for (let fam of fams) {
if (fam.CHIL[0]) {
for (let child of fam.CHIL) {
if (child.id == indi.id) {
if ((!child._FREL || child._FREL.value == 'Natural') && (!child._MREL || child._MREL.value == 'Natural')) {
return fam;
}
}
}
}
}
return fams[0];
}
}