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,637 @@
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 { addTag } = utils.tags;
9
+ const { labelForScope } = utils.scopeDefs;
10
+ const { itemEnum } = utils.itemDefs;
11
+ const { scopeEnum } = utils.scopeDefs;
12
+ const { tokenCategory, tokenEnum } = utils.tokenDefs;
13
+
14
+ const Sequence = class {
15
+ constructor(sType) {
16
+ this.id = utils.generateId();
17
+ this.type = sType;
18
+ this.tags = new Set([]);
19
+ this.blocks = [];
20
+ this.activeScopes = [];
21
+ }
22
+
23
+ addTag(tag) {
24
+ addTag(this.tags, tag);
25
+ }
26
+
27
+ plainText() {
28
+ return this.blocks.map(b => b.plainText()).join('').trim();
29
+ }
30
+
31
+ addItem(i) {
32
+ this.lastBlock().addItem(i);
33
+ }
34
+
35
+ addBlockGraft(g) {
36
+ this.newBlock('hangingGraft');
37
+ this.lastBlock().bg.push(g);
38
+ }
39
+
40
+ lastBlock() {
41
+ if (this.blocks.length === 0) {
42
+ this.newBlock('orphanTokens');
43
+ }
44
+ return this.blocks[this.blocks.length - 1];
45
+ }
46
+
47
+ newBlock(label) {
48
+ if (this.blocks.length > 0 && ['orphanTokens', 'hangingGraft'].includes(this.blocks[this.blocks.length - 1].bs.payload)) {
49
+ this.lastBlock().bs = {
50
+ type: 'scope',
51
+ subType: 'start',
52
+ payload: label,
53
+ };
54
+ } else {
55
+ this.blocks.push(new Block(label));
56
+ }
57
+ }
58
+
59
+ trim() {
60
+ this.blocks.forEach(b => b.trim());
61
+ }
62
+
63
+ reorderSpanWithAtts() {
64
+ this.blocks.forEach(b => b.reorderSpanWithAtts());
65
+ }
66
+
67
+ makeNoteGrafts(parser) {
68
+ this.blocks.forEach(b => b.makeNoteGrafts(parser));
69
+ }
70
+
71
+ close(parser) {
72
+ for (const activeScope of this.activeScopes.filter(() => true).reverse()) {
73
+ this.closeActiveScope(parser, activeScope);
74
+ }
75
+ this.activeScopes = [];
76
+ }
77
+
78
+ closeActiveScope(parser, sc) {
79
+ this.addItem({
80
+ type: 'scope',
81
+ subType: 'end',
82
+ payload: sc.label,
83
+ });
84
+
85
+ if (sc.onEnd) {
86
+ sc.onEnd(parser, sc.label);
87
+ }
88
+ }
89
+
90
+ filterGrafts(options) {
91
+ return this.blocks.map(b => b.filterGrafts(options)).reduce((acc, current) => acc.concat(current), []);
92
+ }
93
+
94
+ filterScopes(options) {
95
+ this.blocks.forEach(b => b.filterScopes(options));
96
+ }
97
+
98
+ text() {
99
+ return this.blocks.map(b => b.text()).join('');
100
+ }
101
+
102
+ addTableScopes() {
103
+ let inTable = false;
104
+
105
+ for (const [blockNo, block] of this.blocks.entries()) {
106
+ if (!inTable && block.bs.payload === 'blockTag/tr') {
107
+ inTable = true;
108
+ this.blocks[blockNo].items.unshift({
109
+ type: 'scope',
110
+ subType: 'start',
111
+ payload: labelForScope('table', []),
112
+ });
113
+ } else if (inTable && block.bs.payload !== 'blockTag/tr') {
114
+ inTable = false;
115
+ this.blocks[(blockNo - 1)].items.push({
116
+ type: 'scope',
117
+ subType: 'end',
118
+ payload: labelForScope('table', []),
119
+ });
120
+ }
121
+ }
122
+
123
+ if (inTable) {
124
+ this.lastBlock().items.push({
125
+ type: 'scope',
126
+ subType: 'end',
127
+ payload: labelForScope('table', []),
128
+ });
129
+ }
130
+ }
131
+
132
+ graftifyIntroductionHeadings(parser) {
133
+ let blockEntries = [...this.blocks.entries()];
134
+ blockEntries.reverse();
135
+ const introHeadingTags = ['iot', 'is'].concat(parser.customTags.introHeading);
136
+
137
+ for (const [n, block] of blockEntries) {
138
+ const blockTag = block.bs.payload.split('/')[1].replace(/[0-9]/g, '');
139
+
140
+ if (introHeadingTags.includes(blockTag)) {
141
+ const headingSequence = new Sequence('heading');
142
+ parser.sequences.heading.push(headingSequence);
143
+ headingSequence.blocks.push(block);
144
+ const headingGraft = {
145
+ type: 'graft',
146
+ subType: 'heading',
147
+ payload: headingSequence.id,
148
+ };
149
+
150
+ if (this.blocks.length < n + 2) {
151
+ this.newBlock('blockTag/hangingGraft');
152
+ }
153
+ this.blocks[n + 1].bg.unshift(headingGraft);
154
+ this.blocks.splice(n, 1);
155
+ } else if (blockTag.startsWith('imt')) {
156
+ const titleType = (blockTag.startsWith('imte') ? 'introEndTitle' : 'introTitle');
157
+ let titleSequence;
158
+
159
+ if (parser.sequences[titleType]) {
160
+ titleSequence = parser.sequences[titleType];
161
+ } else {
162
+ const graftType = (blockTag.startsWith('imte') ? 'endTitle' : 'title');
163
+ titleSequence = new Sequence(graftType);
164
+ parser.sequences[titleType] = titleSequence;
165
+ const titleGraft = {
166
+ type: 'graft',
167
+ subType: graftType,
168
+ payload: titleSequence.id,
169
+ };
170
+
171
+ if (this.blocks.length < n + 2) {
172
+ this.newBlock('blockTag/hangingGraft');
173
+ }
174
+ this.blocks[n + 1].bg.unshift(titleGraft);
175
+ }
176
+ this.blocks.splice(n, 1);
177
+ titleSequence.blocks.unshift(block);
178
+ }
179
+ }
180
+ }
181
+
182
+ moveOrphanScopes() {
183
+ if (this.blocks.length > 1) {
184
+ this.moveOrphanStartScopes();
185
+ this.moveOrphanEndScopes();
186
+ }
187
+ }
188
+
189
+ moveOrphanStartScopes() {
190
+ for (const [blockNo, block] of this.blocks.entries()) {
191
+ if (blockNo >= this.blocks.length - 1) {
192
+ continue;
193
+ }
194
+
195
+ for (const item of [...block.items].reverse()) {
196
+ if (item.subType !== 'start' || item.payload.startsWith('altChapter')) {
197
+ break;
198
+ }
199
+ this.blocks[blockNo + 1].items.unshift(this.blocks[blockNo].items.pop());
200
+ }
201
+ }
202
+ }
203
+
204
+ moveOrphanStartScopes2() {
205
+ for (const [blockNo, block] of this.blocks.entries()) {
206
+ if (blockNo >= this.blocks.length - 1) {
207
+ continue;
208
+ }
209
+
210
+ for (const item of [...block.items].reverse()) {
211
+ if (item.subType !== 'start') {
212
+ break;
213
+ }
214
+ this.blocks[blockNo + 1].items.unshift(this.blocks[blockNo].items.pop());
215
+ }
216
+ }
217
+ }
218
+
219
+ moveOrphanEndScopes() {
220
+ for (const [blockNo, block] of this.blocks.entries()) {
221
+ if (blockNo === 0) {
222
+ continue;
223
+ }
224
+
225
+ for (const item of [...block.items]) {
226
+ if (item.subType !== 'end') {
227
+ break;
228
+ }
229
+ this.blocks[blockNo - 1].items.push(this.blocks[blockNo].items.shift());
230
+ }
231
+ }
232
+ }
233
+
234
+ removeEmptyBlocks(customCanBeEmpty) {
235
+ const canBeEmpty = ['blockTag/b', 'blockTag/ib'].concat(customCanBeEmpty);
236
+ const emptyBlocks = [];
237
+ let changed = false;
238
+
239
+ for (const blockRecord of this.blocks.entries()) {
240
+ if (blockRecord[1].tokens().length === 0 && !canBeEmpty.includes(blockRecord[1].bs.payload)) {
241
+ emptyBlocks.push(blockRecord);
242
+ }
243
+ }
244
+
245
+ for (const [n, block] of emptyBlocks.reverse()) {
246
+ if (n < this.blocks.length - 1) {
247
+ for (const bg of [...block.bg].reverse()) {
248
+ this.blocks[n + 1].bg.unshift(bg);
249
+ }
250
+
251
+ for (const i of block.items.reverse()) {
252
+ this.blocks[n + 1].items.unshift(i);
253
+ }
254
+ this.blocks.splice(n, 1);
255
+ changed = true;
256
+ } else if (block.bg.length === 0 && block.items.length === 0) {
257
+ this.blocks.splice(n, 1);
258
+ changed = true;
259
+ }
260
+ }
261
+
262
+ if (changed) {
263
+ this.removeEmptyBlocks(customCanBeEmpty);
264
+ }
265
+ }
266
+
267
+ removeGraftsToEmptySequences(emptySequences) {
268
+ this.blocks.forEach(b => b.removeGraftsToEmptySequences(emptySequences));
269
+ }
270
+
271
+ succinctifyBlocks(docSet) {
272
+ const ret = [];
273
+ let openScopes = [];
274
+
275
+ const updateOpenScopes = item => {
276
+ if (item.subType === 'start') {
277
+ const existingScopes = openScopes.filter(s => s.payload === item.payload);
278
+
279
+ if (existingScopes.length === 0) {
280
+ openScopes.push(item);
281
+ }
282
+ } else {
283
+ openScopes = openScopes.filter(s => s.payload !== item.payload);
284
+ }
285
+ };
286
+
287
+ let nextToken = 0;
288
+
289
+ for (const block of this.blocks) {
290
+ const contentBA = new ByteArray(block.length);
291
+ const blockGraftsBA = new ByteArray(1);
292
+ const openScopesBA = new ByteArray(1);
293
+ const includedScopesBA = new ByteArray(1);
294
+ const nextTokenBA = new ByteArray(1);
295
+
296
+ nextTokenBA.pushNByte(nextToken);
297
+
298
+ for (const bg of block.bg) {
299
+ this.pushSuccinctGraft(blockGraftsBA, docSet, bg);
300
+ }
301
+
302
+ for (const os of openScopes) {
303
+ this.pushSuccinctScope(openScopesBA, docSet, os);
304
+ }
305
+
306
+ const includedScopes = [];
307
+
308
+ for (const item of block.items) {
309
+ switch (item.type) {
310
+ case 'token':
311
+ this.pushSuccinctToken(contentBA, docSet, item);
312
+
313
+ if (item.subType === 'wordLike') {
314
+ nextToken++;
315
+ }
316
+ break;
317
+ case 'graft':
318
+ this.pushSuccinctGraft(contentBA, docSet, item);
319
+ break;
320
+ case 'scope':
321
+ this.pushSuccinctScope(contentBA, docSet, item);
322
+ updateOpenScopes(item);
323
+
324
+ if (item.subType === 'start') {
325
+ includedScopes.push(item);
326
+ }
327
+ break;
328
+ default:
329
+ throw new Error(`Item type ${item.type} is not handled in succinctifyBlocks`);
330
+ }
331
+ }
332
+
333
+ const blockScopeBA = new ByteArray(10);
334
+ this.pushSuccinctScope(blockScopeBA, docSet, block.bs);
335
+
336
+ for (const is of includedScopes) {
337
+ this.pushSuccinctScope(includedScopesBA, docSet, is);
338
+ }
339
+ contentBA.trim();
340
+ blockGraftsBA.trim();
341
+ blockScopeBA.trim();
342
+ openScopesBA.trim();
343
+ includedScopesBA.trim();
344
+ ret.push({
345
+ c: contentBA,
346
+ bs: blockScopeBA,
347
+ bg: blockGraftsBA,
348
+ os: openScopesBA,
349
+ is: includedScopesBA,
350
+ nt: nextTokenBA,
351
+ });
352
+ }
353
+ return ret;
354
+ }
355
+
356
+ pushSuccinctToken(bA, docSet, item) {
357
+ const charsEnumIndex = docSet.enumForCategoryValue(tokenCategory[item.subType], item.payload);
358
+ pushSuccinctTokenBytes(bA, tokenEnum[item.subType], charsEnumIndex);
359
+ }
360
+
361
+ pushSuccinctGraft(bA, docSet, item) {
362
+ const graftTypeEnumIndex = docSet.enumForCategoryValue('graftTypes', item.subType);
363
+ const seqEnumIndex = docSet.enumForCategoryValue('ids', item.payload);
364
+ pushSuccinctGraftBytes(bA, graftTypeEnumIndex, seqEnumIndex);
365
+ }
366
+
367
+ pushSuccinctScope(bA, docSet, item) {
368
+ const scopeBits = item.payload.split('/');
369
+ const scopeTypeByte = scopeEnum[scopeBits[0]];
370
+ const scopeBitBytes = scopeBits.slice(1).map(b => docSet.enumForCategoryValue('scopeBits', b));
371
+ pushSuccinctScopeBytes(bA, itemEnum[`${item.subType}Scope`], scopeTypeByte, scopeBitBytes);
372
+ }
373
+ };
374
+ const Block = class {
375
+ constructor(blockScope) {
376
+ this.id = utils.generateId();
377
+ this.items = [];
378
+ this.bg = [];
379
+ this.bs = {
380
+ type: 'scope',
381
+ subType: 'start',
382
+ payload: blockScope,
383
+ };
384
+ this.os = [];
385
+ }
386
+
387
+ addItem(i) {
388
+ this.items.push(i);
389
+ }
390
+
391
+ plainText() {
392
+ return this.items.filter(i => i.type === 'token').map(i => i.payload).join('');
393
+ }
394
+
395
+ trim() {
396
+ this.items = this.trimEnd(this.trimStart(this.items));
397
+ }
398
+
399
+ reorderSpanWithAtts() {
400
+ const swaStarts = [];
401
+
402
+ for (const [pos, item] of this.items.entries()) {
403
+ if (item.subType === 'start' && item.payload.startsWith('spanWithAtts')) {
404
+ swaStarts.push(pos + 1);
405
+ }
406
+ }
407
+
408
+ for (const swaStart of swaStarts) {
409
+ let pos = swaStart;
410
+ let tokens = [];
411
+ let scopes = [];
412
+
413
+ // eslint-disable-next-line no-constant-condition
414
+ while (true) {
415
+ if (pos >= this.items.length) {
416
+ break;
417
+ }
418
+
419
+ const item = this.items[pos];
420
+
421
+ if (item.type === 'token') {
422
+ tokens.push(item);
423
+ } else if (item.subType === 'start' && item.payload.startsWith('attribute/spanWithAtts')) {
424
+ scopes.push(item);
425
+ } else {
426
+ break;
427
+ }
428
+ pos++;
429
+ }
430
+
431
+ if (tokens.length !== 0 && scopes.length !== 0) {
432
+ let pos = swaStart;
433
+
434
+ for (const s of scopes) {
435
+ this.items[pos] = s;
436
+ pos++;
437
+ }
438
+
439
+ for (const t of tokens) {
440
+ this.items[pos] = t;
441
+ pos++;
442
+ }
443
+ }
444
+ }
445
+ }
446
+
447
+ inlineToEnd() {
448
+ let toAppend = null;
449
+
450
+ for (const [pos, item] of this.items.entries()) {
451
+ if (item.subType === 'end' && ['inline/f', 'inline/fe', 'inline/x'].includes(item.payload)) {
452
+ toAppend = item;
453
+ this.items.splice(pos, 1);
454
+ break;
455
+ }
456
+ }
457
+
458
+ if (toAppend) {
459
+ this.addItem(toAppend);
460
+ }
461
+ }
462
+
463
+ makeNoteGrafts(parser) {
464
+ const noteStarts = [];
465
+
466
+ for (const [pos, item] of this.items.entries()) {
467
+ if (item.subType === 'start' && (item.payload.startsWith('inline/f') || item.payload.startsWith('inline/x'))) {
468
+ noteStarts.push(pos);
469
+ }
470
+ }
471
+
472
+ for (const noteStart of noteStarts) {
473
+ const noteLabel = this.items[noteStart].payload;
474
+ const callerToken = this.items[noteStart + 1];
475
+
476
+ if (callerToken.type === 'token' && callerToken.payload.length === 1) {
477
+ const callerSequence = new Sequence('noteCaller');
478
+ callerSequence.newBlock(noteLabel);
479
+ callerSequence.addItem(callerToken);
480
+ parser.sequences.noteCaller.push(callerSequence);
481
+ this.items[noteStart + 1] = {
482
+ type: 'graft',
483
+ subType: 'noteCaller',
484
+ payload: callerSequence.id,
485
+ };
486
+ }
487
+ }
488
+ }
489
+
490
+ trimStart(items) {
491
+ if (items.length === 0) {
492
+ return items;
493
+ }
494
+
495
+ const firstItem = items[0];
496
+
497
+ if (['lineSpace', 'eol'].includes(firstItem.subType)) {
498
+ return this.trimStart(items.slice(1));
499
+ }
500
+
501
+ if (firstItem.type === 'token') {
502
+ return items;
503
+ }
504
+ return [firstItem, ...this.trimStart(items.slice(1))];
505
+ }
506
+
507
+ trimEnd(items) {
508
+ if (items.length === 0) {
509
+ return items;
510
+ }
511
+
512
+ const lastItem = items[items.length - 1];
513
+
514
+ if (['lineSpace', 'eol'].includes(lastItem.subType)) {
515
+ return this.trimEnd(items.slice(0, items.length - 1));
516
+ }
517
+
518
+ if (lastItem.type === 'token') {
519
+ return items;
520
+ }
521
+ return [...this.trimEnd(items.slice(0, items.length - 1)), lastItem];
522
+ }
523
+
524
+ filterGrafts(options) {
525
+ // Each graft should be removed or returned
526
+ const ret = [];
527
+ let toRemove = [];
528
+
529
+ for (const [pos, item] of this.grafts()) {
530
+ if (this.graftPassesOptions(item, options)) {
531
+ ret.push(item.payload);
532
+ } else {
533
+ toRemove.push(pos);
534
+ }
535
+ }
536
+
537
+ for (const [count, pos] of Array.from(toRemove.entries())) {
538
+ this.items.splice(pos - count, 1);
539
+ }
540
+ toRemove = [];
541
+
542
+ for (const [pos, item] of this.bg.entries()) {
543
+ if (this.graftPassesOptions(item, options)) {
544
+ ret.push(item.payload);
545
+ } else {
546
+ toRemove.push(pos);
547
+ }
548
+ }
549
+
550
+ for (const [count, pos] of Array.from(toRemove.entries())) {
551
+ this.bg.splice(pos - count, 1);
552
+ }
553
+ return ret;
554
+ }
555
+
556
+ filterScopes(options) {
557
+ const toRemove = [];
558
+
559
+ for (const [pos, item] of this.scopes()) {
560
+ if (!this.scopePassesOptions(item, options)) {
561
+ toRemove.push(pos);
562
+ }
563
+ }
564
+
565
+ for (const [count, pos] of Array.from(toRemove.entries())) {
566
+ this.items.splice(pos - count, 1);
567
+ }
568
+ }
569
+
570
+ graftPassesOptions(item, options) {
571
+ return (
572
+ (!('includeGrafts' in options) || options.includeGrafts.includes(item.subType)) &&
573
+ (!('excludeGrafts' in options) || !options.excludeGrafts.includes(item.subType))
574
+ );
575
+ }
576
+
577
+ scopePassesOptions(item, options) {
578
+ return (
579
+ (!('includeScopes' in options) || this.scopeMatchesOptionArray(item.payload, options.includeScopes)) &&
580
+ (!('excludeScopes' in options) || !this.scopeMatchesOptionArray(item.payload, options.excludeScopes))
581
+ );
582
+ }
583
+
584
+ scopeMatchesOptionArray(itemString, optionArray) {
585
+ for (const optionString of optionArray) {
586
+ if (itemString.startsWith(optionString)) {
587
+ return true;
588
+ }
589
+ }
590
+ return false;
591
+ }
592
+
593
+ removeGraftsToEmptySequences(emptySequences) {
594
+ const ret = [];
595
+ let toRemove = [];
596
+
597
+ for (const [pos, item] of this.grafts()) {
598
+ if (emptySequences.includes(item.payload)) {
599
+ toRemove.push(pos);
600
+ }
601
+ }
602
+
603
+ for (const [count, pos] of Array.from(toRemove.entries())) {
604
+ this.items.splice(pos - count, 1);
605
+ }
606
+ toRemove = [];
607
+
608
+ for (const [pos, item] of this.bg.entries()) {
609
+ if (emptySequences.includes(item.payload)) {
610
+ toRemove.push(pos);
611
+ }
612
+ }
613
+
614
+ for (const [count, pos] of Array.from(toRemove.entries())) {
615
+ this.bg.splice(pos - count, 1);
616
+ }
617
+ return ret;
618
+ }
619
+
620
+ grafts() {
621
+ return Array.from(this.items.entries()).filter(ip => ip[1].type === 'graft');
622
+ }
623
+
624
+ scopes() {
625
+ return Array.from(this.items.entries()).filter(ip => ip[1].type === 'scope');
626
+ }
627
+
628
+ tokens() {
629
+ return Array.from(this.items.entries()).filter(ip => !['scope', 'graft'].includes(ip[1].type));
630
+ }
631
+
632
+ text() {
633
+ return this.tokens().map(t => t[1].payload).join('');
634
+ }
635
+ };
636
+
637
+ module.exports = { Sequence, Block };