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.
- package/.eslintrc.json +79 -0
- package/.gitattributes +2 -0
- package/docs/_config.yml +1 -0
- package/docs/index.md +3 -0
- package/docs/pk_edit_0_9.odt +0 -0
- package/docs/pk_edit_0_9.pdf +0 -0
- package/docs/proskomma_101_slideshow.odp +0 -0
- package/docs/proskomma_101_slideshow.pdf +0 -0
- package/docs/proskomma_edit_html.png +0 -0
- package/docs/proskomma_edit_html.svg +451 -0
- package/docs/proskomma_edit_reference.png +0 -0
- package/docs/proskomma_edit_reference.svg +349 -0
- package/docs/repo_logo.png +0 -0
- package/esm/package.json +3 -0
- package/esm/wrapper.mjs +5 -0
- package/index.cjs +6 -0
- package/package.json +18 -15
- package/src/graph/index.cjs +201 -0
- package/src/graph/lib/do_cv.cjs +249 -0
- package/src/graph/lib/dump.cjs +40 -0
- package/src/graph/lib/remake_blocks.cjs +57 -0
- package/src/graph/lib/sequence_chars.cjs +84 -0
- package/src/graph/lib/sort.cjs +39 -0
- package/src/graph/lib/tribos.cjs +97 -0
- package/src/graph/lib/tribos_expression.cjs +556 -0
- package/src/graph/lib/tribos_ohm_UNUSED.cjs +37 -0
- package/src/graph/lib/tribos_step.cjs +434 -0
- package/src/graph/mutations/add.cjs +91 -0
- package/src/graph/mutations/delete.cjs +61 -0
- package/src/graph/mutations/index.cjs +54 -0
- package/src/graph/mutations/rehash.cjs +17 -0
- package/src/graph/mutations/tags.cjs +120 -0
- package/src/graph/mutations/update.cjs +210 -0
- package/src/graph/mutations/versification.cjs +96 -0
- package/src/graph/queries/block.cjs +228 -0
- package/src/graph/queries/cIndex.cjs +87 -0
- package/src/graph/queries/cell.cjs +42 -0
- package/src/graph/queries/cv.cjs +19 -0
- package/src/graph/queries/cvBook.cjs +16 -0
- package/src/graph/queries/cvChapter.cjs +16 -0
- package/src/graph/queries/cvIndex.cjs +47 -0
- package/src/graph/queries/cvNavigation.cjs +116 -0
- package/src/graph/queries/cvVerseElement.cjs +84 -0
- package/src/graph/queries/cvVerses.cjs +14 -0
- package/src/graph/queries/doc_set.cjs +220 -0
- package/src/graph/queries/document.cjs +555 -0
- package/src/graph/queries/idParts.cjs +30 -0
- package/src/graph/queries/index.cjs +151 -0
- package/src/graph/queries/inputBlockSpec.cjs +17 -0
- package/src/graph/queries/inputItemObject.cjs +12 -0
- package/src/graph/queries/input_att_spec.cjs +14 -0
- package/src/graph/queries/input_key_matches.cjs +11 -0
- package/src/graph/queries/input_key_value.cjs +11 -0
- package/src/graph/queries/input_key_values.cjs +11 -0
- package/src/graph/queries/input_selector_spec.cjs +19 -0
- package/src/graph/queries/item.cjs +71 -0
- package/src/graph/queries/itemGroup.cjs +75 -0
- package/src/graph/queries/key_value.cjs +18 -0
- package/src/graph/queries/kv_entry.cjs +21 -0
- package/src/graph/queries/kv_sequence.cjs +151 -0
- package/src/graph/queries/node.cjs +44 -0
- package/src/graph/queries/orig.cjs +11 -0
- package/src/graph/queries/regex_index.cjs +18 -0
- package/src/graph/queries/row_equals_spec.cjs +11 -0
- package/src/graph/queries/row_match_spec.cjs +11 -0
- package/src/graph/queries/selector_spec.cjs +29 -0
- package/src/graph/queries/sequence.cjs +314 -0
- package/src/graph/queries/table_sequence.cjs +192 -0
- package/src/graph/queries/tree_sequence.cjs +58 -0
- package/src/graph/queries/verseNumber.cjs +44 -0
- package/src/graph/queries/verseRange.cjs +11 -0
- package/src/graph/queries/versification.cjs +25 -0
- package/src/index.cjs +583 -0
- package/src/model/doc_set.cjs +389 -0
- package/src/model/doc_set_helpers/block.cjs +232 -0
- package/src/model/doc_set_helpers/enum.cjs +87 -0
- package/src/model/doc_set_helpers/item.cjs +198 -0
- package/src/model/doc_set_helpers/rehash.cjs +53 -0
- package/src/model/doc_set_helpers/selectors.cjs +58 -0
- package/src/model/doc_set_helpers/serialize.cjs +22 -0
- package/src/model/doc_set_helpers/unsuccinctify.cjs +288 -0
- package/src/model/doc_set_helpers/update.cjs +290 -0
- package/src/model/document.cjs +369 -0
- package/src/model/document_helpers/blocks.cjs +135 -0
- package/src/model/document_helpers/chapter_verse.cjs +291 -0
- package/src/model/document_helpers/pre_enums.cjs +67 -0
- package/src/model/document_helpers/sequences.cjs +205 -0
- package/src/model/document_helpers/serialize_succinct.cjs +55 -0
- package/src/model/document_helpers/succinct_filter.cjs +102 -0
- package/src/model/versifications/eng_vrs.cjs +455 -0
- package/src/model/versifications/index.cjs +38 -0
- package/src/model/versifications/lxx_vrs.cjs +950 -0
- package/src/model/versifications/org_vrs.cjs +155 -0
- package/src/model/versifications/rsc_vrs.cjs +342 -0
- package/src/model/versifications/rso_vrs.cjs +541 -0
- package/src/model/versifications/vul_vrs.cjs +835 -0
- package/src/parser/index.cjs +506 -0
- package/src/parser/lexers/index.cjs +11 -0
- package/src/parser/lexers/lexingRegexes.cjs +45 -0
- package/src/parser/lexers/nodes.cjs +123 -0
- package/src/parser/lexers/object_for_fragment.cjs +123 -0
- package/src/parser/lexers/tsv.cjs +45 -0
- package/src/parser/lexers/usfm.cjs +17 -0
- package/src/parser/lexers/usx/index.cjs +7 -0
- package/src/parser/lexers/usx/usx_lexer.cjs +321 -0
- package/src/parser/lib/tokenize.cjs +37 -0
- package/src/parser/model/index.cjs +637 -0
- package/src/parser/parser_specs.cjs +781 -0
- package/src/pipelines/perf2x/index.cjs +7 -0
- package/src/pipelines/perf2x/perf2PkJsonPipeline.json +41 -0
- package/src/pipelines/perf2x/perf2usfmPipeline.json +65 -0
- package/src/transforms/calculateUsfmChapterPositions.cjs +106 -0
- package/src/transforms/index.cjs +9 -0
- package/src/transforms/perf2PkJson.cjs +534 -0
- package/src/transforms/perf2usfm.cjs +294 -0
- package/src/util/byteArray.cjs +251 -0
- package/src/util/canons.cjs +117 -0
- package/src/util/enums.cjs +41 -0
- package/src/util/generateId.cjs +6 -0
- package/src/util/graftDefs.cjs +15 -0
- package/src/util/index.cjs +29 -0
- package/src/util/inspectSuccinct.cjs +59 -0
- package/src/util/itemDefs.cjs +33 -0
- package/src/util/parserConstantDefs.cjs +30 -0
- package/src/util/scopeDefs.cjs +173 -0
- package/src/util/scriptlike/blocksSpec.cjs +192 -0
- package/src/util/scriptlike/dodson_lexicon.xsl +19 -0
- package/src/util/scriptlike/dodson_lexicon_to_entries.cjs +85 -0
- package/src/util/scriptlike/open_scriptures_hebrew_lexicon.xsl +28 -0
- package/src/util/scriptlike/open_scriptures_hebrew_lexicon_to_entries.cjs +85 -0
- package/src/util/succinct.cjs +159 -0
- package/src/util/tags.cjs +28 -0
- package/src/util/tokenDefs.cjs +27 -0
- package/src/util/versification.cjs +364 -0
- package/dist/index.js +0 -8
- package/dist/index.js.LICENSE.txt +0 -23
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
const utils = require('../util/index.cjs');
|
|
2
|
+
const { Sequence } = require('./model/index.cjs');
|
|
3
|
+
const {
|
|
4
|
+
specs,
|
|
5
|
+
buildSpecLookup,
|
|
6
|
+
} = require('./parser_specs.cjs');
|
|
7
|
+
|
|
8
|
+
const { labelForScope } = utils.scopeDefs;
|
|
9
|
+
const parserConstantDef = utils.parserConstants;
|
|
10
|
+
|
|
11
|
+
const Parser = class {
|
|
12
|
+
constructor(filterOptions, customTags, emptyBlocks) {
|
|
13
|
+
this.filterOptions = filterOptions;
|
|
14
|
+
this.customTags = customTags;
|
|
15
|
+
this.emptyBlocks = emptyBlocks;
|
|
16
|
+
this.specs = specs(this);
|
|
17
|
+
this.specLookup = buildSpecLookup(this.specs);
|
|
18
|
+
this.headers = {};
|
|
19
|
+
this.baseSequenceTypes = parserConstantDef.usfm.baseSequenceTypes;
|
|
20
|
+
this.inlineSequenceTypes = parserConstantDef.usfm.inlineSequenceTypes;
|
|
21
|
+
this.setSequences();
|
|
22
|
+
this.setCurrent();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
setSequences() {
|
|
26
|
+
this.sequences = {};
|
|
27
|
+
|
|
28
|
+
for (const [sType, sArity] of Object.entries({ ...this.baseSequenceTypes, ...this.inlineSequenceTypes })) {
|
|
29
|
+
switch (sArity) {
|
|
30
|
+
case '1':
|
|
31
|
+
this.sequences[sType] = new Sequence(sType);
|
|
32
|
+
break;
|
|
33
|
+
case '?':
|
|
34
|
+
this.sequences[sType] = null;
|
|
35
|
+
break;
|
|
36
|
+
case '*':
|
|
37
|
+
this.sequences[sType] = [];
|
|
38
|
+
break;
|
|
39
|
+
default:
|
|
40
|
+
throw new Error(`Unexpected sequence arity '${sArity}' for '${sType}'`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
this.mainLike = this.sequences.main;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
setCurrent() {
|
|
47
|
+
this.current = {
|
|
48
|
+
sequence: this.sequences.main,
|
|
49
|
+
parentSequence: null,
|
|
50
|
+
baseSequenceType: 'main',
|
|
51
|
+
inlineSequenceType: null,
|
|
52
|
+
attributeContext: null,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
parseItem(lexedItem) {
|
|
57
|
+
let changeBaseSequence = false;
|
|
58
|
+
|
|
59
|
+
if (['startTag'].includes(lexedItem.subclass)) {
|
|
60
|
+
this.closeActiveScopes(`startTag/${lexedItem.fullTagName}`);
|
|
61
|
+
|
|
62
|
+
if (!lexedItem.isNested) {
|
|
63
|
+
this.closeActiveScopes(`implicitEnd`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (['endTag'].includes(lexedItem.subclass)) {
|
|
68
|
+
this.closeActiveScopes(`endTag/${lexedItem.fullTagName}`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (['startMilestoneTag'].includes(lexedItem.subclass) && lexedItem.sOrE === 'e') {
|
|
72
|
+
this.closeActiveScopes(`endMilestone/${lexedItem.tagName}`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (['chapter', 'pubchapter', 'verses'].includes(lexedItem.subclass)) {
|
|
76
|
+
this.closeActiveScopes(lexedItem.subclass, this.sequences.main);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const spec = this.specForItem(lexedItem);
|
|
80
|
+
|
|
81
|
+
if (spec) {
|
|
82
|
+
if ('before' in spec.parser) {
|
|
83
|
+
spec.parser.before(this, lexedItem);
|
|
84
|
+
}
|
|
85
|
+
changeBaseSequence = false;
|
|
86
|
+
|
|
87
|
+
if (spec.parser.baseSequenceType) {
|
|
88
|
+
const returnSequenceType = spec.parser.baseSequenceType === 'mainLike' ? this.mainLike.type : spec.parser.baseSequenceType;
|
|
89
|
+
|
|
90
|
+
changeBaseSequence = (returnSequenceType !== this.current.baseSequenceType) ||
|
|
91
|
+
spec.parser.forceNewSequence;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (changeBaseSequence) {
|
|
95
|
+
this.closeActiveScopes('baseSequenceChange');
|
|
96
|
+
this.changeBaseSequence(spec.parser);
|
|
97
|
+
|
|
98
|
+
if ('newBlock' in spec.parser && spec.parser.newBlock) {
|
|
99
|
+
this.closeActiveScopes('endBlock');
|
|
100
|
+
this.current.sequence.newBlock(labelForScope('blockTag', [lexedItem.fullTagName]));
|
|
101
|
+
}
|
|
102
|
+
} else if (spec.parser.inlineSequenceType) {
|
|
103
|
+
this.current.inlineSequenceType = spec.parser.inlineSequenceType;
|
|
104
|
+
this.current.parentSequence = this.current.sequence;
|
|
105
|
+
|
|
106
|
+
if (this.current.parentSequence.type === 'header') { // Not lovely, needed for \cp before first content
|
|
107
|
+
this.current.parentSequence = this.sequences.main;
|
|
108
|
+
}
|
|
109
|
+
this.current.sequence = new Sequence(this.current.inlineSequenceType);
|
|
110
|
+
this.current.sequence.newBlock(labelForScope('inline', spec.parser.inlineSequenceType));
|
|
111
|
+
this.sequences[this.current.inlineSequenceType].push(this.current.sequence);
|
|
112
|
+
this.current.parentSequence.addItem({
|
|
113
|
+
type: 'graft',
|
|
114
|
+
subType: this.current.inlineSequenceType,
|
|
115
|
+
payload: this.current.sequence.id,
|
|
116
|
+
});
|
|
117
|
+
} else if ('newBlock' in spec.parser && spec.parser.newBlock) {
|
|
118
|
+
this.current.sequence.newBlock(labelForScope('blockTag', [lexedItem.fullTagName]));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if ('during' in spec.parser) {
|
|
122
|
+
spec.parser.during(this, lexedItem);
|
|
123
|
+
}
|
|
124
|
+
this.openNewScopes(spec.parser, lexedItem);
|
|
125
|
+
|
|
126
|
+
if ('after' in spec.parser) {
|
|
127
|
+
spec.parser.after(this, lexedItem);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
tidy() {
|
|
133
|
+
for (const introduction of this.sequences.introduction) {
|
|
134
|
+
introduction.graftifyIntroductionHeadings(this);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const allSequences = this.allSequences();
|
|
138
|
+
|
|
139
|
+
for (const seq of allSequences) {
|
|
140
|
+
seq.trim();
|
|
141
|
+
seq.reorderSpanWithAtts();
|
|
142
|
+
seq.makeNoteGrafts(this);
|
|
143
|
+
seq.moveOrphanScopes();
|
|
144
|
+
seq.removeEmptyBlocks(this.emptyBlocks);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const emptySequences = this.emptySequences(allSequences);
|
|
148
|
+
|
|
149
|
+
for (const seq of allSequences) {
|
|
150
|
+
if (emptySequences) {
|
|
151
|
+
seq.removeGraftsToEmptySequences(emptySequences);
|
|
152
|
+
}
|
|
153
|
+
seq.addTableScopes();
|
|
154
|
+
seq.close(this);
|
|
155
|
+
this.substitutePubNumberScopes(seq);
|
|
156
|
+
seq.moveOrphanStartScopes2();
|
|
157
|
+
|
|
158
|
+
if (seq.type === 'sidebar') {
|
|
159
|
+
this.substituteEsbCatScopes(seq);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (['footnote', 'xref'].includes(seq.type)) {
|
|
163
|
+
seq.lastBlock().inlineToEnd();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
emptySequences(sequences) {
|
|
169
|
+
return sequences.filter(s => s.blocks.length === 0).map(s => s.id);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
substitutePubNumberScopes(seq) {
|
|
173
|
+
const scopeToGraftContent = {};
|
|
174
|
+
const sequenceById = this.sequenceById();
|
|
175
|
+
|
|
176
|
+
for (const block of seq.blocks) {
|
|
177
|
+
let spliceCount = 0;
|
|
178
|
+
const itItems = [...block.items];
|
|
179
|
+
|
|
180
|
+
for (const [n, item] of itItems.entries()) {
|
|
181
|
+
if (item.type === 'graft' && ['pubNumber', 'altNumber'].includes(item.subType)) {
|
|
182
|
+
const graftContent = sequenceById[item.payload].text().trim();
|
|
183
|
+
const scopeId = itItems[n + 1].payload.split('/')[1];
|
|
184
|
+
scopeToGraftContent[scopeId] = graftContent;
|
|
185
|
+
block.items.splice(n - spliceCount, 1);
|
|
186
|
+
spliceCount++;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Substitute scopeIds for graft content
|
|
192
|
+
if (Object.keys(scopeToGraftContent).length > 0) {
|
|
193
|
+
for (const block of seq.blocks) {
|
|
194
|
+
for (const scope of block.items.filter(i => i.type === 'scope')) {
|
|
195
|
+
const scopeParts = scope.payload.split('/');
|
|
196
|
+
|
|
197
|
+
if (['altChapter', 'pubVerse', 'altVerse'].includes(scopeParts[0])) {
|
|
198
|
+
scope.payload = `${scopeParts[0]}/${scopeToGraftContent[scopeParts[1]]}`;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
substituteEsbCatScopes(seq) {
|
|
206
|
+
const scopeToGraftContent = {};
|
|
207
|
+
const sequenceById = this.sequenceById();
|
|
208
|
+
|
|
209
|
+
for (const block of seq.blocks) {
|
|
210
|
+
let spliceCount = 0;
|
|
211
|
+
const itItems = [...block.items];
|
|
212
|
+
|
|
213
|
+
for (const [n, item] of itItems.entries()) {
|
|
214
|
+
if (item.type === 'graft' && item.subType === 'esbCat') {
|
|
215
|
+
const catContent = sequenceById[item.payload].text().trim();
|
|
216
|
+
const scopeId = itItems[1].payload.split('/')[1];
|
|
217
|
+
scopeToGraftContent[scopeId] = catContent;
|
|
218
|
+
block.items.splice(n - spliceCount, 1);
|
|
219
|
+
spliceCount++;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Substitute scopeIds for graft content
|
|
225
|
+
if (Object.keys(scopeToGraftContent).length > 0) {
|
|
226
|
+
for (const block of seq.blocks) {
|
|
227
|
+
for (const scope of block.items.filter(i => i.type === 'scope')) {
|
|
228
|
+
const scopeParts = scope.payload.split('/');
|
|
229
|
+
|
|
230
|
+
if (scopeParts[0] === 'esbCat') {
|
|
231
|
+
scope.payload = `${scopeParts[0]}/${scopeToGraftContent[scopeParts[1]]}`;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
allSequences() {
|
|
239
|
+
const ret = [];
|
|
240
|
+
|
|
241
|
+
for (const [seqName, seqArity] of Object.entries({ ...this.baseSequenceTypes, ...this.inlineSequenceTypes })) {
|
|
242
|
+
switch (seqArity) {
|
|
243
|
+
case '1':
|
|
244
|
+
case '?':
|
|
245
|
+
if (this.sequences[seqName]) {
|
|
246
|
+
ret.push(this.sequences[seqName]);
|
|
247
|
+
}
|
|
248
|
+
break;
|
|
249
|
+
case '*':
|
|
250
|
+
this.sequences[seqName].forEach(s => {
|
|
251
|
+
ret.push(s);
|
|
252
|
+
});
|
|
253
|
+
break;
|
|
254
|
+
default:
|
|
255
|
+
throw new Error(`Unexpected sequence arity '${seqArity}' for '${seqName}'`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return ret;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
sequenceById() {
|
|
262
|
+
const ret = {};
|
|
263
|
+
|
|
264
|
+
this.allSequences().forEach(s => {
|
|
265
|
+
ret[s.id] = s;
|
|
266
|
+
});
|
|
267
|
+
return ret;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
filter() {
|
|
271
|
+
const usedSequences = [];
|
|
272
|
+
const sequenceById = this.sequenceById();
|
|
273
|
+
this.filterGrafts(this.sequences.main.id, sequenceById, usedSequences, this.filterOptions);
|
|
274
|
+
this.removeUnusedSequences(usedSequences);
|
|
275
|
+
this.filterScopes(Object.values(sequenceById), this.filterOptions);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
filterGrafts(seqId, seqById, used, options) {
|
|
279
|
+
used.push(seqId);
|
|
280
|
+
const childSequences = seqById[seqId].filterGrafts(options);
|
|
281
|
+
|
|
282
|
+
for (const si of childSequences) {
|
|
283
|
+
if (seqById[si].type === 'main') {
|
|
284
|
+
console.log('MAIN is child!');
|
|
285
|
+
console.log(JSON.stringify(seqById[seqId], null, 2));
|
|
286
|
+
process.exit(1);
|
|
287
|
+
}
|
|
288
|
+
this.filterGrafts(si, seqById, used, options);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
removeUnusedSequences(usedSequences) {
|
|
293
|
+
for (const seq of this.allSequences()) {
|
|
294
|
+
if (!usedSequences.includes(seq.id)) {
|
|
295
|
+
const seqArity = { ...this.baseSequenceTypes, ...this.inlineSequenceTypes }[seq.type];
|
|
296
|
+
|
|
297
|
+
switch (seqArity) {
|
|
298
|
+
case '1':
|
|
299
|
+
throw new Error('Attempting to remove sequence with arity of 1');
|
|
300
|
+
case '?':
|
|
301
|
+
this.sequences[seq.type] = null;
|
|
302
|
+
break;
|
|
303
|
+
case '*':
|
|
304
|
+
this.sequences[seq.type] = this.sequences[seq.type].filter(s => s.id !== seq.id);
|
|
305
|
+
break;
|
|
306
|
+
default:
|
|
307
|
+
throw new Error(`Unexpected sequence arity '${seqArity}' for '${seq.type}'`);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
filterScopes(sequences, options) {
|
|
314
|
+
sequences.forEach(s => s.filterScopes(options));
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
specForItem(item) {
|
|
318
|
+
const context = item.subclass;
|
|
319
|
+
|
|
320
|
+
if (!(context in this.specLookup)) {
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
for (const accessor of ['tagName', 'sOrE']) {
|
|
325
|
+
if (accessor in item && accessor in this.specLookup[context] && item[accessor] in this.specLookup[context][accessor]) {
|
|
326
|
+
return { parser: this.specLookup[context][accessor][item[accessor]] };
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if ('_noAccessor' in this.specLookup[context]) {
|
|
331
|
+
return { parser: this.specLookup[context]['_noAccessor'] };
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
closeActiveScopes(closeLabel, targetSequence) {
|
|
338
|
+
if (targetSequence === undefined) {
|
|
339
|
+
targetSequence = this.current.sequence;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const matchedScopes = targetSequence.activeScopes.filter(
|
|
343
|
+
sc => sc.endedBy.includes(closeLabel),
|
|
344
|
+
).reverse();
|
|
345
|
+
|
|
346
|
+
targetSequence.activeScopes = targetSequence.activeScopes.filter(
|
|
347
|
+
sc => !sc.endedBy.includes(closeLabel),
|
|
348
|
+
);
|
|
349
|
+
matchedScopes.forEach(ms => this.closeActiveScope(ms, targetSequence));
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
closeActiveScope(sc, targetSequence) {
|
|
353
|
+
this.addScope('end', sc.label, targetSequence);
|
|
354
|
+
|
|
355
|
+
if (sc.onEnd) {
|
|
356
|
+
sc.onEnd(this, sc.label);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
changeBaseSequence(parserSpec) {
|
|
361
|
+
const newType = parserSpec.baseSequenceType;
|
|
362
|
+
|
|
363
|
+
if (newType === 'mainLike') {
|
|
364
|
+
this.current.sequence = this.mainLike;
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
this.current.baseSequenceType = newType;
|
|
368
|
+
const arity = this.baseSequenceTypes[newType];
|
|
369
|
+
|
|
370
|
+
switch (arity) {
|
|
371
|
+
case '1':
|
|
372
|
+
this.current.sequence = this.sequences[newType];
|
|
373
|
+
break;
|
|
374
|
+
case '?':
|
|
375
|
+
if (!this.sequences[newType]) {
|
|
376
|
+
this.sequences[newType] = new Sequence(newType);
|
|
377
|
+
}
|
|
378
|
+
this.current.sequence = this.sequences[newType];
|
|
379
|
+
break;
|
|
380
|
+
case '*':
|
|
381
|
+
this.current.sequence = new Sequence(newType);
|
|
382
|
+
|
|
383
|
+
if (!parserSpec.useTempSequence) {
|
|
384
|
+
this.sequences[newType].push(this.current.sequence);
|
|
385
|
+
}
|
|
386
|
+
break;
|
|
387
|
+
default:
|
|
388
|
+
throw new Error(`Unexpected base sequence arity '${arity}' for '${newType}'`);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
if (!parserSpec.useTempSequence && this.current.sequence.type !== 'main') {
|
|
392
|
+
this.mainLike.addBlockGraft({
|
|
393
|
+
type: 'graft',
|
|
394
|
+
subType: this.current.baseSequenceType,
|
|
395
|
+
payload: this.current.sequence.id,
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
returnToBaseSequence() {
|
|
401
|
+
this.current.inlineSequenceType = null;
|
|
402
|
+
this.current.sequence = this.current.parentSequence;
|
|
403
|
+
this.current.parentSequence = null;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
openNewScopes(parserSpec, pt) {
|
|
407
|
+
if (parserSpec.newScopes) {
|
|
408
|
+
let targetSequence = this.current.sequence;
|
|
409
|
+
|
|
410
|
+
if ('mainSequence' in parserSpec && parserSpec.mainSequence) {
|
|
411
|
+
targetSequence = this.sequences.main;
|
|
412
|
+
}
|
|
413
|
+
parserSpec.newScopes.forEach(sc => this.openNewScope(pt, sc, true, targetSequence));
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
openNewScope(pt, sc, addItem, targetSequence) {
|
|
418
|
+
if (addItem === undefined) {
|
|
419
|
+
addItem = true;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
if (targetSequence === undefined) {
|
|
423
|
+
targetSequence = this.current.sequence;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
if (addItem) {
|
|
427
|
+
targetSequence.addItem({
|
|
428
|
+
type: 'scope',
|
|
429
|
+
subType: 'start',
|
|
430
|
+
payload: sc.label(pt),
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const newScope = {
|
|
435
|
+
label: sc.label(pt),
|
|
436
|
+
endedBy: this.substituteEndedBys(sc.endedBy, pt),
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
if ('onEnd' in sc) {
|
|
440
|
+
newScope.onEnd = sc.onEnd;
|
|
441
|
+
}
|
|
442
|
+
targetSequence.activeScopes.push(newScope);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
substituteEndedBys(endedBy, pt) {
|
|
446
|
+
return endedBy.map(
|
|
447
|
+
eb => {
|
|
448
|
+
let ret = eb
|
|
449
|
+
.replace('$fullTagName$', pt.fullTagName)
|
|
450
|
+
.replace('$tagName$', pt.tagName);
|
|
451
|
+
|
|
452
|
+
if (this.current.attributeContext) {
|
|
453
|
+
ret = ret.replace(
|
|
454
|
+
'$attributeContext$',
|
|
455
|
+
this.current.attributeContext
|
|
456
|
+
.replace('milestone', 'endMilestone')
|
|
457
|
+
.replace('spanWithAtts', 'endTag'),
|
|
458
|
+
);
|
|
459
|
+
}
|
|
460
|
+
return ret;
|
|
461
|
+
},
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
addToken(pt) {
|
|
466
|
+
this.current.sequence.addItem({
|
|
467
|
+
type: 'token',
|
|
468
|
+
subType: pt.subclass,
|
|
469
|
+
payload: pt.printValue,
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
addScope(sOrE, label, targetSequence) {
|
|
474
|
+
if (targetSequence === undefined) {
|
|
475
|
+
targetSequence = this.current.sequence;
|
|
476
|
+
}
|
|
477
|
+
targetSequence.addItem({
|
|
478
|
+
type: 'scope',
|
|
479
|
+
subType: sOrE,
|
|
480
|
+
payload: label,
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
addEmptyMilestone(label) {
|
|
485
|
+
this.mainLike.addItem({
|
|
486
|
+
type: 'scope',
|
|
487
|
+
subType: 'start',
|
|
488
|
+
payload: label,
|
|
489
|
+
});
|
|
490
|
+
this.mainLike.addItem({
|
|
491
|
+
type: 'scope',
|
|
492
|
+
subType: 'end',
|
|
493
|
+
payload: label,
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
setAttributeContext(label) {
|
|
498
|
+
this.current.attributeContext = label;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
clearAttributeContext() {
|
|
502
|
+
this.current.attributeContext = null;
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
module.exports = { Parser };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const { parseUsfm } = require('./usfm.cjs');
|
|
2
|
+
const { parseUsx } = require('./usx/index.cjs');
|
|
3
|
+
const { parseTableToDocument } = require('./tsv.cjs');
|
|
4
|
+
const { parseNodes } = require('./nodes.cjs');
|
|
5
|
+
|
|
6
|
+
module.exports = {
|
|
7
|
+
parseUsfm,
|
|
8
|
+
parseUsx,
|
|
9
|
+
parseTableToDocument,
|
|
10
|
+
parseNodes,
|
|
11
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const xre = require('xregexp');
|
|
2
|
+
|
|
3
|
+
const lexingRegexes = [
|
|
4
|
+
['chapter', 'chapter', xre('([\\r\\n]*\\\\c[ \\t]+(\\d+)[ \\t\\r\\n]*)')],
|
|
5
|
+
[
|
|
6
|
+
'pubchapter',
|
|
7
|
+
'pubchapter',
|
|
8
|
+
xre('([\\r\\n]*\\\\cp[ \\t]+([^\\r\\n]+)[ \\t\\r\\n]*)'),
|
|
9
|
+
],
|
|
10
|
+
['verses', 'verses', xre('(\\\\v[ \\t]+([\\d\\-]+)[ \\t\\r\\n]*)')],
|
|
11
|
+
[
|
|
12
|
+
'attribute',
|
|
13
|
+
'attribute',
|
|
14
|
+
xre('([ \\t]*\\|?[ \\t]*([A-Za-z0-9\\-]+)="([^"]*)"[ \\t]?)'),
|
|
15
|
+
],
|
|
16
|
+
[
|
|
17
|
+
'attribute',
|
|
18
|
+
'defaultAttribute',
|
|
19
|
+
xre('([ \\t]*\\|[ \\t]*([^\\|\\\\]*))'),
|
|
20
|
+
],
|
|
21
|
+
['milestone', 'emptyMilestone', xre('(\\\\([a-z1-9]+)\\\\[*])')],
|
|
22
|
+
['milestone', 'startMilestoneTag', xre('(\\\\([a-z1-9]+)-([se]))')],
|
|
23
|
+
['milestone', 'endMilestoneMarker', xre('(\\\\([*]))')],
|
|
24
|
+
['tag', 'endTag', xre('(\\\\([+]?[a-z\\-]+)([1-9]?(-([1-9]))?)[*])')],
|
|
25
|
+
['tag', 'startTag', xre('(\\\\([+]?[a-z\\-]+)([1-9]?(-([1-9]))?)[ \\t]?)')],
|
|
26
|
+
['bad', 'bareSlash', xre('(\\\\)')],
|
|
27
|
+
['printable', 'eol', xre('([ \\t]*[\\r\\n]+[ \\t]*)')],
|
|
28
|
+
['break', 'noBreakSpace', xre('~')],
|
|
29
|
+
['break', 'softLineBreak', xre('//')],
|
|
30
|
+
[
|
|
31
|
+
'printable',
|
|
32
|
+
'wordLike',
|
|
33
|
+
xre('([\\p{Letter}\\p{Number}\\p{Mark}\\u2060]{1,127})'),
|
|
34
|
+
],
|
|
35
|
+
['printable', 'lineSpace', xre('([\\p{Separator}\t]{1,127})')],
|
|
36
|
+
['printable', 'punctuation', xre('([\\p{Punctuation}\\p{Math_Symbol}\\p{Currency_Symbol}\\p{Modifier_Symbol}\\p{Other_Symbol}])')],
|
|
37
|
+
['bad', 'unknown', xre('(.)')],
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
const mainRegex = xre.union(lexingRegexes.map((x) => x[2]));
|
|
41
|
+
|
|
42
|
+
module.exports = {
|
|
43
|
+
lexingRegexes,
|
|
44
|
+
mainRegex,
|
|
45
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
const utils = require('../../util/index.cjs');
|
|
2
|
+
const { labelForScope } = utils.scopeDefs;
|
|
3
|
+
const { Sequence } = require('../model/index.cjs');
|
|
4
|
+
const { tokenizeString } = require('../lib/tokenize.cjs');
|
|
5
|
+
|
|
6
|
+
let nextNodeId = 0;
|
|
7
|
+
|
|
8
|
+
const numberNodes = (node, parentId) => {
|
|
9
|
+
if (typeof parentId !== 'number') {
|
|
10
|
+
nextNodeId = 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const ret = {
|
|
14
|
+
...node,
|
|
15
|
+
id: nextNodeId,
|
|
16
|
+
parentId: typeof parentId === 'number' ? parentId : 'none',
|
|
17
|
+
};
|
|
18
|
+
nextNodeId++;
|
|
19
|
+
|
|
20
|
+
if (node.children) {
|
|
21
|
+
ret.children = node.children.map(cn => numberNodes(cn, ret.id));
|
|
22
|
+
}
|
|
23
|
+
return ret;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const flattenNodes = node => {
|
|
27
|
+
const ret = [{}];
|
|
28
|
+
ret[0].id = node.id;
|
|
29
|
+
ret[0].parentId = node.parentId;
|
|
30
|
+
|
|
31
|
+
if (node.content) {
|
|
32
|
+
ret[0].content = node.content;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (node.children) {
|
|
36
|
+
ret[0].children = [];
|
|
37
|
+
|
|
38
|
+
for (const cn of node.children) {
|
|
39
|
+
ret[0].children.push(cn.id);
|
|
40
|
+
flattenNodes(cn).forEach(n => ret.push(n));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return ret;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const parseNodes = (str, parser, bookCode) => {
|
|
47
|
+
parser.headers.id = bookCode;
|
|
48
|
+
parser.headers.bookCode = bookCode;
|
|
49
|
+
const treeSequence = new Sequence('tree');
|
|
50
|
+
|
|
51
|
+
for (const node of flattenNodes(numberNodes(JSON.parse(str)))) {
|
|
52
|
+
treeSequence.newBlock(labelForScope('tTreeNode', [`${node.id}`]));
|
|
53
|
+
const scopePayload = labelForScope('tTreeParent', [`${node.parentId}`]);
|
|
54
|
+
|
|
55
|
+
treeSequence.lastBlock().items.push({
|
|
56
|
+
type: 'scope',
|
|
57
|
+
subType: 'start',
|
|
58
|
+
payload: scopePayload,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
if (node.content) {
|
|
62
|
+
for (const [name, content] of Object.entries(node.content)) {
|
|
63
|
+
const treeContentStart = treeSequence.lastBlock().items.length;
|
|
64
|
+
const tokenized = tokenizeString(content);
|
|
65
|
+
const scopePayload = labelForScope('tTreeContent', [name, node.id, `${treeContentStart}`, `${tokenized.length}`]);
|
|
66
|
+
|
|
67
|
+
treeSequence.lastBlock().items.push({
|
|
68
|
+
type: 'scope',
|
|
69
|
+
subType: 'start',
|
|
70
|
+
payload: scopePayload,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
for (const [payload, subType] of tokenized) {
|
|
74
|
+
treeSequence.lastBlock().items.push({
|
|
75
|
+
type: 'token',
|
|
76
|
+
subType,
|
|
77
|
+
payload,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
treeSequence.lastBlock().items.push({
|
|
81
|
+
type: 'scope',
|
|
82
|
+
subType: 'end',
|
|
83
|
+
payload: scopePayload,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (node.children) {
|
|
89
|
+
for (const [childN, childNodeN] of node.children.entries()) {
|
|
90
|
+
const scopePayload = labelForScope('tTreeChild', [childN, childNodeN]);
|
|
91
|
+
|
|
92
|
+
treeSequence.lastBlock().items.push({
|
|
93
|
+
type: 'scope',
|
|
94
|
+
subType: 'start',
|
|
95
|
+
payload: scopePayload,
|
|
96
|
+
});
|
|
97
|
+
treeSequence.lastBlock().items.push({
|
|
98
|
+
type: 'scope',
|
|
99
|
+
subType: 'end',
|
|
100
|
+
payload: scopePayload,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
treeSequence.lastBlock().items.push({
|
|
105
|
+
type: 'scope',
|
|
106
|
+
subType: 'end',
|
|
107
|
+
payload: scopePayload,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
parser.sequences.tree.push(treeSequence);
|
|
112
|
+
parser.sequences.main.addBlockGraft({
|
|
113
|
+
type: 'graft',
|
|
114
|
+
subType: 'tree',
|
|
115
|
+
payload: treeSequence.id,
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
module.exports = {
|
|
120
|
+
flattenNodes,
|
|
121
|
+
numberNodes,
|
|
122
|
+
parseNodes,
|
|
123
|
+
};
|