@helloao/tools 0.2.0 → 0.3.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.
Files changed (75) hide show
  1. package/dist/cjs/generation/api.cjs +856 -36
  2. package/dist/cjs/generation/api.cjs.map +3 -3
  3. package/dist/cjs/generation/audio.cjs +5 -5
  4. package/dist/cjs/generation/audio.cjs.map +1 -1
  5. package/dist/cjs/generation/book-order.cjs.map +1 -1
  6. package/dist/cjs/generation/common-types.cjs +359 -14
  7. package/dist/cjs/generation/common-types.cjs.map +2 -2
  8. package/dist/cjs/generation/dataset.cjs +13 -9
  9. package/dist/cjs/generation/dataset.cjs.map +2 -2
  10. package/dist/cjs/generation/index.cjs +8 -5
  11. package/dist/cjs/generation/index.cjs.map +2 -2
  12. package/dist/cjs/generation/simple.cjs +294 -0
  13. package/dist/cjs/generation/simple.cjs.map +7 -0
  14. package/dist/cjs/index.cjs +4 -4
  15. package/dist/cjs/index.cjs.map +1 -1
  16. package/dist/cjs/log.cjs.map +1 -1
  17. package/dist/cjs/parser/codex-parser.cjs +3 -3
  18. package/dist/cjs/parser/codex-parser.cjs.map +3 -3
  19. package/dist/cjs/parser/commentary-csv-parser.cjs +14 -3
  20. package/dist/cjs/parser/commentary-csv-parser.cjs.map +3 -3
  21. package/dist/cjs/parser/index.cjs +1 -1
  22. package/dist/cjs/parser/iterators.cjs.map +1 -1
  23. package/dist/cjs/parser/lockman-parser.cjs +1 -1
  24. package/dist/cjs/parser/lockman-parser.cjs.map +1 -1
  25. package/dist/cjs/parser/tyndale-xml-parser.cjs +1 -1
  26. package/dist/cjs/parser/tyndale-xml-parser.cjs.map +1 -1
  27. package/dist/cjs/parser/types.cjs.map +1 -1
  28. package/dist/cjs/parser/usfm-parser.cjs +2 -2
  29. package/dist/cjs/parser/usfm-parser.cjs.map +1 -1
  30. package/dist/cjs/parser/usx-parser.cjs +122 -26
  31. package/dist/cjs/parser/usx-parser.cjs.map +2 -2
  32. package/dist/cjs/parser/words.cjs +187 -0
  33. package/dist/cjs/parser/words.cjs.map +7 -0
  34. package/dist/cjs/utils.cjs +1 -1
  35. package/dist/esm/generation/api.js +835 -37
  36. package/dist/esm/generation/api.js.map +3 -3
  37. package/dist/esm/generation/audio.js +1 -1
  38. package/dist/esm/generation/audio.js.map +1 -1
  39. package/dist/esm/generation/book-order.js.map +1 -1
  40. package/dist/esm/generation/common-types.js +327 -14
  41. package/dist/esm/generation/common-types.js.map +2 -2
  42. package/dist/esm/generation/dataset.js +6 -2
  43. package/dist/esm/generation/dataset.js.map +2 -2
  44. package/dist/esm/generation/index.js +2 -1
  45. package/dist/esm/generation/index.js.map +2 -2
  46. package/dist/esm/generation/simple.js +260 -0
  47. package/dist/esm/generation/simple.js.map +7 -0
  48. package/dist/esm/index.js.map +1 -1
  49. package/dist/esm/log.js.map +1 -1
  50. package/dist/esm/parser/codex-parser.js +3 -3
  51. package/dist/esm/parser/codex-parser.js.map +3 -3
  52. package/dist/esm/parser/commentary-csv-parser.js +3 -2
  53. package/dist/esm/parser/commentary-csv-parser.js.map +2 -2
  54. package/dist/esm/parser/iterators.js.map +1 -1
  55. package/dist/esm/parser/lockman-parser.js +1 -1
  56. package/dist/esm/parser/lockman-parser.js.map +1 -1
  57. package/dist/esm/parser/tyndale-xml-parser.js +1 -1
  58. package/dist/esm/parser/tyndale-xml-parser.js.map +1 -1
  59. package/dist/esm/parser/usfm-parser.js +1 -1
  60. package/dist/esm/parser/usfm-parser.js.map +1 -1
  61. package/dist/esm/parser/usx-parser.js +130 -26
  62. package/dist/esm/parser/usx-parser.js.map +2 -2
  63. package/dist/esm/parser/words.js +149 -0
  64. package/dist/esm/parser/words.js.map +7 -0
  65. package/dist/types/generation/api.d.ts +6879 -918
  66. package/dist/types/generation/common-types.d.ts +432 -2
  67. package/dist/types/generation/index.d.ts +2 -1
  68. package/dist/types/generation/simple.d.ts +110 -0
  69. package/dist/types/parser/commentary-csv-parser.d.ts +1 -1
  70. package/dist/types/parser/lockman-parser.d.ts +1 -1
  71. package/dist/types/parser/tyndale-xml-parser.d.ts +1 -1
  72. package/dist/types/parser/types.d.ts +63 -0
  73. package/dist/types/parser/usx-parser.d.ts +6 -5
  74. package/dist/types/parser/words.d.ts +104 -0
  75. package/package.json +3 -2
@@ -0,0 +1,294 @@
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 simple_exports = {};
20
+ __export(simple_exports, {
21
+ simplifyChapter: () => simplifyChapter,
22
+ simplifyCommentaryChapter: () => simplifyCommentaryChapter,
23
+ simplifyHebrewSubtitle: () => simplifyHebrewSubtitle,
24
+ simplifyVerse: () => simplifyVerse,
25
+ simplifyVerseContent: () => simplifyVerseContent
26
+ });
27
+ module.exports = __toCommonJS(simple_exports);
28
+ function simplifyVerseContent(content, footnotes = /* @__PURE__ */ new Map(), usedFootnotes = /* @__PURE__ */ new Set(), words = []) {
29
+ let text = "";
30
+ const verseFootnotes = [];
31
+ const headings = [];
32
+ const wordsOfJesus = [];
33
+ const poem = [];
34
+ const verseWords = [];
35
+ const wordsByContentIndex = /* @__PURE__ */ new Map();
36
+ for (let word of words) {
37
+ let arr = wordsByContentIndex.get(word.contentIndex);
38
+ if (!arr) {
39
+ arr = [];
40
+ wordsByContentIndex.set(word.contentIndex, arr);
41
+ }
42
+ arr.push(word);
43
+ }
44
+ const truncateTo = (length) => {
45
+ if (length >= text.length) {
46
+ return;
47
+ }
48
+ text = text.slice(0, length);
49
+ for (let footnote of verseFootnotes) {
50
+ footnote.offset = Math.min(footnote.offset, length);
51
+ }
52
+ for (let heading of headings) {
53
+ heading.offset = Math.min(heading.offset, length);
54
+ }
55
+ for (let range of [...wordsOfJesus, ...poem, ...verseWords]) {
56
+ range.start = Math.min(range.start, length);
57
+ range.end = Math.min(range.end, length);
58
+ }
59
+ };
60
+ const addWordsForContent = (contentIndex, contentStart, contentLength) => {
61
+ const contentWords = wordsByContentIndex.get(contentIndex);
62
+ if (!contentWords) {
63
+ return;
64
+ }
65
+ for (let { contentIndex: _index, ...word } of contentWords) {
66
+ verseWords.push({
67
+ ...word,
68
+ start: contentStart + Math.min(word.start, contentLength),
69
+ end: contentStart + Math.min(word.end, contentLength)
70
+ });
71
+ }
72
+ };
73
+ const startNewLine = () => {
74
+ truncateTo(text.replace(/[^\S\n]+$/, "").length);
75
+ text += "\n";
76
+ };
77
+ const needsSeparator = (next) => {
78
+ if (text.length <= 0 || /\s$/.test(text) || !next) {
79
+ return false;
80
+ }
81
+ if (typeof next === "string") {
82
+ return next.length > 0 && !/^\s/.test(next);
83
+ }
84
+ if ("text" in next) {
85
+ return typeof next.poem !== "number" && next.text.length > 0 && !/^\s/.test(next.text);
86
+ }
87
+ return false;
88
+ };
89
+ for (let i = 0; i < content.length; i++) {
90
+ const part = content[i];
91
+ if (typeof part === "string") {
92
+ addWordsForContent(i, text.length, part.length);
93
+ text += part;
94
+ continue;
95
+ }
96
+ if ("text" in part) {
97
+ if (typeof part.poem === "number" && text.length > 0 && !text.endsWith("\n")) {
98
+ startNewLine();
99
+ }
100
+ const start = text.length;
101
+ addWordsForContent(i, start, part.text.length);
102
+ text += part.text;
103
+ const end = text.length;
104
+ if (end > start) {
105
+ if (part.wordsOfJesus) {
106
+ wordsOfJesus.push({ start, end });
107
+ }
108
+ if (typeof part.poem === "number") {
109
+ poem.push({ start, end, level: part.poem });
110
+ }
111
+ }
112
+ } else if ("lineBreak" in part) {
113
+ if (text.length > 0 && !text.endsWith("\n")) {
114
+ startNewLine();
115
+ }
116
+ } else if ("noteId" in part) {
117
+ const footnote = footnotes.get(part.noteId);
118
+ if (footnote) {
119
+ usedFootnotes.add(part.noteId);
120
+ verseFootnotes.push({
121
+ noteId: footnote.noteId,
122
+ offset: text.length,
123
+ text: footnote.text,
124
+ caller: footnote.caller
125
+ });
126
+ }
127
+ if (needsSeparator(content[i + 1])) {
128
+ text += " ";
129
+ }
130
+ } else if ("heading" in part) {
131
+ headings.push({
132
+ offset: text.length,
133
+ text: part.heading
134
+ });
135
+ if (needsSeparator(content[i + 1])) {
136
+ text += " ";
137
+ }
138
+ }
139
+ }
140
+ truncateTo(text.replace(/\s+$/, "").length);
141
+ const leading = text.length - text.replace(/^\s+/, "").length;
142
+ if (leading > 0) {
143
+ text = text.slice(leading);
144
+ for (let footnote of verseFootnotes) {
145
+ footnote.offset = Math.max(0, footnote.offset - leading);
146
+ }
147
+ for (let heading of headings) {
148
+ heading.offset = Math.max(0, heading.offset - leading);
149
+ }
150
+ for (let range of [...wordsOfJesus, ...poem, ...verseWords]) {
151
+ range.start = Math.max(0, range.start - leading);
152
+ range.end = Math.max(0, range.end - leading);
153
+ }
154
+ }
155
+ return {
156
+ text,
157
+ footnotes: verseFootnotes,
158
+ headings,
159
+ wordsOfJesus: mergeAdjacentRanges(wordsOfJesus, text),
160
+ poem: poem.filter((range) => range.start < range.end),
161
+ words: verseWords.filter((word) => word.start < word.end)
162
+ };
163
+ }
164
+ function mergeAdjacentRanges(ranges, text) {
165
+ const merged = [];
166
+ for (let range of ranges) {
167
+ if (range.start >= range.end) {
168
+ continue;
169
+ }
170
+ const previous = merged[merged.length - 1];
171
+ if (previous && range.start >= previous.end && !/\S/.test(text.slice(previous.end, range.start))) {
172
+ previous.end = range.end;
173
+ } else {
174
+ merged.push(range);
175
+ }
176
+ }
177
+ return merged;
178
+ }
179
+ function simplifyVerse(verse, footnotes, usedFootnotes, words, remappedWords) {
180
+ const simplified = simplifyVerseContent(
181
+ verse.content,
182
+ footnotes,
183
+ usedFootnotes,
184
+ words
185
+ );
186
+ if (remappedWords) {
187
+ remappedWords.push(...simplified.words);
188
+ }
189
+ return {
190
+ type: "verse",
191
+ number: verse.number,
192
+ ...omitEmptyProperties(simplified)
193
+ };
194
+ }
195
+ function simplifyHebrewSubtitle(subtitle, footnotes, usedFootnotes) {
196
+ const simplified = simplifyVerseContent(
197
+ subtitle.content,
198
+ footnotes,
199
+ usedFootnotes
200
+ );
201
+ return {
202
+ type: "hebrew_subtitle",
203
+ ...omitEmptyProperties(simplified)
204
+ };
205
+ }
206
+ function omitEmptyProperties(content) {
207
+ return {
208
+ text: content.text,
209
+ footnotes: content.footnotes,
210
+ ...content.headings.length > 0 ? { headings: content.headings } : {},
211
+ ...content.wordsOfJesus.length > 0 ? { wordsOfJesus: content.wordsOfJesus } : {},
212
+ ...content.poem.length > 0 ? { poem: content.poem } : {}
213
+ };
214
+ }
215
+ function simplifyChapter(chapter, words) {
216
+ const footnotes = /* @__PURE__ */ new Map();
217
+ for (let footnote of chapter.footnotes) {
218
+ footnotes.set(footnote.noteId, footnote);
219
+ }
220
+ const usedFootnotes = /* @__PURE__ */ new Set();
221
+ const content = [];
222
+ const versesByNumber = /* @__PURE__ */ new Map();
223
+ const simpleWords = {};
224
+ for (let c of chapter.content) {
225
+ if (c.type === "verse") {
226
+ const verseWords = words?.[String(c.number)];
227
+ const remappedWords = [];
228
+ const verse = simplifyVerse(
229
+ c,
230
+ footnotes,
231
+ usedFootnotes,
232
+ verseWords,
233
+ remappedWords
234
+ );
235
+ if (remappedWords.length > 0) {
236
+ simpleWords[String(c.number)] = remappedWords;
237
+ }
238
+ versesByNumber.set(verse.number, verse);
239
+ content.push(verse);
240
+ } else if (c.type === "hebrew_subtitle") {
241
+ content.push(simplifyHebrewSubtitle(c, footnotes, usedFootnotes));
242
+ } else if (c.type === "heading") {
243
+ content.push({
244
+ type: "heading",
245
+ text: c.content.join(" ")
246
+ });
247
+ } else if (c.type === "line_break") {
248
+ content.push({
249
+ type: "line_break"
250
+ });
251
+ }
252
+ }
253
+ const unreferencedFootnotes = [];
254
+ for (let footnote of chapter.footnotes) {
255
+ if (usedFootnotes.has(footnote.noteId)) {
256
+ continue;
257
+ }
258
+ const verse = footnote.reference ? versesByNumber.get(footnote.reference.verse) : void 0;
259
+ if (verse) {
260
+ verse.footnotes.push({
261
+ noteId: footnote.noteId,
262
+ offset: verse.text.length,
263
+ text: footnote.text,
264
+ caller: footnote.caller
265
+ });
266
+ } else {
267
+ unreferencedFootnotes.push(footnote);
268
+ }
269
+ }
270
+ return {
271
+ chapter: {
272
+ number: chapter.number,
273
+ content,
274
+ footnotes: unreferencedFootnotes
275
+ },
276
+ words: simpleWords
277
+ };
278
+ }
279
+ function simplifyCommentaryChapter(chapter) {
280
+ return {
281
+ number: chapter.number,
282
+ ...chapter.introduction !== void 0 ? { introduction: chapter.introduction } : {},
283
+ content: chapter.content.map((verse) => simplifyVerse(verse))
284
+ };
285
+ }
286
+ // Annotate the CommonJS export names for ESM import in node:
287
+ 0 && (module.exports = {
288
+ simplifyChapter,
289
+ simplifyCommentaryChapter,
290
+ simplifyHebrewSubtitle,
291
+ simplifyVerse,
292
+ simplifyVerseContent
293
+ });
294
+ //# sourceMappingURL=simple.cjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../generation/simple.ts"],
4
+ "sourcesContent": ["import {\r\n ChapterData,\r\n ChapterFootnote,\r\n ChapterHebrewSubtitle,\r\n ChapterVerse,\r\n ChapterWord,\r\n CommentaryChapterData,\r\n SimpleChapterContent,\r\n SimpleChapterData,\r\n SimpleChapterHebrewSubtitle,\r\n SimpleChapterVerse,\r\n SimpleChapterWord,\r\n SimpleCommentaryChapterData,\r\n SimpleInlineHeading,\r\n SimplePoemRange,\r\n SimpleTextRange,\r\n SimpleVerseFootnote,\r\n TranslationBookChapterWords,\r\n SimpleTranslationBookChapterWords,\r\n} from './common-types.js';\r\n\r\n/**\r\n * The types of content that can be contained in a verse or Hebrew Subtitle.\r\n */\r\ntype VerseContent =\r\n | ChapterVerse['content'][number]\r\n | ChapterHebrewSubtitle['content'][number];\r\n\r\n/**\r\n * The result of flattening the content of a verse into a single string.\r\n */\r\nexport interface SimplifiedVerseContent {\r\n /**\r\n * The text of the verse.\r\n */\r\n text: string;\r\n\r\n /**\r\n * The footnotes that occur in the verse.\r\n */\r\n footnotes: SimpleVerseFootnote[];\r\n\r\n /**\r\n * The headings that occur in the middle of the verse.\r\n */\r\n headings: SimpleInlineHeading[];\r\n\r\n /**\r\n * The ranges of text that represent the Words of Jesus.\r\n */\r\n wordsOfJesus: SimpleTextRange[];\r\n\r\n /**\r\n * The ranges of text that represent lines of poetry.\r\n */\r\n poem: SimplePoemRange[];\r\n\r\n /**\r\n * The word-level annotations for the verse, with their offsets remapped onto the text.\r\n */\r\n words: SimpleChapterWord[];\r\n}\r\n\r\n/**\r\n * Flattens the content of a verse into a single string, recording the positions of the\r\n * footnotes, headings, and formatting that occur in it.\r\n *\r\n * The rules used to build the text are:\r\n * - Strings and formatted text are appended as-is. The source data already contains the\r\n * spacing that is needed between them.\r\n * - Lines of poetry and line breaks start a new line.\r\n * - Footnote and heading markers are replaced with a single space when one is needed to\r\n * keep the surrounding words apart.\r\n *\r\n * All of the recorded offsets are measured in UTF-16 code units, which is what\r\n * `String.prototype.slice()` and `String.prototype.length` use.\r\n *\r\n * Word-level annotations are anchored to a range of characters in a single item of the\r\n * content array. Since the simplified format replaces that array with a single string,\r\n * their offsets are remapped onto the text that is built here.\r\n *\r\n * @param content The content of the verse.\r\n * @param footnotes The footnotes for the chapter, keyed by note ID.\r\n * @param usedFootnotes A set that the IDs of the referenced footnotes are added to.\r\n * @param words The word-level annotations for the verse.\r\n */\r\nexport function simplifyVerseContent(\r\n content: readonly VerseContent[],\r\n footnotes: Map<number, ChapterFootnote> = new Map(),\r\n usedFootnotes: Set<number> = new Set(),\r\n words: readonly ChapterWord[] = []\r\n): SimplifiedVerseContent {\r\n let text = '';\r\n const verseFootnotes: SimpleVerseFootnote[] = [];\r\n const headings: SimpleInlineHeading[] = [];\r\n const wordsOfJesus: SimpleTextRange[] = [];\r\n const poem: SimplePoemRange[] = [];\r\n const verseWords: SimpleChapterWord[] = [];\r\n\r\n const wordsByContentIndex = new Map<number, ChapterWord[]>();\r\n for (let word of words) {\r\n let arr = wordsByContentIndex.get(word.contentIndex);\r\n if (!arr) {\r\n arr = [];\r\n wordsByContentIndex.set(word.contentIndex, arr);\r\n }\r\n arr.push(word);\r\n }\r\n\r\n /**\r\n * Removes the given number of characters from the end of the text and moves any\r\n * offsets that pointed into the removed region back to the new end of the text.\r\n */\r\n const truncateTo = (length: number) => {\r\n if (length >= text.length) {\r\n return;\r\n }\r\n text = text.slice(0, length);\r\n for (let footnote of verseFootnotes) {\r\n footnote.offset = Math.min(footnote.offset, length);\r\n }\r\n for (let heading of headings) {\r\n heading.offset = Math.min(heading.offset, length);\r\n }\r\n for (let range of [...wordsOfJesus, ...poem, ...verseWords]) {\r\n range.start = Math.min(range.start, length);\r\n range.end = Math.min(range.end, length);\r\n }\r\n };\r\n\r\n /**\r\n * Moves the annotations for the content item at the given index onto the text that\r\n * the item was appended to.\r\n */\r\n const addWordsForContent = (\r\n contentIndex: number,\r\n contentStart: number,\r\n contentLength: number\r\n ) => {\r\n const contentWords = wordsByContentIndex.get(contentIndex);\r\n if (!contentWords) {\r\n return;\r\n }\r\n\r\n for (let { contentIndex: _index, ...word } of contentWords) {\r\n verseWords.push({\r\n ...word,\r\n start: contentStart + Math.min(word.start, contentLength),\r\n end: contentStart + Math.min(word.end, contentLength),\r\n });\r\n }\r\n };\r\n\r\n /**\r\n * Starts a new line, first removing any spaces that were left at the end of the\r\n * current one.\r\n */\r\n const startNewLine = () => {\r\n truncateTo(text.replace(/[^\\S\\n]+$/, '').length);\r\n text += '\\n';\r\n };\r\n\r\n /**\r\n * Determines whether a space needs to be inserted in place of a marker in order to\r\n * keep the text that surrounds it apart.\r\n */\r\n const needsSeparator = (next: VerseContent | undefined) => {\r\n if (text.length <= 0 || /\\s$/.test(text) || !next) {\r\n return false;\r\n }\r\n if (typeof next === 'string') {\r\n return next.length > 0 && !/^\\s/.test(next);\r\n }\r\n if ('text' in next) {\r\n // Poem lines always start a new line, so they never need a separator.\r\n return (\r\n typeof next.poem !== 'number' &&\r\n next.text.length > 0 &&\r\n !/^\\s/.test(next.text)\r\n );\r\n }\r\n // Line breaks start their own line, and consecutive markers only ever need\r\n // a single separator between them.\r\n return false;\r\n };\r\n\r\n for (let i = 0; i < content.length; i++) {\r\n const part = content[i];\r\n\r\n if (typeof part === 'string') {\r\n addWordsForContent(i, text.length, part.length);\r\n text += part;\r\n continue;\r\n }\r\n\r\n if ('text' in part) {\r\n if (\r\n typeof part.poem === 'number' &&\r\n text.length > 0 &&\r\n !text.endsWith('\\n')\r\n ) {\r\n startNewLine();\r\n }\r\n\r\n const start = text.length;\r\n addWordsForContent(i, start, part.text.length);\r\n text += part.text;\r\n const end = text.length;\r\n\r\n if (end > start) {\r\n if (part.wordsOfJesus) {\r\n wordsOfJesus.push({ start, end });\r\n }\r\n if (typeof part.poem === 'number') {\r\n poem.push({ start, end, level: part.poem });\r\n }\r\n }\r\n } else if ('lineBreak' in part) {\r\n if (text.length > 0 && !text.endsWith('\\n')) {\r\n startNewLine();\r\n }\r\n } else if ('noteId' in part) {\r\n const footnote = footnotes.get(part.noteId);\r\n if (footnote) {\r\n usedFootnotes.add(part.noteId);\r\n verseFootnotes.push({\r\n noteId: footnote.noteId,\r\n offset: text.length,\r\n text: footnote.text,\r\n caller: footnote.caller,\r\n });\r\n }\r\n if (needsSeparator(content[i + 1])) {\r\n text += ' ';\r\n }\r\n } else if ('heading' in part) {\r\n headings.push({\r\n offset: text.length,\r\n text: part.heading,\r\n });\r\n if (needsSeparator(content[i + 1])) {\r\n text += ' ';\r\n }\r\n }\r\n }\r\n\r\n // Trim the whitespace that line breaks and separators can leave behind.\r\n truncateTo(text.replace(/\\s+$/, '').length);\r\n\r\n const leading = text.length - text.replace(/^\\s+/, '').length;\r\n if (leading > 0) {\r\n text = text.slice(leading);\r\n for (let footnote of verseFootnotes) {\r\n footnote.offset = Math.max(0, footnote.offset - leading);\r\n }\r\n for (let heading of headings) {\r\n heading.offset = Math.max(0, heading.offset - leading);\r\n }\r\n for (let range of [...wordsOfJesus, ...poem, ...verseWords]) {\r\n range.start = Math.max(0, range.start - leading);\r\n range.end = Math.max(0, range.end - leading);\r\n }\r\n }\r\n\r\n return {\r\n text,\r\n footnotes: verseFootnotes,\r\n headings,\r\n wordsOfJesus: mergeAdjacentRanges(wordsOfJesus, text),\r\n poem: poem.filter((range) => range.start < range.end),\r\n words: verseWords.filter((word) => word.start < word.end),\r\n };\r\n}\r\n\r\n/**\r\n * Merges the ranges that are only separated by whitespace into single ranges.\r\n * @param ranges The ranges to merge. Must be sorted by their start offset.\r\n * @param text The text that the ranges point into.\r\n */\r\nfunction mergeAdjacentRanges(\r\n ranges: SimpleTextRange[],\r\n text: string\r\n): SimpleTextRange[] {\r\n const merged: SimpleTextRange[] = [];\r\n for (let range of ranges) {\r\n if (range.start >= range.end) {\r\n continue;\r\n }\r\n const previous = merged[merged.length - 1];\r\n if (\r\n previous &&\r\n range.start >= previous.end &&\r\n !/\\S/.test(text.slice(previous.end, range.start))\r\n ) {\r\n previous.end = range.end;\r\n } else {\r\n merged.push(range);\r\n }\r\n }\r\n return merged;\r\n}\r\n\r\n/**\r\n * Converts the given verse into its simplified representation.\r\n * @param verse The verse to convert.\r\n * @param footnotes The footnotes for the chapter, keyed by note ID.\r\n * @param usedFootnotes A set that the IDs of the referenced footnotes are added to.\r\n * @param words The word-level annotations for the verse.\r\n * @param remappedWords An array that the remapped word-level annotations are added to.\r\n */\r\nexport function simplifyVerse(\r\n verse: ChapterVerse,\r\n footnotes?: Map<number, ChapterFootnote>,\r\n usedFootnotes?: Set<number>,\r\n words?: readonly ChapterWord[],\r\n remappedWords?: SimpleChapterWord[]\r\n): SimpleChapterVerse {\r\n const simplified = simplifyVerseContent(\r\n verse.content,\r\n footnotes,\r\n usedFootnotes,\r\n words\r\n );\r\n\r\n if (remappedWords) {\r\n remappedWords.push(...simplified.words);\r\n }\r\n\r\n return {\r\n type: 'verse',\r\n number: verse.number,\r\n ...omitEmptyProperties(simplified),\r\n };\r\n}\r\n\r\n/**\r\n * Converts the given Hebrew Subtitle into its simplified representation.\r\n * @param subtitle The subtitle to convert.\r\n * @param footnotes The footnotes for the chapter, keyed by note ID.\r\n * @param usedFootnotes A set that the IDs of the referenced footnotes are added to.\r\n */\r\nexport function simplifyHebrewSubtitle(\r\n subtitle: ChapterHebrewSubtitle,\r\n footnotes?: Map<number, ChapterFootnote>,\r\n usedFootnotes?: Set<number>\r\n): SimpleChapterHebrewSubtitle {\r\n const simplified = simplifyVerseContent(\r\n subtitle.content,\r\n footnotes,\r\n usedFootnotes\r\n );\r\n\r\n return {\r\n type: 'hebrew_subtitle',\r\n ...omitEmptyProperties(simplified),\r\n };\r\n}\r\n\r\n/**\r\n * Omits the optional properties of the given simplified content when they are empty.\r\n * @param content The content to omit the empty properties from.\r\n */\r\nfunction omitEmptyProperties(content: SimplifiedVerseContent) {\r\n return {\r\n text: content.text,\r\n footnotes: content.footnotes,\r\n ...(content.headings.length > 0 ? { headings: content.headings } : {}),\r\n ...(content.wordsOfJesus.length > 0\r\n ? { wordsOfJesus: content.wordsOfJesus }\r\n : {}),\r\n ...(content.poem.length > 0 ? { poem: content.poem } : {}),\r\n };\r\n}\r\n\r\n/**\r\n * The result of converting a chapter into the simplified chapter format.\r\n */\r\nexport interface SimplifiedChapter {\r\n /**\r\n * The simplified chapter.\r\n */\r\n chapter: SimpleChapterData;\r\n\r\n /**\r\n * The word-level annotations for the chapter, with their offsets remapped onto the\r\n * text of each simplified verse. Empty if the chapter has no annotations.\r\n */\r\n words: SimpleTranslationBookChapterWords;\r\n}\r\n\r\n/**\r\n * Converts the given chapter into the simplified chapter format.\r\n *\r\n * In the simplified format, the content of each verse is a single string instead of a list\r\n * of formatted content, and the footnotes are available on the verse that they occur in,\r\n * along with the offset that they occur at.\r\n *\r\n * The word-level annotations are returned separately, since they are published in their\r\n * own file. They are converted here because their offsets have to be remapped onto the\r\n * text that is built for each verse.\r\n *\r\n * @param chapter The chapter to convert.\r\n * @param words The word-level annotations for the chapter, keyed by verse number.\r\n */\r\nexport function simplifyChapter(\r\n chapter: ChapterData,\r\n words?: TranslationBookChapterWords\r\n): SimplifiedChapter {\r\n const footnotes = new Map<number, ChapterFootnote>();\r\n for (let footnote of chapter.footnotes) {\r\n footnotes.set(footnote.noteId, footnote);\r\n }\r\n\r\n const usedFootnotes = new Set<number>();\r\n const content: SimpleChapterContent[] = [];\r\n const versesByNumber = new Map<number, SimpleChapterVerse>();\r\n const simpleWords: SimpleTranslationBookChapterWords = {};\r\n\r\n for (let c of chapter.content) {\r\n if (c.type === 'verse') {\r\n const verseWords = words?.[String(c.number)];\r\n const remappedWords: SimpleChapterWord[] = [];\r\n const verse = simplifyVerse(\r\n c,\r\n footnotes,\r\n usedFootnotes,\r\n verseWords,\r\n remappedWords\r\n );\r\n if (remappedWords.length > 0) {\r\n simpleWords[String(c.number)] = remappedWords;\r\n }\r\n versesByNumber.set(verse.number, verse);\r\n content.push(verse);\r\n } else if (c.type === 'hebrew_subtitle') {\r\n content.push(simplifyHebrewSubtitle(c, footnotes, usedFootnotes));\r\n } else if (c.type === 'heading') {\r\n content.push({\r\n type: 'heading',\r\n text: c.content.join(' '),\r\n });\r\n } else if (c.type === 'line_break') {\r\n content.push({\r\n type: 'line_break',\r\n });\r\n }\r\n }\r\n\r\n // Footnotes that aren't referenced by any verse content, but that do reference a\r\n // verse, get attached to the end of that verse.\r\n const unreferencedFootnotes: ChapterFootnote[] = [];\r\n for (let footnote of chapter.footnotes) {\r\n if (usedFootnotes.has(footnote.noteId)) {\r\n continue;\r\n }\r\n\r\n const verse = footnote.reference\r\n ? versesByNumber.get(footnote.reference.verse)\r\n : undefined;\r\n\r\n if (verse) {\r\n verse.footnotes.push({\r\n noteId: footnote.noteId,\r\n offset: verse.text.length,\r\n text: footnote.text,\r\n caller: footnote.caller,\r\n });\r\n } else {\r\n unreferencedFootnotes.push(footnote);\r\n }\r\n }\r\n\r\n return {\r\n chapter: {\r\n number: chapter.number,\r\n content,\r\n footnotes: unreferencedFootnotes,\r\n },\r\n words: simpleWords,\r\n };\r\n}\r\n\r\n/**\r\n * Converts the given commentary chapter into the simplified chapter format.\r\n * @param chapter The chapter to convert.\r\n */\r\nexport function simplifyCommentaryChapter(\r\n chapter: CommentaryChapterData\r\n): SimpleCommentaryChapterData {\r\n return {\r\n number: chapter.number,\r\n ...(chapter.introduction !== undefined\r\n ? { introduction: chapter.introduction }\r\n : {}),\r\n content: chapter.content.map((verse) => simplifyVerse(verse)),\r\n };\r\n}\r\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -34,10 +34,10 @@ __export(helloao_tools_exports, {
34
34
  utils: () => utils
35
35
  });
