proskomma-core 0.9.10 → 0.9.13

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 (136) hide show
  1. package/.eslintrc.json +79 -0
  2. package/.gitattributes +2 -0
  3. package/docs/_config.yml +1 -0
  4. package/docs/index.md +3 -0
  5. package/docs/pk_edit_0_9.odt +0 -0
  6. package/docs/pk_edit_0_9.pdf +0 -0
  7. package/docs/proskomma_101_slideshow.odp +0 -0
  8. package/docs/proskomma_101_slideshow.pdf +0 -0
  9. package/docs/proskomma_edit_html.png +0 -0
  10. package/docs/proskomma_edit_html.svg +451 -0
  11. package/docs/proskomma_edit_reference.png +0 -0
  12. package/docs/proskomma_edit_reference.svg +349 -0
  13. package/docs/repo_logo.png +0 -0
  14. package/esm/package.json +3 -0
  15. package/esm/wrapper.mjs +5 -0
  16. package/index.cjs +6 -0
  17. package/package.json +18 -15
  18. package/src/graph/index.cjs +201 -0
  19. package/src/graph/lib/do_cv.cjs +249 -0
  20. package/src/graph/lib/dump.cjs +40 -0
  21. package/src/graph/lib/remake_blocks.cjs +57 -0
  22. package/src/graph/lib/sequence_chars.cjs +84 -0
  23. package/src/graph/lib/sort.cjs +39 -0
  24. package/src/graph/lib/tribos.cjs +97 -0
  25. package/src/graph/lib/tribos_expression.cjs +556 -0
  26. package/src/graph/lib/tribos_ohm_UNUSED.cjs +37 -0
  27. package/src/graph/lib/tribos_step.cjs +434 -0
  28. package/src/graph/mutations/add.cjs +91 -0
  29. package/src/graph/mutations/delete.cjs +61 -0
  30. package/src/graph/mutations/index.cjs +54 -0
  31. package/src/graph/mutations/rehash.cjs +17 -0
  32. package/src/graph/mutations/tags.cjs +120 -0
  33. package/src/graph/mutations/update.cjs +210 -0
  34. package/src/graph/mutations/versification.cjs +96 -0
  35. package/src/graph/queries/block.cjs +228 -0
  36. package/src/graph/queries/cIndex.cjs +87 -0
  37. package/src/graph/queries/cell.cjs +42 -0
  38. package/src/graph/queries/cv.cjs +19 -0
  39. package/src/graph/queries/cvBook.cjs +16 -0
  40. package/src/graph/queries/cvChapter.cjs +16 -0
  41. package/src/graph/queries/cvIndex.cjs +47 -0
  42. package/src/graph/queries/cvNavigation.cjs +116 -0
  43. package/src/graph/queries/cvVerseElement.cjs +84 -0
  44. package/src/graph/queries/cvVerses.cjs +14 -0
  45. package/src/graph/queries/doc_set.cjs +220 -0
  46. package/src/graph/queries/document.cjs +555 -0
  47. package/src/graph/queries/idParts.cjs +30 -0
  48. package/src/graph/queries/index.cjs +151 -0
  49. package/src/graph/queries/inputBlockSpec.cjs +17 -0
  50. package/src/graph/queries/inputItemObject.cjs +12 -0
  51. package/src/graph/queries/input_att_spec.cjs +14 -0
  52. package/src/graph/queries/input_key_matches.cjs +11 -0
  53. package/src/graph/queries/input_key_value.cjs +11 -0
  54. package/src/graph/queries/input_key_values.cjs +11 -0
  55. package/src/graph/queries/input_selector_spec.cjs +19 -0
  56. package/src/graph/queries/item.cjs +71 -0
  57. package/src/graph/queries/itemGroup.cjs +75 -0
  58. package/src/graph/queries/key_value.cjs +18 -0
  59. package/src/graph/queries/kv_entry.cjs +21 -0
  60. package/src/graph/queries/kv_sequence.cjs +151 -0
  61. package/src/graph/queries/node.cjs +44 -0
  62. package/src/graph/queries/orig.cjs +11 -0
  63. package/src/graph/queries/regex_index.cjs +18 -0
  64. package/src/graph/queries/row_equals_spec.cjs +11 -0
  65. package/src/graph/queries/row_match_spec.cjs +11 -0
  66. package/src/graph/queries/selector_spec.cjs +29 -0
  67. package/src/graph/queries/sequence.cjs +314 -0
  68. package/src/graph/queries/table_sequence.cjs +192 -0
  69. package/src/graph/queries/tree_sequence.cjs +58 -0
  70. package/src/graph/queries/verseNumber.cjs +44 -0
  71. package/src/graph/queries/verseRange.cjs +11 -0
  72. package/src/graph/queries/versification.cjs +25 -0
  73. package/src/index.cjs +583 -0
  74. package/src/model/doc_set.cjs +389 -0
  75. package/src/model/doc_set_helpers/block.cjs +232 -0
  76. package/src/model/doc_set_helpers/enum.cjs +87 -0
  77. package/src/model/doc_set_helpers/item.cjs +198 -0
  78. package/src/model/doc_set_helpers/rehash.cjs +53 -0
  79. package/src/model/doc_set_helpers/selectors.cjs +58 -0
  80. package/src/model/doc_set_helpers/serialize.cjs +22 -0
  81. package/src/model/doc_set_helpers/unsuccinctify.cjs +288 -0
  82. package/src/model/doc_set_helpers/update.cjs +290 -0
  83. package/src/model/document.cjs +369 -0
  84. package/src/model/document_helpers/blocks.cjs +135 -0
  85. package/src/model/document_helpers/chapter_verse.cjs +291 -0
  86. package/src/model/document_helpers/pre_enums.cjs +67 -0
  87. package/src/model/document_helpers/sequences.cjs +205 -0
  88. package/src/model/document_helpers/serialize_succinct.cjs +55 -0
  89. package/src/model/document_helpers/succinct_filter.cjs +102 -0
  90. package/src/model/versifications/eng_vrs.cjs +455 -0
  91. package/src/model/versifications/index.cjs +38 -0
  92. package/src/model/versifications/lxx_vrs.cjs +950 -0
  93. package/src/model/versifications/org_vrs.cjs +155 -0
  94. package/src/model/versifications/rsc_vrs.cjs +342 -0
  95. package/src/model/versifications/rso_vrs.cjs +541 -0
  96. package/src/model/versifications/vul_vrs.cjs +835 -0
  97. package/src/parser/index.cjs +506 -0
  98. package/src/parser/lexers/index.cjs +11 -0
  99. package/src/parser/lexers/lexingRegexes.cjs +45 -0
  100. package/src/parser/lexers/nodes.cjs +123 -0
  101. package/src/parser/lexers/object_for_fragment.cjs +123 -0
  102. package/src/parser/lexers/tsv.cjs +45 -0
  103. package/src/parser/lexers/usfm.cjs +17 -0
  104. package/src/parser/lexers/usx/index.cjs +7 -0
  105. package/src/parser/lexers/usx/usx_lexer.cjs +321 -0
  106. package/src/parser/lib/tokenize.cjs +37 -0
  107. package/src/parser/model/index.cjs +637 -0
  108. package/src/parser/parser_specs.cjs +781 -0
  109. package/src/pipelines/perf2x/index.cjs +7 -0
  110. package/src/pipelines/perf2x/perf2PkJsonPipeline.json +41 -0
  111. package/src/pipelines/perf2x/perf2usfmPipeline.json +65 -0
  112. package/src/transforms/calculateUsfmChapterPositions.cjs +106 -0
  113. package/src/transforms/index.cjs +9 -0
  114. package/src/transforms/perf2PkJson.cjs +534 -0
  115. package/src/transforms/perf2usfm.cjs +294 -0
  116. package/src/util/byteArray.cjs +251 -0
  117. package/src/util/canons.cjs +117 -0
  118. package/src/util/enums.cjs +41 -0
  119. package/src/util/generateId.cjs +6 -0
  120. package/src/util/graftDefs.cjs +15 -0
  121. package/src/util/index.cjs +29 -0
  122. package/src/util/inspectSuccinct.cjs +59 -0
  123. package/src/util/itemDefs.cjs +33 -0
  124. package/src/util/parserConstantDefs.cjs +30 -0
  125. package/src/util/scopeDefs.cjs +173 -0
  126. package/src/util/scriptlike/blocksSpec.cjs +192 -0
  127. package/src/util/scriptlike/dodson_lexicon.xsl +19 -0
  128. package/src/util/scriptlike/dodson_lexicon_to_entries.cjs +85 -0
  129. package/src/util/scriptlike/open_scriptures_hebrew_lexicon.xsl +28 -0
  130. package/src/util/scriptlike/open_scriptures_hebrew_lexicon_to_entries.cjs +85 -0
  131. package/src/util/succinct.cjs +159 -0
  132. package/src/util/tags.cjs +28 -0
  133. package/src/util/tokenDefs.cjs +27 -0
  134. package/src/util/versification.cjs +364 -0
  135. package/dist/index.js +0 -8
  136. package/dist/index.js.LICENSE.txt +0 -23
