1 | 'use strict';
|
2 |
|
3 | var identity = require('./nodes/identity.js');
|
4 | var publicApi = require('./public-api.js');
|
5 | var visit = require('./visit.js');
|
6 |
|
7 | const scalarChar = {
|
8 | BLOCK_FOLDED: '>',
|
9 | BLOCK_LITERAL: '|',
|
10 | PLAIN: ':',
|
11 | QUOTE_DOUBLE: '"',
|
12 | QUOTE_SINGLE: "'"
|
13 | };
|
14 | function anchorExists(doc, anchor) {
|
15 | let found = false;
|
16 | visit.visit(doc, {
|
17 | Value(_key, node) {
|
18 | if (node.anchor === anchor) {
|
19 | found = true;
|
20 | return visit.visit.BREAK;
|
21 | }
|
22 | }
|
23 | });
|
24 | return found;
|
25 | }
|
26 |
|
27 | function testEvents(src) {
|
28 | const docs = publicApi.parseAllDocuments(src);
|
29 | const errDoc = docs.find(doc => doc.errors.length > 0);
|
30 | const error = errDoc ? errDoc.errors[0].message : null;
|
31 | const events = ['+STR'];
|
32 | try {
|
33 | for (let i = 0; i < docs.length; ++i) {
|
34 | const doc = docs[i];
|
35 | let root = doc.contents;
|
36 | if (Array.isArray(root))
|
37 | root = root[0];
|
38 | const [rootStart] = doc.range || [0];
|
39 | const error = doc.errors[0];
|
40 | if (error && (!error.pos || error.pos[0] < rootStart))
|
41 | throw new Error();
|
42 | let docStart = '+DOC';
|
43 | if (doc.directives.docStart)
|
44 | docStart += ' ---';
|
45 | else if (doc.contents &&
|
46 | doc.contents.range[2] === doc.contents.range[0] &&
|
47 | !doc.contents.anchor &&
|
48 | !doc.contents.tag)
|
49 | continue;
|
50 | events.push(docStart);
|
51 | addEvents(events, doc, error?.pos[0] ?? -1, root);
|
52 | let docEnd = '-DOC';
|
53 | if (doc.directives.docEnd)
|
54 | docEnd += ' ...';
|
55 | events.push(docEnd);
|
56 | }
|
57 | }
|
58 | catch (e) {
|
59 | return { events, error: error ?? e };
|
60 | }
|
61 | events.push('-STR');
|
62 | return { events, error };
|
63 | }
|
64 | function addEvents(events, doc, errPos, node) {
|
65 | if (!node) {
|
66 | events.push('=VAL :');
|
67 | return;
|
68 | }
|
69 | if (errPos !== -1 && identity.isNode(node) && node.range[0] >= errPos)
|
70 | throw new Error();
|
71 | let props = '';
|
72 | let anchor = identity.isScalar(node) || identity.isCollection(node) ? node.anchor : undefined;
|
73 | if (anchor) {
|
74 | if (/\d$/.test(anchor)) {
|
75 | const alt = anchor.replace(/\d$/, '');
|
76 | if (anchorExists(doc, alt))
|
77 | anchor = alt;
|
78 | }
|
79 | props = ` &${anchor}`;
|
80 | }
|
81 | if (identity.isNode(node) && node.tag)
|
82 | props += ` <${node.tag}>`;
|
83 | if (identity.isMap(node)) {
|
84 | const ev = node.flow ? '+MAP {}' : '+MAP';
|
85 | events.push(`${ev}${props}`);
|
86 | node.items.forEach(({ key, value }) => {
|
87 | addEvents(events, doc, errPos, key);
|
88 | addEvents(events, doc, errPos, value);
|
89 | });
|
90 | events.push('-MAP');
|
91 | }
|
92 | else if (identity.isSeq(node)) {
|
93 | const ev = node.flow ? '+SEQ []' : '+SEQ';
|
94 | events.push(`${ev}${props}`);
|
95 | node.items.forEach(item => {
|
96 | addEvents(events, doc, errPos, item);
|
97 | });
|
98 | events.push('-SEQ');
|
99 | }
|
100 | else if (identity.isPair(node)) {
|
101 | events.push(`+MAP${props}`);
|
102 | addEvents(events, doc, errPos, node.key);
|
103 | addEvents(events, doc, errPos, node.value);
|
104 | events.push('-MAP');
|
105 | }
|
106 | else if (identity.isAlias(node)) {
|
107 | let alias = node.source;
|
108 | if (alias && /\d$/.test(alias)) {
|
109 | const alt = alias.replace(/\d$/, '');
|
110 | if (anchorExists(doc, alt))
|
111 | alias = alt;
|
112 | }
|
113 | events.push(`=ALI${props} *${alias}`);
|
114 | }
|
115 | else {
|
116 | const scalar = scalarChar[String(node.type)];
|
117 | if (!scalar)
|
118 | throw new Error(`Unexpected node type ${node.type}`);
|
119 | const value = node.source
|
120 | .replace(/\\/g, '\\\\')
|
121 | .replace(/\0/g, '\\0')
|
122 | .replace(/\x07/g, '\\a')
|
123 | .replace(/\x08/g, '\\b')
|
124 | .replace(/\t/g, '\\t')
|
125 | .replace(/\n/g, '\\n')
|
126 | .replace(/\v/g, '\\v')
|
127 | .replace(/\f/g, '\\f')
|
128 | .replace(/\r/g, '\\r')
|
129 | .replace(/\x1b/g, '\\e');
|
130 | events.push(`=VAL${props} ${scalar}${value}`);
|
131 | }
|
132 | }
|
133 |
|
134 | exports.testEvents = testEvents;
|