@helloao/tools 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,446 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var theographic_exports = {};
20
+ __export(theographic_exports, {
21
+ THEOGRAPHIC_DATASET: () => THEOGRAPHIC_DATASET,
22
+ generateDatasetFromTheographic: () => generateDatasetFromTheographic,
23
+ osisBookMap: () => osisBookMap,
24
+ slugify: () => slugify,
25
+ stripMarkdownLinks: () => stripMarkdownLinks
26
+ });
27
+ module.exports = __toCommonJS(theographic_exports);
28
+ var import_book_order = require("./book-order.js");
29
+ var import_log = require("../log.js");
30
+ var import_compat = require("es-toolkit/compat");
31
+ const THEOGRAPHIC_DATASET = {
32
+ id: "theographic",
33
+ name: "Theographic Bible Metadata",
34
+ englishName: "Theographic Bible Metadata",
35
+ website: "https://github.com/robertrouse/theographic-bible-metadata",
36
+ licenseUrl: "https://creativecommons.org/licenses/by-sa/4.0/",
37
+ licenseNotes: "Changes were made to the data to fit the Free Use Bible API format.",
38
+ language: "eng",
39
+ textDirection: "ltr"
40
+ };
41
+ const osisBookMap = /* @__PURE__ */ new Map([
42
+ ["Gen", "GEN"],
43
+ ["Exod", "EXO"],
44
+ ["Lev", "LEV"],
45
+ ["Num", "NUM"],
46
+ ["Deut", "DEU"],
47
+ ["Josh", "JOS"],
48
+ ["Judg", "JDG"],
49
+ ["Ruth", "RUT"],
50
+ ["1Sam", "1SA"],
51
+ ["2Sam", "2SA"],
52
+ ["1Kgs", "1KI"],
53
+ ["2Kgs", "2KI"],
54
+ ["1Chr", "1CH"],
55
+ ["2Chr", "2CH"],
56
+ ["Ezra", "EZR"],
57
+ ["Neh", "NEH"],
58
+ ["Esth", "EST"],
59
+ ["Job", "JOB"],
60
+ ["Ps", "PSA"],
61
+ ["Prov", "PRO"],
62
+ ["Eccl", "ECC"],
63
+ ["Song", "SNG"],
64
+ ["Isa", "ISA"],
65
+ ["Jer", "JER"],
66
+ ["Lam", "LAM"],
67
+ ["Ezek", "EZK"],
68
+ ["Dan", "DAN"],
69
+ ["Hos", "HOS"],
70
+ ["Joel", "JOL"],
71
+ ["Amos", "AMO"],
72
+ ["Obad", "OBA"],
73
+ ["Jonah", "JON"],
74
+ ["Mic", "MIC"],
75
+ ["Nah", "NAM"],
76
+ ["Hab", "HAB"],
77
+ ["Zeph", "ZEP"],
78
+ ["Hag", "HAG"],
79
+ ["Zech", "ZEC"],
80
+ ["Mal", "MAL"],
81
+ ["Matt", "MAT"],
82
+ ["Mark", "MRK"],
83
+ ["Luke", "LUK"],
84
+ ["John", "JHN"],
85
+ ["Acts", "ACT"],
86
+ ["Rom", "ROM"],
87
+ ["1Cor", "1CO"],
88
+ ["2Cor", "2CO"],
89
+ ["Gal", "GAL"],
90
+ ["Eph", "EPH"],
91
+ ["Phil", "PHP"],
92
+ ["Col", "COL"],
93
+ ["1Thess", "1TH"],
94
+ ["2Thess", "2TH"],
95
+ ["1Tim", "1TI"],
96
+ ["2Tim", "2TI"],
97
+ ["Titus", "TIT"],
98
+ ["Phlm", "PHM"],
99
+ ["Heb", "HEB"],
100
+ ["Jas", "JAS"],
101
+ ["1Pet", "1PE"],
102
+ ["2Pet", "2PE"],
103
+ ["1John", "1JN"],
104
+ ["2John", "2JN"],
105
+ ["3John", "3JN"],
106
+ ["Jude", "JUD"],
107
+ ["Rev", "REV"]
108
+ ]);
109
+ function slugify(str) {
110
+ return str.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
111
+ }
112
+ function stripMarkdownLinks(text) {
113
+ return text.replace(/\[([^\]]*)\]\([^)]*\)/g, "$1");
114
+ }
115
+ function generateDatasetFromTheographic(files, dataset = THEOGRAPHIC_DATASET) {
116
+ const logger = (0, import_log.getLogger)();
117
+ for (let book of files.books) {
118
+ const osisName = book.fields.osisName;
119
+ if (!osisBookMap.has(osisName)) {
120
+ logger.warn(
121
+ "[theographic] Unknown OSIS book name!",
122
+ osisName,
123
+ book.id
124
+ );
125
+ }
126
+ }
127
+ const verseMap = /* @__PURE__ */ new Map();
128
+ for (let verse of files.verses) {
129
+ const osisRef = verse.fields.osisRef;
130
+ if (!osisRef) {
131
+ continue;
132
+ }
133
+ const [osisBook, chapter, verseNumber] = osisRef.split(".");
134
+ const book = osisBookMap.get(osisBook);
135
+ if (!book) {
136
+ logger.warn("[theographic] Unknown OSIS reference!", osisRef);
137
+ continue;
138
+ }
139
+ const chapterNumber = parseInt(chapter);
140
+ const verseNum = parseInt(verseNumber);
141
+ if (isNaN(chapterNumber) || isNaN(verseNum)) {
142
+ logger.warn("[theographic] Invalid OSIS reference!", osisRef);
143
+ continue;
144
+ }
145
+ verseMap.set(verse.id, {
146
+ book,
147
+ order: import_book_order.bookOrderMap.get(book) ?? 9999,
148
+ chapter: chapterNumber,
149
+ verse: verseNum
150
+ });
151
+ }
152
+ const peopleMap = /* @__PURE__ */ new Map();
153
+ for (let person of files.people) {
154
+ const id = person.fields.slug;
155
+ if (!id) {
156
+ logger.warn(
157
+ "[theographic] Person does not have a slug!",
158
+ person.id
159
+ );
160
+ continue;
161
+ }
162
+ peopleMap.set(person.id, {
163
+ id,
164
+ type: "people",
165
+ name: person.fields.displayTitle ?? person.fields.name
166
+ });
167
+ }
168
+ const placesMap = /* @__PURE__ */ new Map();
169
+ for (let place of files.places) {
170
+ const id = place.fields.slug;
171
+ if (!id) {
172
+ logger.warn("[theographic] Place does not have a slug!", place.id);
173
+ continue;
174
+ }
175
+ placesMap.set(place.id, {
176
+ id,
177
+ type: "places",
178
+ name: place.fields.displayTitle ?? place.fields.kjvName ?? place.fields.esvName
179
+ });
180
+ }
181
+ const eventsMap = /* @__PURE__ */ new Map();
182
+ for (let event of files.events) {
183
+ const title = event.fields.title;
184
+ const eventID = event.fields.eventID;
185
+ if (!title || typeof eventID !== "number") {
186
+ logger.warn(
187
+ "[theographic] Event does not have a title or event ID!",
188
+ event.id
189
+ );
190
+ continue;
191
+ }
192
+ eventsMap.set(event.id, {
193
+ id: `${slugify(title)}_${eventID}`,
194
+ type: "events",
195
+ name: title
196
+ });
197
+ }
198
+ const groupsMap = /* @__PURE__ */ new Map();
199
+ for (let group of files.peopleGroups) {
200
+ const name = group.fields.groupName;
201
+ if (!name) {
202
+ logger.warn(
203
+ "[theographic] People group does not have a name!",
204
+ group.id
205
+ );
206
+ continue;
207
+ }
208
+ groupsMap.set(group.id, {
209
+ id: slugify(name),
210
+ type: "groups",
211
+ name
212
+ });
213
+ }
214
+ function resolveReferences(verseIds) {
215
+ if (!Array.isArray(verseIds)) {
216
+ return [];
217
+ }
218
+ const resolved = [];
219
+ const seen = /* @__PURE__ */ new Set();
220
+ for (let id of verseIds) {
221
+ const verse = verseMap.get(id);
222
+ if (!verse) {
223
+ logger.warn("[theographic] Unknown verse record ID!", id);
224
+ continue;
225
+ }
226
+ const key = `${verse.book}.${verse.chapter}.${verse.verse}`;
227
+ if (seen.has(key)) {
228
+ continue;
229
+ }
230
+ seen.add(key);
231
+ resolved.push(verse);
232
+ }
233
+ resolved.sort(
234
+ (a, b) => a.order - b.order || a.chapter - b.chapter || a.verse - b.verse
235
+ );
236
+ const references = [];
237
+ for (let verse of resolved) {
238
+ const last = references[references.length - 1];
239
+ if (last && last.book === verse.book && last.chapter === verse.chapter && (last.endVerse ?? last.verse) === verse.verse - 1) {
240
+ last.endVerse = verse.verse;
241
+ } else {
242
+ references.push({
243
+ book: verse.book,
244
+ chapter: verse.chapter,
245
+ verse: verse.verse
246
+ });
247
+ }
248
+ }
249
+ return references;
250
+ }
251
+ function resolveRefs(map, ids) {
252
+ if (!Array.isArray(ids)) {
253
+ return void 0;
254
+ }
255
+ const refs = [];
256
+ const seen = /* @__PURE__ */ new Set();
257
+ for (let id of ids) {
258
+ const ref = map.get(id);
259
+ if (!ref) {
260
+ logger.warn("[theographic] Unknown entity record ID!", id);
261
+ continue;
262
+ }
263
+ if (seen.has(ref.id)) {
264
+ continue;
265
+ }
266
+ seen.add(ref.id);
267
+ refs.push({ ...ref });
268
+ }
269
+ return refs.length > 0 ? refs : void 0;
270
+ }
271
+ function resolveRef(map, ids) {
272
+ const refs = resolveRefs(map, ids);
273
+ return refs?.[0];
274
+ }
275
+ function parseYear(year) {
276
+ if (typeof year === "number") {
277
+ return year;
278
+ }
279
+ if (typeof year === "string") {
280
+ const num = parseInt(year);
281
+ if (!isNaN(num)) {
282
+ return num;
283
+ }
284
+ }
285
+ return void 0;
286
+ }
287
+ function parseCoordinate(value) {
288
+ if (typeof value === "number") {
289
+ return value;
290
+ }
291
+ if (typeof value === "string") {
292
+ const num = parseFloat(value);
293
+ if (!isNaN(num)) {
294
+ return num;
295
+ }
296
+ }
297
+ return void 0;
298
+ }
299
+ function parseNames(names) {
300
+ if (typeof names !== "string") {
301
+ return void 0;
302
+ }
303
+ const list = names.split(",").map((n) => n.trim()).filter((n) => n.length > 0);
304
+ return list.length > 0 ? list : void 0;
305
+ }
306
+ function parseDescription(dictText) {
307
+ if (!Array.isArray(dictText)) {
308
+ return void 0;
309
+ }
310
+ const paragraphs = dictText.filter((t) => typeof t === "string").map((t) => stripMarkdownLinks(t).trim()).filter((t) => t.length > 0);
311
+ return paragraphs.length > 0 ? paragraphs : void 0;
312
+ }
313
+ const people = [];
314
+ for (let record of files.people) {
315
+ const ref = peopleMap.get(record.id);
316
+ if (!ref) {
317
+ continue;
318
+ }
319
+ const fields = record.fields;
320
+ const person = {
321
+ id: ref.id,
322
+ name: ref.name,
323
+ alsoCalled: parseNames(fields.alsoCalled),
324
+ isProperName: typeof fields.isProperName === "boolean" ? fields.isProperName : void 0,
325
+ gender: fields.gender ?? void 0,
326
+ description: parseDescription(fields.dictText),
327
+ birthYear: parseYear(fields.birthYear),
328
+ deathYear: parseYear(fields.deathYear),
329
+ minYear: parseYear(fields.minYear),
330
+ maxYear: parseYear(fields.maxYear),
331
+ birthPlace: resolveRef(placesMap, fields.birthPlace),
332
+ deathPlace: resolveRef(placesMap, fields.deathPlace),
333
+ father: resolveRefs(peopleMap, fields.father),
334
+ mother: resolveRefs(peopleMap, fields.mother),
335
+ partners: resolveRefs(peopleMap, fields.partners),
336
+ children: resolveRefs(peopleMap, fields.children),
337
+ siblings: resolveRefs(peopleMap, fields.siblings),
338
+ halfSiblingsSameMother: resolveRefs(
339
+ peopleMap,
340
+ fields.halfSiblingsSameMother
341
+ ),
342
+ halfSiblingsSameFather: resolveRefs(
343
+ peopleMap,
344
+ fields.halfSiblingsSameFather
345
+ ),
346
+ memberOf: resolveRefs(groupsMap, fields.memberOf),
347
+ events: resolveRefs(eventsMap, fields.timeline),
348
+ references: resolveReferences(fields.verses)
349
+ };
350
+ people.push(omitUndefined(person));
351
+ }
352
+ const places = [];
353
+ for (let record of files.places) {
354
+ const ref = placesMap.get(record.id);
355
+ if (!ref) {
356
+ continue;
357
+ }
358
+ const fields = record.fields;
359
+ const place = {
360
+ id: ref.id,
361
+ name: ref.name,
362
+ kjvName: fields.kjvName ?? void 0,
363
+ esvName: fields.esvName ?? void 0,
364
+ aliases: parseNames(fields.aliases),
365
+ featureType: fields.featureType ?? void 0,
366
+ featureSubType: fields.featureSubType ?? void 0,
367
+ latitude: parseCoordinate(fields.latitude),
368
+ longitude: parseCoordinate(fields.longitude),
369
+ precision: fields.precision ?? void 0,
370
+ description: parseDescription(fields.dictText),
371
+ comment: fields.comment ?? void 0,
372
+ rootPlace: resolveRef(placesMap, fields.rootID),
373
+ duplicateOf: resolveRef(placesMap, fields.duplicate_of),
374
+ people: resolveRefs(peopleMap, fields.hasBeenHere),
375
+ peopleBorn: resolveRefs(peopleMap, fields.peopleBorn),
376
+ peopleDied: resolveRefs(peopleMap, fields.peopleDied),
377
+ events: resolveRefs(eventsMap, fields.eventsHere),
378
+ references: resolveReferences(fields.verses)
379
+ };
380
+ places.push(omitUndefined(place));
381
+ }
382
+ const events = [];
383
+ for (let record of files.events) {
384
+ const ref = eventsMap.get(record.id);
385
+ if (!ref) {
386
+ continue;
387
+ }
388
+ const fields = record.fields;
389
+ const event = {
390
+ id: ref.id,
391
+ name: ref.name,
392
+ startDate: fields.startDate ?? void 0,
393
+ duration: fields.duration ?? void 0,
394
+ participants: resolveRefs(peopleMap, fields.participants),
395
+ locations: resolveRefs(placesMap, fields.locations),
396
+ groups: resolveRefs(groupsMap, fields.groups),
397
+ partOf: resolveRef(eventsMap, fields.partOf),
398
+ predecessor: resolveRef(eventsMap, fields.predecessor),
399
+ references: resolveReferences(fields.verses)
400
+ };
401
+ events.push(omitUndefined(event));
402
+ }
403
+ const peopleGroups = [];
404
+ for (let record of files.peopleGroups) {
405
+ const ref = groupsMap.get(record.id);
406
+ if (!ref) {
407
+ continue;
408
+ }
409
+ const fields = record.fields;
410
+ const group = {
411
+ id: ref.id,
412
+ name: ref.name,
413
+ members: resolveRefs(peopleMap, fields.members),
414
+ events: resolveRefs(eventsMap, fields.events_dev),
415
+ references: resolveReferences(fields.verses)
416
+ };
417
+ peopleGroups.push(omitUndefined(group));
418
+ }
419
+ return {
420
+ ...dataset,
421
+ books: [],
422
+ people: (0, import_compat.sortBy)(people, (p) => p.id),
423
+ places: (0, import_compat.sortBy)(places, (p) => p.id),
424
+ events: (0, import_compat.sortBy)(events, (e) => e.id),
425
+ peopleGroups: (0, import_compat.sortBy)(peopleGroups, (g) => g.id)
426
+ };
427
+ }
428
+ function omitUndefined(obj) {
429
+ const result = {};
430
+ for (let key of Object.keys(obj)) {
431
+ const value = obj[key];
432
+ if (value !== void 0) {
433
+ result[key] = value;
434
+ }
435
+ }
436
+ return result;
437
+ }
438
+ // Annotate the CommonJS export names for ESM import in node:
439
+ 0 && (module.exports = {
440
+ THEOGRAPHIC_DATASET,
441
+ generateDatasetFromTheographic,
442
+ osisBookMap,
443
+ slugify,
444
+ stripMarkdownLinks
445
+ });
446
+ //# sourceMappingURL=theographic.cjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../generation/theographic.ts"],
4
+ "sourcesContent": ["import {\r\n Dataset,\r\n DatasetEntityRef,\r\n DatasetEvent,\r\n DatasetPeopleGroup,\r\n DatasetPerson,\r\n DatasetPlace,\r\n} from './common-types.js';\r\nimport { VerseRef } from '../utils.js';\r\nimport { DatasetDataset } from './dataset.js';\r\nimport { bookOrderMap } from './book-order.js';\r\nimport { getLogger } from '../log.js';\r\nimport { BookId } from '../utils.js';\r\nimport { sortBy } from 'es-toolkit/compat';\r\n\r\n/**\r\n * The dataset information for the Theographic Bible Metadata dataset.\r\n * See https://github.com/robertrouse/theographic-bible-metadata\r\n */\r\nexport const THEOGRAPHIC_DATASET: Dataset = {\r\n id: 'theographic',\r\n name: 'Theographic Bible Metadata',\r\n englishName: 'Theographic Bible Metadata',\r\n website: 'https://github.com/robertrouse/theographic-bible-metadata',\r\n licenseUrl: 'https://creativecommons.org/licenses/by-sa/4.0/',\r\n licenseNotes:\r\n 'Changes were made to the data to fit the Free Use Bible API format.',\r\n language: 'eng',\r\n textDirection: 'ltr',\r\n};\r\n\r\n/**\r\n * Defines an interface for a raw Theographic record.\r\n * The Theographic JSON files are Airtable exports, where each record has an Airtable record ID and a map of fields.\r\n */\r\nexport interface TheographicRecord {\r\n /**\r\n * The Airtable record ID of the record. e.g. \"recO5ToygNrV47m4M\"\r\n */\r\n id: string;\r\n\r\n /**\r\n * The fields of the record.\r\n */\r\n fields: {\r\n [key: string]: any;\r\n };\r\n}\r\n\r\n/**\r\n * The parsed contents of the Theographic JSON files that are needed\r\n * to generate the dataset.\r\n */\r\nexport interface TheographicFiles {\r\n books: TheographicRecord[];\r\n verses: TheographicRecord[];\r\n people: TheographicRecord[];\r\n places: TheographicRecord[];\r\n events: TheographicRecord[];\r\n peopleGroups: TheographicRecord[];\r\n}\r\n\r\n/**\r\n * Maps Theographic OSIS book names to USFM book IDs.\r\n */\r\nexport const osisBookMap = new Map<string, BookId>([\r\n ['Gen', 'GEN'],\r\n ['Exod', 'EXO'],\r\n ['Lev', 'LEV'],\r\n ['Num', 'NUM'],\r\n ['Deut', 'DEU'],\r\n ['Josh', 'JOS'],\r\n ['Judg', 'JDG'],\r\n ['Ruth', 'RUT'],\r\n ['1Sam', '1SA'],\r\n ['2Sam', '2SA'],\r\n ['1Kgs', '1KI'],\r\n ['2Kgs', '2KI'],\r\n ['1Chr', '1CH'],\r\n ['2Chr', '2CH'],\r\n ['Ezra', 'EZR'],\r\n ['Neh', 'NEH'],\r\n ['Esth', 'EST'],\r\n ['Job', 'JOB'],\r\n ['Ps', 'PSA'],\r\n ['Prov', 'PRO'],\r\n ['Eccl', 'ECC'],\r\n ['Song', 'SNG'],\r\n ['Isa', 'ISA'],\r\n ['Jer', 'JER'],\r\n ['Lam', 'LAM'],\r\n ['Ezek', 'EZK'],\r\n ['Dan', 'DAN'],\r\n ['Hos', 'HOS'],\r\n ['Joel', 'JOL'],\r\n ['Amos', 'AMO'],\r\n ['Obad', 'OBA'],\r\n ['Jonah', 'JON'],\r\n ['Mic', 'MIC'],\r\n ['Nah', 'NAM'],\r\n ['Hab', 'HAB'],\r\n ['Zeph', 'ZEP'],\r\n ['Hag', 'HAG'],\r\n ['Zech', 'ZEC'],\r\n ['Mal', 'MAL'],\r\n ['Matt', 'MAT'],\r\n ['Mark', 'MRK'],\r\n ['Luke', 'LUK'],\r\n ['John', 'JHN'],\r\n ['Acts', 'ACT'],\r\n ['Rom', 'ROM'],\r\n ['1Cor', '1CO'],\r\n ['2Cor', '2CO'],\r\n ['Gal', 'GAL'],\r\n ['Eph', 'EPH'],\r\n ['Phil', 'PHP'],\r\n ['Col', 'COL'],\r\n ['1Thess', '1TH'],\r\n ['2Thess', '2TH'],\r\n ['1Tim', '1TI'],\r\n ['2Tim', '2TI'],\r\n ['Titus', 'TIT'],\r\n ['Phlm', 'PHM'],\r\n ['Heb', 'HEB'],\r\n ['Jas', 'JAS'],\r\n ['1Pet', '1PE'],\r\n ['2Pet', '2PE'],\r\n ['1John', '1JN'],\r\n ['2John', '2JN'],\r\n ['3John', '3JN'],\r\n ['Jude', 'JUD'],\r\n ['Rev', 'REV'],\r\n]);\r\n\r\n/**\r\n * Slugifies the given string so that it can be used as an entity ID.\r\n * @param str The string to slugify.\r\n */\r\nexport function slugify(str: string): string {\r\n return str\r\n .toLowerCase()\r\n .replace(/[^a-z0-9]+/g, '-')\r\n .replace(/^-+|-+$/g, '');\r\n}\r\n\r\n/**\r\n * Removes markdown links from the given text, keeping only the link text.\r\n * For example, \"[Esther 1:10](/esth#Esth.1.10)\" becomes \"Esther 1:10\".\r\n * @param text The text to clean.\r\n */\r\nexport function stripMarkdownLinks(text: string): string {\r\n return text.replace(/\\[([^\\]]*)\\]\\([^)]*\\)/g, '$1');\r\n}\r\n\r\ninterface ResolvedVerse {\r\n book: BookId;\r\n order: number;\r\n chapter: number;\r\n verse: number;\r\n}\r\n\r\n/**\r\n * Generates a dataset from the given Theographic Bible Metadata files.\r\n *\r\n * The returned dataset contains the people, places, events, and people groups\r\n * from the Theographic data, with all cross-entity relationships resolved to entity IDs\r\n * and all verse links resolved to Bible verse references.\r\n *\r\n * The transformation is deterministic: the same input always produces the same output.\r\n *\r\n * @param files The parsed Theographic JSON files.\r\n * @param dataset The dataset information to use. Defaults to {@link THEOGRAPHIC_DATASET}.\r\n */\r\nexport function generateDatasetFromTheographic(\r\n files: TheographicFiles,\r\n dataset: Dataset = THEOGRAPHIC_DATASET\r\n): DatasetDataset {\r\n const logger = getLogger();\r\n\r\n // Validate that every Theographic book maps to a known USFM book ID.\r\n for (let book of files.books) {\r\n const osisName = book.fields.osisName;\r\n if (!osisBookMap.has(osisName)) {\r\n logger.warn(\r\n '[theographic] Unknown OSIS book name!',\r\n osisName,\r\n book.id\r\n );\r\n }\r\n }\r\n\r\n // Maps Theographic verse record IDs to Bible verse references.\r\n const verseMap = new Map<string, ResolvedVerse>();\r\n for (let verse of files.verses) {\r\n const osisRef: string = verse.fields.osisRef;\r\n if (!osisRef) {\r\n continue;\r\n }\r\n const [osisBook, chapter, verseNumber] = osisRef.split('.');\r\n const book = osisBookMap.get(osisBook);\r\n if (!book) {\r\n logger.warn('[theographic] Unknown OSIS reference!', osisRef);\r\n continue;\r\n }\r\n const chapterNumber = parseInt(chapter);\r\n const verseNum = parseInt(verseNumber);\r\n if (isNaN(chapterNumber) || isNaN(verseNum)) {\r\n logger.warn('[theographic] Invalid OSIS reference!', osisRef);\r\n continue;\r\n }\r\n verseMap.set(verse.id, {\r\n book,\r\n order: bookOrderMap.get(book) ?? 9999,\r\n chapter: chapterNumber,\r\n verse: verseNum,\r\n });\r\n }\r\n\r\n // Maps Theographic entity record IDs to entity references.\r\n const peopleMap = new Map<string, DatasetEntityRef>();\r\n for (let person of files.people) {\r\n const id = person.fields.slug;\r\n if (!id) {\r\n logger.warn(\r\n '[theographic] Person does not have a slug!',\r\n person.id\r\n );\r\n continue;\r\n }\r\n peopleMap.set(person.id, {\r\n id,\r\n type: 'people',\r\n name: person.fields.displayTitle ?? person.fields.name,\r\n });\r\n }\r\n\r\n const placesMap = new Map<string, DatasetEntityRef>();\r\n for (let place of files.places) {\r\n const id = place.fields.slug;\r\n if (!id) {\r\n logger.warn('[theographic] Place does not have a slug!', place.id);\r\n continue;\r\n }\r\n placesMap.set(place.id, {\r\n id,\r\n type: 'places',\r\n name:\r\n place.fields.displayTitle ??\r\n place.fields.kjvName ??\r\n place.fields.esvName,\r\n });\r\n }\r\n\r\n const eventsMap = new Map<string, DatasetEntityRef>();\r\n for (let event of files.events) {\r\n const title = event.fields.title;\r\n const eventID = event.fields.eventID;\r\n if (!title || typeof eventID !== 'number') {\r\n logger.warn(\r\n '[theographic] Event does not have a title or event ID!',\r\n event.id\r\n );\r\n continue;\r\n }\r\n eventsMap.set(event.id, {\r\n id: `${slugify(title)}_${eventID}`,\r\n type: 'events',\r\n name: title,\r\n });\r\n }\r\n\r\n const groupsMap = new Map<string, DatasetEntityRef>();\r\n for (let group of files.peopleGroups) {\r\n const name = group.fields.groupName;\r\n if (!name) {\r\n logger.warn(\r\n '[theographic] People group does not have a name!',\r\n group.id\r\n );\r\n continue;\r\n }\r\n groupsMap.set(group.id, {\r\n id: slugify(name),\r\n type: 'groups',\r\n name,\r\n });\r\n }\r\n\r\n /**\r\n * Resolves a list of Theographic verse record IDs into a sorted, deduplicated list of\r\n * verse references. Consecutive verses in the same chapter are collapsed into a single\r\n * reference using endVerse.\r\n */\r\n function resolveReferences(verseIds: unknown): VerseRef[] {\r\n if (!Array.isArray(verseIds)) {\r\n return [];\r\n }\r\n const resolved: ResolvedVerse[] = [];\r\n const seen = new Set<string>();\r\n for (let id of verseIds) {\r\n const verse = verseMap.get(id);\r\n if (!verse) {\r\n logger.warn('[theographic] Unknown verse record ID!', id);\r\n continue;\r\n }\r\n const key = `${verse.book}.${verse.chapter}.${verse.verse}`;\r\n if (seen.has(key)) {\r\n continue;\r\n }\r\n seen.add(key);\r\n resolved.push(verse);\r\n }\r\n\r\n resolved.sort(\r\n (a, b) =>\r\n a.order - b.order || a.chapter - b.chapter || a.verse - b.verse\r\n );\r\n\r\n const references: VerseRef[] = [];\r\n for (let verse of resolved) {\r\n const last = references[references.length - 1];\r\n if (\r\n last &&\r\n last.book === verse.book &&\r\n last.chapter === verse.chapter &&\r\n (last.endVerse ?? last.verse) === verse.verse - 1\r\n ) {\r\n last.endVerse = verse.verse;\r\n } else {\r\n references.push({\r\n book: verse.book,\r\n chapter: verse.chapter,\r\n verse: verse.verse,\r\n });\r\n }\r\n }\r\n\r\n return references;\r\n }\r\n\r\n /**\r\n * Resolves a list of Theographic record IDs into a list of entity references.\r\n */\r\n function resolveRefs(\r\n map: Map<string, DatasetEntityRef>,\r\n ids: unknown\r\n ): DatasetEntityRef[] | undefined {\r\n if (!Array.isArray(ids)) {\r\n return undefined;\r\n }\r\n const refs: DatasetEntityRef[] = [];\r\n const seen = new Set<string>();\r\n for (let id of ids) {\r\n const ref = map.get(id);\r\n if (!ref) {\r\n logger.warn('[theographic] Unknown entity record ID!', id);\r\n continue;\r\n }\r\n if (seen.has(ref.id)) {\r\n continue;\r\n }\r\n seen.add(ref.id);\r\n refs.push({ ...ref });\r\n }\r\n return refs.length > 0 ? refs : undefined;\r\n }\r\n\r\n /**\r\n * Resolves a single Theographic record ID (stored as a one-element array) into an entity reference.\r\n */\r\n function resolveRef(\r\n map: Map<string, DatasetEntityRef>,\r\n ids: unknown\r\n ): DatasetEntityRef | undefined {\r\n const refs = resolveRefs(map, ids);\r\n return refs?.[0];\r\n }\r\n\r\n function parseYear(year: unknown): number | undefined {\r\n if (typeof year === 'number') {\r\n return year;\r\n }\r\n if (typeof year === 'string') {\r\n const num = parseInt(year);\r\n if (!isNaN(num)) {\r\n return num;\r\n }\r\n }\r\n return undefined;\r\n }\r\n\r\n function parseCoordinate(value: unknown): number | undefined {\r\n if (typeof value === 'number') {\r\n return value;\r\n }\r\n if (typeof value === 'string') {\r\n const num = parseFloat(value);\r\n if (!isNaN(num)) {\r\n return num;\r\n }\r\n }\r\n return undefined;\r\n }\r\n\r\n function parseNames(names: unknown): string[] | undefined {\r\n if (typeof names !== 'string') {\r\n return undefined;\r\n }\r\n const list = names\r\n .split(',')\r\n .map((n) => n.trim())\r\n .filter((n) => n.length > 0);\r\n return list.length > 0 ? list : undefined;\r\n }\r\n\r\n function parseDescription(dictText: unknown): string[] | undefined {\r\n if (!Array.isArray(dictText)) {\r\n return undefined;\r\n }\r\n const paragraphs = dictText\r\n .filter((t) => typeof t === 'string')\r\n .map((t) => stripMarkdownLinks(t).trim())\r\n .filter((t) => t.length > 0);\r\n return paragraphs.length > 0 ? paragraphs : undefined;\r\n }\r\n\r\n const people: DatasetPerson[] = [];\r\n for (let record of files.people) {\r\n const ref = peopleMap.get(record.id);\r\n if (!ref) {\r\n continue;\r\n }\r\n const fields = record.fields;\r\n const person: DatasetPerson = {\r\n id: ref.id,\r\n name: ref.name!,\r\n alsoCalled: parseNames(fields.alsoCalled),\r\n isProperName:\r\n typeof fields.isProperName === 'boolean'\r\n ? fields.isProperName\r\n : undefined,\r\n gender: fields.gender ?? undefined,\r\n description: parseDescription(fields.dictText),\r\n birthYear: parseYear(fields.birthYear),\r\n deathYear: parseYear(fields.deathYear),\r\n minYear: parseYear(fields.minYear),\r\n maxYear: parseYear(fields.maxYear),\r\n birthPlace: resolveRef(placesMap, fields.birthPlace),\r\n deathPlace: resolveRef(placesMap, fields.deathPlace),\r\n father: resolveRefs(peopleMap, fields.father),\r\n mother: resolveRefs(peopleMap, fields.mother),\r\n partners: resolveRefs(peopleMap, fields.partners),\r\n children: resolveRefs(peopleMap, fields.children),\r\n siblings: resolveRefs(peopleMap, fields.siblings),\r\n halfSiblingsSameMother: resolveRefs(\r\n peopleMap,\r\n fields.halfSiblingsSameMother\r\n ),\r\n halfSiblingsSameFather: resolveRefs(\r\n peopleMap,\r\n fields.halfSiblingsSameFather\r\n ),\r\n memberOf: resolveRefs(groupsMap, fields.memberOf),\r\n events: resolveRefs(eventsMap, fields.timeline),\r\n references: resolveReferences(fields.verses),\r\n };\r\n people.push(omitUndefined(person));\r\n }\r\n\r\n const places: DatasetPlace[] = [];\r\n for (let record of files.places) {\r\n const ref = placesMap.get(record.id);\r\n if (!ref) {\r\n continue;\r\n }\r\n const fields = record.fields;\r\n const place: DatasetPlace = {\r\n id: ref.id,\r\n name: ref.name!,\r\n kjvName: fields.kjvName ?? undefined,\r\n esvName: fields.esvName ?? undefined,\r\n aliases: parseNames(fields.aliases),\r\n featureType: fields.featureType ?? undefined,\r\n featureSubType: fields.featureSubType ?? undefined,\r\n latitude: parseCoordinate(fields.latitude),\r\n longitude: parseCoordinate(fields.longitude),\r\n precision: fields.precision ?? undefined,\r\n description: parseDescription(fields.dictText),\r\n comment: fields.comment ?? undefined,\r\n rootPlace: resolveRef(placesMap, fields.rootID),\r\n duplicateOf: resolveRef(placesMap, fields.duplicate_of),\r\n people: resolveRefs(peopleMap, fields.hasBeenHere),\r\n peopleBorn: resolveRefs(peopleMap, fields.peopleBorn),\r\n peopleDied: resolveRefs(peopleMap, fields.peopleDied),\r\n events: resolveRefs(eventsMap, fields.eventsHere),\r\n references: resolveReferences(fields.verses),\r\n };\r\n places.push(omitUndefined(place));\r\n }\r\n\r\n const events: DatasetEvent[] = [];\r\n for (let record of files.events) {\r\n const ref = eventsMap.get(record.id);\r\n if (!ref) {\r\n continue;\r\n }\r\n const fields = record.fields;\r\n const event: DatasetEvent = {\r\n id: ref.id,\r\n name: ref.name!,\r\n startDate: fields.startDate ?? undefined,\r\n duration: fields.duration ?? undefined,\r\n participants: resolveRefs(peopleMap, fields.participants),\r\n locations: resolveRefs(placesMap, fields.locations),\r\n groups: resolveRefs(groupsMap, fields.groups),\r\n partOf: resolveRef(eventsMap, fields.partOf),\r\n predecessor: resolveRef(eventsMap, fields.predecessor),\r\n references: resolveReferences(fields.verses),\r\n };\r\n events.push(omitUndefined(event));\r\n }\r\n\r\n const peopleGroups: DatasetPeopleGroup[] = [];\r\n for (let record of files.peopleGroups) {\r\n const ref = groupsMap.get(record.id);\r\n if (!ref) {\r\n continue;\r\n }\r\n const fields = record.fields;\r\n const group: DatasetPeopleGroup = {\r\n id: ref.id,\r\n name: ref.name!,\r\n members: resolveRefs(peopleMap, fields.members),\r\n events: resolveRefs(eventsMap, fields.events_dev),\r\n references: resolveReferences(fields.verses),\r\n };\r\n peopleGroups.push(omitUndefined(group));\r\n }\r\n\r\n return {\r\n ...dataset,\r\n books: [],\r\n people: sortBy(people, (p) => p.id),\r\n places: sortBy(places, (p) => p.id),\r\n events: sortBy(events, (e) => e.id),\r\n peopleGroups: sortBy(peopleGroups, (g) => g.id),\r\n };\r\n}\r\n\r\n/**\r\n * Returns a copy of the given object with all undefined properties removed.\r\n * This keeps the generated JSON files free of explicit \"undefined\"/null noise\r\n * and makes the output deterministic.\r\n */\r\nfunction omitUndefined<T extends object>(obj: T): T {\r\n const result: any = {};\r\n for (let key of Object.keys(obj)) {\r\n const value = (obj as any)[key];\r\n if (value !== undefined) {\r\n result[key] = value;\r\n }\r\n }\r\n return result;\r\n}\r\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }