@helloao/tools 0.0.5 → 0.0.6-alpha

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 (107) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +98 -98
  3. package/dist/cjs/generation/api.cjs +240 -0
  4. package/dist/cjs/generation/api.cjs.map +7 -0
  5. package/dist/cjs/generation/audio.cjs +83 -0
  6. package/dist/cjs/generation/audio.cjs.map +7 -0
  7. package/dist/cjs/generation/book-order.cjs +508 -0
  8. package/dist/cjs/generation/book-order.cjs.map +7 -0
  9. package/dist/cjs/generation/common-types.cjs +17 -0
  10. package/dist/cjs/generation/common-types.cjs.map +7 -0
  11. package/dist/cjs/generation/dataset.cjs +158 -0
  12. package/dist/cjs/generation/dataset.cjs.map +7 -0
  13. package/dist/cjs/generation/index.cjs +51 -0
  14. package/dist/cjs/generation/index.cjs.map +7 -0
  15. package/dist/cjs/index.cjs +45 -0
  16. package/dist/cjs/index.cjs.map +7 -0
  17. package/dist/cjs/parser/codex-parser.cjs +176 -0
  18. package/dist/cjs/parser/codex-parser.cjs.map +7 -0
  19. package/dist/cjs/parser/index.cjs +48 -0
  20. package/dist/cjs/parser/index.cjs.map +7 -0
  21. package/dist/cjs/parser/iterators.cjs +204 -0
  22. package/dist/cjs/parser/iterators.cjs.map +7 -0
  23. package/dist/cjs/parser/types.cjs +17 -0
  24. package/dist/cjs/parser/types.cjs.map +7 -0
  25. package/dist/cjs/parser/usfm-parser.cjs +791 -0
  26. package/dist/cjs/parser/usfm-parser.cjs.map +7 -0
  27. package/dist/cjs/parser/usx-parser.cjs +471 -0
  28. package/dist/cjs/parser/usx-parser.cjs.map +7 -0
  29. package/dist/cjs/utils.cjs +85 -0
  30. package/dist/cjs/utils.cjs.map +7 -0
  31. package/dist/esm/generation/api.js +198 -0
  32. package/dist/esm/generation/api.js.map +7 -0
  33. package/dist/esm/generation/audio.js +53 -0
  34. package/dist/esm/generation/audio.js.map +7 -0
  35. package/dist/esm/generation/book-order.js +478 -0
  36. package/dist/esm/generation/book-order.js.map +7 -0
  37. package/dist/esm/generation/common-types.js +2 -0
  38. package/dist/esm/generation/common-types.js.map +7 -0
  39. package/dist/esm/generation/dataset.js +132 -0
  40. package/dist/esm/generation/dataset.js.map +7 -0
  41. package/dist/esm/generation/index.js +8 -0
  42. package/dist/esm/generation/index.js.map +7 -0
  43. package/dist/esm/index.js +6 -0
  44. package/dist/esm/index.js.map +7 -0
  45. package/dist/esm/parser/codex-parser.js +144 -0
  46. package/dist/esm/parser/codex-parser.js.map +7 -0
  47. package/dist/esm/parser/index.js +8 -0
  48. package/dist/esm/parser/index.js.map +7 -0
  49. package/dist/esm/parser/iterators.js +152 -0
  50. package/dist/esm/parser/iterators.js.map +7 -0
  51. package/dist/esm/parser/types.js +2 -0
  52. package/dist/esm/parser/types.js.map +7 -0
  53. package/dist/esm/parser/usfm-parser.js +749 -0
  54. package/dist/esm/parser/usfm-parser.js.map +7 -0
  55. package/dist/esm/parser/usx-parser.js +447 -0
  56. package/dist/esm/parser/usx-parser.js.map +7 -0
  57. package/dist/esm/utils.js +51 -0
  58. package/dist/esm/utils.js.map +7 -0
  59. package/{generation → dist/types/generation}/api.d.ts +14 -2
  60. package/{generation → dist/types/generation}/audio.d.ts +1 -1
  61. package/{generation → dist/types/generation}/dataset.d.ts +1 -1
  62. package/dist/types/generation/index.d.ts +7 -0
  63. package/dist/types/index.d.ts +5 -0
  64. package/{parser → dist/types/parser}/codex-parser.d.ts +1 -1
  65. package/dist/types/parser/index.d.ts +7 -0
  66. package/{parser → dist/types/parser}/usfm-parser.d.ts +1 -1
  67. package/{parser → dist/types/parser}/usx-parser.d.ts +2 -2
  68. package/package.json +25 -4
  69. package/typings/types.d.ts +13 -13
  70. package/generation/api.js +0 -179
  71. package/generation/api.spec.d.ts +0 -2
  72. package/generation/api.spec.js +0 -656
  73. package/generation/audio.js +0 -60
  74. package/generation/audio.spec.d.ts +0 -2
  75. package/generation/audio.spec.js +0 -36
  76. package/generation/book-order.js +0 -494
  77. package/generation/book-order.spec.d.ts +0 -2
  78. package/generation/book-order.spec.js +0 -8
  79. package/generation/common-types.js +0 -2
  80. package/generation/dataset.js +0 -106
  81. package/generation/index.d.ts +0 -7
  82. package/generation/index.js +0 -38
  83. package/index.d.ts +0 -5
  84. package/index.js +0 -32
  85. package/parser/codex-parser.js +0 -160
  86. package/parser/codex-parser.spec.d.ts +0 -2
  87. package/parser/codex-parser.spec.js +0 -645
  88. package/parser/index.d.ts +0 -7
  89. package/parser/index.js +0 -35
  90. package/parser/iterators.js +0 -222
  91. package/parser/iterators.spec.d.ts +0 -2
  92. package/parser/iterators.spec.js +0 -174
  93. package/parser/types.js +0 -2
  94. package/parser/usfm-parser.js +0 -840
  95. package/parser/usfm-parser.spec.d.ts +0 -2
  96. package/parser/usfm-parser.spec.js +0 -1593
  97. package/parser/usx-parser.js +0 -425
  98. package/parser/usx-parser.spec.d.ts +0 -2
  99. package/parser/usx-parser.spec.js +0 -1260
  100. package/utils.js +0 -73
  101. package/utils.spec.d.ts +0 -2
  102. package/utils.spec.js +0 -42
  103. /package/{generation → dist/types/generation}/book-order.d.ts +0 -0
  104. /package/{generation → dist/types/generation}/common-types.d.ts +0 -0
  105. /package/{parser → dist/types/parser}/iterators.d.ts +0 -0
  106. /package/{parser → dist/types/parser}/types.d.ts +0 -0
  107. /package/{utils.d.ts → dist/types/utils.d.ts} +0 -0
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2022 AO Lab
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2022 AO Lab
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,98 +1,98 @@
1
- ## Hello AO Tools
2
-
3
- Tools for the [Free Use Bible API](https://bible.helloao.org).
4
-
5
- ### Features
6
-
7
- - Parse [USFM](https://ubsicap.github.io/usfm/), [USX](https://ubsicap.github.io/usx/), and Codex (JSON) files and understand some basic structure.
8
- - Generate JSON from USFM, USX, and other formats.
9
-
10
- ### Installation
11
-
12
- ```
13
- $ npm install @helloao/tools
14
- ```
15
-
16
- ### Usage
17
-
18
- #### Parse a USX File
19
- ```typescript
20
- import { parser } from '@helloao/tools';
21
- // Used to parse XML
22
- const parser = new DOMParser();
23
- const usx = new parser.USXParser(parser);
24
- const parseTree = usx.parse('YOUR USX');
25
- console.log(parseTree);
26
- ```
27
-
28
- #### Generate the API Files for a translation
29
-
30
- ```typescript
31
- import { parser, generation } from '@helloao/tools';
32
-
33
- // Used to parse XML
34
- const domParser = new DOMParser();
35
-
36
- // Each input file needs some metadata about the translation that it is associated with
37
- const translation: generation.ParseTreeMetadata = {
38
- translation: {
39
-
40
- // The ID of the translation
41
- // this should be unique for the translation
42
- id: 'my translation id',
43
-
44
- // The name of the translation in the translation's language
45
- name: 'my translation name',
46
-
47
- // The name of the translation in English
48
- englishName: 'my translation name',
49
-
50
- // The website that hosts information about the translation
51
- website: 'translation website',
52
-
53
- // The URL that hosts information about the license that the
54
- // translation is shared under
55
- licenseUrl: 'translation license',
56
-
57
- // The ISO 639 letter language tag that the translation is primarily in.
58
- language: 'eng',
59
-
60
- // The direction that the text is written in.
61
- // "ltr" means "left to right" and "rtl" means "right to left"
62
- direction: 'ltr',
63
- }
64
- };
65
-
66
- // The list of files that should be processed.
67
- const files: generation.InputFile[] = [
68
- {
69
- // the metadata about the translation for this file
70
- metadata: translation,
71
-
72
- // The content contained in the file
73
- content: 'YOUR USX',
74
-
75
- // The type of the file.
76
- // One of "usx", "usfm", and "json"
77
- fileType: 'usx'
78
- }
79
- ];
80
-
81
- // Generate a dataset from the files
82
- // Datasets organize all the files and their content
83
- // by translation, book, chapter, and verse
84
- const dataset = generation.dataset.generateDataset(files, domParser);
85
-
86
- // Generate an API representation from the files
87
- // This adds links between chapters and additional metadata.
88
- const api = generation.api.generateApiForDataset(dataset);
89
-
90
- // Generate output files from the API representation.
91
- // This will give us a list of files and file paths that represent
92
- // the entire API.
93
- const outputFiles = generation.api.generateFilesForApi(api);
94
-
95
- for (let file of outputFiles) {
96
- console.log(file.path, file.content);
97
- }
98
- ```
1
+ ## Hello AO Tools
2
+
3
+ Tools for the [Free Use Bible API](https://bible.helloao.org).
4
+
5
+ ### Features
6
+
7
+ - Parse [USFM](https://ubsicap.github.io/usfm/), [USX](https://ubsicap.github.io/usx/), and Codex (JSON) files and understand some basic structure.
8
+ - Generate JSON from USFM, USX, and other formats.
9
+
10
+ ### Installation
11
+
12
+ ```
13
+ $ npm install @helloao/tools
14
+ ```
15
+
16
+ ### Usage
17
+
18
+ #### Parse a USX File
19
+
20
+ ```typescript
21
+ import { parser } from '@helloao/tools';
22
+ // Used to parse XML
23
+ const parser = new DOMParser();
24
+ const usx = new parser.USXParser(parser);
25
+ const parseTree = usx.parse('YOUR USX');
26
+ console.log(parseTree);
27
+ ```
28
+
29
+ #### Generate the API Files for a translation
30
+
31
+ ```typescript
32
+ import { parser, generation } from '@helloao/tools';
33
+
34
+ // Used to parse XML
35
+ const domParser = new DOMParser();
36
+
37
+ // Each input file needs some metadata about the translation that it is associated with
38
+ const translation: generation.ParseTreeMetadata = {
39
+ translation: {
40
+ // The ID of the translation
41
+ // this should be unique for the translation
42
+ id: 'my translation id',
43
+
44
+ // The name of the translation in the translation's language
45
+ name: 'my translation name',
46
+
47
+ // The name of the translation in English
48
+ englishName: 'my translation name',
49
+
50
+ // The website that hosts information about the translation
51
+ website: 'translation website',
52
+
53
+ // The URL that hosts information about the license that the
54
+ // translation is shared under
55
+ licenseUrl: 'translation license',
56
+
57
+ // The ISO 639 letter language tag that the translation is primarily in.
58
+ language: 'eng',
59
+
60
+ // The direction that the text is written in.
61
+ // "ltr" means "left to right" and "rtl" means "right to left"
62
+ direction: 'ltr',
63
+ },
64
+ };
65
+
66
+ // The list of files that should be processed.
67
+ const files: generation.InputFile[] = [
68
+ {
69
+ // the metadata about the translation for this file
70
+ metadata: translation,
71
+
72
+ // The content contained in the file
73
+ content: 'YOUR USX',
74
+
75
+ // The type of the file.
76
+ // One of "usx", "usfm", and "json"
77
+ fileType: 'usx',
78
+ },
79
+ ];
80
+
81
+ // Generate a dataset from the files
82
+ // Datasets organize all the files and their content
83
+ // by translation, book, chapter, and verse
84
+ const dataset = generation.dataset.generateDataset(files, domParser);
85
+
86
+ // Generate an API representation from the files
87
+ // This adds links between chapters and additional metadata.
88
+ const api = generation.api.generateApiForDataset(dataset);
89
+
90
+ // Generate output files from the API representation.
91
+ // This will give us a list of files and file paths that represent
92
+ // the entire API.
93
+ const outputFiles = generation.api.generateFilesForApi(api);
94
+
95
+ for (let file of outputFiles) {
96
+ console.log(file.path, file.content);
97
+ }
98
+ ```
@@ -0,0 +1,240 @@
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 api_exports = {};
20
+ __export(api_exports, {
21
+ bookChapterApiLink: () => bookChapterApiLink,
22
+ bookChapterAudioApiLink: () => bookChapterAudioApiLink,
23
+ downloadedFile: () => downloadedFile,
24
+ generateApiForDataset: () => generateApiForDataset,
25
+ generateFilesForApi: () => generateFilesForApi,
26
+ generateOutputFilesFromDatasets: () => generateOutputFilesFromDatasets,
27
+ jsonFile: () => jsonFile,
28
+ listOfBooksApiLink: () => listOfBooksApiLink,
29
+ replaceSpacesWithUnderscores: () => replaceSpacesWithUnderscores
30
+ });
31
+ module.exports = __toCommonJS(api_exports);
32
+ function generateApiForDataset(dataset, options = {}) {
33
+ const { useCommonName, pathPrefix } = options;
34
+ const apiPathPrefix = pathPrefix ? pathPrefix : "";
35
+ let api = {
36
+ availableTranslations: {
37
+ translations: []
38
+ },
39
+ translationBooks: [],
40
+ translationBookChapters: [],
41
+ translationBookChapterAudio: [],
42
+ pathPrefix: apiPathPrefix
43
+ };
44
+ const getNativeName = options.getNativeName;
45
+ const getEnglishName = options.getEnglishName;
46
+ for (let { books, ...translation } of dataset.translations) {
47
+ const apiTranslation = {
48
+ ...translation,
49
+ availableFormats: ["json"],
50
+ listOfBooksApiLink: listOfBooksApiLink(
51
+ translation.id,
52
+ apiPathPrefix
53
+ ),
54
+ numberOfBooks: books.length,
55
+ totalNumberOfChapters: 0,
56
+ totalNumberOfVerses: 0,
57
+ languageName: getNativeName ? getNativeName(translation.language) ?? void 0 : void 0,
58
+ languageEnglishName: getEnglishName ? getEnglishName(translation.language) ?? void 0 : void 0
59
+ };
60
+ const translationBooks = {
61
+ translation: apiTranslation,
62
+ books: []
63
+ };
64
+ let translationChapters = [];
65
+ for (let { chapters, ...book } of books) {
66
+ const apiBook = {
67
+ ...book,
68
+ firstChapterApiLink: bookChapterApiLink(
69
+ translation.id,
70
+ getBookLink(book),
71
+ 1,
72
+ "json",
73
+ apiPathPrefix
74
+ ),
75
+ lastChapterApiLink: bookChapterApiLink(
76
+ translation.id,
77
+ getBookLink(book),
78
+ chapters.length,
79
+ "json",
80
+ apiPathPrefix
81
+ ),
82
+ numberOfChapters: chapters.length,
83
+ totalNumberOfVerses: 0
84
+ };
85
+ for (let { chapter, thisChapterAudioLinks } of chapters) {
86
+ const audio = {};
87
+ const apiBookChapter = {
88
+ translation: apiTranslation,
89
+ book: apiBook,
90
+ chapter,
91
+ thisChapterLink: bookChapterApiLink(
92
+ translation.id,
93
+ getBookLink(book),
94
+ chapter.number,
95
+ "json",
96
+ apiPathPrefix
97
+ ),
98
+ thisChapterAudioLinks: audio,
99
+ nextChapterApiLink: null,
100
+ nextChapterAudioLinks: null,
101
+ previousChapterApiLink: null,
102
+ previousChapterAudioLinks: null,
103
+ numberOfVerses: 0
104
+ };
105
+ for (let reader in thisChapterAudioLinks) {
106
+ if (options.generateAudioFiles) {
107
+ const apiAudio = {
108
+ chapter: apiBookChapter,
109
+ link: bookChapterAudioApiLink(
110
+ translation.id,
111
+ getBookLink(book),
112
+ chapter.number,
113
+ reader,
114
+ apiPathPrefix
115
+ ),
116
+ originalUrl: thisChapterAudioLinks[reader]
117
+ };
118
+ audio[reader] = apiAudio.link;
119
+ api.translationBookChapterAudio.push(apiAudio);
120
+ } else {
121
+ audio[reader] = thisChapterAudioLinks[reader];
122
+ }
123
+ }
124
+ for (let c of chapter.content) {
125
+ if (c.type === "verse") {
126
+ apiBookChapter.numberOfVerses++;
127
+ }
128
+ }
129
+ apiBook.totalNumberOfVerses += apiBookChapter.numberOfVerses;
130
+ translationChapters.push(apiBookChapter);
131
+ api.translationBookChapters.push(apiBookChapter);
132
+ }
133
+ translationBooks.books.push(apiBook);
134
+ apiTranslation.totalNumberOfChapters += apiBook.numberOfChapters;
135
+ apiTranslation.totalNumberOfVerses += apiBook.totalNumberOfVerses;
136
+ }
137
+ for (let i = 0; i < translationChapters.length; i++) {
138
+ if (i > 0) {
139
+ translationChapters[i].previousChapterApiLink = bookChapterApiLink(
140
+ translation.id,
141
+ getBookLink(translationChapters[i - 1].book),
142
+ translationChapters[i - 1].chapter.number,
143
+ "json",
144
+ apiPathPrefix
145
+ );
146
+ translationChapters[i].previousChapterAudioLinks = translationChapters[i - 1].thisChapterAudioLinks;
147
+ }
148
+ if (i < translationChapters.length - 1) {
149
+ translationChapters[i].nextChapterApiLink = bookChapterApiLink(
150
+ translation.id,
151
+ getBookLink(translationChapters[i + 1].book),
152
+ translationChapters[i + 1].chapter.number,
153
+ "json",
154
+ apiPathPrefix
155
+ );
156
+ translationChapters[i].nextChapterAudioLinks = translationChapters[i + 1].thisChapterAudioLinks;
157
+ }
158
+ }
159
+ api.availableTranslations.translations.push(apiTranslation);
160
+ api.translationBooks.push(translationBooks);
161
+ }
162
+ return api;
163
+ function getBookLink(book) {
164
+ return useCommonName ? book.commonName : book.id;
165
+ }
166
+ }
167
+ function generateFilesForApi(api) {
168
+ let files = [];
169
+ files.push(
170
+ jsonFile(
171
+ `${api.pathPrefix}/api/available_translations.json`,
172
+ api.availableTranslations,
173
+ true
174
+ )
175
+ );
176
+ for (let translationBooks of api.translationBooks) {
177
+ files.push(
178
+ jsonFile(
179
+ translationBooks.translation.listOfBooksApiLink,
180
+ translationBooks
181
+ )
182
+ );
183
+ }
184
+ for (let bookChapter of api.translationBookChapters) {
185
+ files.push(jsonFile(bookChapter.thisChapterLink, bookChapter));
186
+ }
187
+ for (let audio of api.translationBookChapterAudio) {
188
+ files.push(downloadedFile(audio.link, audio.originalUrl));
189
+ }
190
+ return files;
191
+ }
192
+ async function* generateOutputFilesFromDatasets(datasets, options) {
193
+ for await (let dataset of datasets) {
194
+ const api = generateApiForDataset(dataset, options);
195
+ const files = generateFilesForApi(api);
196
+ yield files;
197
+ }
198
+ }
199
+ function listOfBooksApiLink(translationId, prefix = "") {
200
+ return `${prefix}/api/${translationId}/books.json`;
201
+ }
202
+ function bookChapterApiLink(translationId, commonName, chapterNumber, extension, prefix = "") {
203
+ return `${prefix}/api/${translationId}/${replaceSpacesWithUnderscores(
204
+ commonName
205
+ )}/${chapterNumber}.${extension}`;
206
+ }
207
+ function bookChapterAudioApiLink(translationId, bookId, chapterNumber, reader, prefix = "") {
208
+ return `${prefix}/api/${translationId}/${replaceSpacesWithUnderscores(
209
+ bookId
210
+ )}/${chapterNumber}.${reader}.mp3`;
211
+ }
212
+ function jsonFile(path, content, mergable) {
213
+ return {
214
+ path,
215
+ content,
216
+ mergable
217
+ };
218
+ }
219
+ function downloadedFile(path, url) {
220
+ return {
221
+ path,
222
+ content: () => fetch(url).then((response) => response.body)
223
+ };
224
+ }
225
+ function replaceSpacesWithUnderscores(str) {
226
+ return str.replace(/[<>:"/\\|?*\s]/g, "_");
227
+ }
228
+ // Annotate the CommonJS export names for ESM import in node:
229
+ 0 && (module.exports = {
230
+ bookChapterApiLink,
231
+ bookChapterAudioApiLink,
232
+ downloadedFile,
233
+ generateApiForDataset,
234
+ generateFilesForApi,
235
+ generateOutputFilesFromDatasets,
236
+ jsonFile,
237
+ listOfBooksApiLink,
238
+ replaceSpacesWithUnderscores
239
+ });
240
+ //# sourceMappingURL=api.cjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../generation/api.ts"],
4
+ "sourcesContent": ["import {\n OutputFile,\n Translation,\n TranslationBook,\n TranslationBookChapter,\n TranslationBookChapterAudioLinks,\n} from './common-types.js';\nimport { DatasetOutput } from './dataset.js';\n\n/**\n * Defines the output of the API generation.\n */\nexport interface ApiOutput {\n /**\n * The list of available translations.\n * This maps to the /api/available-translations.json endpoint.\n */\n availableTranslations: ApiAvailableTranslations;\n\n /**\n * The list of books for each translation.\n * This maps to the /api/:translationId/books.json endpoint.\n */\n translationBooks: ApiTranslationBooks[];\n\n /**\n * The list of chapters for each book.\n * This maps to the following endpoints:\n * - /api/:translationId/:bookId/:chapterNumber.json\n * - /api/:translationId/:bookCommonName/:chapterNumber.json\n */\n translationBookChapters: ApiTranslationBookChapter[];\n\n /**\n * The list of audio files.\n * This maps to the following endpoints:\n * - /api/:translationId/:bookId/:chapterNumber.:reader.mp3\n */\n translationBookChapterAudio: ApiTranslationBookChapterAudio[];\n\n /**\n * The path prefix that the API should use.\n */\n pathPrefix: string;\n}\n\n/**\n * The list of available translations.\n * Maps to the /api/available-translations.json endpoint.\n */\nexport interface ApiAvailableTranslations {\n /**\n * The list of translations.\n */\n translations: ApiTranslation[];\n}\n\n/**\n * Defines a translation that is used in the API.\n */\nexport interface ApiTranslation extends Translation {\n /**\n * The API link for the list of available books for this translation.\n */\n listOfBooksApiLink: string;\n\n /**\n * The available list of formats.\n */\n availableFormats: ('json' | 'usfm')[];\n\n /**\n * The number of books that are contained in this translation.\n *\n * Complete translations should have the same number of books as the Bible (66).\n */\n numberOfBooks: number;\n\n /**\n * The total number of chapters that are contained in this translation.\n *\n * Complete translations should have the same number of chapters as the Bible (1,189).\n */\n totalNumberOfChapters: number;\n\n /**\n * The total number of verses that are contained in this translation.\n *\n * Complete translations should have the same number of verses as the Bible (around 31,102 - some translations exclude verses based on the aparent likelyhood of existing in the original source texts).\n */\n totalNumberOfVerses: number;\n\n /**\n * Gets the name of the language that the translation is in.\n * Null or undefined if the name of the language is not known.\n */\n languageName?: string;\n\n /**\n * Gets the name of the language in English.\n * Null or undefined if the language doesn't have an english name.\n */\n languageEnglishName?: string;\n}\n\n/**\n * Defines an interface that contains information about the books that are available for a translation.\n */\nexport interface ApiTranslationBooks {\n /**\n * The translation information for the books.\n */\n translation: ApiTranslation;\n\n /**\n * The list of books that are available for the translation.\n */\n books: ApiTranslationBook[];\n}\n\n/**\n * Defines a translation book that is used in the API.\n */\nexport interface ApiTranslationBook extends TranslationBook {\n /**\n * The link to the first chapter of the book.\n */\n firstChapterApiLink: string;\n\n /**\n * The link to the last chapter of the book.\n */\n lastChapterApiLink: string;\n\n /**\n * The number of chapters that the book contains.\n */\n numberOfChapters: number;\n\n /**\n * The number of verses that the book contains.\n */\n totalNumberOfVerses: number;\n}\n\n/**\n * Defines an interface that contains information about a book chapter.\n */\nexport interface ApiTranslationBookChapter extends TranslationBookChapter {\n /**\n * The translation information for the book chapter.\n */\n translation: ApiTranslation;\n\n /**\n * The book information for the book chapter.\n */\n book: ApiTranslationBook;\n\n /**\n * The link to this chapter.\n */\n thisChapterLink: string;\n\n /**\n * The link to the next chapter.\n * Null if this is the last chapter in the translation.\n */\n nextChapterApiLink: string | null;\n\n /**\n * The links to the audio versions for the next chapter.\n * Null if this is the last chapter in the translation.\n */\n nextChapterAudioLinks: TranslationBookChapterAudioLinks | null;\n\n /**\n * The link to the previous chapter.\n * Null if this is the first chapter in the translation.\n */\n previousChapterApiLink: string | null;\n\n /**\n * The links to the audio versions for the previous chapter.\n * Null if this is the first chapter in the translation.\n */\n previousChapterAudioLinks: TranslationBookChapterAudioLinks | null;\n\n /**\n * The number of verses that the chapter contains.\n */\n numberOfVerses: number;\n}\n\nexport interface ApiTranslationBookChapterAudio {\n /**\n * The chapter that the audio is for.\n */\n chapter: ApiTranslationBookChapter;\n\n /**\n * The link that the audio should be placed at.\n */\n link: string;\n\n /**\n * The original URL of the audio.\n */\n originalUrl: string;\n}\n\n/**\n * The options for generating the API.\n */\nexport interface GenerateApiOptions {\n /**\n * Whether to use the common name for the book chapter API link. If false, then book IDs are used.\n * Audio URLs will always use the book ID.\n * Defaults to false.\n */\n useCommonName?: boolean;\n\n /**\n * Whether to replace the audio URLs in the dataset with ones that are hosted locally.\n * If true, then the audio URLs in the dataset will be replaced with ones that reference files hosted by the API itself.\n * If false, then the audio URLs in the dataset will be left as is.\n * Defaults to false.\n */\n generateAudioFiles?: boolean;\n\n /**\n * Gets the english name of the given language.\n * If not provided, then the english name for the language will be unknown and omitted.\n * @param language The language to get the english name for.\n */\n getEnglishName?: (language: string) => string | null | undefined;\n\n /**\n * Gets the native name of the given language.\n * If not provided, then the native name for the language will be unknown and omitted.\n * @param language The language to get the native name for.\n */\n getNativeName?: (language: string) => string | null | undefined;\n\n /**\n * The prefix that should be added to paths that are generated.\n */\n pathPrefix?: string;\n}\n\n/**\n * Generates the API output for the given dataset.\n * @param dataset The dataset to generate the API for.\n * @param options The options for generating the API.\n */\nexport function generateApiForDataset(\n dataset: DatasetOutput,\n options: GenerateApiOptions = {}\n): ApiOutput {\n const { useCommonName, pathPrefix } = options;\n const apiPathPrefix = pathPrefix ? pathPrefix : '';\n let api: ApiOutput = {\n availableTranslations: {\n translations: [],\n },\n translationBooks: [],\n translationBookChapters: [],\n translationBookChapterAudio: [],\n pathPrefix: apiPathPrefix,\n };\n\n const getNativeName = options.getNativeName;\n const getEnglishName = options.getEnglishName;\n\n for (let { books, ...translation } of dataset.translations) {\n const apiTranslation: ApiTranslation = {\n ...translation,\n availableFormats: ['json'],\n listOfBooksApiLink: listOfBooksApiLink(\n translation.id,\n apiPathPrefix\n ),\n numberOfBooks: books.length,\n totalNumberOfChapters: 0,\n totalNumberOfVerses: 0,\n languageName: getNativeName\n ? getNativeName(translation.language) ?? undefined\n : undefined,\n languageEnglishName: getEnglishName\n ? getEnglishName(translation.language) ?? undefined\n : undefined,\n };\n\n const translationBooks: ApiTranslationBooks = {\n translation: apiTranslation,\n books: [],\n };\n\n let translationChapters: ApiTranslationBookChapter[] = [];\n\n for (let { chapters, ...book } of books) {\n const apiBook: ApiTranslationBook = {\n ...book,\n firstChapterApiLink: bookChapterApiLink(\n translation.id,\n getBookLink(book),\n 1,\n 'json',\n apiPathPrefix\n ),\n lastChapterApiLink: bookChapterApiLink(\n translation.id,\n getBookLink(book),\n chapters.length,\n 'json',\n apiPathPrefix\n ),\n numberOfChapters: chapters.length,\n totalNumberOfVerses: 0,\n };\n\n for (let { chapter, thisChapterAudioLinks } of chapters) {\n const audio: TranslationBookChapterAudioLinks = {};\n const apiBookChapter: ApiTranslationBookChapter = {\n translation: apiTranslation,\n book: apiBook,\n chapter: chapter,\n thisChapterLink: bookChapterApiLink(\n translation.id,\n getBookLink(book),\n chapter.number,\n 'json',\n apiPathPrefix\n ),\n thisChapterAudioLinks: audio,\n nextChapterApiLink: null,\n nextChapterAudioLinks: null,\n previousChapterApiLink: null,\n previousChapterAudioLinks: null,\n numberOfVerses: 0,\n };\n\n for (let reader in thisChapterAudioLinks) {\n if (options.generateAudioFiles) {\n const apiAudio: ApiTranslationBookChapterAudio = {\n chapter: apiBookChapter,\n link: bookChapterAudioApiLink(\n translation.id,\n getBookLink(book),\n chapter.number,\n reader,\n apiPathPrefix\n ),\n originalUrl: thisChapterAudioLinks[reader],\n };\n audio[reader] = apiAudio.link;\n api.translationBookChapterAudio.push(apiAudio);\n } else {\n audio[reader] = thisChapterAudioLinks[reader];\n }\n }\n\n for (let c of chapter.content) {\n if (c.type === 'verse') {\n apiBookChapter.numberOfVerses++;\n }\n }\n\n apiBook.totalNumberOfVerses += apiBookChapter.numberOfVerses;\n\n translationChapters.push(apiBookChapter);\n api.translationBookChapters.push(apiBookChapter);\n }\n\n translationBooks.books.push(apiBook);\n\n apiTranslation.totalNumberOfChapters += apiBook.numberOfChapters;\n apiTranslation.totalNumberOfVerses += apiBook.totalNumberOfVerses;\n }\n\n for (let i = 0; i < translationChapters.length; i++) {\n if (i > 0) {\n translationChapters[i].previousChapterApiLink =\n bookChapterApiLink(\n translation.id,\n getBookLink(translationChapters[i - 1].book),\n translationChapters[i - 1].chapter.number,\n 'json',\n apiPathPrefix\n );\n translationChapters[i].previousChapterAudioLinks =\n translationChapters[i - 1].thisChapterAudioLinks;\n }\n\n if (i < translationChapters.length - 1) {\n translationChapters[i].nextChapterApiLink = bookChapterApiLink(\n translation.id,\n getBookLink(translationChapters[i + 1].book),\n translationChapters[i + 1].chapter.number,\n 'json',\n apiPathPrefix\n );\n translationChapters[i].nextChapterAudioLinks =\n translationChapters[i + 1].thisChapterAudioLinks;\n }\n }\n\n api.availableTranslations.translations.push(apiTranslation);\n api.translationBooks.push(translationBooks);\n }\n\n return api;\n\n function getBookLink(book: TranslationBook): string {\n return useCommonName ? book.commonName : book.id;\n }\n}\n\n/**\n * Generates the output files for the given API.\n * @param api The API that the files should be generated for.\n */\nexport function generateFilesForApi(api: ApiOutput): OutputFile[] {\n let files: OutputFile[] = [];\n\n files.push(\n jsonFile(\n `${api.pathPrefix}/api/available_translations.json`,\n api.availableTranslations,\n true\n )\n );\n for (let translationBooks of api.translationBooks) {\n files.push(\n jsonFile(\n translationBooks.translation.listOfBooksApiLink,\n translationBooks\n )\n );\n }\n\n for (let bookChapter of api.translationBookChapters) {\n files.push(jsonFile(bookChapter.thisChapterLink, bookChapter));\n }\n\n for (let audio of api.translationBookChapterAudio) {\n files.push(downloadedFile(audio.link, audio.originalUrl));\n }\n\n return files;\n}\n\n/**\n * Generates the output files for the given datasets.\n * @param datasets The datasets to generate the output files for.\n * @param options The options for generating the API files.\n */\nexport async function* generateOutputFilesFromDatasets(\n datasets: AsyncIterable<DatasetOutput>,\n options?: GenerateApiOptions\n): AsyncGenerator<OutputFile[]> {\n for await (let dataset of datasets) {\n const api = generateApiForDataset(dataset, options);\n const files = generateFilesForApi(api);\n\n yield files;\n }\n}\n\n/**\n * Gets the API Link for the list of books endpoint for a translation.\n * @param translationId The ID of the translation.\n * @returns\n */\nexport function listOfBooksApiLink(\n translationId: string,\n prefix: string = ''\n): string {\n return `${prefix}/api/${translationId}/books.json`;\n}\n\n/**\n * Getes the API link for a book chapter.\n * @param translationId The ID of the translation.\n * @param commonName The name of the book.\n * @param chapterNumber The number of the book.\n * @param extension The extension of the file.\n */\nexport function bookChapterApiLink(\n translationId: string,\n commonName: string,\n chapterNumber: number,\n extension: string,\n prefix: string = ''\n) {\n return `${prefix}/api/${translationId}/${replaceSpacesWithUnderscores(\n commonName\n )}/${chapterNumber}.${extension}`;\n}\n\nexport function bookChapterAudioApiLink(\n translationId: string,\n bookId: string,\n chapterNumber: number,\n reader: string,\n prefix: string = ''\n) {\n return `${prefix}/api/${translationId}/${replaceSpacesWithUnderscores(\n bookId\n )}/${chapterNumber}.${reader}.mp3`;\n}\n\nexport function jsonFile(\n path: string,\n content: any,\n mergable?: boolean\n): OutputFile {\n return {\n path,\n content,\n mergable,\n };\n}\n\nexport function downloadedFile(path: string, url: string): OutputFile {\n return {\n path,\n content: () => fetch(url).then((response) => response.body),\n };\n}\n\nexport function replaceSpacesWithUnderscores(str: string): string {\n return str.replace(/[<>:\"/\\\\|?*\\s]/g, '_');\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,83 @@
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 audio_exports = {};
20
+ __export(audio_exports, {
21
+ KNOWN_AUDIO_TRANSLATIONS: () => KNOWN_AUDIO_TRANSLATIONS,
22
+ capitalize: () => capitalize,
23
+ getAudioUrlsForChapter: () => getAudioUrlsForChapter
24
+ });
25
+ module.exports = __toCommonJS(audio_exports);
26
+ var import_lodash = require("lodash");
27
+ var import_book_order = require("./book-order.js");
28
+ const openBibleUrlGenerator = (translation, reader, postfix) => {
29
+ return (bookId, chapter) => {
30
+ const bookOrder = (0, import_lodash.padStart)(
31
+ import_book_order.bookOrderMap.get(bookId).toString(),
32
+ 2,
33
+ "0"
34
+ );
35
+ const chapterStr = (0, import_lodash.padStart)(chapter.toString(), 3, "0");
36
+ let link = `https://openbible.com/audio/${reader}/${translation}_${bookOrder}_${capitalize(
37
+ bookId
38
+ )}_${chapterStr}`;
39
+ if (postfix) {
40
+ link += `_${postfix}`;
41
+ }
42
+ link += ".mp3";
43
+ return link;
44
+ };
45
+ };
46
+ const KNOWN_AUDIO_TRANSLATIONS = /* @__PURE__ */ new Map([
47
+ [
48
+ "BSB",
49
+ /* @__PURE__ */ new Map([
50
+ ["gilbert", openBibleUrlGenerator("BSB", "gilbert", "G")],
51
+ ["hays", openBibleUrlGenerator("BSB", "hays", "H")],
52
+ ["souer", openBibleUrlGenerator("BSB", "souer", null)]
53
+ ])
54
+ ]
55
+ ]);
56
+ function getAudioUrlsForChapter(translationId, bookId, chapter) {
57
+ const translation = KNOWN_AUDIO_TRANSLATIONS.get(translationId);
58
+ if (!translation) {
59
+ return {};
60
+ }
61
+ const links = {};
62
+ for (let [reader, generator] of translation) {
63
+ const url = generator(bookId, chapter);
64
+ if (url) {
65
+ links[reader] = url;
66
+ }
67
+ }
68
+ return links;
69
+ }
70
+ function capitalize(str) {
71
+ const char = str.charAt(0);
72
+ if (/[0-9]/.test(char)) {
73
+ return str.charAt(0) + str.charAt(1).toUpperCase() + str.slice(2).toLowerCase();
74
+ }
75
+ return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
76
+ }
77
+ // Annotate the CommonJS export names for ESM import in node:
78
+ 0 && (module.exports = {
79
+ KNOWN_AUDIO_TRANSLATIONS,
80
+ capitalize,
81
+ getAudioUrlsForChapter
82
+ });
83
+ //# sourceMappingURL=audio.cjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../generation/audio.ts"],
4
+ "sourcesContent": ["import { padStart } from 'lodash';\nimport { bookOrderMap } from './book-order.js';\nimport { TranslationBookChapterAudioLinks } from './common-types.js';\n\ntype AudioTranslationUrlGenerator = (bookId: string, chapter: number) => string;\n\nconst openBibleUrlGenerator: (\n translation: string,\n reader: string,\n postfix: string | null\n) => AudioTranslationUrlGenerator = (translation, reader, postfix) => {\n return (bookId, chapter) => {\n const bookOrder = padStart(\n bookOrderMap.get(bookId)!.toString(),\n 2,\n '0'\n );\n const chapterStr = padStart(chapter.toString(), 3, '0');\n\n let link = `https://openbible.com/audio/${reader}/${translation}_${bookOrder}_${capitalize(\n bookId\n )}_${chapterStr}`;\n\n if (postfix) {\n link += `_${postfix}`;\n }\n\n link += '.mp3';\n\n return link;\n };\n};\n\n/**\n * A map of translation IDs to a map of reader IDs to the URL generator for the audio file.\n */\nexport const KNOWN_AUDIO_TRANSLATIONS: Map<\n string,\n Map<string, AudioTranslationUrlGenerator>\n> = new Map([\n [\n 'BSB',\n new Map([\n ['gilbert', openBibleUrlGenerator('BSB', 'gilbert', 'G')],\n ['hays', openBibleUrlGenerator('BSB', 'hays', 'H')],\n ['souer', openBibleUrlGenerator('BSB', 'souer', null)],\n ]),\n ],\n]);\n\n/**\n * Gets the audio URLs for the given translation, book, and chapter.\n * @param translationId The ID of the translation.\n * @param bookId The ID of the book.\n * @param chapter The number of the chapter.\n */\nexport function getAudioUrlsForChapter(\n translationId: string,\n bookId: string,\n chapter: number\n): TranslationBookChapterAudioLinks {\n const translation = KNOWN_AUDIO_TRANSLATIONS.get(translationId);\n if (!translation) {\n return {};\n }\n\n const links: TranslationBookChapterAudioLinks = {};\n for (let [reader, generator] of translation) {\n const url = generator(bookId, chapter);\n if (url) {\n links[reader] = url;\n }\n }\n return links;\n}\n\n/**\n * Capitalizes the first letter of the given string.\n * @param str The string to capitalize.\n */\nexport function capitalize(str: string): string {\n const char = str.charAt(0);\n if (/[0-9]/.test(char)) {\n return (\n str.charAt(0) +\n str.charAt(1).toUpperCase() +\n str.slice(2).toLowerCase()\n );\n }\n\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAyB;AACzB,wBAA6B;AAK7B,MAAM,wBAI8B,CAAC,aAAa,QAAQ,YAAY;AAClE,SAAO,CAAC,QAAQ,YAAY;AACxB,UAAM,gBAAY;AAAA,MACd,+BAAa,IAAI,MAAM,EAAG,SAAS;AAAA,MACnC;AAAA,MACA;AAAA,IACJ;AACA,UAAM,iBAAa,wBAAS,QAAQ,SAAS,GAAG,GAAG,GAAG;AAEtD,QAAI,OAAO,+BAA+B,MAAM,IAAI,WAAW,IAAI,SAAS,IAAI;AAAA,MAC5E;AAAA,IACJ,CAAC,IAAI,UAAU;AAEf,QAAI,SAAS;AACT,cAAQ,IAAI,OAAO;AAAA,IACvB;AAEA,YAAQ;AAER,WAAO;AAAA,EACX;AACJ;AAKO,MAAM,2BAGT,oBAAI,IAAI;AAAA,EACR;AAAA,IACI;AAAA,IACA,oBAAI,IAAI;AAAA,MACJ,CAAC,WAAW,sBAAsB,OAAO,WAAW,GAAG,CAAC;AAAA,MACxD,CAAC,QAAQ,sBAAsB,OAAO,QAAQ,GAAG,CAAC;AAAA,MAClD,CAAC,SAAS,sBAAsB,OAAO,SAAS,IAAI,CAAC;AAAA,IACzD,CAAC;AAAA,EACL;AACJ,CAAC;AAQM,SAAS,uBACZ,eACA,QACA,SACgC;AAChC,QAAM,cAAc,yBAAyB,IAAI,aAAa;AAC9D,MAAI,CAAC,aAAa;AACd,WAAO,CAAC;AAAA,EACZ;AAEA,QAAM,QAA0C,CAAC;AACjD,WAAS,CAAC,QAAQ,SAAS,KAAK,aAAa;AACzC,UAAM,MAAM,UAAU,QAAQ,OAAO;AACrC,QAAI,KAAK;AACL,YAAM,MAAM,IAAI;AAAA,IACpB;AAAA,EACJ;AACA,SAAO;AACX;AAMO,SAAS,WAAW,KAAqB;AAC5C,QAAM,OAAO,IAAI,OAAO,CAAC;AACzB,MAAI,QAAQ,KAAK,IAAI,GAAG;AACpB,WACI,IAAI,OAAO,CAAC,IACZ,IAAI,OAAO,CAAC,EAAE,YAAY,IAC1B,IAAI,MAAM,CAAC,EAAE,YAAY;AAAA,EAEjC;AAEA,SAAO,IAAI,OAAO,CAAC,EAAE,YAAY,IAAI,IAAI,MAAM,CAAC,EAAE,YAAY;AAClE;",
6
+ "names": []
7
+ }