@helloao/tools 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/generation/api.d.ts +203 -0
- package/generation/api.js +153 -0
- package/generation/api.spec.d.ts +2 -0
- package/generation/api.spec.js +463 -0
- package/generation/audio.d.ts +20 -0
- package/generation/audio.js +60 -0
- package/generation/audio.spec.d.ts +2 -0
- package/generation/audio.spec.js +36 -0
- package/generation/book-order.d.ts +15 -0
- package/generation/book-order.js +494 -0
- package/generation/book-order.spec.d.ts +2 -0
- package/generation/book-order.spec.js +8 -0
- package/generation/common-types.d.ts +327 -0
- package/generation/common-types.js +2 -0
- package/generation/dataset.d.ts +34 -0
- package/generation/dataset.js +106 -0
- package/generation/index.d.ts +7 -0
- package/generation/index.js +38 -0
- package/index.d.ts +5 -0
- package/index.js +32 -0
- package/package.json +27 -0
- package/parser/codex-parser.d.ts +97 -0
- package/parser/codex-parser.js +160 -0
- package/parser/codex-parser.spec.d.ts +2 -0
- package/parser/codex-parser.spec.js +645 -0
- package/parser/index.d.ts +7 -0
- package/parser/index.js +35 -0
- package/parser/iterators.d.ts +89 -0
- package/parser/iterators.js +222 -0
- package/parser/iterators.spec.d.ts +2 -0
- package/parser/iterators.spec.js +174 -0
- package/parser/types.d.ts +144 -0
- package/parser/types.js +2 -0
- package/parser/usfm-parser.d.ts +135 -0
- package/parser/usfm-parser.js +840 -0
- package/parser/usfm-parser.spec.d.ts +2 -0
- package/parser/usfm-parser.spec.js +1593 -0
- package/parser/usx-parser.d.ts +33 -0
- package/parser/usx-parser.js +425 -0
- package/parser/usx-parser.spec.d.ts +2 -0
- package/parser/usx-parser.spec.js +1260 -0
- package/typings/types.d.ts +14 -0
- package/utils.d.ts +29 -0
- package/utils.js +73 -0
- package/utils.spec.d.ts +2 -0
- package/utils.spec.js +42 -0
package/LICENSE
ADDED
|
@@ -0,0 +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.
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { OutputFile, Translation, TranslationBook, TranslationBookChapter, TranslationBookChapterAudioLinks } from "./common-types";
|
|
2
|
+
import { DatasetOutput } from "./dataset";
|
|
3
|
+
/**
|
|
4
|
+
* Defines the output of the API generation.
|
|
5
|
+
*/
|
|
6
|
+
export interface ApiOutput {
|
|
7
|
+
/**
|
|
8
|
+
* The list of available translations.
|
|
9
|
+
* This maps to the /api/available-translations.json endpoint.
|
|
10
|
+
*/
|
|
11
|
+
availableTranslations: ApiAvailableTranslations;
|
|
12
|
+
/**
|
|
13
|
+
* The list of books for each translation.
|
|
14
|
+
* This maps to the /api/:translationId/books.json endpoint.
|
|
15
|
+
*/
|
|
16
|
+
translationBooks: ApiTranslationBooks[];
|
|
17
|
+
/**
|
|
18
|
+
* The list of chapters for each book.
|
|
19
|
+
* This maps to the following endpoints:
|
|
20
|
+
* - /api/:translationId/:bookId/:chapterNumber.json
|
|
21
|
+
* - /api/:translationId/:bookCommonName/:chapterNumber.json
|
|
22
|
+
*/
|
|
23
|
+
translationBookChapters: ApiTranslationBookChapter[];
|
|
24
|
+
/**
|
|
25
|
+
* The list of audio files.
|
|
26
|
+
* This maps to the following endpoints:
|
|
27
|
+
* - /api/:translationId/:bookId/:chapterNumber.:reader.mp3
|
|
28
|
+
*/
|
|
29
|
+
translationBookChapterAudio: ApiTranslationBookChapterAudio[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The list of available translations.
|
|
33
|
+
* Maps to the /api/available-translations.json endpoint.
|
|
34
|
+
*/
|
|
35
|
+
export interface ApiAvailableTranslations {
|
|
36
|
+
/**
|
|
37
|
+
* The list of translations.
|
|
38
|
+
*/
|
|
39
|
+
translations: ApiTranslation[];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Defines a translation that is used in the API.
|
|
43
|
+
*/
|
|
44
|
+
export interface ApiTranslation extends Translation {
|
|
45
|
+
/**
|
|
46
|
+
* The API link for the list of available books for this translation.
|
|
47
|
+
*/
|
|
48
|
+
listOfBooksApiLink: string;
|
|
49
|
+
/**
|
|
50
|
+
* The available list of formats.
|
|
51
|
+
*/
|
|
52
|
+
availableFormats: ('json' | 'usfm')[];
|
|
53
|
+
/**
|
|
54
|
+
* The number of books that are contained in this translation.
|
|
55
|
+
*
|
|
56
|
+
* Complete translations should have the same number of books as the Bible (66).
|
|
57
|
+
*/
|
|
58
|
+
numberOfBooks: number;
|
|
59
|
+
/**
|
|
60
|
+
* The total number of chapters that are contained in this translation.
|
|
61
|
+
*
|
|
62
|
+
* Complete translations should have the same number of chapters as the Bible (1,189).
|
|
63
|
+
*/
|
|
64
|
+
totalNumberOfChapters: number;
|
|
65
|
+
/**
|
|
66
|
+
* The total number of verses that are contained in this translation.
|
|
67
|
+
*
|
|
68
|
+
* 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).
|
|
69
|
+
*/
|
|
70
|
+
totalNumberOfVerses: number;
|
|
71
|
+
/**
|
|
72
|
+
* Gets the name of the language that the translation is in.
|
|
73
|
+
* Null or undefined if the name of the language is not known.
|
|
74
|
+
*/
|
|
75
|
+
languageName?: string;
|
|
76
|
+
/**
|
|
77
|
+
* Gets the name of the language in English.
|
|
78
|
+
* Null or undefined if the language doesn't have an english name.
|
|
79
|
+
*/
|
|
80
|
+
languageEnglishName?: string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Defines an interface that contains information about the books that are available for a translation.
|
|
84
|
+
*/
|
|
85
|
+
export interface ApiTranslationBooks {
|
|
86
|
+
/**
|
|
87
|
+
* The translation information for the books.
|
|
88
|
+
*/
|
|
89
|
+
translation: ApiTranslation;
|
|
90
|
+
/**
|
|
91
|
+
* The list of books that are available for the translation.
|
|
92
|
+
*/
|
|
93
|
+
books: ApiTranslationBook[];
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Defines a translation book that is used in the API.
|
|
97
|
+
*/
|
|
98
|
+
export interface ApiTranslationBook extends TranslationBook {
|
|
99
|
+
/**
|
|
100
|
+
* The link to the first chapter of the book.
|
|
101
|
+
*/
|
|
102
|
+
firstChapterApiLink: string;
|
|
103
|
+
/**
|
|
104
|
+
* The link to the last chapter of the book.
|
|
105
|
+
*/
|
|
106
|
+
lastChapterApiLink: string;
|
|
107
|
+
/**
|
|
108
|
+
* The number of chapters that the book contains.
|
|
109
|
+
*/
|
|
110
|
+
numberOfChapters: number;
|
|
111
|
+
/**
|
|
112
|
+
* The number of verses that the book contains.
|
|
113
|
+
*/
|
|
114
|
+
totalNumberOfVerses: number;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Defines an interface that contains information about a book chapter.
|
|
118
|
+
*/
|
|
119
|
+
export interface ApiTranslationBookChapter extends TranslationBookChapter {
|
|
120
|
+
/**
|
|
121
|
+
* The translation information for the book chapter.
|
|
122
|
+
*/
|
|
123
|
+
translation: ApiTranslation;
|
|
124
|
+
/**
|
|
125
|
+
* The book information for the book chapter.
|
|
126
|
+
*/
|
|
127
|
+
book: ApiTranslationBook;
|
|
128
|
+
/**
|
|
129
|
+
* The link to this chapter.
|
|
130
|
+
*/
|
|
131
|
+
thisChapterLink: string;
|
|
132
|
+
/**
|
|
133
|
+
* The link to the next chapter.
|
|
134
|
+
* Null if this is the last chapter in the translation.
|
|
135
|
+
*/
|
|
136
|
+
nextChapterApiLink: string | null;
|
|
137
|
+
/**
|
|
138
|
+
* The links to the audio versions for the next chapter.
|
|
139
|
+
* Null if this is the last chapter in the translation.
|
|
140
|
+
*/
|
|
141
|
+
nextChapterAudioLinks: TranslationBookChapterAudioLinks | null;
|
|
142
|
+
/**
|
|
143
|
+
* The link to the previous chapter.
|
|
144
|
+
* Null if this is the first chapter in the translation.
|
|
145
|
+
*/
|
|
146
|
+
previousChapterApiLink: string | null;
|
|
147
|
+
/**
|
|
148
|
+
* The links to the audio versions for the previous chapter.
|
|
149
|
+
* Null if this is the first chapter in the translation.
|
|
150
|
+
*/
|
|
151
|
+
previousChapterAudioLinks: TranslationBookChapterAudioLinks | null;
|
|
152
|
+
/**
|
|
153
|
+
* The number of verses that the chapter contains.
|
|
154
|
+
*/
|
|
155
|
+
numberOfVerses: number;
|
|
156
|
+
}
|
|
157
|
+
export interface ApiTranslationBookChapterAudio {
|
|
158
|
+
/**
|
|
159
|
+
* The chapter that the audio is for.
|
|
160
|
+
*/
|
|
161
|
+
chapter: ApiTranslationBookChapter;
|
|
162
|
+
/**
|
|
163
|
+
* The link that the audio should be placed at.
|
|
164
|
+
*/
|
|
165
|
+
link: string;
|
|
166
|
+
/**
|
|
167
|
+
* The original URL of the audio.
|
|
168
|
+
*/
|
|
169
|
+
originalUrl: string;
|
|
170
|
+
}
|
|
171
|
+
export interface GenerateApiOptions {
|
|
172
|
+
/**
|
|
173
|
+
* Whether to use the common name for the book chapter API link. If false, then book IDs are used.
|
|
174
|
+
* Audio URLs will always use the book ID.
|
|
175
|
+
* Defaults to false.
|
|
176
|
+
*/
|
|
177
|
+
useCommonName?: boolean;
|
|
178
|
+
/**
|
|
179
|
+
* Whether to replace the audio URLs in the dataset with ones that are hosted locally.
|
|
180
|
+
* If true, then the audio URLs in the dataset will be replaced with ones that reference files hosted by the API itself.
|
|
181
|
+
* If false, then the audio URLs in the dataset will be left as is.
|
|
182
|
+
* Defaults to false.
|
|
183
|
+
*/
|
|
184
|
+
generateAudioFiles?: boolean;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Generates the API output for the given dataset.
|
|
188
|
+
* @param dataset The dataset to generate the API for.
|
|
189
|
+
* @param options The options for generating the API.
|
|
190
|
+
*/
|
|
191
|
+
export declare function generateApiForDataset(dataset: DatasetOutput, options?: GenerateApiOptions): ApiOutput;
|
|
192
|
+
/**
|
|
193
|
+
* Generates the output files for the given API.
|
|
194
|
+
* @param api The API that the files should be generated for.
|
|
195
|
+
*/
|
|
196
|
+
export declare function generateFilesForApi(api: ApiOutput): OutputFile[];
|
|
197
|
+
export declare function listOfBooksApiLink(translationId: string): string;
|
|
198
|
+
export declare function bookChapterApiLink(translationId: string, commonName: string, chapterNumber: number, extension: string): string;
|
|
199
|
+
export declare function bookChapterAudioApiLink(translationId: string, bookId: string, chapterNumber: number, reader: string): string;
|
|
200
|
+
export declare function jsonFile(path: string, content: any, mergable?: boolean): OutputFile;
|
|
201
|
+
export declare function downloadedFile(path: string, url: string): OutputFile;
|
|
202
|
+
export declare function replaceSpacesWithUnderscores(str: string): string;
|
|
203
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateApiForDataset = generateApiForDataset;
|
|
4
|
+
exports.generateFilesForApi = generateFilesForApi;
|
|
5
|
+
exports.listOfBooksApiLink = listOfBooksApiLink;
|
|
6
|
+
exports.bookChapterApiLink = bookChapterApiLink;
|
|
7
|
+
exports.bookChapterAudioApiLink = bookChapterAudioApiLink;
|
|
8
|
+
exports.jsonFile = jsonFile;
|
|
9
|
+
exports.downloadedFile = downloadedFile;
|
|
10
|
+
exports.replaceSpacesWithUnderscores = replaceSpacesWithUnderscores;
|
|
11
|
+
const all_iso_language_codes_1 = require("all-iso-language-codes");
|
|
12
|
+
/**
|
|
13
|
+
* Generates the API output for the given dataset.
|
|
14
|
+
* @param dataset The dataset to generate the API for.
|
|
15
|
+
* @param options The options for generating the API.
|
|
16
|
+
*/
|
|
17
|
+
function generateApiForDataset(dataset, options = {}) {
|
|
18
|
+
const { useCommonName } = options;
|
|
19
|
+
let api = {
|
|
20
|
+
availableTranslations: {
|
|
21
|
+
translations: [],
|
|
22
|
+
},
|
|
23
|
+
translationBooks: [],
|
|
24
|
+
translationBookChapters: [],
|
|
25
|
+
translationBookChapterAudio: [],
|
|
26
|
+
};
|
|
27
|
+
for (let { books, ...translation } of dataset.translations) {
|
|
28
|
+
const apiTranslation = {
|
|
29
|
+
...translation,
|
|
30
|
+
availableFormats: ['json'],
|
|
31
|
+
listOfBooksApiLink: listOfBooksApiLink(translation.id),
|
|
32
|
+
numberOfBooks: books.length,
|
|
33
|
+
totalNumberOfChapters: 0,
|
|
34
|
+
totalNumberOfVerses: 0,
|
|
35
|
+
languageName: (0, all_iso_language_codes_1.getNativeName)(translation.language) ?? undefined,
|
|
36
|
+
languageEnglishName: (0, all_iso_language_codes_1.getEnglishName)(translation.language) ?? undefined,
|
|
37
|
+
};
|
|
38
|
+
const translationBooks = {
|
|
39
|
+
translation: apiTranslation,
|
|
40
|
+
books: [],
|
|
41
|
+
};
|
|
42
|
+
let translationChapters = [];
|
|
43
|
+
for (let { chapters, ...book } of books) {
|
|
44
|
+
const apiBook = {
|
|
45
|
+
...book,
|
|
46
|
+
firstChapterApiLink: bookChapterApiLink(translation.id, getBookLink(book), 1, 'json'),
|
|
47
|
+
lastChapterApiLink: bookChapterApiLink(translation.id, getBookLink(book), chapters.length, 'json'),
|
|
48
|
+
numberOfChapters: chapters.length,
|
|
49
|
+
totalNumberOfVerses: 0,
|
|
50
|
+
};
|
|
51
|
+
for (let { chapter, thisChapterAudioLinks } of chapters) {
|
|
52
|
+
const audio = {};
|
|
53
|
+
const apiBookChapter = {
|
|
54
|
+
translation: apiTranslation,
|
|
55
|
+
book: apiBook,
|
|
56
|
+
chapter: chapter,
|
|
57
|
+
thisChapterLink: bookChapterApiLink(translation.id, getBookLink(book), chapter.number, 'json'),
|
|
58
|
+
thisChapterAudioLinks: audio,
|
|
59
|
+
nextChapterApiLink: null,
|
|
60
|
+
nextChapterAudioLinks: null,
|
|
61
|
+
previousChapterApiLink: null,
|
|
62
|
+
previousChapterAudioLinks: null,
|
|
63
|
+
numberOfVerses: 0,
|
|
64
|
+
};
|
|
65
|
+
for (let reader in thisChapterAudioLinks) {
|
|
66
|
+
if (options.generateAudioFiles) {
|
|
67
|
+
const apiAudio = {
|
|
68
|
+
chapter: apiBookChapter,
|
|
69
|
+
link: bookChapterAudioApiLink(translation.id, getBookLink(book), chapter.number, reader),
|
|
70
|
+
originalUrl: thisChapterAudioLinks[reader],
|
|
71
|
+
};
|
|
72
|
+
audio[reader] = apiAudio.link;
|
|
73
|
+
api.translationBookChapterAudio.push(apiAudio);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
audio[reader] = thisChapterAudioLinks[reader];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
for (let c of chapter.content) {
|
|
80
|
+
if (c.type === 'verse') {
|
|
81
|
+
apiBookChapter.numberOfVerses++;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
apiBook.totalNumberOfVerses += apiBookChapter.numberOfVerses;
|
|
85
|
+
translationChapters.push(apiBookChapter);
|
|
86
|
+
api.translationBookChapters.push(apiBookChapter);
|
|
87
|
+
}
|
|
88
|
+
translationBooks.books.push(apiBook);
|
|
89
|
+
apiTranslation.totalNumberOfChapters += apiBook.numberOfChapters;
|
|
90
|
+
apiTranslation.totalNumberOfVerses += apiBook.totalNumberOfVerses;
|
|
91
|
+
}
|
|
92
|
+
for (let i = 0; i < translationChapters.length; i++) {
|
|
93
|
+
if (i > 0) {
|
|
94
|
+
translationChapters[i].previousChapterApiLink = bookChapterApiLink(translation.id, getBookLink(translationChapters[i - 1].book), translationChapters[i - 1].chapter.number, 'json');
|
|
95
|
+
translationChapters[i].previousChapterAudioLinks = translationChapters[i - 1].thisChapterAudioLinks;
|
|
96
|
+
}
|
|
97
|
+
if (i < translationChapters.length - 1) {
|
|
98
|
+
translationChapters[i].nextChapterApiLink = bookChapterApiLink(translation.id, getBookLink(translationChapters[i + 1].book), translationChapters[i + 1].chapter.number, 'json');
|
|
99
|
+
translationChapters[i].nextChapterAudioLinks = translationChapters[i + 1].thisChapterAudioLinks;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
api.availableTranslations.translations.push(apiTranslation);
|
|
103
|
+
api.translationBooks.push(translationBooks);
|
|
104
|
+
}
|
|
105
|
+
return api;
|
|
106
|
+
function getBookLink(book) {
|
|
107
|
+
return useCommonName ? book.commonName : book.id;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Generates the output files for the given API.
|
|
112
|
+
* @param api The API that the files should be generated for.
|
|
113
|
+
*/
|
|
114
|
+
function generateFilesForApi(api) {
|
|
115
|
+
let files = [];
|
|
116
|
+
files.push(jsonFile('/api/available_translations.json', api.availableTranslations, true));
|
|
117
|
+
for (let translationBooks of api.translationBooks) {
|
|
118
|
+
files.push(jsonFile(translationBooks.translation.listOfBooksApiLink, translationBooks));
|
|
119
|
+
}
|
|
120
|
+
for (let bookChapter of api.translationBookChapters) {
|
|
121
|
+
files.push(jsonFile(bookChapter.thisChapterLink, bookChapter));
|
|
122
|
+
}
|
|
123
|
+
for (let audio of api.translationBookChapterAudio) {
|
|
124
|
+
files.push(downloadedFile(audio.link, audio.originalUrl));
|
|
125
|
+
}
|
|
126
|
+
return files;
|
|
127
|
+
}
|
|
128
|
+
;
|
|
129
|
+
function listOfBooksApiLink(translationId) {
|
|
130
|
+
return `/api/${translationId}/books.json`;
|
|
131
|
+
}
|
|
132
|
+
function bookChapterApiLink(translationId, commonName, chapterNumber, extension) {
|
|
133
|
+
return `/api/${translationId}/${replaceSpacesWithUnderscores(commonName)}/${chapterNumber}.${extension}`;
|
|
134
|
+
}
|
|
135
|
+
function bookChapterAudioApiLink(translationId, bookId, chapterNumber, reader) {
|
|
136
|
+
return `/api/${translationId}/${replaceSpacesWithUnderscores(bookId)}/${chapterNumber}.${reader}.mp3`;
|
|
137
|
+
}
|
|
138
|
+
function jsonFile(path, content, mergable) {
|
|
139
|
+
return {
|
|
140
|
+
path,
|
|
141
|
+
content,
|
|
142
|
+
mergable
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function downloadedFile(path, url) {
|
|
146
|
+
return {
|
|
147
|
+
path,
|
|
148
|
+
content: () => fetch(url).then(response => response.body),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function replaceSpacesWithUnderscores(str) {
|
|
152
|
+
return str.replace(/[<>:"/\\|?*\s]/g, '_');
|
|
153
|
+
}
|