36
36
  module.exports = __toCommonJS(helloao_tools_exports);
37
- var utils = __toESM(require("./utils.js"));
38
- var generation = __toESM(require("./generation/index.js"));
39
- var parser = __toESM(require("./parser/index.js"));
40
- var log = __toESM(require("./log.js"));
37
+ var utils = __toESM(require("./utils.js"), 1);
38
+ var generation = __toESM(require("./generation/index.js"), 1);
39
+ var parser = __toESM(require("./parser/index.js"), 1);
40
+ var log = __toESM(require("./log.js"), 1);
41
41
  // Annotate the CommonJS export names for ESM import in node:
42
42
  0 && (module.exports = {
43
43
  generation,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../index.ts"],
4
- "sourcesContent": ["import * as utils from './utils.js';\r\nimport * as generation from './generation/index.js';\r\nimport * as parser from './parser/index.js';\r\nimport * as log from './log.js';\r\n\r\nexport { utils, generation, parser, log };\r\n"],
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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAAuB;AACvB,iBAA4B;AAC5B,aAAwB;AACxB,UAAqB;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../log.ts"],
4
- "sourcesContent": ["/**\r\n * A simple logging interface that can be used to log messages.\r\n */\r\nexport interface Logger {\r\n log: (message: any, ...args: any[]) => void;\r\n warn: (message: string, ...args: any[]) => void;\r\n error: (message: string, ...args: any[]) => void;\r\n}\r\n\r\n/**\r\n * A logger that logs messages to the console.\r\n */\r\nexport const consoleLogger: Logger = {\r\n log: (message: string, ...args) => {\r\n console.log(message, ...args);\r\n },\r\n warn: (message: string, ...args) => {\r\n console.warn(message, ...args);\r\n },\r\n error: (message: string, ...args) => {\r\n console.error(message, ...args);\r\n },\r\n};\r\n\r\n/**\r\n * The logger that should be used for logging messages.\r\n */\r\nlet logger: Logger = consoleLogger;\r\n\r\n/**\r\n * Gets the logger that is currently being used for logging messages.\r\n * @returns The logger that is currently being used.\r\n */\r\nexport function getLogger(): Logger {\r\n return logger;\r\n}\r\n\r\n/**\r\n * Sets the logger to use for logging messages.\r\n * @param newLogger The new logger to use.\r\n */\r\nexport function setLogger(newLogger: Logger) {\r\n logger = newLogger;\r\n}\r\n"],
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": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYO,MAAM,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,SAAS,YAAoB;AAChC,SAAO;AACX;AAMO,SAAS,UAAU,WAAmB;AACzC,WAAS;AACb;",
6
6
  "names": []
7
7
  }
@@ -120,11 +120,11 @@ class CodexParser {
120
120
  const chapter = ensureChapter(chapterNumber);
121
121
  chapter.footnotes.push(footnote);
122
122
  }
123
- function addReference(ref2, content) {
124
- addChapterContent(ref2.chapter, [
123
+ function addReference(ref, content) {
124
+ addChapterContent(ref.chapter, [
125
125
  {
126
126
  type: "verse",
127
- number: ref2.verse,
127
+ number: ref.verse,
128
128
  content
129
129
  }
130
130
  ]);
@@ -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": "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",
6
- "names": ["ref", "lines"]
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": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAkB;AAQlB,mBAAyD;AAElD,MAAM,uBAAuB,aAAE,OAAO;AAAA,EACzC,MAAM,aAAE,QAAQ,iBAAiB;AAAA,EACjC,MAAM,aAAE,OAAO;AAAA,IACX,SAAS,aAAE,OAAO,OAAO,EAAE,IAAI;AAAA,EACnC,CAAC;AACL,CAAC;AAEM,MAAM,cAAc,aAAE,OAAO;AAAA,EAChC,MAAM,aAAE,QAAQ,MAAM;AAAA,EACtB,IAAI,aAAE,OAAO;AAAA,EACb,UAAU,aAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,SAAS,aAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,OAAO,aAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,MAAM,aACD,OAAO;AAAA,IACJ,kBAAkB,aAAE,MAAM,aAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACnD,CAAC,EACA,SAAS;AAClB,CAAC;AAEM,MAAM,iBAAiB,aAAE,OAAO;AAAA,EACnC,MAAM,aAAE,QAAQ,UAAU;AAAA,EAC1B,IAAI,aAAE,OAAO;AACjB,CAAC;AAEM,MAAM,iBAAiB,aAAE,mBAAmB,QAAQ;AAAA,EACvD;AAAA,EACA;AAAA,EACA;AACJ,CAAC;AAEM,MAAM,cAAc,aAAE,OAAO;AAAA,EAChC,OAAO,aAAE;AAAA,IACL,aAAE,OAAO;AAAA,MACL,MAAM,aAAE,OAAO;AAAA,MACf,YAAY,aAAE,OAAO;AAAA,MACrB,OAAO,aAAE,OAAO;AAAA,MAChB,UAAU,aACL,OAAO;AAAA,QACJ,MAAM,aAAE,OAAO;AAAA,MACnB,CAAC,EACA,YAAY,EACZ,SAAS,EACT,SAAS;AAAA,IAClB,CAAC;AAAA,EACL;AACJ,CAAC;AAKM,MAAM,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOb,eAAuB;AAAA,EAEvB;AAAA,EAER,YAAY,QAAmB;AAC3B,SAAK,UAAU;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,MAAM,OAA0B;AACnC,UAAM,OAAO,KAAK,MAAM,KAAK;AAC7B,UAAM,OAAO,YAAY,MAAM,IAAI;AAEnC,QAAI,OAAkB;AAAA,MAClB,MAAM;AAAA,MACN,SAAS,CAAC;AAAA,IACd;AAEA,QAAI,WAAiC,oBAAI,IAAI;AAC7C,QAAI,cAA8B;AAElC,aAAS,cAAc,eAAuB;AAC1C,UAAI,UAAU,SAAS,IAAI,aAAa;AACxC,UAAI,CAAC,SAAS;AACV,kBAAU;AAAA,UACN,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,SAAS,CAAC;AAAA,UACV,WAAW,CAAC;AAAA,QAChB;AACA,sBAAc;AACd,iBAAS,IAAI,eAAe,OAAO;AAAA,MACvC;AAEA,aAAO;AAAA,IACX;AAEA,aAAS,mBAAmB,KAAuB;AAC/C,UAAI,UAAU;AACd,eAAS,WAAW,IAAI,YAAY;AAChC,mBAAW,QAAQ;AAAA,MACvB;AACA,aAAO;AAAA,IACX;AAEA,aAAS,kBACL,eACA,SACF;AACE,YAAM,UAAU,cAAc,aAAa;AAC3C,cAAQ,QAAQ,KAAK,GAAG,OAAO;AAAA,IACnC;AAEA,aAAS,mBACL,eACA,UACF;AACE,YAAM,UAAU,cAAc,aAAa;AAC3C,cAAQ,UAAU,KAAK,QAAQ;AAAA,IACnC;AAEA,aAAS,aAAa,KAAe,SAA2B;AAC5D,wBAAkB,IAAI,SAAS;AAAA,QAC3B;AAAA,UACI,MAAM;AAAA,UACN,QAAQ,IAAI;AAAA,UACZ;AAAA,QACJ;AAAA,MACJ,CAAC;AAAA,IACL;AAEA,aAAS,UAAU,OAAe;AAC9B,aAAO,MAAM,QAAQ,YAAY,EAAE;AAAA,IACvC;AAEA,aAAS,UAAU,SAAiB;AAChC,aAAO;AAAA,QACH,MAAM;AAAA,QACN,SAAS,CAAC,OAAO;AAAA,MACrB;AAAA,IACJ;AAEA,aAAS,cAAcA,QAAyB;AAC5C,aAAOA,OAAM;AAAA,QACT,CAAC,MAAM,YAAY;AACf,cAAI,OAAO,YAAY,YAAY,QAAQ,KAAK,MAAM,IAAI;AACtD,mBAAO;AAAA,UACX;AACA,cAAI,KAAK,WAAW,GAAG;AACnB,mBAAO,CAAC,OAAO;AAAA,UACnB,OAAO;AACH,mBAAO;AAAA,cACH,GAAG;AAAA,cACH;AAAA,gBACI,WAAW;AAAA,cACf;AAAA,cACA;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ;AAAA,QACA,CAAC;AAAA,MACL;AAAA,IACJ;AAEA,QAAI,oBAAqC;AACzC,QAAI,QAA0B,CAAC;AAE/B,aAAS,QAAQ,KAAK,OAAO;AACzB,UAAI,KAAK,eAAe,UAAU,KAAK,OAAO;AAC1C,YAAI,CAAC,KAAK,SAAU;AAEpB,cAAM,iBAAiB,eAAe,UAAU,KAAK,QAAQ;AAE7D,YAAI,CAAC,eAAe,QAAS;AAC7B,cAAM,WAAW,eAAe;AAChC,YAAI,SAAS,SAAS,QAAQ;AAC1B,cAAI,gBAAY,kCAAoB,SAAS,EAAE;AAC/C,cAAI,CAAC,WAAW;AACZ,gBAAI,SAAS,YAAY,SAAS,SAAS;AACvC,oBAAM,aAAS,wBAAU,SAAS,QAAQ;AAC1C,kBAAI,CAAC,QAAQ;AACT,sBAAM,IAAI;AAAA,kBACN,sCACI,SAAS;AAAA,gBACjB;AAAA,cACJ;AAEA,kBAAI,SAAS,OAAO;AAChB,4BAAY;AAAA,kBACR,MAAM;AAAA,kBACN,SAAS,SAAS;AAAA,kBAClB,OAAO,SAAS;AAAA,gBACpB;AAAA,cACJ,WAAW,mBAAmB,OAAO;AACjC,oBACI,kBAAkB,YACd,SAAS,WACb,kBAAkB,SAAS,QAC7B;AACE,wBAAM,IAAI;AAAA,oBACN;AAAA,kBACJ;AAAA,gBACJ;AAGA,4BAAY;AAAA,kBACR,MAAM;AAAA,kBACN,SAAS,SAAS;AAAA,kBAClB,OAAO,kBAAkB;AAAA,gBAC7B;AAAA,cACJ,OAAO;AACH,sBAAM,IAAI;AAAA,kBACN;AAAA,gBACJ;AAAA,cACJ;AAAA,YACJ,WAAW,SAAS,MAAM,kBAAkB,QAAQ;AAChD,8BAAY;AAAA,gBACR,SAAS,KAAK,iBAAiB,CAAC;AAAA,cACpC;AACA,kBAAI,CAAC,WAAW;AACZ,sBAAM,IAAI;AAAA,kBACN;AAAA,gBACJ;AAAA,cACJ;AAAA,YACJ,OAAO;AACH,oBAAM,IAAI;AAAA,gBACN;AAAA,cACJ;AAAA,YACJ;AAAA,UACJ;AAEA,cACI,sBACC,UAAU,SAAS,kBAAkB,QAClC,UAAU,YAAY,kBAAkB,WACxC,UAAU,UAAU,kBAAkB,QAC5C;AACE,yBAAa,mBAAmB,cAAc,KAAK,CAAC;AACpD,oBAAQ,CAAC;AAAA,UACb;AAEA,8BAAoB;AAEpB,cAAI,CAAC,KAAK,GAAI,MAAK,KAAK,UAAU;AAElC,gBAAM,MAAM,KAAK,QAAQ;AAAA,YACrB,KAAK;AAAA,YACL;AAAA,UACJ;AAEA,mBAAS,WAAW,IAAI,UAAU;AAC9B,kBAAM,eAAe,QAAQ;AAAA,cACzB;AAAA,YACJ;AACA,uBAAW,YAAY,cAAc;AACjC,oBAAM,eACF,SAAS,aAAa,eAAe;AACzC,kBAAI,cAAc;AACd,sBAAM,cACF,KAAK,QAAQ;AAAA,kBACT;AAAA,kBACA;AAAA,gBACJ;AACJ,sBAAM,eACF,mBAAmB,WAAW;AAClC,oBAAI,cAAc;AACd,qCAAmB,UAAU,SAAS;AAAA,oBAClC,QAAQ,KAAK;AAAA,oBACb,MAAM;AAAA,oBACN,QAAQ;AAAA,kBACZ,CAAC;AAAA,gBACL;AAAA,cACJ;AACA,uBAAS,OAAO;AAAA,YACpB;AAAA,UACJ;AAEA,gBAAM,UAAU,mBAAmB,GAAG;AAEtC,cAAI,SAAS;AAET,kBAAM,WAAW,QAAQ,MAAM,IAAI;AAEnC,kBAAM,KAAK,GAAG,QAAQ;AAAA,UAC1B;AAAA,QACJ,WAAW,SAAS,SAAS,YAAY;AACrC,gBAAM,gBAAY,kCAAoB,GAAG,SAAS,EAAE,IAAI;AACxD,cAAI,WAAW;AACX,kBAAM,MAAM,KAAK,QAAQ;AAAA,cACrB,KAAK;AAAA,cACL;AAAA,YACJ;AACA,kBAAM,UAAU,mBAAmB,GAAG;AAEtC,gBAAI,CAAC,SAAS;AACV;AAAA,YACJ;AAGA,kBAAMA,SAAQ,QACT,MAAM,IAAI,EACV,OAAyB,CAAC,MAAM,YAAY;AACzC,kBAAI,KAAK,WAAW;AAChB,uBAAO,CAAC,UAAU,OAAO,CAAC;AAAA;AAE1B,uBAAO;AAAA,kBACH,GAAG;AAAA,kBACH;AAAA,oBACI,MAAM;AAAA,kBACV;AAAA,kBACA,UAAU,OAAO;AAAA,gBACrB;AAAA,YACR,GAAG,CAAC,CAAC;AAET,YAAAA,OAAM;AAAA,cAAQ,CAAC,SACX,kBAAkB,UAAU,SAAS,CAAC,IAAI,CAAC;AAAA,YAC/C;AAAA,UACJ,OAAO;AACH,kBAAM,MAAM,KAAK,QAAQ;AAAA,cACrB,KAAK;AAAA,cACL;AAAA,YACJ;AACA,kBAAM,UAAU,mBAAmB,GAAG;AAGtC,gBAAI,WAAW,CAAC,KAAK,UAAU;AAC3B,kBAAI,aAAa;AACb,gBAAC,YAAwB,UAAU,KAAK;AAAA,kBACpC,QAAQ,KAAK;AAAA,kBACb,MAAM;AAAA,kBACN,QAAQ;AAAA,gBACZ,CAAC;AAAA,cACL;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAEA,QAAI,mBAAmB;AACnB,mBAAa,mBAAmB,cAAc,KAAK,CAAC;AAAA,IACxD;AAEA,aAAS,WAAW,SAAS,OAAO,GAAG;AACnC,WAAK,QAAQ,KAAK,OAAO;AAAA,IAC7B;AAEA,WAAO;AAAA,EACX;AACJ;",
6
+ "names": ["lines"]
7
7
  }
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,19 +17,28 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
  var commentary_csv_parser_exports = {};
20
30
  __export(commentary_csv_parser_exports, {
21
31
  CommentaryCsvParser: () => CommentaryCsvParser
22
32
  });
23
33
  module.exports = __toCommonJS(commentary_csv_parser_exports);
24
- var import_utils = require("../utils");
25
- var import_papaparse = require("papaparse");
34
+ var import_utils = require("../utils.js");
35
+ var import_papaparse = __toESM(require("papaparse"), 1);
36
+ const { parse } = import_papaparse.default;
26
37
  class CommentaryCsvParser {
27
38
  parse(data) {
28
39
  const firstLine = data.indexOf("\n");
29
40
  data = data.substring(firstLine + 1);
30
- const lines = (0, import_papaparse.parse)(data, {
41
+ const lines = parse(data, {
31
42
  header: false,
32
43
  // transformHeader: (_, index) => {
33
44
  // const headers = ['book', 'chapter', 'verse', 'commentaries'];
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../parser/commentary-csv-parser.ts"],
4
- "sourcesContent": ["import {\r\n CommentaryBookNode,\r\n CommentaryChapterNode,\r\n CommentaryParseTree,\r\n} from './types';\r\nimport { getBookId, parseVerseReference } from '../utils';\r\nimport { parse } from 'papaparse';\r\n\r\nexport interface CsvLine {\r\n book: string;\r\n chapter: string;\r\n verse: string;\r\n commentaries: string;\r\n}\r\n\r\nexport class CommentaryCsvParser {\r\n parse(data: string): CommentaryParseTree {\r\n // remove header automatically\r\n const firstLine = data.indexOf('\\n');\r\n data = data.substring(firstLine + 1);\r\n\r\n const lines = parse<string[]>(data, {\r\n header: false,\r\n // transformHeader: (_, index) => {\r\n // const headers = ['book', 'chapter', 'verse', 'commentaries'];\r\n // if (index < headers.length) {\r\n // return headers[index];\r\n // } else {\r\n // return '';\r\n // }\r\n // },\r\n delimiter: ',',\r\n escapeChar: '\"',\r\n quoteChar: '\"',\r\n });\r\n return this.parseLines(\r\n lines.data.map((line: string[]) => ({\r\n book: line[0],\r\n chapter: line[1],\r\n verse: line[2],\r\n commentaries: line[3],\r\n }))\r\n );\r\n }\r\n\r\n parseLines(data: CsvLine[]): CommentaryParseTree {\r\n let tree: CommentaryParseTree = {\r\n type: 'commentary/root',\r\n books: [],\r\n };\r\n\r\n let book: CommentaryBookNode | null = null;\r\n let chapter: CommentaryChapterNode | null = null;\r\n for (let line of data) {\r\n if (hasValue(line.book)) {\r\n const id = getBookId(line.book);\r\n if (!id) {\r\n throw new Error('Invalid book: ' + line.book);\r\n }\r\n\r\n book = tree.books.find((b) => b.book === id) ?? null;\r\n if (!book) {\r\n book = {\r\n type: 'book',\r\n book: id,\r\n introduction: null,\r\n chapters: [],\r\n };\r\n tree.books.push(book);\r\n }\r\n\r\n if (!book.introduction) {\r\n book.introduction = hasValue(line.commentaries)\r\n ? line.commentaries\r\n : null;\r\n }\r\n } else if (hasValue(line.chapter)) {\r\n const number = parseInt(line.chapter);\r\n if (isNaN(number)) {\r\n throw new Error('Invalid chapter number: ' + line.chapter);\r\n }\r\n\r\n if (!book) {\r\n throw new Error('Chapter without book');\r\n }\r\n\r\n chapter = {\r\n type: 'chapter',\r\n number,\r\n introduction: hasValue(line.commentaries)\r\n ? line.commentaries\r\n : null,\r\n verses: [],\r\n };\r\n book.chapters.push(chapter);\r\n } else if (hasValue(line.verse)) {\r\n const ref = parseVerseReference(line.verse);\r\n if (ref) {\r\n if (ref.book === book?.book) {\r\n // @ts-ignore\r\n if (ref.chapter === chapter?.number) {\r\n chapter.verses.push({\r\n type: 'verse',\r\n number: ref.verse,\r\n content: [line.commentaries],\r\n });\r\n } else {\r\n chapter = {\r\n type: 'chapter',\r\n number: ref.chapter,\r\n introduction: null,\r\n verses: [\r\n {\r\n type: 'verse',\r\n number: ref.verse,\r\n content: [line.commentaries],\r\n },\r\n ],\r\n };\r\n\r\n book.chapters.push(chapter);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return tree;\r\n }\r\n}\r\n\r\nfunction hasValue(value: string | null): boolean {\r\n return (\r\n value !== null &&\r\n value !== undefined &&\r\n value !== '' &&\r\n value.trim() !== ''\r\n );\r\n}\r\n"],
5
- "mappings": "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",
6
- "names": []
4
+ "sourcesContent": ["import {\r\n CommentaryBookNode,\r\n CommentaryChapterNode,\r\n CommentaryParseTree,\r\n} from './types.js';\r\nimport { getBookId, parseVerseReference } from '../utils.js';\r\nimport papaparse from 'papaparse';\r\n\r\nconst { parse } = papaparse;\r\n\r\nexport interface CsvLine {\r\n book: string;\r\n chapter: string;\r\n verse: string;\r\n commentaries: string;\r\n}\r\n\r\nexport class CommentaryCsvParser {\r\n parse(data: string): CommentaryParseTree {\r\n // remove header automatically\r\n const firstLine = data.indexOf('\\n');\r\n data = data.substring(firstLine + 1);\r\n\r\n const lines = parse<string[]>(data, {\r\n header: false,\r\n // transformHeader: (_, index) => {\r\n // const headers = ['book', 'chapter', 'verse', 'commentaries'];\r\n // if (index < headers.length) {\r\n // return headers[index];\r\n // } else {\r\n // return '';\r\n // }\r\n // },\r\n delimiter: ',',\r\n escapeChar: '\"',\r\n quoteChar: '\"',\r\n });\r\n return this.parseLines(\r\n lines.data.map((line: string[]) => ({\r\n book: line[0],\r\n chapter: line[1],\r\n verse: line[2],\r\n commentaries: line[3],\r\n }))\r\n );\r\n }\r\n\r\n parseLines(data: CsvLine[]): CommentaryParseTree {\r\n let tree: CommentaryParseTree = {\r\n type: 'commentary/root',\r\n books: [],\r\n };\r\n\r\n let book: CommentaryBookNode | null = null;\r\n let chapter: CommentaryChapterNode | null = null;\r\n for (let line of data) {\r\n if (hasValue(line.book)) {\r\n const id = getBookId(line.book);\r\n if (!id) {\r\n throw new Error('Invalid book: ' + line.book);\r\n }\r\n\r\n book = tree.books.find((b) => b.book === id) ?? null;\r\n if (!book) {\r\n book = {\r\n type: 'book',\r\n book: id,\r\n introduction: null,\r\n chapters: [],\r\n };\r\n tree.books.push(book);\r\n }\r\n\r\n if (!book.introduction) {\r\n book.introduction = hasValue(line.commentaries)\r\n ? line.commentaries\r\n : null;\r\n }\r\n } else if (hasValue(line.chapter)) {\r\n const number = parseInt(line.chapter);\r\n if (isNaN(number)) {\r\n throw new Error('Invalid chapter number: ' + line.chapter);\r\n }\r\n\r\n if (!book) {\r\n throw new Error('Chapter without book');\r\n }\r\n\r\n chapter = {\r\n type: 'chapter',\r\n number,\r\n introduction: hasValue(line.commentaries)\r\n ? line.commentaries\r\n : null,\r\n verses: [],\r\n };\r\n book.chapters.push(chapter);\r\n } else if (hasValue(line.verse)) {\r\n const ref = parseVerseReference(line.verse);\r\n if (ref) {\r\n if (ref.book === book?.book) {\r\n // @ts-ignore\r\n if (ref.chapter === chapter?.number) {\r\n chapter.verses.push({\r\n type: 'verse',\r\n number: ref.verse,\r\n content: [line.commentaries],\r\n });\r\n } else {\r\n chapter = {\r\n type: 'chapter',\r\n number: ref.chapter,\r\n introduction: null,\r\n verses: [\r\n {\r\n type: 'verse',\r\n number: ref.verse,\r\n content: [line.commentaries],\r\n },\r\n ],\r\n };\r\n\r\n book.chapters.push(chapter);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return tree;\r\n }\r\n}\r\n\r\nfunction hasValue(value: string | null): boolean {\r\n return (\r\n value !== null &&\r\n value !== undefined &&\r\n value !== '' &&\r\n value.trim() !== ''\r\n );\r\n}\r\n"],
5
+ "mappings": "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",
6
+ "names": ["papaparse"]
7
7
  }
@@ -37,7 +37,7 @@ __reExport(parser_exports, require("./usfm-parser.js"), module.exports);
37
37
  __reExport(parser_exports, require("./usx-parser.js"), module.exports);
38
38
  __reExport(parser_exports, require("./codex-parser.js"), module.exports);
39
39
  __reExport(parser_exports, require("./commentary-csv-parser.js"), module.exports);
40
- var iterators = __toESM(require("./iterators.js"));
40
+ var iterators = __toESM(require("./iterators.js"), 1);
41
41
  // Annotate the CommonJS export names for ESM import in node:
42
42
  0 && (module.exports = {
43
43
  iterators,