@helloao/tools 0.2.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.
- package/dist/cjs/generation/api.cjs +2213 -216
- package/dist/cjs/generation/api.cjs.map +3 -3
- package/dist/cjs/generation/audio.cjs +5 -5
- package/dist/cjs/generation/audio.cjs.map +1 -1
- package/dist/cjs/generation/book-order.cjs.map +1 -1
- package/dist/cjs/generation/common-types.cjs +782 -14
- package/dist/cjs/generation/common-types.cjs.map +2 -2
- package/dist/cjs/generation/dataset.cjs +13 -9
- package/dist/cjs/generation/dataset.cjs.map +2 -2
- package/dist/cjs/generation/index.cjs +8 -5
- package/dist/cjs/generation/index.cjs.map +2 -2
- package/dist/cjs/generation/simple.cjs +294 -0
- package/dist/cjs/generation/simple.cjs.map +7 -0
- package/dist/cjs/generation/theographic.cjs +446 -0
- package/dist/cjs/generation/theographic.cjs.map +7 -0
- package/dist/cjs/index.cjs +4 -4
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/log.cjs.map +1 -1
- package/dist/cjs/parser/codex-parser.cjs +3 -3
- package/dist/cjs/parser/codex-parser.cjs.map +3 -3
- package/dist/cjs/parser/commentary-csv-parser.cjs +14 -3
- package/dist/cjs/parser/commentary-csv-parser.cjs.map +3 -3
- package/dist/cjs/parser/index.cjs +1 -1
- package/dist/cjs/parser/iterators.cjs.map +1 -1
- package/dist/cjs/parser/lockman-parser.cjs +1 -1
- package/dist/cjs/parser/lockman-parser.cjs.map +1 -1
- package/dist/cjs/parser/tyndale-xml-parser.cjs +1 -1
- package/dist/cjs/parser/tyndale-xml-parser.cjs.map +1 -1
- package/dist/cjs/parser/types.cjs.map +1 -1
- package/dist/cjs/parser/usfm-parser.cjs +2 -2
- package/dist/cjs/parser/usfm-parser.cjs.map +1 -1
- package/dist/cjs/parser/usx-parser.cjs +122 -26
- package/dist/cjs/parser/usx-parser.cjs.map +2 -2
- package/dist/cjs/parser/words.cjs +187 -0
- package/dist/cjs/parser/words.cjs.map +7 -0
- package/dist/cjs/utils.cjs +1 -1
- package/dist/esm/generation/api.js +2155 -214
- package/dist/esm/generation/api.js.map +3 -3
- package/dist/esm/generation/audio.js +1 -1
- package/dist/esm/generation/audio.js.map +1 -1
- package/dist/esm/generation/book-order.js.map +1 -1
- package/dist/esm/generation/common-types.js +738 -14
- package/dist/esm/generation/common-types.js.map +2 -2
- package/dist/esm/generation/dataset.js +6 -2
- package/dist/esm/generation/dataset.js.map +2 -2
- package/dist/esm/generation/index.js +2 -1
- package/dist/esm/generation/index.js.map +2 -2
- package/dist/esm/generation/simple.js +260 -0
- package/dist/esm/generation/simple.js.map +7 -0
- package/dist/esm/generation/theographic.js +412 -0
- package/dist/esm/generation/theographic.js.map +7 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/log.js.map +1 -1
- package/dist/esm/parser/codex-parser.js +3 -3
- package/dist/esm/parser/codex-parser.js.map +3 -3
- package/dist/esm/parser/commentary-csv-parser.js +3 -2
- package/dist/esm/parser/commentary-csv-parser.js.map +2 -2
- package/dist/esm/parser/iterators.js.map +1 -1
- package/dist/esm/parser/lockman-parser.js +1 -1
- package/dist/esm/parser/lockman-parser.js.map +1 -1
- package/dist/esm/parser/tyndale-xml-parser.js +1 -1
- package/dist/esm/parser/tyndale-xml-parser.js.map +1 -1
- package/dist/esm/parser/usfm-parser.js +1 -1
- package/dist/esm/parser/usfm-parser.js.map +1 -1
- package/dist/esm/parser/usx-parser.js +130 -26
- package/dist/esm/parser/usx-parser.js.map +2 -2
- package/dist/esm/parser/words.js +149 -0
- package/dist/esm/parser/words.js.map +7 -0
- package/dist/types/generation/api.d.ts +9006 -1101
- package/dist/types/generation/common-types.d.ts +1318 -106
- package/dist/types/generation/dataset.d.ts +17 -1
- package/dist/types/generation/index.d.ts +2 -1
- package/dist/types/generation/simple.d.ts +110 -0
- package/dist/types/generation/theographic.d.ts +64 -0
- package/dist/types/parser/commentary-csv-parser.d.ts +1 -1
- package/dist/types/parser/lockman-parser.d.ts +1 -1
- package/dist/types/parser/tyndale-xml-parser.d.ts +1 -1
- package/dist/types/parser/types.d.ts +63 -0
- package/dist/types/parser/usx-parser.d.ts +6 -5
- package/dist/types/parser/words.d.ts +104 -0
- package/package.json +3 -2
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
import { bookOrderMap } from "./book-order.js";
|
|
3
|
+
import { getLogger } from "../log.js";
|
|
4
|
+
import { sortBy } from "es-toolkit/compat";
|
|
5
|
+
export const THEOGRAPHIC_DATASET = {
|
|
6
|
+
id: "theographic",
|
|
7
|
+
name: "Theographic Bible Metadata",
|
|
8
|
+
englishName: "Theographic Bible Metadata",
|
|
9
|
+
website: "https://github.com/robertrouse/theographic-bible-metadata",
|
|
10
|
+
licenseUrl: "https://creativecommons.org/licenses/by-sa/4.0/",
|
|
11
|
+
licenseNotes: "Changes were made to the data to fit the Free Use Bible API format.",
|
|
12
|
+
language: "eng",
|
|
13
|
+
textDirection: "ltr"
|
|
14
|
+
};
|
|
15
|
+
export const osisBookMap = /* @__PURE__ */ new Map([
|
|
16
|
+
["Gen", "GEN"],
|
|
17
|
+
["Exod", "EXO"],
|
|
18
|
+
["Lev", "LEV"],
|
|
19
|
+
["Num", "NUM"],
|
|
20
|
+
["Deut", "DEU"],
|
|
21
|
+
["Josh", "JOS"],
|
|
22
|
+
["Judg", "JDG"],
|
|
23
|
+
["Ruth", "RUT"],
|
|
24
|
+
["1Sam", "1SA"],
|
|
25
|
+
["2Sam", "2SA"],
|
|
26
|
+
["1Kgs", "1KI"],
|
|
27
|
+
["2Kgs", "2KI"],
|
|
28
|
+
["1Chr", "1CH"],
|
|
29
|
+
["2Chr", "2CH"],
|
|
30
|
+
["Ezra", "EZR"],
|
|
31
|
+
["Neh", "NEH"],
|
|
32
|
+
["Esth", "EST"],
|
|
33
|
+
["Job", "JOB"],
|
|
34
|
+
["Ps", "PSA"],
|
|
35
|
+
["Prov", "PRO"],
|
|
36
|
+
["Eccl", "ECC"],
|
|
37
|
+
["Song", "SNG"],
|
|
38
|
+
["Isa", "ISA"],
|
|
39
|
+
["Jer", "JER"],
|
|
40
|
+
["Lam", "LAM"],
|
|
41
|
+
["Ezek", "EZK"],
|
|
42
|
+
["Dan", "DAN"],
|
|
43
|
+
["Hos", "HOS"],
|
|
44
|
+
["Joel", "JOL"],
|
|
45
|
+
["Amos", "AMO"],
|
|
46
|
+
["Obad", "OBA"],
|
|
47
|
+
["Jonah", "JON"],
|
|
48
|
+
["Mic", "MIC"],
|
|
49
|
+
["Nah", "NAM"],
|
|
50
|
+
["Hab", "HAB"],
|
|
51
|
+
["Zeph", "ZEP"],
|
|
52
|
+
["Hag", "HAG"],
|
|
53
|
+
["Zech", "ZEC"],
|
|
54
|
+
["Mal", "MAL"],
|
|
55
|
+
["Matt", "MAT"],
|
|
56
|
+
["Mark", "MRK"],
|
|
57
|
+
["Luke", "LUK"],
|
|
58
|
+
["John", "JHN"],
|
|
59
|
+
["Acts", "ACT"],
|
|
60
|
+
["Rom", "ROM"],
|
|
61
|
+
["1Cor", "1CO"],
|
|
62
|
+
["2Cor", "2CO"],
|
|
63
|
+
["Gal", "GAL"],
|
|
64
|
+
["Eph", "EPH"],
|
|
65
|
+
["Phil", "PHP"],
|
|
66
|
+
["Col", "COL"],
|
|
67
|
+
["1Thess", "1TH"],
|
|
68
|
+
["2Thess", "2TH"],
|
|
69
|
+
["1Tim", "1TI"],
|
|
70
|
+
["2Tim", "2TI"],
|
|
71
|
+
["Titus", "TIT"],
|
|
72
|
+
["Phlm", "PHM"],
|
|
73
|
+
["Heb", "HEB"],
|
|
74
|
+
["Jas", "JAS"],
|
|
75
|
+
["1Pet", "1PE"],
|
|
76
|
+
["2Pet", "2PE"],
|
|
77
|
+
["1John", "1JN"],
|
|
78
|
+
["2John", "2JN"],
|
|
79
|
+
["3John", "3JN"],
|
|
80
|
+
["Jude", "JUD"],
|
|
81
|
+
["Rev", "REV"]
|
|
82
|
+
]);
|
|
83
|
+
export function slugify(str) {
|
|
84
|
+
return str.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
85
|
+
}
|
|
86
|
+
export function stripMarkdownLinks(text) {
|
|
87
|
+
return text.replace(/\[([^\]]*)\]\([^)]*\)/g, "$1");
|
|
88
|
+
}
|
|
89
|
+
export function generateDatasetFromTheographic(files, dataset = THEOGRAPHIC_DATASET) {
|
|
90
|
+
const logger = getLogger();
|
|
91
|
+
for (let book of files.books) {
|
|
92
|
+
const osisName = book.fields.osisName;
|
|
93
|
+
if (!osisBookMap.has(osisName)) {
|
|
94
|
+
logger.warn(
|
|
95
|
+
"[theographic] Unknown OSIS book name!",
|
|
96
|
+
osisName,
|
|
97
|
+
book.id
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const verseMap = /* @__PURE__ */ new Map();
|
|
102
|
+
for (let verse of files.verses) {
|
|
103
|
+
const osisRef = verse.fields.osisRef;
|
|
104
|
+
if (!osisRef) {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const [osisBook, chapter, verseNumber] = osisRef.split(".");
|
|
108
|
+
const book = osisBookMap.get(osisBook);
|
|
109
|
+
if (!book) {
|
|
110
|
+
logger.warn("[theographic] Unknown OSIS reference!", osisRef);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const chapterNumber = parseInt(chapter);
|
|
114
|
+
const verseNum = parseInt(verseNumber);
|
|
115
|
+
if (isNaN(chapterNumber) || isNaN(verseNum)) {
|
|
116
|
+
logger.warn("[theographic] Invalid OSIS reference!", osisRef);
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
verseMap.set(verse.id, {
|
|
120
|
+
book,
|
|
121
|
+
order: bookOrderMap.get(book) ?? 9999,
|
|
122
|
+
chapter: chapterNumber,
|
|
123
|
+
verse: verseNum
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
const peopleMap = /* @__PURE__ */ new Map();
|
|
127
|
+
for (let person of files.people) {
|
|
128
|
+
const id = person.fields.slug;
|
|
129
|
+
if (!id) {
|
|
130
|
+
logger.warn(
|
|
131
|
+
"[theographic] Person does not have a slug!",
|
|
132
|
+
person.id
|
|
133
|
+
);
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
peopleMap.set(person.id, {
|
|
137
|
+
id,
|
|
138
|
+
type: "people",
|
|
139
|
+
name: person.fields.displayTitle ?? person.fields.name
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
const placesMap = /* @__PURE__ */ new Map();
|
|
143
|
+
for (let place of files.places) {
|
|
144
|
+
const id = place.fields.slug;
|
|
145
|
+
if (!id) {
|
|
146
|
+
logger.warn("[theographic] Place does not have a slug!", place.id);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
placesMap.set(place.id, {
|
|
150
|
+
id,
|
|
151
|
+
type: "places",
|
|
152
|
+
name: place.fields.displayTitle ?? place.fields.kjvName ?? place.fields.esvName
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
const eventsMap = /* @__PURE__ */ new Map();
|
|
156
|
+
for (let event of files.events) {
|
|
157
|
+
const title = event.fields.title;
|
|
158
|
+
const eventID = event.fields.eventID;
|
|
159
|
+
if (!title || typeof eventID !== "number") {
|
|
160
|
+
logger.warn(
|
|
161
|
+
"[theographic] Event does not have a title or event ID!",
|
|
162
|
+
event.id
|
|
163
|
+
);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
eventsMap.set(event.id, {
|
|
167
|
+
id: `${slugify(title)}_${eventID}`,
|
|
168
|
+
type: "events",
|
|
169
|
+
name: title
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
const groupsMap = /* @__PURE__ */ new Map();
|
|
173
|
+
for (let group of files.peopleGroups) {
|
|
174
|
+
const name = group.fields.groupName;
|
|
175
|
+
if (!name) {
|
|
176
|
+
logger.warn(
|
|
177
|
+
"[theographic] People group does not have a name!",
|
|
178
|
+
group.id
|
|
179
|
+
);
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
groupsMap.set(group.id, {
|
|
183
|
+
id: slugify(name),
|
|
184
|
+
type: "groups",
|
|
185
|
+
name
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
function resolveReferences(verseIds) {
|
|
189
|
+
if (!Array.isArray(verseIds)) {
|
|
190
|
+
return [];
|
|
191
|
+
}
|
|
192
|
+
const resolved = [];
|
|
193
|
+
const seen = /* @__PURE__ */ new Set();
|
|
194
|
+
for (let id of verseIds) {
|
|
195
|
+
const verse = verseMap.get(id);
|
|
196
|
+
if (!verse) {
|
|
197
|
+
logger.warn("[theographic] Unknown verse record ID!", id);
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
const key = `${verse.book}.${verse.chapter}.${verse.verse}`;
|
|
201
|
+
if (seen.has(key)) {
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
seen.add(key);
|
|
205
|
+
resolved.push(verse);
|
|
206
|
+
}
|
|
207
|
+
resolved.sort(
|
|
208
|
+
(a, b) => a.order - b.order || a.chapter - b.chapter || a.verse - b.verse
|
|
209
|
+
);
|
|
210
|
+
const references = [];
|
|
211
|
+
for (let verse of resolved) {
|
|
212
|
+
const last = references[references.length - 1];
|
|
213
|
+
if (last && last.book === verse.book && last.chapter === verse.chapter && (last.endVerse ?? last.verse) === verse.verse - 1) {
|
|
214
|
+
last.endVerse = verse.verse;
|
|
215
|
+
} else {
|
|
216
|
+
references.push({
|
|
217
|
+
book: verse.book,
|
|
218
|
+
chapter: verse.chapter,
|
|
219
|
+
verse: verse.verse
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return references;
|
|
224
|
+
}
|
|
225
|
+
function resolveRefs(map, ids) {
|
|
226
|
+
if (!Array.isArray(ids)) {
|
|
227
|
+
return void 0;
|
|
228
|
+
}
|
|
229
|
+
const refs = [];
|
|
230
|
+
const seen = /* @__PURE__ */ new Set();
|
|
231
|
+
for (let id of ids) {
|
|
232
|
+
const ref = map.get(id);
|
|
233
|
+
if (!ref) {
|
|
234
|
+
logger.warn("[theographic] Unknown entity record ID!", id);
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
if (seen.has(ref.id)) {
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
seen.add(ref.id);
|
|
241
|
+
refs.push({ ...ref });
|
|
242
|
+
}
|
|
243
|
+
return refs.length > 0 ? refs : void 0;
|
|
244
|
+
}
|
|
245
|
+
function resolveRef(map, ids) {
|
|
246
|
+
const refs = resolveRefs(map, ids);
|
|
247
|
+
return refs?.[0];
|
|
248
|
+
}
|
|
249
|
+
function parseYear(year) {
|
|
250
|
+
if (typeof year === "number") {
|
|
251
|
+
return year;
|
|
252
|
+
}
|
|
253
|
+
if (typeof year === "string") {
|
|
254
|
+
const num = parseInt(year);
|
|
255
|
+
if (!isNaN(num)) {
|
|
256
|
+
return num;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return void 0;
|
|
260
|
+
}
|
|
261
|
+
function parseCoordinate(value) {
|
|
262
|
+
if (typeof value === "number") {
|
|
263
|
+
return value;
|
|
264
|
+
}
|
|
265
|
+
if (typeof value === "string") {
|
|
266
|
+
const num = parseFloat(value);
|
|
267
|
+
if (!isNaN(num)) {
|
|
268
|
+
return num;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return void 0;
|
|
272
|
+
}
|
|
273
|
+
function parseNames(names) {
|
|
274
|
+
if (typeof names !== "string") {
|
|
275
|
+
return void 0;
|
|
276
|
+
}
|
|
277
|
+
const list = names.split(",").map((n) => n.trim()).filter((n) => n.length > 0);
|
|
278
|
+
return list.length > 0 ? list : void 0;
|
|
279
|
+
}
|
|
280
|
+
function parseDescription(dictText) {
|
|
281
|
+
if (!Array.isArray(dictText)) {
|
|
282
|
+
return void 0;
|
|
283
|
+
}
|
|
284
|
+
const paragraphs = dictText.filter((t) => typeof t === "string").map((t) => stripMarkdownLinks(t).trim()).filter((t) => t.length > 0);
|
|
285
|
+
return paragraphs.length > 0 ? paragraphs : void 0;
|
|
286
|
+
}
|
|
287
|
+
const people = [];
|
|
288
|
+
for (let record of files.people) {
|
|
289
|
+
const ref = peopleMap.get(record.id);
|
|
290
|
+
if (!ref) {
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
const fields = record.fields;
|
|
294
|
+
const person = {
|
|
295
|
+
id: ref.id,
|
|
296
|
+
name: ref.name,
|
|
297
|
+
alsoCalled: parseNames(fields.alsoCalled),
|
|
298
|
+
isProperName: typeof fields.isProperName === "boolean" ? fields.isProperName : void 0,
|
|
299
|
+
gender: fields.gender ?? void 0,
|
|
300
|
+
description: parseDescription(fields.dictText),
|
|
301
|
+
birthYear: parseYear(fields.birthYear),
|
|
302
|
+
deathYear: parseYear(fields.deathYear),
|
|
303
|
+
minYear: parseYear(fields.minYear),
|
|
304
|
+
maxYear: parseYear(fields.maxYear),
|
|
305
|
+
birthPlace: resolveRef(placesMap, fields.birthPlace),
|
|
306
|
+
deathPlace: resolveRef(placesMap, fields.deathPlace),
|
|
307
|
+
father: resolveRefs(peopleMap, fields.father),
|
|
308
|
+
mother: resolveRefs(peopleMap, fields.mother),
|
|
309
|
+
partners: resolveRefs(peopleMap, fields.partners),
|
|
310
|
+
children: resolveRefs(peopleMap, fields.children),
|
|
311
|
+
siblings: resolveRefs(peopleMap, fields.siblings),
|
|
312
|
+
halfSiblingsSameMother: resolveRefs(
|
|
313
|
+
peopleMap,
|
|
314
|
+
fields.halfSiblingsSameMother
|
|
315
|
+
),
|
|
316
|
+
halfSiblingsSameFather: resolveRefs(
|
|
317
|
+
peopleMap,
|
|
318
|
+
fields.halfSiblingsSameFather
|
|
319
|
+
),
|
|
320
|
+
memberOf: resolveRefs(groupsMap, fields.memberOf),
|
|
321
|
+
events: resolveRefs(eventsMap, fields.timeline),
|
|
322
|
+
references: resolveReferences(fields.verses)
|
|
323
|
+
};
|
|
324
|
+
people.push(omitUndefined(person));
|
|
325
|
+
}
|
|
326
|
+
const places = [];
|
|
327
|
+
for (let record of files.places) {
|
|
328
|
+
const ref = placesMap.get(record.id);
|
|
329
|
+
if (!ref) {
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
const fields = record.fields;
|
|
333
|
+
const place = {
|
|
334
|
+
id: ref.id,
|
|
335
|
+
name: ref.name,
|
|
336
|
+
kjvName: fields.kjvName ?? void 0,
|
|
337
|
+
esvName: fields.esvName ?? void 0,
|
|
338
|
+
aliases: parseNames(fields.aliases),
|
|
339
|
+
featureType: fields.featureType ?? void 0,
|
|
340
|
+
featureSubType: fields.featureSubType ?? void 0,
|
|
341
|
+
latitude: parseCoordinate(fields.latitude),
|
|
342
|
+
longitude: parseCoordinate(fields.longitude),
|
|
343
|
+
precision: fields.precision ?? void 0,
|
|
344
|
+
description: parseDescription(fields.dictText),
|
|
345
|
+
comment: fields.comment ?? void 0,
|
|
346
|
+
rootPlace: resolveRef(placesMap, fields.rootID),
|
|
347
|
+
duplicateOf: resolveRef(placesMap, fields.duplicate_of),
|
|
348
|
+
people: resolveRefs(peopleMap, fields.hasBeenHere),
|
|
349
|
+
peopleBorn: resolveRefs(peopleMap, fields.peopleBorn),
|
|
350
|
+
peopleDied: resolveRefs(peopleMap, fields.peopleDied),
|
|
351
|
+
events: resolveRefs(eventsMap, fields.eventsHere),
|
|
352
|
+
references: resolveReferences(fields.verses)
|
|
353
|
+
};
|
|
354
|
+
places.push(omitUndefined(place));
|
|
355
|
+
}
|
|
356
|
+
const events = [];
|
|
357
|
+
for (let record of files.events) {
|
|
358
|
+
const ref = eventsMap.get(record.id);
|
|
359
|
+
if (!ref) {
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
const fields = record.fields;
|
|
363
|
+
const event = {
|
|
364
|
+
id: ref.id,
|
|
365
|
+
name: ref.name,
|
|
366
|
+
startDate: fields.startDate ?? void 0,
|
|
367
|
+
duration: fields.duration ?? void 0,
|
|
368
|
+
participants: resolveRefs(peopleMap, fields.participants),
|
|
369
|
+
locations: resolveRefs(placesMap, fields.locations),
|
|
370
|
+
groups: resolveRefs(groupsMap, fields.groups),
|
|
371
|
+
partOf: resolveRef(eventsMap, fields.partOf),
|
|
372
|
+
predecessor: resolveRef(eventsMap, fields.predecessor),
|
|
373
|
+
references: resolveReferences(fields.verses)
|
|
374
|
+
};
|
|
375
|
+
events.push(omitUndefined(event));
|
|
376
|
+
}
|
|
377
|
+
const peopleGroups = [];
|
|
378
|
+
for (let record of files.peopleGroups) {
|
|
379
|
+
const ref = groupsMap.get(record.id);
|
|
380
|
+
if (!ref) {
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
const fields = record.fields;
|
|
384
|
+
const group = {
|
|
385
|
+
id: ref.id,
|
|
386
|
+
name: ref.name,
|
|
387
|
+
members: resolveRefs(peopleMap, fields.members),
|
|
388
|
+
events: resolveRefs(eventsMap, fields.events_dev),
|
|
389
|
+
references: resolveReferences(fields.verses)
|
|
390
|
+
};
|
|
391
|
+
peopleGroups.push(omitUndefined(group));
|
|
392
|
+
}
|
|
393
|
+
return {
|
|
394
|
+
...dataset,
|
|
395
|
+
books: [],
|
|
396
|
+
people: sortBy(people, (p) => p.id),
|
|
397
|
+
places: sortBy(places, (p) => p.id),
|
|
398
|
+
events: sortBy(events, (e) => e.id),
|
|
399
|
+
peopleGroups: sortBy(peopleGroups, (g) => g.id)
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
function omitUndefined(obj) {
|
|
403
|
+
const result = {};
|
|
404
|
+
for (let key of Object.keys(obj)) {
|
|
405
|
+
const value = obj[key];
|
|
406
|
+
if (value !== void 0) {
|
|
407
|
+
result[key] = value;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return result;
|
|
411
|
+
}
|
|
412
|
+
//# sourceMappingURL=theographic.js.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
|
+
}
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../index.ts"],
|
|
4
|
-
"sourcesContent": ["import * as utils from './utils.js';\
|
|
4
|
+
"sourcesContent": ["import * as utils from './utils.js';\nimport * as generation from './generation/index.js';\nimport * as parser from './parser/index.js';\nimport * as log from './log.js';\n\nexport { utils, generation, parser, log };\n"],
|
|
5
5
|
"mappings": ";AAAA,YAAY,WAAW;AACvB,YAAY,gBAAgB;AAC5B,YAAY,YAAY;AACxB,YAAY,SAAS;AAErB,SAAS,OAAO,YAAY,QAAQ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/esm/log.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../log.ts"],
|
|
4
|
-
"sourcesContent": ["/**\
|
|
4
|
+
"sourcesContent": ["/**\n * A simple logging interface that can be used to log messages.\n */\nexport interface Logger {\n log: (message: any, ...args: any[]) => void;\n warn: (message: string, ...args: any[]) => void;\n error: (message: string, ...args: any[]) => void;\n}\n\n/**\n * A logger that logs messages to the console.\n */\nexport const consoleLogger: Logger = {\n log: (message: string, ...args) => {\n console.log(message, ...args);\n },\n warn: (message: string, ...args) => {\n console.warn(message, ...args);\n },\n error: (message: string, ...args) => {\n console.error(message, ...args);\n },\n};\n\n/**\n * The logger that should be used for logging messages.\n */\nlet logger: Logger = consoleLogger;\n\n/**\n * Gets the logger that is currently being used for logging messages.\n * @returns The logger that is currently being used.\n */\nexport function getLogger(): Logger {\n return logger;\n}\n\n/**\n * Sets the logger to use for logging messages.\n * @param newLogger The new logger to use.\n */\nexport function setLogger(newLogger: Logger) {\n logger = newLogger;\n}\n"],
|
|
5
5
|
"mappings": ";AAYO,aAAM,gBAAwB;AAAA,EACjC,KAAK,CAAC,YAAoB,SAAS;AAC/B,YAAQ,IAAI,SAAS,GAAG,IAAI;AAAA,EAChC;AAAA,EACA,MAAM,CAAC,YAAoB,SAAS;AAChC,YAAQ,KAAK,SAAS,GAAG,IAAI;AAAA,EACjC;AAAA,EACA,OAAO,CAAC,YAAoB,SAAS;AACjC,YAAQ,MAAM,SAAS,GAAG,IAAI;AAAA,EAClC;AACJ;AAKA,IAAI,SAAiB;AAMd,gBAAS,YAAoB;AAChC,SAAO;AACX;AAMO,gBAAS,UAAU,WAAmB;AACzC,WAAS;AACb;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -93,11 +93,11 @@ export class CodexParser {
|
|
|
93
93
|
const chapter = ensureChapter(chapterNumber);
|
|
94
94
|
chapter.footnotes.push(footnote);
|
|
95
95
|
}
|
|
96
|
-
function addReference(
|
|
97
|
-
addChapterContent(
|
|
96
|
+
function addReference(ref, content) {
|
|
97
|
+
addChapterContent(ref.chapter, [
|
|
98
98
|
{
|
|
99
99
|
type: "verse",
|
|
100
|
-
number:
|
|
100
|
+
number: ref.verse,
|
|
101
101
|
content
|
|
102
102
|
}
|
|
103
103
|
]);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../parser/codex-parser.ts"],
|
|
4
|
-
"sourcesContent": ["import { z } from 'zod';\r\nimport {\r\n Chapter,\r\n ChapterContent,\r\n ParseTree,\r\n Verse,\r\n VerseContent,\r\n} from './types.js';\r\nimport { getBookId, parseVerseReference, VerseRef } from '../utils.js';\r\nimport { ref } from 'process';\r\n\r\nexport const chapterHeadingSchema = z.object({\r\n type: z.literal('chapter-heading'),\r\n data: z.object({\r\n chapter: z.coerce.number().int(),\r\n }),\r\n});\r\n\r\nexport const verseSchema = z.object({\r\n type: z.literal('text'),\r\n id: z.string(),\r\n bookCode: z.string().optional(),\r\n chapter: z.number().optional(),\r\n verse: z.number().optional(),\r\n data: z\r\n .object({\r\n globalReferences: z.array(z.string()).optional(),\r\n })\r\n .optional(),\r\n});\r\n\r\nexport const paratextSchema = z.object({\r\n type: z.literal('paratext'),\r\n id: z.string(),\r\n});\r\n\r\nexport const metadataSchema = z.discriminatedUnion('type', [\r\n chapterHeadingSchema,\r\n verseSchema,\r\n paratextSchema,\r\n]);\r\n\r\nexport const codexSchema = z.object({\r\n cells: z.array(\r\n z.object({\r\n kind: z.number(),\r\n languageId: z.string(),\r\n value: z.string(),\r\n metadata: z\r\n .object({\r\n type: z.string(),\r\n })\r\n .passthrough()\r\n .nullable()\r\n .optional(),\r\n })\r\n ),\r\n});\r\n\r\n/**\r\n * Defines a parser for codex files.\r\n */\r\nexport class CodexParser {\r\n // TODO:\r\n // /**\r\n // * Whether to preserve markdown in the parsed content.\r\n // */\r\n // preserveMarkdown: boolean = true;\r\n\r\n private _noteCounter: number = 0;\r\n\r\n private _parser: DOMParser;\r\n\r\n constructor(parser: DOMParser) {\r\n this._parser = parser;\r\n }\r\n\r\n /**\r\n * Parses the specified codex content.\r\n *\r\n * @param codex The codex content to parse.\r\n * @returns The parse tree that was generated.\r\n */\r\n public parse(codex: string): ParseTree {\r\n const json = JSON.parse(codex);\r\n const data = codexSchema.parse(json);\r\n\r\n let root: ParseTree = {\r\n type: 'root',\r\n content: [],\r\n };\r\n\r\n let chapters: Map<number, Chapter> = new Map();\r\n let lastChapter: Chapter | null = null;\r\n\r\n function ensureChapter(chapterNumber: number) {\r\n let chapter = chapters.get(chapterNumber);\r\n if (!chapter) {\r\n chapter = {\r\n type: 'chapter',\r\n number: chapterNumber,\r\n content: [],\r\n footnotes: [],\r\n };\r\n lastChapter = chapter;\r\n chapters.set(chapterNumber, chapter);\r\n }\r\n\r\n return chapter;\r\n }\r\n\r\n function getDocumentContent(doc: Document): string {\r\n let content = '';\r\n for (let element of doc.childNodes) {\r\n content += element.textContent;\r\n }\r\n return content;\r\n }\r\n\r\n function addChapterContent(\r\n chapterNumber: number,\r\n content: ChapterContent[]\r\n ) {\r\n const chapter = ensureChapter(chapterNumber);\r\n chapter.content.push(...content);\r\n }\r\n\r\n function addChapterFootnote(\r\n chapterNumber: number,\r\n footnote: Chapter['footnotes'][0]\r\n ) {\r\n const chapter = ensureChapter(chapterNumber);\r\n chapter.footnotes.push(footnote);\r\n }\r\n\r\n function addReference(ref: VerseRef, content: Verse['content']) {\r\n addChapterContent(ref.chapter, [\r\n {\r\n type: 'verse',\r\n number: ref.verse,\r\n content: content,\r\n },\r\n ]);\r\n }\r\n\r\n function stripHTML(value: string) {\r\n return value.replace(/<[^>]*>/g, '');\r\n }\r\n\r\n function toHeading(content: string) {\r\n return {\r\n type: 'heading',\r\n content: [content],\r\n } satisfies ChapterContent;\r\n }\r\n\r\n function addLineBreaks(lines: Verse['content']) {\r\n return lines.reduce(\r\n (prev, current) => {\r\n if (typeof current === 'string' && current.trim() === '') {\r\n return prev; // skip empty lines\r\n }\r\n if (prev.length === 0) {\r\n return [current];\r\n } else {\r\n return [\r\n ...prev,\r\n {\r\n lineBreak: true,\r\n },\r\n current,\r\n ] satisfies Verse['content'];\r\n }\r\n },\r\n [] as Verse['content']\r\n );\r\n }\r\n\r\n let previousReference: VerseRef | null = null;\r\n let lines: Verse['content'] = [];\r\n\r\n for (let cell of data.cells) {\r\n if (cell.languageId === 'html' && cell.value) {\r\n if (!cell.metadata) continue; // ignore html cells without metadata\r\n\r\n const metadataResult = metadataSchema.safeParse(cell.metadata);\r\n\r\n if (!metadataResult.success) continue; // ignore cells with invalid/unknown metadata\r\n const metadata = metadataResult.data;\r\n if (metadata.type === 'text') {\r\n let reference = parseVerseReference(metadata.id);\r\n if (!reference) {\r\n if (metadata.bookCode && metadata.chapter) {\r\n const bookId = getBookId(metadata.bookCode);\r\n if (!bookId) {\r\n throw new Error(\r\n 'Could not find book ID for code: ' +\r\n metadata.bookCode\r\n );\r\n }\r\n\r\n if (metadata.verse) {\r\n reference = {\r\n book: bookId,\r\n chapter: metadata.chapter,\r\n verse: metadata.verse,\r\n };\r\n } else if (previousReference?.verse) {\r\n if (\r\n previousReference.chapter !==\r\n metadata.chapter ||\r\n previousReference.book !== bookId\r\n ) {\r\n throw new Error(\r\n 'Cannot infer verse number for non-consecutive verse reference.'\r\n );\r\n }\r\n\r\n // Sometimes codex doesn't include verse numbers for every cell, so we infer it from the previous reference\r\n reference = {\r\n book: bookId,\r\n chapter: metadata.chapter,\r\n verse: previousReference.verse,\r\n };\r\n } else {\r\n throw new Error(\r\n 'Could not find verse reference in metadata.'\r\n );\r\n }\r\n } else if (metadata.data?.globalReferences?.length) {\r\n reference = parseVerseReference(\r\n metadata.data.globalReferences[0]\r\n );\r\n if (!reference) {\r\n throw new Error(\r\n 'Could not find verse reference in globalReferences metadata.'\r\n );\r\n }\r\n } else {\r\n throw new Error(\r\n 'Could not find verse reference in metadata.'\r\n );\r\n }\r\n }\r\n\r\n if (\r\n previousReference &&\r\n (reference.book !== previousReference.book ||\r\n reference.chapter !== previousReference.chapter ||\r\n reference.verse !== previousReference.verse)\r\n ) {\r\n addReference(previousReference, addLineBreaks(lines));\r\n lines = [];\r\n }\r\n\r\n previousReference = reference;\r\n\r\n if (!root.id) root.id = reference.book; // set book id if not already set\r\n\r\n const doc = this._parser.parseFromString(\r\n cell.value,\r\n 'text/html'\r\n );\r\n\r\n for (let element of doc.children) {\r\n const allFootnotes = element.querySelectorAll(\r\n 'sup.footnote-marker[data-footnote]'\r\n );\r\n for (const footnote of allFootnotes) {\r\n const footnoteData =\r\n footnote.getAttribute('data-footnote');\r\n if (footnoteData) {\r\n const footnoteDoc =\r\n this._parser.parseFromString(\r\n footnoteData,\r\n 'text/html'\r\n );\r\n const footnoteText =\r\n getDocumentContent(footnoteDoc);\r\n if (footnoteText) {\r\n addChapterFootnote(reference.chapter, {\r\n noteId: this._noteCounter++,\r\n text: footnoteText,\r\n caller: null,\r\n });\r\n }\r\n }\r\n footnote.remove();\r\n }\r\n }\r\n\r\n const content = getDocumentContent(doc);\r\n\r\n if (content) {\r\n // add line breaks in heading if there are multiple lines\r\n const newLines = content.split('\\n');\r\n\r\n lines.push(...newLines);\r\n }\r\n } else if (metadata.type === 'paratext') {\r\n const reference = parseVerseReference(`${metadata.id}:1`); // chapter headings do not have a verse reference always default to 1\r\n if (reference) {\r\n const doc = this._parser.parseFromString(\r\n cell.value,\r\n 'text/html'\r\n );\r\n const content = getDocumentContent(doc);\r\n\r\n if (!content) {\r\n continue;\r\n }\r\n\r\n // add line breaks in heading if there are multiple lines\r\n const lines = content\r\n .split('\\n')\r\n .reduce<ChapterContent[]>((prev, current) => {\r\n if (prev.length === 0)\r\n return [toHeading(current)];\r\n else\r\n return [\r\n ...prev,\r\n {\r\n type: 'line_break',\r\n },\r\n toHeading(current),\r\n ] satisfies ChapterContent[];\r\n }, []);\r\n\r\n lines.forEach((line) =>\r\n addChapterContent(reference.chapter, [line])\r\n );\r\n } else {\r\n const doc = this._parser.parseFromString(\r\n cell.value,\r\n 'text/html'\r\n );\r\n const content = getDocumentContent(doc);\r\n // parse paratext that isn't a chapter reference as footnote\r\n // const content = stripHTML(cell.value);\r\n if (content && !cell.metadata) {\r\n if (lastChapter) {\r\n (lastChapter as Chapter).footnotes.push({\r\n noteId: this._noteCounter++,\r\n text: content,\r\n caller: null,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (previousReference) {\r\n addReference(previousReference, addLineBreaks(lines));\r\n }\r\n\r\n for (let chapter of chapters.values()) {\r\n root.content.push(chapter);\r\n }\r\n\r\n return root;\r\n }\r\n}\r\n"],
|
|
5
|
-
"mappings": ";AAAA,SAAS,SAAS;AAQlB,SAAS,WAAW,2BAAqC;
|
|
6
|
-
"names": ["
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod';\r\nimport {\r\n Chapter,\r\n ChapterContent,\r\n ParseTree,\r\n Verse,\r\n VerseContent,\r\n} from './types.js';\r\nimport { getBookId, parseVerseReference, VerseRef } from '../utils.js';\r\n\r\nexport const chapterHeadingSchema = z.object({\r\n type: z.literal('chapter-heading'),\r\n data: z.object({\r\n chapter: z.coerce.number().int(),\r\n }),\r\n});\r\n\r\nexport const verseSchema = z.object({\r\n type: z.literal('text'),\r\n id: z.string(),\r\n bookCode: z.string().optional(),\r\n chapter: z.number().optional(),\r\n verse: z.number().optional(),\r\n data: z\r\n .object({\r\n globalReferences: z.array(z.string()).optional(),\r\n })\r\n .optional(),\r\n});\r\n\r\nexport const paratextSchema = z.object({\r\n type: z.literal('paratext'),\r\n id: z.string(),\r\n});\r\n\r\nexport const metadataSchema = z.discriminatedUnion('type', [\r\n chapterHeadingSchema,\r\n verseSchema,\r\n paratextSchema,\r\n]);\r\n\r\nexport const codexSchema = z.object({\r\n cells: z.array(\r\n z.object({\r\n kind: z.number(),\r\n languageId: z.string(),\r\n value: z.string(),\r\n metadata: z\r\n .object({\r\n type: z.string(),\r\n })\r\n .passthrough()\r\n .nullable()\r\n .optional(),\r\n })\r\n ),\r\n});\r\n\r\n/**\r\n * Defines a parser for codex files.\r\n */\r\nexport class CodexParser {\r\n // TODO:\r\n // /**\r\n // * Whether to preserve markdown in the parsed content.\r\n // */\r\n // preserveMarkdown: boolean = true;\r\n\r\n private _noteCounter: number = 0;\r\n\r\n private _parser: DOMParser;\r\n\r\n constructor(parser: DOMParser) {\r\n this._parser = parser;\r\n }\r\n\r\n /**\r\n * Parses the specified codex content.\r\n *\r\n * @param codex The codex content to parse.\r\n * @returns The parse tree that was generated.\r\n */\r\n public parse(codex: string): ParseTree {\r\n const json = JSON.parse(codex);\r\n const data = codexSchema.parse(json);\r\n\r\n let root: ParseTree = {\r\n type: 'root',\r\n content: [],\r\n };\r\n\r\n let chapters: Map<number, Chapter> = new Map();\r\n let lastChapter: Chapter | null = null;\r\n\r\n function ensureChapter(chapterNumber: number) {\r\n let chapter = chapters.get(chapterNumber);\r\n if (!chapter) {\r\n chapter = {\r\n type: 'chapter',\r\n number: chapterNumber,\r\n content: [],\r\n footnotes: [],\r\n };\r\n lastChapter = chapter;\r\n chapters.set(chapterNumber, chapter);\r\n }\r\n\r\n return chapter;\r\n }\r\n\r\n function getDocumentContent(doc: Document): string {\r\n let content = '';\r\n for (let element of doc.childNodes) {\r\n content += element.textContent;\r\n }\r\n return content;\r\n }\r\n\r\n function addChapterContent(\r\n chapterNumber: number,\r\n content: ChapterContent[]\r\n ) {\r\n const chapter = ensureChapter(chapterNumber);\r\n chapter.content.push(...content);\r\n }\r\n\r\n function addChapterFootnote(\r\n chapterNumber: number,\r\n footnote: Chapter['footnotes'][0]\r\n ) {\r\n const chapter = ensureChapter(chapterNumber);\r\n chapter.footnotes.push(footnote);\r\n }\r\n\r\n function addReference(ref: VerseRef, content: Verse['content']) {\r\n addChapterContent(ref.chapter, [\r\n {\r\n type: 'verse',\r\n number: ref.verse,\r\n content: content,\r\n },\r\n ]);\r\n }\r\n\r\n function stripHTML(value: string) {\r\n return value.replace(/<[^>]*>/g, '');\r\n }\r\n\r\n function toHeading(content: string) {\r\n return {\r\n type: 'heading',\r\n content: [content],\r\n } satisfies ChapterContent;\r\n }\r\n\r\n function addLineBreaks(lines: Verse['content']) {\r\n return lines.reduce(\r\n (prev, current) => {\r\n if (typeof current === 'string' && current.trim() === '') {\r\n return prev; // skip empty lines\r\n }\r\n if (prev.length === 0) {\r\n return [current];\r\n } else {\r\n return [\r\n ...prev,\r\n {\r\n lineBreak: true,\r\n },\r\n current,\r\n ] satisfies Verse['content'];\r\n }\r\n },\r\n [] as Verse['content']\r\n );\r\n }\r\n\r\n let previousReference: VerseRef | null = null;\r\n let lines: Verse['content'] = [];\r\n\r\n for (let cell of data.cells) {\r\n if (cell.languageId === 'html' && cell.value) {\r\n if (!cell.metadata) continue; // ignore html cells without metadata\r\n\r\n const metadataResult = metadataSchema.safeParse(cell.metadata);\r\n\r\n if (!metadataResult.success) continue; // ignore cells with invalid/unknown metadata\r\n const metadata = metadataResult.data;\r\n if (metadata.type === 'text') {\r\n let reference = parseVerseReference(metadata.id);\r\n if (!reference) {\r\n if (metadata.bookCode && metadata.chapter) {\r\n const bookId = getBookId(metadata.bookCode);\r\n if (!bookId) {\r\n throw new Error(\r\n 'Could not find book ID for code: ' +\r\n metadata.bookCode\r\n );\r\n }\r\n\r\n if (metadata.verse) {\r\n reference = {\r\n book: bookId,\r\n chapter: metadata.chapter,\r\n verse: metadata.verse,\r\n };\r\n } else if (previousReference?.verse) {\r\n if (\r\n previousReference.chapter !==\r\n metadata.chapter ||\r\n previousReference.book !== bookId\r\n ) {\r\n throw new Error(\r\n 'Cannot infer verse number for non-consecutive verse reference.'\r\n );\r\n }\r\n\r\n // Sometimes codex doesn't include verse numbers for every cell, so we infer it from the previous reference\r\n reference = {\r\n book: bookId,\r\n chapter: metadata.chapter,\r\n verse: previousReference.verse,\r\n };\r\n } else {\r\n throw new Error(\r\n 'Could not find verse reference in metadata.'\r\n );\r\n }\r\n } else if (metadata.data?.globalReferences?.length) {\r\n reference = parseVerseReference(\r\n metadata.data.globalReferences[0]\r\n );\r\n if (!reference) {\r\n throw new Error(\r\n 'Could not find verse reference in globalReferences metadata.'\r\n );\r\n }\r\n } else {\r\n throw new Error(\r\n 'Could not find verse reference in metadata.'\r\n );\r\n }\r\n }\r\n\r\n if (\r\n previousReference &&\r\n (reference.book !== previousReference.book ||\r\n reference.chapter !== previousReference.chapter ||\r\n reference.verse !== previousReference.verse)\r\n ) {\r\n addReference(previousReference, addLineBreaks(lines));\r\n lines = [];\r\n }\r\n\r\n previousReference = reference;\r\n\r\n if (!root.id) root.id = reference.book; // set book id if not already set\r\n\r\n const doc = this._parser.parseFromString(\r\n cell.value,\r\n 'text/html'\r\n );\r\n\r\n for (let element of doc.children) {\r\n const allFootnotes = element.querySelectorAll(\r\n 'sup.footnote-marker[data-footnote]'\r\n );\r\n for (const footnote of allFootnotes) {\r\n const footnoteData =\r\n footnote.getAttribute('data-footnote');\r\n if (footnoteData) {\r\n const footnoteDoc =\r\n this._parser.parseFromString(\r\n footnoteData,\r\n 'text/html'\r\n );\r\n const footnoteText =\r\n getDocumentContent(footnoteDoc);\r\n if (footnoteText) {\r\n addChapterFootnote(reference.chapter, {\r\n noteId: this._noteCounter++,\r\n text: footnoteText,\r\n caller: null,\r\n });\r\n }\r\n }\r\n footnote.remove();\r\n }\r\n }\r\n\r\n const content = getDocumentContent(doc);\r\n\r\n if (content) {\r\n // add line breaks in heading if there are multiple lines\r\n const newLines = content.split('\\n');\r\n\r\n lines.push(...newLines);\r\n }\r\n } else if (metadata.type === 'paratext') {\r\n const reference = parseVerseReference(`${metadata.id}:1`); // chapter headings do not have a verse reference always default to 1\r\n if (reference) {\r\n const doc = this._parser.parseFromString(\r\n cell.value,\r\n 'text/html'\r\n );\r\n const content = getDocumentContent(doc);\r\n\r\n if (!content) {\r\n continue;\r\n }\r\n\r\n // add line breaks in heading if there are multiple lines\r\n const lines = content\r\n .split('\\n')\r\n .reduce<ChapterContent[]>((prev, current) => {\r\n if (prev.length === 0)\r\n return [toHeading(current)];\r\n else\r\n return [\r\n ...prev,\r\n {\r\n type: 'line_break',\r\n },\r\n toHeading(current),\r\n ] satisfies ChapterContent[];\r\n }, []);\r\n\r\n lines.forEach((line) =>\r\n addChapterContent(reference.chapter, [line])\r\n );\r\n } else {\r\n const doc = this._parser.parseFromString(\r\n cell.value,\r\n 'text/html'\r\n );\r\n const content = getDocumentContent(doc);\r\n // parse paratext that isn't a chapter reference as footnote\r\n // const content = stripHTML(cell.value);\r\n if (content && !cell.metadata) {\r\n if (lastChapter) {\r\n (lastChapter as Chapter).footnotes.push({\r\n noteId: this._noteCounter++,\r\n text: content,\r\n caller: null,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (previousReference) {\r\n addReference(previousReference, addLineBreaks(lines));\r\n }\r\n\r\n for (let chapter of chapters.values()) {\r\n root.content.push(chapter);\r\n }\r\n\r\n return root;\r\n }\r\n}\r\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["lines"]
|
|
7
7
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
import { getBookId, parseVerseReference } from "../utils";
|
|
3
|
-
import
|
|
2
|
+
import { getBookId, parseVerseReference } from "../utils.js";
|
|
3
|
+
import papaparse from "papaparse";
|
|
4
|
+
const { parse } = papaparse;
|
|
4
5
|
export class CommentaryCsvParser {
|
|
5
6
|
parse(data) {
|
|
6
7
|
const firstLine = data.indexOf("\n");
|