@@ -0,0 +1,135 @@
1
+ const utils = require('../../util/index.cjs');
2
+ const ByteArray = utils.ByteArray;
3
+ const {
4
+ pushSuccinctGraftBytes,
5
+ pushSuccinctScopeBytes,
6
+ pushSuccinctTokenBytes,
7
+ } = utils.succinct;
8
+ const { itemEnum } = utils.itemDefs;
9
+ const {
10
+ scopeEnum, scopeEnumLabels, nComponentsForScope,
11
+ } = utils.scopeDefs;
12
+ const { tokenCategory, tokenEnum } = utils.tokenDefs;
13
+ const { headerBytes } = utils.succinct;
14
+
15
+ const { updateBlockGrafts } = require('../doc_set_helpers/update.cjs');
16
+
17
+ const deleteBlock = (document, seqId, blockN, buildCV) => {
18
+ if (buildCV !== false) {
19
+ buildCV = true;
20
+ }
21
+
22
+ if (!(seqId in document.sequences)) {
23
+ return false;
24
+ }
25
+
26
+ const sequence = document.sequences[seqId];
27
+
28
+ if (blockN < 0 || blockN >= sequence.blocks.length) {
29
+ return false;
30
+ }
31
+ sequence.blocks.splice(blockN, 1);
32
+
33
+ if (buildCV) {
34
+ document.buildChapterVerseIndex(this);
35
+ }
36
+ return true;
37
+ };
38
+
39
+ const newBlock = (document, seqId, blockN, blockScope, blockGrafts, buildCV) => {
40
+ if (buildCV !== false) {
41
+ buildCV = true;
42
+ }
43
+
44
+ if (!(seqId in document.sequences)) {
45
+ return false;
46
+ }
47
+
48
+ const sequence = document.sequences[seqId];
49
+
50
+ if (blockN < 0 || blockN > sequence.blocks.length) {
51
+ return false;
52
+ }
53
+
54
+ const docSet = document.processor.docSets[document.docSetId];
55
+ docSet.maybeBuildPreEnums();
56
+
57
+ const newBlock = {
58
+ bs: new ByteArray(0),
59
+ bg: new ByteArray(0),
60
+ c: new ByteArray(0),
61
+ os: new ByteArray(0),
62
+ is: new ByteArray(0),
63
+ nt: new ByteArray(0),
64
+ };
65
+ const scopeBits = blockScope.split('/');
66
+ const scopeTypeByte = scopeEnum[scopeBits[0]];
67
+ const expectedNScopeBits = nComponentsForScope(scopeBits[0]);
68
+
69
+ if (scopeBits.length !== expectedNScopeBits) {
70
+ throw new Error(`Scope ${blockScope} has ${scopeBits.length} component(s) (expected ${expectedNScopeBits}`);
71
+ }
72
+
73
+ const scopeBitBytes = scopeBits.slice(1).map(b => docSet.enumForCategoryValue('scopeBits', b, true));
74
+ pushSuccinctScopeBytes(newBlock.bs, itemEnum[`startScope`], scopeTypeByte, scopeBitBytes);
75
+ newBlock.bs.trim();
76
+
77
+ if (blockGrafts) {
78
+ updateBlockGrafts(
79
+ docSet,
80
+ document.id,
81
+ seqId,
82
+ blockN,
83
+ blockGrafts,
84
+ );
85
+ }
86
+ sequence.blocks.splice(blockN, 0, newBlock);
87
+
88
+ if (buildCV) {
89
+ document.buildChapterVerseIndex();
90
+ }
91
+ return true;
92
+ };
93
+
94
+ const rewriteBlock = (block, oldToNew) => {
95
+ for (const blockKey of ['bs', 'bg', 'c', 'is', 'os']) {
96
+ const oldBa = block[blockKey];
97
+ const newBa = new ByteArray(oldBa.length);
98
+ let pos = 0;
99
+
100
+ while (pos < oldBa.length) {
101
+ const [itemLength, itemType, itemSubtype] = headerBytes(oldBa, pos);
102
+
103
+ if (itemType === itemEnum['token']) {
104
+ if (itemSubtype === tokenEnum.wordLike) {
105
+ pushSuccinctTokenBytes(newBa, itemSubtype, oldToNew.wordLike[oldBa.nByte(pos + 2)]);
106
+ } else {
107
+ pushSuccinctTokenBytes(newBa, itemSubtype, oldToNew.notWordLike[oldBa.nByte(pos + 2)]);
108
+ }
109
+ } else if (itemType === itemEnum['graft']) {
110
+ pushSuccinctGraftBytes(newBa, oldToNew.graftTypes[itemSubtype], oldToNew.ids[oldBa.nByte(pos + 2)]);
111
+ } else {
112
+ let nScopeBitBytes = nComponentsForScope(scopeEnumLabels[itemSubtype]);
113
+ const scopeBitBytes = [];
114
+ let offset = 2;
115
+
116
+ while (nScopeBitBytes > 1) {
117
+ const scopeBitByte = oldToNew.scopeBits[oldBa.nByte(pos + offset)];
118
+ scopeBitBytes.push(scopeBitByte);
119
+ offset += oldBa.nByteLength(scopeBitByte);
120
+ nScopeBitBytes--;
121
+ }
122
+ pushSuccinctScopeBytes(newBa, itemType, itemSubtype, scopeBitBytes);
123
+ }
124
+ pos += itemLength;
125
+ }
126
+ newBa.trim();
127
+ block[blockKey] = newBa;
128
+ }
129
+ };
130
+
131
+ module.exports = {
132
+ newBlock,
133
+ deleteBlock,
134
+ rewriteBlock,
135
+ };
@@ -0,0 +1,291 @@
1
+ const BitSet = require('bitset');
2
+
3
+ const utils = require('../../util/index.cjs');
4
+ const ByteArray = utils.ByteArray;
5
+ const { itemEnum } = utils.itemDefs;
6
+ const { tokenEnum } = utils.tokenDefs;
7
+
8
+ const emptyCVIndexType = 0;
9
+ const shortCVIndexType = 2;
10
+ const longCVIndexType = 3;
11
+
12
+ const buildChapterVerseIndex = document => {
13
+ const mainSequence = document.sequences[document.mainId];
14
+ const docSet = document.processor.docSets[document.docSetId];
15
+ docSet.buildPreEnums();
16
+ docSet.buildEnumIndexes();
17
+ const chapterVerseIndexes = {};
18
+ const chapterIndexes = {};
19
+ let chapterN = '0';
20
+ let verseN = '0';
21
+ let verses = '1';
22
+ let nextTokenN = 0;
23
+
24
+ mainSequence.chapterVerses = {};
25
+
26
+ if (docSet.enums.wordLike.length === 0) {
27
+ throw new Error('No wordLike content in docSet - probably a USFM issue, maybe missing \\mt?');
28
+ }
29
+ mainSequence.tokensPresent = new BitSet(
30
+ new Array(docSet.enums.wordLike.length)
31
+ .fill(0)
32
+ .map(b => b.toString())
33
+ .join(''),
34
+ );
35
+
36
+ for (const [blockN, block] of mainSequence.blocks.entries()) {
37
+ let pos = 0;
38
+ let succinct = block.c;
39
+ let itemN = -1;
40
+
41
+ while (pos < succinct.length) {
42
+ itemN++;
43
+ const [itemLength, itemType, itemSubtype] = utils.succinct.headerBytes(succinct, pos);
44
+
45
+ if (itemType === itemEnum['startScope']) {
46
+ let scopeLabel = docSet.succinctScopeLabel(succinct, itemSubtype, pos);
47
+
48
+ if (scopeLabel.startsWith('chapter/')) {
49
+ chapterN = scopeLabel.split('/')[1];
50
+ chapterVerseIndexes[chapterN] = {};
51
+ chapterIndexes[chapterN] = {
52
+ startBlock: blockN,
53
+ startItem: itemN,
54
+ nextToken: nextTokenN,
55
+ };
56
+ } else if (scopeLabel.startsWith('verse/')) {
57
+ verseN = scopeLabel.split('/')[1];
58
+
59
+ if (verseN === '1' && !('0' in chapterVerseIndexes[chapterN])) {
60
+ if (chapterIndexes[chapterN].nextToken < nextTokenN) {
61
+ chapterVerseIndexes[chapterN]['0'] = [{
62
+ startBlock: chapterIndexes[chapterN].startBlock,
63
+ startItem: chapterIndexes[chapterN].startItem,
64
+ endBlock: blockN,
65
+ endItem: Math.max(itemN - 1, 0),
66
+ nextToken: chapterIndexes[chapterN].nextToken,
67
+ verses: '0',
68
+ }];
69
+ }
70
+ }
71
+
72
+ if (!(verseN in chapterVerseIndexes[chapterN])) {
73
+ chapterVerseIndexes[chapterN][verseN] = [];
74
+ }
75
+ chapterVerseIndexes[chapterN][verseN].push({
76
+ startBlock: blockN,
77
+ startItem: itemN,
78
+ nextToken: nextTokenN,
79
+ });
80
+ } else if (scopeLabel.startsWith('verses/')) {
81
+ verses = scopeLabel.split('/')[1];
82
+ }
83
+ } else if (itemType === itemEnum['endScope']) {
84
+ let scopeLabel = docSet.succinctScopeLabel(succinct, itemSubtype, pos);
85
+
86
+ if (scopeLabel.startsWith('chapter/')) {
87
+ chapterN = scopeLabel.split('/')[1];
88
+ let chapterRecord = chapterIndexes[chapterN];
89
+
90
+ if (chapterRecord) { // Check start chapter has not been deleted
91
+ chapterRecord.endBlock = blockN;
92
+ chapterRecord.endItem = itemN;
93
+ }
94
+ } else if (scopeLabel.startsWith('verse/')) {
95
+ verseN = scopeLabel.split('/')[1];
96
+ let versesRecord = chapterVerseIndexes[chapterN][verseN];
97
+
98
+ if (versesRecord) { // Check start verse has not been deleted
99
+ const verseRecord = chapterVerseIndexes[chapterN][verseN][chapterVerseIndexes[chapterN][verseN].length - 1];
100
+ verseRecord.endBlock = blockN;
101
+ verseRecord.endItem = itemN;
102
+ verseRecord.verses = verses;
103
+ }
104
+ }
105
+ } else if (itemType === itemEnum['token'] && itemSubtype === tokenEnum['wordLike']) {
106
+ mainSequence.tokensPresent
107
+ .set(
108
+ succinct.nByte(pos + 2),
109
+ 1,
110
+ );
111
+ nextTokenN++;
112
+ }
113
+ pos += itemLength;
114
+ }
115
+ }
116
+
117
+ for (const [chapterN, chapterVerses] of Object.entries(chapterVerseIndexes)) {
118
+ const ba = new ByteArray();
119
+ mainSequence.chapterVerses[chapterN] = ba;
120
+ const sortedVerses = Object.keys(chapterVerses)
121
+ .map(n => parseInt(n))
122
+ .sort((a, b) => a - b);
123
+
124
+ if (sortedVerses.length === 0) {
125
+ continue;
126
+ }
127
+
128
+ const maxVerse = sortedVerses[sortedVerses.length - 1];
129
+ const verseSlots = Array.from(Array(maxVerse + 1).keys());
130
+ let pos = 0;
131
+
132
+ for (const verseSlot of verseSlots) {
133
+ const verseKey = `${verseSlot}`;
134
+
135
+ if (verseKey in chapterVerses) {
136
+ const verseElements = chapterVerses[verseKey];
137
+ const nVerseElements = verseElements.length;
138
+
139
+ for (const [verseElementN, verseElement] of verseElements.entries()) {
140
+ if (!verseElement.verses) {
141
+ console.log(`** VerseElement without verses for ${verseSlot} in buildChapterVerseIndex`);
142
+ continue;
143
+ }
144
+
145
+ const versesEnumIndex = docSet.enumForCategoryValue('scopeBits', verseElement.verses);
146
+ const recordType = verseElement.startBlock === verseElement.endBlock ? shortCVIndexType : longCVIndexType;
147
+ ba.pushByte(0);
148
+
149
+ if (recordType === shortCVIndexType) {
150
+ ba.pushNBytes([
151
+ verseElement.startBlock,
152
+ verseElement.startItem,
153
+ verseElement.endItem,
154
+ verseElement.nextToken,
155
+ versesEnumIndex,
156
+ ]);
157
+ } else {
158
+ ba.pushNBytes([
159
+ verseElement.startBlock,
160
+ verseElement.endBlock,
161
+ verseElement.startItem,
162
+ verseElement.endItem,
163
+ verseElement.nextToken,
164
+ versesEnumIndex,
165
+ ]);
166
+ }
167
+ ba.setByte(pos, makeVerseLengthByte(recordType, verseElementN === (nVerseElements - 1), ba.length - pos));
168
+ pos = ba.length;
169
+ }
170
+ } else {
171
+ ba.pushByte(makeVerseLengthByte(emptyCVIndexType, true, 1));
172
+ pos++;
173
+ }
174
+ }
175
+ ba.trim();
176
+ }
177
+ mainSequence.chapters = {};
178
+
179
+ for (const [chapterN, chapterElement] of Object.entries(chapterIndexes)) {
180
+ if (!('startBlock' in chapterElement) || !('endBlock' in chapterElement)) {
181
+ continue;
182
+ }
183
+
184
+ const ba = new ByteArray();
185
+ mainSequence.chapters[chapterN] = ba;
186
+ const recordType = chapterElement.startBlock === chapterElement.endBlock ? shortCVIndexType : longCVIndexType;
187
+ ba.pushByte(0);
188
+
189
+ if (recordType === shortCVIndexType) {
190
+ ba.pushNBytes([chapterElement.startBlock, chapterElement.startItem, chapterElement.endItem, chapterElement.nextToken]);
191
+ } else {
192
+ ba.pushNBytes([chapterElement.startBlock, chapterElement.endBlock, chapterElement.startItem, chapterElement.endItem, chapterElement.nextToken]);
193
+ }
194
+ ba.setByte(0, makeVerseLengthByte(recordType, true, ba.length));
195
+ ba.trim();
196
+ }
197
+ };
198
+
199
+ const chapterVerseIndex = (document, chapN) => {
200
+ const docSet = document.processor.docSets[document.docSetId];
201
+ docSet.buildEnumIndexes();
202
+ const ret = [];
203
+ const succinct = document.sequences[document.mainId].chapterVerses[chapN];
204
+
205
+ if (succinct) {
206
+ let pos = 0;
207
+ let currentVerseRecord = [];
208
+
209
+ while (pos < succinct.length) {
210
+ const [recordType, isLast, recordLength] = verseLengthByte(succinct, pos);
211
+
212
+ if (recordType === shortCVIndexType) {
213
+ const nBytes = succinct.nBytes(pos + 1, 5);
214
+
215
+ currentVerseRecord.push({
216
+ startBlock: nBytes[0],
217
+ endBlock: nBytes[0],
218
+ startItem: nBytes[1],
219
+ endItem: nBytes[2],
220
+ nextToken: nBytes[3],
221
+ verses: docSet.enums.scopeBits.countedString(docSet.enumIndexes.scopeBits[nBytes[4]]),
222
+ });
223
+ } else if (recordType === longCVIndexType) {
224
+ const nBytes = succinct.nBytes(pos + 1, 6);
225
+
226
+ currentVerseRecord.push({
227
+ startBlock: nBytes[0],
228
+ endBlock: nBytes[1],
229
+ startItem: nBytes[2],
230
+ endItem: nBytes[3],
231
+ nextToken: nBytes[4],
232
+ verses: docSet.enums.scopeBits.countedString(docSet.enumIndexes.scopeBits[nBytes[5]]),
233
+ });
234
+ }
235
+
236
+ if (isLast) {
237
+ ret.push(currentVerseRecord);
238
+ currentVerseRecord = [];
239
+ }
240
+ pos += recordLength;
241
+ }
242
+ }
243
+ return ret;
244
+ };
245
+
246
+ const chapterIndex = (document, chapN) => {
247
+ const succinct = document.sequences[document.mainId].chapters[chapN];
248
+
249
+ if (succinct) {
250
+ const recordType = verseLengthByte(succinct, 0)[0];
251
+
252
+ if (recordType === shortCVIndexType) {
253
+ const nBytes = succinct.nBytes(1, 4);
254
+
255
+ return {
256
+ startBlock: nBytes[0],
257
+ endBlock: nBytes[0],
258
+ startItem: nBytes[1],
259
+ endItem: nBytes[2],
260
+ nextToken: nBytes[3],
261
+ };
262
+ } else if (recordType === longCVIndexType) {
263
+ const nBytes = succinct.nBytes(1, 5);
264
+
265
+ return {
266
+ startBlock: nBytes[0],
267
+ endBlock: nBytes[1],
268
+ startItem: nBytes[2],
269
+ endItem: nBytes[3],
270
+ nextToken: nBytes[4],
271
+ };
272
+ }
273
+ }
274
+ };
275
+
276
+ const makeVerseLengthByte = (recordType, isLast, length) => length + (isLast ? 32 : 0) + (recordType * 64);
277
+
278
+ const verseLengthByte= (succinct, pos) => {
279
+ const sByte = succinct.byte(pos);
280
+ return [
281
+ sByte >> 6,
282
+ (sByte >> 5) % 2 === 1,
283
+ sByte % 32,
284
+ ];
285
+ };
286
+
287
+ module.exports = {
288
+ buildChapterVerseIndex,
289
+ chapterVerseIndex,
290
+ chapterIndex,
291
+ };
@@ -0,0 +1,67 @@
1
+ const utils = require('../../util/index.cjs');
2
+
3
+ const recordPreEnums = (docSet, seq) => {
4
+ docSet.recordPreEnum('scopeBits', '0');
5
+
6
+ for (const [blockN, block] of seq.blocks.entries()) {
7
+ for (const [itemN, item] of [...block.items, block.bs, ...block.bg].entries()) {
8
+ if (item.subType === 'wordLike') {
9
+ docSet.recordPreEnum('wordLike', item.payload);
10
+ } else if (['lineSpace', 'eol', 'punctuation', 'softLineBreak', 'bareSlash', 'unknown'].includes(item.subType)) {
11
+ docSet.recordPreEnum('notWordLike', item.payload);
12
+ } else if (item.type === 'graft') {
13
+ docSet.recordPreEnum('graftTypes', item.subType);
14
+ } else if (item.subType === 'start') {
15
+ const labelBits = item.payload.split('/');
16
+
17
+ if (labelBits.length !== utils.scopeDefs.nComponentsForScope(labelBits[0])) {
18
+ throw new Error(`Scope ${item.payload} has unexpected number of components`);
19
+ }
20
+
21
+ for (const labelBit of labelBits.slice(1)) {
22
+ docSet.recordPreEnum('scopeBits', labelBit);
23
+ }
24
+ }
25
+ }
26
+ }
27
+ };
28
+
29
+ const rerecordPreEnums = (docSet, seq) => {
30
+ docSet.recordPreEnum('scopeBits', '0');
31
+ docSet.recordPreEnum('ids', seq.id);
32
+
33
+ for (const block of seq.blocks) {
34
+ for (const blockKey of ['bs', 'bg', 'c', 'is', 'os']) {
35
+ rerecordBlockPreEnums(docSet, block[blockKey]);
36
+ }
37
+ }
38
+ };
39
+
40
+ const rerecordBlockPreEnums= (docSet, ba) => {
41
+ for (const item of docSet.unsuccinctifyItems(ba, {}, 0)) {
42
+ if (item[0] === 'token') {
43
+ if (item[1] === 'wordLike') {
44
+ docSet.recordPreEnum('wordLike', item[2]);
45
+ } else {
46
+ docSet.recordPreEnum('notWordLike', item[2]);
47
+ }
48
+ } else if (item[0] === 'graft') {
49
+ docSet.recordPreEnum('graftTypes', item[1]);
50
+ } else if (item[0] === 'scope' && item[1] === 'start') {
51
+ const labelBits = item[2].split('/');
52
+
53
+ if (labelBits.length !== utils.scopeDefs.nComponentsForScope(labelBits[0])) {
54
+ throw new Error(`Scope ${item[2]} has unexpected number of components`);
55
+ }
56
+
57
+ for (const labelBit of labelBits.slice(1)) {
58
+ docSet.recordPreEnum('scopeBits', labelBit);
59
+ }
60
+ }
61
+ }
62
+ };
63
+
64
+ module.exports = {
65
+ recordPreEnums,
66
+ rerecordPreEnums,
67
+ };
@@ -0,0 +1,205 @@
1
+ const deepCopy = require('deep-copy-all');
2
+
3
+ const utils = require('../../util/index.cjs');
4
+
5
+ const gcSequences = document => {
6
+ const usedSequences = new Set();
7
+ const docSet = document.processor.docSets[document.docSetId];
8
+ docSet.maybeBuildEnumIndexes();
9
+
10
+ const followGrafts = (document, sequence, used) => {
11
+ used.add(sequence.id);
12
+
13
+ for (const block of sequence.blocks) {
14
+ for (const blockGraft of docSet.unsuccinctifyGrafts(block.bg)) {
15
+ if (!used.has(blockGraft[2])) {
16
+ followGrafts(document, document.sequences[blockGraft[2]], used);
17
+ }
18
+ }
19
+
20
+ for (const inlineGraft of docSet.unsuccinctifyItems(block.c, { grafts: true }, 0)) {
21
+ if (!used.has(inlineGraft[2])) {
22
+ followGrafts(document, document.sequences[inlineGraft[2]], used);
23
+ }
24
+ }
25
+ }
26
+ };
27
+
28
+ followGrafts(document, document.sequences[document.mainId], usedSequences);
29
+ let changed = false;
30
+
31
+ for (const sequenceId of Object.keys(document.sequences)) {
32
+ if (!usedSequences.has(sequenceId)) {
33
+ delete document.sequences[sequenceId];
34
+ changed = true;
35
+ }
36
+ }
37
+
38
+ return changed;
39
+ };
40
+
41
+ const newSequence = (document, seqType, tags) => {
42
+ const seqId = utils.generateId();
43
+
44
+ document.sequences[seqId] = {
45
+ id: seqId,
46
+ type: seqType,
47
+ tags: new Set(tags || []),
48
+ isBaseType: (seqType in document.baseSequenceTypes),
49
+ blocks: [],
50
+ };
51
+
52
+ return seqId;
53
+ };
54
+
55
+ const deleteSequence = (document, seqId) => {
56
+ if (!(seqId in document.sequences)) {
57
+ return false;
58
+ }
59
+
60
+ if (document.sequences[seqId].type === 'main') {
61
+ throw new Error('Cannot delete main sequence');
62
+ }
63
+
64
+ if (document.sequences[seqId].type in document.baseSequenceTypes) {
65
+ gcSequenceReferences(document,'block', seqId);
66
+ } else {
67
+ gcSequenceReferences(document,'inline', seqId);
68
+ }
69
+ delete document.sequences[seqId];
70
+ document.buildChapterVerseIndex(this);
71
+ document.gcSequences();
72
+ return true;
73
+ };
74
+
75
+ const gcSequenceReferences = (document, seqContext, seqId) => {
76
+ const docSet = document.processor.docSets[document.docSetId];
77
+
78
+ for (const sequence of Object.values(document.sequences)) {
79
+ for (const block of sequence.blocks) {
80
+ const succinct = seqContext === 'block' ? block.bg : block.c;
81
+ let pos = 0;
82
+
83
+ while (pos < succinct.length) {
84
+ const [itemLength, itemType] = utils.succinct.headerBytes(succinct, pos);
85
+
86
+ if (itemType !== utils.itemDefs.itemEnum.graft) {
87
+ pos += itemLength;
88
+ } else {
89
+ const graftSeqId = utils.succinct.succinctGraftSeqId(docSet.enums, docSet.enumIndexes, succinct, pos);
90
+
91
+ if (graftSeqId === seqId) {
92
+ succinct.deleteItem(pos);
93
+ } else {
94
+ pos += itemLength;
95
+ }
96
+ }
97
+ }
98
+ }
99
+ }
100
+ };
101
+
102
+ const modifySequence = (
103
+ document,
104
+ seqId,
105
+ sequenceRewriteFunc,
106
+ blockFilterFunc,
107
+ itemFilterFunc,
108
+ blockRewriteFunc,
109
+ itemRewriteFunc,
110
+ ) => {
111
+ const docSet = document.processor.docSets[document.docSetId];
112
+ docSet.maybeBuildEnumIndexes();
113
+ sequenceRewriteFunc = sequenceRewriteFunc || (s => s);
114
+ const oldSequence = document.sequences[seqId];
115
+ const newSequence = sequenceRewriteFunc({
116
+ id: seqId,
117
+ type: oldSequence.type,
118
+ tags: oldSequence.tags,
119
+ isBaseType: oldSequence.isBaseType,
120
+ verseMapping: oldSequence.verseMapping,
121
+ });
122
+
123
+ pushModifiedBlocks(
124
+ oldSequence,
125
+ newSequence,
126
+ blockFilterFunc,
127
+ itemFilterFunc,
128
+ blockRewriteFunc,
129
+ itemRewriteFunc,
130
+ );
131
+ document.sequences[seqId] = newSequence;
132
+
133
+ if (newSequence.type === 'main') {
134
+ document.buildChapterVerseIndex();
135
+ }
136
+ return newSequence;
137
+ };
138
+
139
+ const pushModifiedBlocks = (
140
+ oldSequence,
141
+ newSequence,
142
+ blockFilterFunc,
143
+ itemFilterFunc,
144
+ blockRewriteFunc,
145
+ itemRewriteFunc,
146
+ ) => {
147
+ blockFilterFunc = blockFilterFunc || ((oldSequence, blockN, block) => !!block);
148
+ itemFilterFunc = itemFilterFunc ||
149
+ ((oldSequence, oldBlockN, block, itemN, itemType, itemSubType, pos) => !!block || pos);
150
+ blockRewriteFunc = blockRewriteFunc || ((oldSequence, blockN, block) => block);
151
+ itemRewriteFunc = itemRewriteFunc ||
152
+ (
153
+ (oldSequence, oldBlockN, oldBlock, newBlock, itemN, itemLength, itemType, itemSubType, pos) => {
154
+ for (let n = 0; n < itemLength; n++) {
155
+ newBlock.c.pushByte(oldBlock.c.byte(pos + n));
156
+ }
157
+ }
158
+ );
159
+ newSequence.blocks = [];
160
+
161
+ for (const [blockN, block] of oldSequence.blocks.entries()) {
162
+ if (blockFilterFunc(oldSequence, blockN, block)) {
163
+ const newBlock = blockRewriteFunc(oldSequence, blockN, deepCopy(block));
164
+ newBlock.c.clear();
165
+ modifyBlockItems(
166
+ oldSequence,
167
+ blockN,
168
+ block,
169
+ newBlock,
170
+ itemFilterFunc,
171
+ itemRewriteFunc,
172
+ );
173
+ newSequence.blocks.push(newBlock);
174
+ }
175
+ }
176
+ };
177
+
178
+ const modifyBlockItems = (
179
+ oldSequence,
180
+ oldBlockN,
181
+ oldBlock,
182
+ newBlock,
183
+ itemFilterFunc,
184
+ itemRewriteFunc,
185
+ ) => {
186
+ let pos = 0;
187
+ let itemN = -1;
188
+
189
+ while (pos < oldBlock.c.length) {
190
+ itemN++;
191
+ const [itemLength, itemType, itemSubtype] = utils.succinct.headerBytes(oldBlock.c, pos);
192
+
193
+ if (itemFilterFunc(oldSequence, oldBlockN, oldBlock, itemN, itemType, itemSubtype, pos)) {
194
+ itemRewriteFunc(oldSequence, oldBlockN, oldBlock, newBlock, itemN, itemLength, itemType, itemSubtype, pos);
195
+ }
196
+ pos += itemLength;
197
+ }
198
+ };
199
+
200
+ module.exports = {
201
+ newSequence,
202
+ gcSequences,
203
+ deleteSequence,
204
+ modifySequence,
205
+ };