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,781 @@
1
+ const utils = require('../util/index.cjs');
2
+ const { labelForScope } = utils.scopeDefs;
3
+ const { constructorForFragment } = require('./lexers/object_for_fragment.cjs');
4
+
5
+ const buildSpecLookup = specs => {
6
+ const ret = {};
7
+
8
+ for (const spec of specs) {
9
+ for (const context of spec.contexts) {
10
+ if (!(context[0] in ret)) {
11
+ ret[context[0]] = {};
12
+ }
13
+
14
+ const accessor = context[1];
15
+
16
+ if (!accessor) {
17
+ ret[context[0]]._noAccessor = spec.parser;
18
+ } else {
19
+ if (!(accessor in ret[context[0]])) {
20
+ ret[context[0]][accessor] = {};
21
+ }
22
+
23
+ for (const accessorValue of context[2]) {
24
+ ret[context[0]][accessor][accessorValue] = spec.parser;
25
+ }
26
+ }
27
+ }
28
+ }
29
+ return ret;
30
+ };
31
+
32
+ const specs = (pt) => [
33
+ {
34
+ // HEADERS - make temp sequence, then add to headers object
35
+ contexts: [
36
+ [
37
+ 'startTag',
38
+ 'tagName',
39
+ [
40
+ 'id',
41
+ 'usfm',
42
+ 'ide',
43
+ 'sts',
44
+ 'h',
45
+ 'toc',
46
+ 'toca',
47
+ 'cl',
48
+ ],
49
+ ],
50
+ ],
51
+ parser: {
52
+ baseSequenceType: 'header',
53
+ forceNewSequence: true,
54
+ newBlock: true,
55
+ useTempSequence: true,
56
+ newScopes: [
57
+ {
58
+ label: pt => pt.fullTagName,
59
+ endedBy: ['baseSequenceChange'],
60
+ onEnd: (parser, label) => {
61
+ parser.headers[label] = parser.current.sequence.plainText();
62
+
63
+ if (label === 'id') {
64
+ if (
65
+ parser.headers[label].length === 3 ||
66
+ (
67
+ parser.headers[label].length > 3 &&
68
+ parser.headers[label].substring(3, 4) === ' '
69
+ )
70
+ ) {
71
+ const bookCode = parser.headers[label].substring(0, 3);
72
+ parser.headers['bookCode'] = bookCode;
73
+ }
74
+ }
75
+ },
76
+ },
77
+ ],
78
+ },
79
+ },
80
+ {
81
+ // HEADINGS - Start new sequence
82
+ contexts: [
83
+ [
84
+ 'startTag',
85
+ 'tagName',
86
+ [
87
+ 'ms',
88
+ 'mr',
89
+ 's',
90
+ 'sr',
91
+ 'r',
92
+ 'qa',
93
+ 'sp',
94
+ 'sd',
95
+ ].concat(pt.customTags.heading),
96
+ ],
97
+ ],
98
+ parser: {
99
+ baseSequenceType: 'heading',
100
+ forceNewSequence: true,
101
+ newBlock: true,
102
+ newScopes: [],
103
+ },
104
+ },
105
+ {
106
+ // TITLE - make a sequence or add to existing one
107
+ contexts: [
108
+ [
109
+ 'startTag',
110
+ 'tagName',
111
+ [
112
+ 'mt',
113
+ ],
114
+ ],
115
+ ],
116
+ parser: {
117
+ baseSequenceType: 'title',
118
+ newBlock: true,
119
+ newScopes: [],
120
+ },
121
+ },
122
+ {
123
+ // END TITLE - make a sequence or add to existing one
124
+ contexts: [
125
+ [
126
+ 'startTag',
127
+ 'tagName',
128
+ [
129
+ 'mte',
130
+ ],
131
+ ],
132
+ ],
133
+ parser: {
134
+ baseSequenceType: 'endTitle',
135
+ newBlock: true,
136
+ newScopes: [],
137
+ },
138
+ },
139
+ {
140
+ // INTRODUCTION - make a sequence or add to existing one
141
+ contexts: [
142
+ [
143
+ 'startTag',
144
+ 'tagName',
145
+ [
146
+ 'imt',
147
+ 'is',
148
+ 'ip',
149
+ 'ipi',
150
+ 'im',
151
+ 'imi',
152
+ 'ipq',
153
+ 'imq',
154
+ 'ipr',
155
+ 'iq',
156
+ 'ib',
157
+ 'ili',
158
+ 'iot',
159
+ 'io',
160
+ 'iex',
161
+ 'imte',
162
+ ].concat(pt.customTags.intro),
163
+ ],
164
+ ],
165
+ parser: {
166
+ baseSequenceType: 'introduction',
167
+ newBlock: true,
168
+ newScopes: [],
169
+ },
170
+ },
171
+ {
172
+ // START SIDEBAR - make a new sequence
173
+ contexts: [
174
+ [
175
+ 'startTag',
176
+ 'tagName',
177
+ [
178
+ 'esb',
179
+ ],
180
+ ],
181
+ ],
182
+ parser: {
183
+ baseSequenceType: 'sidebar',
184
+ newBlock: true,
185
+ newScopes: [],
186
+ after: (parser) => {
187
+ parser.mainLike = parser.current.sequence;
188
+ },
189
+ },
190
+ },
191
+ {
192
+ // END SIDEBAR - return to main
193
+ contexts: [
194
+ [
195
+ 'startTag',
196
+ 'tagName',
197
+ [
198
+ 'esbe',
199
+ ],
200
+ ],
201
+ ],
202
+ parser: {
203
+ baseSequenceType: 'main',
204
+ newBlock: true,
205
+ newScopes: [],
206
+ after: (parser) => {
207
+ parser.mainLike = parser.sequences.main;
208
+ },
209
+ },
210
+ },
211
+ {
212
+ // CAT - graft label and add stub scope, then remove graft and modify scope at tidy stage
213
+ contexts: [
214
+ [
215
+ 'startTag',
216
+ 'tagName',
217
+ ['cat'],
218
+ ],
219
+ ],
220
+ parser: {
221
+ inlineSequenceType: 'esbCat',
222
+ forceNewSequence: true,
223
+ newScopes: [
224
+ {
225
+ label: pt => labelForScope('inline', [pt.fullTagName]),
226
+ endedBy: ['endTag/cat', 'endBlock', 'implicitEnd'],
227
+ onEnd: (parser) => parser.returnToBaseSequence(),
228
+ },
229
+ ],
230
+ during: (parser, pt) => {
231
+ const scopeId = utils.generateId();
232
+ const esbScope = {
233
+ label: () => labelForScope('esbCat', [scopeId]),
234
+ endedBy: ['startTag/esbe'],
235
+ };
236
+ parser.openNewScope(pt, esbScope, true, parser.mainLike);
237
+ },
238
+ },
239
+ },
240
+ {
241
+ // REMARK - make new sequence
242
+ contexts: [
243
+ [
244
+ 'startTag',
245
+ 'tagName',
246
+ [
247
+ 'rem',
248
+ ],
249
+ ],
250
+ ],
251
+ parser: {
252
+ baseSequenceType: 'remark',
253
+ forceNewSequence: true,
254
+ newScopes: [],
255
+ },
256
+ },
257
+ {
258
+ // PARAGRAPH STYLES - Make new block on main
259
+ contexts: [
260
+ [
261
+ 'startTag',
262
+ 'tagName',
263
+ [
264
+ 'cd',
265
+ 'p',
266
+ 'm',
267
+ 'po',
268
+ 'pr',
269
+ 'cls',
270
+ 'pmo',
271
+ 'pm',
272
+ 'pmc',
273
+ 'pmr',
274
+ 'pi',
275
+ 'mi',
276
+ 'nb',
277
+ 'pc',
278
+ 'ph',
279
+ 'b',
280
+ 'q',
281
+ 'qr',
282
+ 'qc',
283
+ 'qa',
284
+ 'qm',
285
+ 'qd',
286
+ 'lh',
287
+ 'li',
288
+ 'lf',
289
+ 'lim',
290
+ 'd',
291
+ ].concat(pt.customTags.paragraph),
292
+ ],
293
+ ],
294
+ parser: {
295
+ baseSequenceType: 'mainLike',
296
+ newBlock: true,
297
+ newScopes: [],
298
+ },
299
+ },
300
+ {
301
+ // ROW - Make new block
302
+ contexts: [
303
+ [
304
+ 'startTag',
305
+ 'tagName',
306
+ ['tr'],
307
+ ],
308
+ ],
309
+ parser: {
310
+ newBlock: true,
311
+ newScopes: [],
312
+ },
313
+ },
314
+ {
315
+ // FOOTNOTE/ENDNOTE - new inline sequence
316
+ contexts: [
317
+ [
318
+ 'startTag',
319
+ 'tagName',
320
+ [
321
+ 'f',
322
+ 'fe',
323
+ ],
324
+ ],
325
+ ],
326
+ parser: {
327
+ inlineSequenceType: 'footnote',
328
+ forceNewSequence: true,
329
+ newScopes: [
330
+ {
331
+ label: pt => labelForScope('inline', [pt.fullTagName]),
332
+ endedBy: ['endTag/f', 'endTag/fe', 'endBlock'],
333
+ onEnd: (parser) => parser.returnToBaseSequence(),
334
+ },
335
+ ],
336
+ },
337
+ },
338
+ {
339
+ // CROSS REFERENCE - make new inline sequence
340
+ contexts: [
341
+ [
342
+ 'startTag',
343
+ 'tagName',
344
+ [
345
+ 'x',
346
+ ],
347
+ ],
348
+ ],
349
+ parser: {
350
+ inlineSequenceType: 'xref',
351
+ forceNewSequence: true,
352
+ newScopes: [
353
+ {
354
+ label: pt => labelForScope('inline', [pt.fullTagName]),
355
+ endedBy: ['endTag/x', 'endBlock'],
356
+ onEnd: (parser) => parser.returnToBaseSequence(),
357
+ },
358
+ ],
359
+ },
360
+ },
361
+ {
362
+ // FIGURE - new inline sequence
363
+ contexts: [
364
+ [
365
+ 'startTag',
366
+ 'tagName',
367
+ [
368
+ 'fig',
369
+ ],
370
+ ],
371
+ ],
372
+ parser: {
373
+ inlineSequenceType: 'fig',
374
+ forceNewSequence: true,
375
+ newScopes: [
376
+ {
377
+ label: pt => labelForScope('spanWithAtts', [pt.tagName]),
378
+ endedBy: ['endBlock', 'endTag/$tagName$'],
379
+ onEnd: (parser) => parser.clearAttributeContext(),
380
+ },
381
+ ],
382
+ during: (parser, pt) => {
383
+ parser.setAttributeContext(labelForScope('spanWithAtts', [pt.tagName]));
384
+ },
385
+ },
386
+ },
387
+ {
388
+ // CHAPTER - chapter scope
389
+ contexts: [['chapter']],
390
+ parser: {
391
+ mainSequence: true,
392
+ newScopes: [
393
+ {
394
+ label: pt => labelForScope('chapter', [pt.number]),
395
+ endedBy: ['chapter'],
396
+ },
397
+ ],
398
+ },
399
+ },
400
+ {
401
+ // CP - graft label and add stub scope, then remove graft and modify scope at tidy stage
402
+ contexts: [['pubchapter']],
403
+ parser: {
404
+ mainSequence: true,
405
+ newScopes: [
406
+ {
407
+ label: pt => labelForScope('pubChapter', [pt.numberString]),
408
+ endedBy: ['pubchapter', 'chapter'],
409
+ },
410
+ ],
411
+ },
412
+ },
413
+ {
414
+ // CA - graft label and add stub scope, then remove graft and modify scope at tidy stage
415
+ contexts: [
416
+ [
417
+ 'startTag',
418
+ 'tagName',
419
+ ['ca'],
420
+ ],
421
+ ],
422
+ parser: {
423
+ inlineSequenceType: 'altNumber',
424
+ forceNewSequence: true,
425
+ newScopes: [
426
+ {
427
+ label: pt => labelForScope('inline', [pt.fullTagName]),
428
+ endedBy: ['endTag/ca', 'endBlock', 'implicitEnd'],
429
+ onEnd: (parser) => parser.returnToBaseSequence(),
430
+ },
431
+ ],
432
+ during: (parser, pt) => {
433
+ const scopeId = utils.generateId();
434
+ const caScope = {
435
+ label: () => labelForScope('altChapter', [scopeId]),
436
+ endedBy: ['startTag/ca', 'chapter'],
437
+ };
438
+ parser.openNewScope(pt, caScope, true, parser.sequences.main);
439
+ },
440
+ },
441
+ },
442
+ {
443
+ // VERSES - verse and verses scopes
444
+ contexts: [
445
+ ['verses'],
446
+ ],
447
+ parser: {
448
+ mainSequence: true,
449
+ newScopes: [
450
+ {
451
+ label: pt => labelForScope('verses', [pt.numberString]),
452
+ endedBy: ['verses', 'chapter', 'pubchapter'],
453
+ },
454
+ ],
455
+ during: (parser, pt) => {
456
+ pt.numbers.forEach(n => {
457
+ const verseScope = {
458
+ label: () => labelForScope('verse', [n]),
459
+ endedBy: ['verses', 'chapter', 'pubchapter'],
460
+ };
461
+ parser.openNewScope(pt, verseScope, true, parser.sequences.main);
462
+ },
463
+ );
464
+ },
465
+ },
466
+ },
467
+ {
468
+ // VP - graft label and add stub scope, then remove graft and modify scope at tidy stage
469
+ contexts: [
470
+ [
471
+ 'startTag',
472
+ 'tagName',
473
+ ['vp'],
474
+ ],
475
+ ],
476
+ parser: {
477
+ inlineSequenceType: 'pubNumber',
478
+ forceNewSequence: true,
479
+ newScopes: [
480
+ {
481
+ label: pt => labelForScope('inline', [pt.fullTagName]),
482
+ endedBy: ['endTag/vp', 'endBlock', 'implicitEnd'],
483
+ onEnd: (parser) => parser.returnToBaseSequence(),
484
+ },
485
+ ],
486
+ during: (parser, pt) => {
487
+ const scopeId = utils.generateId();
488
+ const vpScope = {
489
+ label: () => labelForScope('pubVerse', [scopeId]),
490
+ endedBy: ['startTag/vp', 'verses', 'chapter', 'pubchapter'],
491
+ };
492
+ parser.openNewScope(pt, vpScope, true, parser.sequences.main);
493
+ },
494
+ },
495
+ },
496
+ {
497
+ // VA - graft label and add stub scope, then remove graft and modify scope at tidy stage
498
+ contexts: [
499
+ [
500
+ 'startTag',
501
+ 'tagName',
502
+ ['va'],
503
+ ],
504
+ ],
505
+ parser: {
506
+ inlineSequenceType: 'altNumber',
507
+ forceNewSequence: true,
508
+ newScopes: [
509
+ {
510
+ label: pt => labelForScope('inline', [pt.fullTagName]),
511
+ endedBy: ['endTag/va', 'endBlock', 'implicitEnd'],
512
+ onEnd: (parser) => parser.returnToBaseSequence(),
513
+ },
514
+ ],
515
+ during: (parser, pt) => {
516
+ const scopeId = utils.generateId();
517
+ const vpScope = {
518
+ label: () => labelForScope('altVerse', [scopeId]),
519
+ endedBy: ['startTag/va', 'verses', 'chapter', 'pubchapter'],
520
+ };
521
+ parser.openNewScope(pt, vpScope, true, parser.sequences.main);
522
+ },
523
+ },
524
+ },
525
+ {
526
+ // CHARACTER MARKUP - add scope
527
+ contexts: [
528
+ [
529
+ 'startTag',
530
+ 'tagName',
531
+ [
532
+ 'qs',
533
+ 'qac',
534
+ 'litl',
535
+ 'lik',
536
+ 'liv',
537
+ 'fr',
538
+ 'fq',
539
+ 'fqa',
540
+ 'fk',
541
+ 'fl',
542
+ 'fw',
543
+ 'fp',
544
+ 'fv',
545
+ 'ft',
546
+ 'fdc',
547
+ 'fm',
548
+ 'xo',
549
+ 'xk',
550
+ 'xq',
551
+ 'xt',
552
+ 'xta',
553
+ 'xop',
554
+ 'xot',
555
+ 'xnt',
556
+ 'xdc',
557
+ 'rq',
558
+ 'add',
559
+ 'bk',
560
+ 'dc',
561
+ 'k',
562
+ 'nd',
563
+ 'ord',
564
+ 'pn',
565
+ 'png',
566
+ 'qt',
567
+ 'sig',
568
+ 'sls',
569
+ 'tl',
570
+ 'wj',
571
+ 'em',
572
+ 'bd',
573
+ 'it',
574
+ 'bdit',
575
+ 'no',
576
+ 'sc',
577
+ 'sup',
578
+ 'ior',
579
+ 'iqt',
580
+ ].concat(pt.customTags.char),
581
+ ],
582
+ ],
583
+ parser: {
584
+ newScopes: [
585
+ {
586
+ label: pt => labelForScope('span', [pt.fullTagName]),
587
+ endedBy: ['endBlock', 'endTag/$fullTagName$', 'implicitEnd'],
588
+ },
589
+ ],
590
+ },
591
+ },
592
+ {
593
+ // CELL - unpick tagName, add scope
594
+ contexts: [
595
+ [
596
+ 'startTag',
597
+ 'tagName',
598
+ [
599
+ 'th',
600
+ 'thr',
601
+ 'tc',
602
+ 'tcr',
603
+ ],
604
+ ],
605
+ ],
606
+ parser: {
607
+ newScopes: [
608
+ {
609
+ label: pt => labelForScope('cell', [pt.fullTagName]),
610
+ endedBy: [
611
+ 'startTag/th',
612
+ 'startTag/thr',
613
+ 'startTag/tc',
614
+ 'startTag/tcr',
615
+ 'startTag/th2',
616
+ 'startTag/thr2',
617
+ 'startTag/tc2',
618
+ 'startTag/tcr2',
619
+ 'startTag/th3',
620
+ 'startTag/thr3',
621
+ 'startTag/tc3',
622
+ 'startTag/tcr3',
623
+ 'endBlock',
624
+ 'endTag/$fullTagName$',
625
+ ],
626
+ },
627
+ ],
628
+ },
629
+ },
630
+ {
631
+ // EMPTY MILESTONE - add open and close scope
632
+ contexts: [
633
+ ['emptyMilestone'],
634
+ ],
635
+ parser: { during: (parser, pt) => parser.addEmptyMilestone(labelForScope('milestone', [pt.tagName])) },
636
+ },
637
+ {
638
+ // START MILESTONE - open scope, set attribute context
639
+ contexts: [
640
+ ['startMilestoneTag', 'sOrE', 's'],
641
+ ],
642
+ parser: {
643
+ newScopes: [
644
+ {
645
+ label: pt => labelForScope('milestone', [pt.tagName]),
646
+ endedBy: ['endMilestone/$tagName$'],
647
+ },
648
+ ],
649
+ during: (parser, pt) => {
650
+ parser.setAttributeContext(labelForScope('milestone', [pt.tagName]));
651
+ },
652
+ },
653
+ },
654
+ {
655
+ // END MILESTONE - close scope, clear attribute context
656
+ contexts: [
657
+ ['endMilestoneMarker'],
658
+ ],
659
+ parser: { during: (parser) => parser.clearAttributeContext() },
660
+ },
661
+ {
662
+ // ATTRIBUTE - open scope based on attribute context
663
+ contexts: [
664
+ ['attribute'],
665
+ ['defaultAttribute'],
666
+ ],
667
+ parser: {
668
+ during: (parser, pt) => {
669
+ const defaults = {
670
+ w: 'lemma',
671
+ rb: 'gloss',
672
+ xt: 'link-href',
673
+ };
674
+
675
+ if (parser.current.attributeContext) {
676
+ const contextParts = parser.current.attributeContext.split('/');
677
+
678
+ if ((pt.key === 'default') && (contextParts.length === 2)) {
679
+ pt.key = defaults[contextParts[1]] || `unknownDefault_${contextParts[1]}`;
680
+ pt.printValue = pt.printValue.replace(/default/, pt.key);
681
+ }
682
+ [...pt.values.entries()].forEach(na => {
683
+ const attScope = {
684
+ label: pt => labelForScope('attribute', [parser.current.attributeContext, pt.key, na[0], na[1]]),
685
+ endedBy: [`$attributeContext$`],
686
+ };
687
+ parser.openNewScope(pt, attScope);
688
+ },
689
+ );
690
+ } else {
691
+ parser.addToken(constructorForFragment.printable('unknown', [pt.printValue]));
692
+ }
693
+ },
694
+ },
695
+ },
696
+ {
697
+ // WORD-LEVEL MARKUP - open scope and set attribute context
698
+ contexts: [
699
+ [
700
+ 'startTag',
701
+ 'tagName',
702
+ [
703
+ 'w',
704
+ 'rb',
705
+ // 'xt',
706
+ ].concat(pt.customTags.word),
707
+ ],
708
+ ],
709
+ parser: {
710
+ newScopes: [
711
+ {
712
+ label: pt => labelForScope('spanWithAtts', [pt.tagName]),
713
+ endedBy: ['endBlock', 'endTag/$tagName$'],
714
+ onEnd: (parser) => parser.clearAttributeContext(),
715
+ },
716
+ ],
717
+ during: (parser, pt) => {
718
+ parser.setAttributeContext(labelForScope('spanWithAtts', [pt.tagName]));
719
+ },
720
+ },
721
+ },
722
+ {
723
+ // TOKEN - add a token!
724
+ contexts: [
725
+ ['wordLike'],
726
+ ['lineSpace'],
727
+ ['punctuation'],
728
+ ['eol'],
729
+ ],
730
+ parser: { during: (parser, pt) => parser.addToken(pt) },
731
+ },
732
+ {
733
+ // NO BREAK SPACE - make a token!
734
+ contexts: [
735
+ ['noBreakSpace'],
736
+ ],
737
+ parser: {
738
+ during: (parser) => {
739
+ parser.addToken(constructorForFragment.printable('lineSpace', ['\xa0']));
740
+ },
741
+ },
742
+ },
743
+ {
744
+ // SOFT LINE BREAK - make a token!
745
+ contexts: [
746
+ ['softLineBreak'],
747
+ ],
748
+ parser: {
749
+ during: (parser) => {
750
+ parser.addToken(constructorForFragment.printable('softLineBreak', ['//']));
751
+ },
752
+ },
753
+ },
754
+ {
755
+ // BARESLASH - make a token!
756
+ contexts: [
757
+ ['bareSlash'],
758
+ ],
759
+ parser: {
760
+ during: (parser) => {
761
+ parser.addToken(constructorForFragment.printable('bareSlash', ['\\']));
762
+ },
763
+ },
764
+ },
765
+ {
766
+ // UNKNOWN - make a token!
767
+ contexts: [
768
+ ['unknown'],
769
+ ],
770
+ parser: {
771
+ during: (parser, pt) => {
772
+ parser.addToken(constructorForFragment.printable('unknown', [pt.printValue]));
773
+ },
774
+ },
775
+ },
776
+ ];
777
+
778
+ module.exports = {
779
+ specs,
780
+ buildSpecLookup,
781
+ };