@bablr/agast-helpers 0.8.0 → 0.10.0
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/lib/builders.js +159 -88
- package/lib/path.js +1571 -419
- package/lib/print.js +78 -41
- package/lib/shorthand.js +17 -13
- package/lib/stream.js +437 -164
- package/lib/symbols.js +5 -2
- package/lib/tags.js +285 -0
- package/lib/template.js +52 -46
- package/lib/tree.js +165 -687
- package/package.json +6 -4
- package/lib/children.js +0 -120
- package/lib/path-facade.js +0 -39
package/lib/tree.js
CHANGED
|
@@ -1,72 +1,77 @@
|
|
|
1
|
-
import { Coroutine } from '@bablr/coroutine';
|
|
2
1
|
import {
|
|
3
|
-
nodeFlags,
|
|
4
2
|
buildReferenceTag,
|
|
5
|
-
buildNullTag,
|
|
6
3
|
buildOpenNodeTag,
|
|
7
4
|
buildLiteralTag,
|
|
8
5
|
buildCloseNodeTag,
|
|
9
6
|
tokenFlags,
|
|
10
|
-
buildInitializerTag,
|
|
11
|
-
buildBindingTag,
|
|
12
|
-
buildProperty,
|
|
13
7
|
buildChild,
|
|
14
|
-
buildShiftTag,
|
|
15
8
|
buildGapTag,
|
|
9
|
+
buildOpenFragmentTag,
|
|
16
10
|
} from './builders.js';
|
|
17
11
|
import {
|
|
18
12
|
printPrettyCSTML as printPrettyCSTMLFromStream,
|
|
19
13
|
printCSTML as printCSTMLFromStream,
|
|
20
14
|
printSource as printSourceFromStream,
|
|
21
|
-
|
|
15
|
+
treeFromStream,
|
|
16
|
+
treeFromStreamSync,
|
|
17
|
+
treeFromStreamAsync,
|
|
18
|
+
evaluateReturnSync,
|
|
19
|
+
evaluateReturnAsync,
|
|
22
20
|
} from './stream.js';
|
|
23
21
|
import {
|
|
24
|
-
DoctypeTag,
|
|
25
22
|
OpenNodeTag,
|
|
26
23
|
CloseNodeTag,
|
|
27
24
|
ReferenceTag,
|
|
28
25
|
GapTag,
|
|
29
|
-
NullTag,
|
|
30
|
-
InitializerTag,
|
|
31
26
|
LiteralTag,
|
|
32
27
|
AttributeDefinition,
|
|
33
28
|
BindingTag,
|
|
34
|
-
Property,
|
|
35
29
|
ShiftTag,
|
|
30
|
+
Property,
|
|
31
|
+
NullNode,
|
|
32
|
+
TreeNode,
|
|
33
|
+
GapNode,
|
|
36
34
|
} from './symbols.js';
|
|
37
|
-
import * as
|
|
38
|
-
import * as Children from './children.js';
|
|
35
|
+
import * as Tags from './tags.js';
|
|
39
36
|
export * from './builders.js';
|
|
40
37
|
export * from './print.js';
|
|
41
38
|
import {
|
|
42
39
|
get,
|
|
40
|
+
getOr,
|
|
41
|
+
has,
|
|
42
|
+
list,
|
|
43
43
|
TagPath,
|
|
44
|
-
|
|
45
|
-
isFragmentNode,
|
|
44
|
+
isCover,
|
|
46
45
|
isNullNode,
|
|
47
46
|
isGapNode,
|
|
48
47
|
getOpenTag,
|
|
49
48
|
getCloseTag,
|
|
50
49
|
getRoot,
|
|
51
|
-
|
|
52
|
-
getFirstNodeShiftStack,
|
|
50
|
+
getTags,
|
|
53
51
|
} from './path.js';
|
|
54
|
-
import { isPlainObject } from './object.js';
|
|
52
|
+
import { freeze, isPlainObject } from './object.js';
|
|
55
53
|
|
|
56
54
|
export {
|
|
57
55
|
get,
|
|
58
|
-
|
|
56
|
+
getOr,
|
|
57
|
+
has,
|
|
58
|
+
list,
|
|
59
|
+
isCover,
|
|
59
60
|
isNullNode,
|
|
60
61
|
isGapNode,
|
|
61
62
|
getOpenTag,
|
|
62
63
|
getCloseTag,
|
|
63
64
|
getRoot,
|
|
64
|
-
|
|
65
|
+
treeFromStream,
|
|
66
|
+
treeFromStreamSync,
|
|
67
|
+
treeFromStreamAsync,
|
|
68
|
+
evaluateReturnSync,
|
|
69
|
+
evaluateReturnAsync,
|
|
65
70
|
};
|
|
66
71
|
|
|
67
|
-
export const buildToken = (
|
|
72
|
+
export const buildToken = (name, value, attributes = {}) => {
|
|
68
73
|
return treeFromStreamSync([
|
|
69
|
-
buildOpenNodeTag(tokenFlags,
|
|
74
|
+
buildOpenNodeTag(tokenFlags, name, null, attributes),
|
|
70
75
|
buildLiteralTag(value),
|
|
71
76
|
buildCloseNodeTag(),
|
|
72
77
|
]);
|
|
@@ -75,25 +80,26 @@ export const buildToken = (type, value, attributes = {}) => {
|
|
|
75
80
|
const isString = (str) => typeof str === 'string';
|
|
76
81
|
|
|
77
82
|
const { isArray } = Array;
|
|
78
|
-
const { freeze, hasOwn } = Object;
|
|
79
83
|
|
|
80
84
|
export const mergeReferences = (outer, inner) => {
|
|
81
|
-
let { type, name,
|
|
85
|
+
let { type, name, index, flags: { array, expression, intrinsic, hasGap } = {} } = outer;
|
|
82
86
|
|
|
83
87
|
if (
|
|
84
88
|
(name != null && inner.name != null && name !== inner.name) ||
|
|
85
|
-
(type != null && inner.type != null && type !== inner.type)
|
|
89
|
+
(type != null && inner.type != null && type !== inner.type && inner.type !== '.')
|
|
86
90
|
) {
|
|
87
91
|
return inner;
|
|
88
92
|
}
|
|
89
93
|
|
|
90
|
-
|
|
94
|
+
array = !!(array || inner.flags.array);
|
|
91
95
|
expression = !!(expression || inner.flags.expression);
|
|
96
|
+
intrinsic = !!(intrinsic || inner.flags.intrinsic);
|
|
92
97
|
hasGap = !!(hasGap || inner.flags.hasGap);
|
|
93
98
|
name = type === '.' ? inner.name : name;
|
|
94
99
|
type = type === '.' ? inner.type : type;
|
|
95
100
|
|
|
96
|
-
return buildReferenceTag(type, name,
|
|
101
|
+
return buildReferenceTag(type, name, freeze({ array, expression, intrinsic, hasGap }), index)
|
|
102
|
+
.value;
|
|
97
103
|
};
|
|
98
104
|
|
|
99
105
|
export const mergeReferenceTags = (outer, inner) => {
|
|
@@ -102,385 +108,176 @@ export const mergeReferenceTags = (outer, inner) => {
|
|
|
102
108
|
return buildChild(ReferenceTag, value);
|
|
103
109
|
};
|
|
104
110
|
|
|
105
|
-
export const
|
|
106
|
-
|
|
107
|
-
return type === '.' && !isArray && !(flags.expression || flags.hasGap);
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
function* __treeFromStream(tags, options) {
|
|
111
|
-
let path = null;
|
|
112
|
-
let rootPath = null;
|
|
113
|
-
let held = null;
|
|
114
|
-
let doctype = null;
|
|
115
|
-
const co = new Coroutine(getStreamIterator(tags));
|
|
116
|
-
const expressionsCo = new Coroutine(getStreamIterator(options.expressions || []));
|
|
117
|
-
let referenceTag = null;
|
|
118
|
-
let bindingTag = null;
|
|
119
|
-
|
|
120
|
-
for (;;) {
|
|
121
|
-
co.advance();
|
|
122
|
-
|
|
123
|
-
if (co.current instanceof Promise) {
|
|
124
|
-
co.current = yield co.current;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (co.done) break;
|
|
111
|
+
export const documentFromStream = (tags, options) => {
|
|
112
|
+
throw new Error('not implemented');
|
|
128
113
|
|
|
129
|
-
|
|
114
|
+
// strip doctype tag off
|
|
130
115
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (tag.type === DoctypeTag) {
|
|
136
|
-
doctype = tag;
|
|
137
|
-
continue;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (held && tag.type !== OpenNodeTag && tag.type !== GapTag) {
|
|
141
|
-
throw new Error('cannot eat this type of tag while holding');
|
|
142
|
-
}
|
|
116
|
+
// return buildChild(Document, freeze({ doctype, tree }));
|
|
117
|
+
};
|
|
143
118
|
|
|
144
|
-
|
|
119
|
+
export const isEmpty = (node) => {
|
|
120
|
+
if (node == null) return true;
|
|
145
121
|
|
|
122
|
+
for (const tag of Tags.traverse(getTags(node))) {
|
|
146
123
|
switch (tag.type) {
|
|
147
|
-
case
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
case ReferenceTag: {
|
|
153
|
-
referenceTag = tag;
|
|
154
|
-
suppressTag = true;
|
|
155
|
-
break;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
case BindingTag: {
|
|
159
|
-
bindingTag = tag;
|
|
160
|
-
suppressTag = true;
|
|
161
|
-
break;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
case InitializerTag: {
|
|
165
|
-
add(path.node, referenceTag, []);
|
|
166
|
-
suppressTag = true;
|
|
167
|
-
referenceTag = null;
|
|
168
|
-
break;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
case NullTag:
|
|
172
|
-
case GapTag: {
|
|
173
|
-
if (!path) {
|
|
174
|
-
return buildStubNode(tag);
|
|
175
|
-
}
|
|
124
|
+
case Property: {
|
|
125
|
+
if (tag.value.property.reference.type === '@') {
|
|
126
|
+
return false;
|
|
127
|
+
} else {
|
|
128
|
+
const { property } = tag.value;
|
|
176
129
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
if (path.parent && referenceTag.type !== ReferenceTag) throw new Error();
|
|
180
|
-
|
|
181
|
-
let node = createNode(tag);
|
|
182
|
-
|
|
183
|
-
if (isGap) {
|
|
184
|
-
if (held) {
|
|
185
|
-
node = held;
|
|
186
|
-
add(path.node, referenceTag, node, bindingTag);
|
|
187
|
-
suppressTag = true;
|
|
188
|
-
} else if (!expressionsCo.done) {
|
|
189
|
-
expressionsCo.advance();
|
|
190
|
-
|
|
191
|
-
let outerReference = referenceTag;
|
|
192
|
-
|
|
193
|
-
if (!expressionsCo.done) {
|
|
194
|
-
node =
|
|
195
|
-
node == null
|
|
196
|
-
? buildStubNode(buildNullTag())
|
|
197
|
-
: expressionsCo.value == null
|
|
198
|
-
? buildStubNode(buildNullTag())
|
|
199
|
-
: expressionsCo.value;
|
|
200
|
-
suppressTag = true;
|
|
201
|
-
|
|
202
|
-
if (isFragmentNode(node)) {
|
|
203
|
-
const parentNode = path.node;
|
|
204
|
-
|
|
205
|
-
let referenceTag;
|
|
206
|
-
let bindingTag;
|
|
207
|
-
|
|
208
|
-
for (const tag of Children.traverse(node.children)) {
|
|
209
|
-
switch (tag.type) {
|
|
210
|
-
case DoctypeTag: {
|
|
211
|
-
break;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
case OpenNodeTag: {
|
|
215
|
-
referenceTag = bindingTag = null;
|
|
216
|
-
if (!tag.value.type) {
|
|
217
|
-
break;
|
|
218
|
-
} else {
|
|
219
|
-
throw new Error();
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
case ReferenceTag:
|
|
224
|
-
referenceTag = tag;
|
|
225
|
-
break;
|
|
226
|
-
|
|
227
|
-
case InitializerTag: {
|
|
228
|
-
add(parentNode, mergeReferenceTags(outerReference, referenceTag), []);
|
|
229
|
-
break;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
case BindingTag: {
|
|
233
|
-
bindingTag = tag;
|
|
234
|
-
break;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
case GapTag:
|
|
238
|
-
case NullTag: {
|
|
239
|
-
add(
|
|
240
|
-
parentNode,
|
|
241
|
-
mergeReferenceTags(outerReference, referenceTag),
|
|
242
|
-
buildStubNode(tag),
|
|
243
|
-
bindingTag,
|
|
244
|
-
);
|
|
245
|
-
referenceTag = bindingTag = null;
|
|
246
|
-
break;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
default:
|
|
250
|
-
throw new Error();
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
} else {
|
|
254
|
-
if (path.node.flags.token) {
|
|
255
|
-
throw new Error('not implemented');
|
|
256
|
-
}
|
|
257
|
-
add(path.node, referenceTag, node, bindingTag ?? buildBindingTag());
|
|
258
|
-
}
|
|
259
|
-
} else {
|
|
260
|
-
if (!path.node.flags.token) {
|
|
261
|
-
add(path.node, referenceTag, node, bindingTag ?? buildBindingTag());
|
|
262
|
-
}
|
|
263
|
-
}
|
|
130
|
+
if (!isNullNode(property.node)) {
|
|
131
|
+
return false;
|
|
264
132
|
}
|
|
265
133
|
}
|
|
266
|
-
|
|
267
|
-
referenceTag = null;
|
|
268
|
-
held = isGap ? null : held;
|
|
269
|
-
|
|
270
|
-
if (!path.node.flags.token) {
|
|
271
|
-
path = { parent: path, node, depth: (path.depth ?? -1) + 1, arrays: new Set() };
|
|
272
|
-
}
|
|
273
|
-
|
|
274
134
|
break;
|
|
275
135
|
}
|
|
276
136
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
// ({ node } = btree.getAt(-1, property));
|
|
285
|
-
// properties[ref.value.name].pop();
|
|
286
|
-
// } else {
|
|
287
|
-
// ({ node } = property);
|
|
288
|
-
// properties[ref.value.name] = null;
|
|
289
|
-
// }
|
|
290
|
-
|
|
291
|
-
// held = node;
|
|
292
|
-
// break;
|
|
293
|
-
// }
|
|
294
|
-
|
|
295
|
-
case OpenNodeTag: {
|
|
296
|
-
if (path) {
|
|
297
|
-
const node = createNode(tag);
|
|
298
|
-
|
|
299
|
-
if (path) {
|
|
300
|
-
add(path.node, referenceTag, node, bindingTag ?? buildBindingTag());
|
|
301
|
-
referenceTag = null;
|
|
302
|
-
}
|
|
137
|
+
case LiteralTag:
|
|
138
|
+
case GapTag:
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return true;
|
|
143
|
+
};
|
|
303
144
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
const { type, flags, attributes } = tag.value;
|
|
145
|
+
export const streamFromTree = (tree, options = {}) => {
|
|
146
|
+
if (tree && !isPlainObject(tree)) throw new Error();
|
|
307
147
|
|
|
308
|
-
|
|
148
|
+
return __streamFromTree(null, tree, options);
|
|
149
|
+
};
|
|
309
150
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
children: [],
|
|
314
|
-
properties: {},
|
|
315
|
-
attributes: attributes_,
|
|
316
|
-
};
|
|
151
|
+
function* __streamFromTree(doctypeTag, rootNode, options) {
|
|
152
|
+
const { unshift = false } = options;
|
|
153
|
+
if (!rootNode || !Tags.getSize(getTags(rootNode))) return;
|
|
317
154
|
|
|
318
|
-
|
|
155
|
+
let tagPath = TagPath.fromNode(rootNode, 0);
|
|
319
156
|
|
|
320
|
-
|
|
321
|
-
}
|
|
157
|
+
let count = 0;
|
|
322
158
|
|
|
323
|
-
|
|
324
|
-
|
|
159
|
+
if (doctypeTag) {
|
|
160
|
+
yield doctypeTag;
|
|
161
|
+
}
|
|
325
162
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
}
|
|
163
|
+
do {
|
|
164
|
+
if (tagPath.tag.type === OpenNodeTag && !tagPath.tag.value.selfClosing) count++;
|
|
165
|
+
if (tagPath.tag.type === CloseNodeTag) count--;
|
|
330
166
|
|
|
331
|
-
if (
|
|
332
|
-
|
|
167
|
+
if (
|
|
168
|
+
!(
|
|
169
|
+
tagPath.tag.type === AttributeDefinition ||
|
|
170
|
+
(tagPath.tag.type === BindingTag && !tagPath.tag.value.segments?.length)
|
|
171
|
+
)
|
|
172
|
+
) {
|
|
173
|
+
yield tagPath.tag;
|
|
333
174
|
}
|
|
175
|
+
} while ((tagPath = unshift ? tagPath.nextUnshifted : tagPath.next));
|
|
334
176
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
case GapTag:
|
|
338
|
-
case CloseNodeTag: {
|
|
339
|
-
const completedNode = path.node;
|
|
177
|
+
// if (count !== 0) throw new Error();
|
|
178
|
+
}
|
|
340
179
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
180
|
+
export const vcsStreamFromTree = (rootNode) => {
|
|
181
|
+
return __vcsStreamFromTree(rootNode);
|
|
182
|
+
};
|
|
344
183
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
184
|
+
function* __vcsStreamFromTree(rootNode) {
|
|
185
|
+
let stack = null;
|
|
186
|
+
let agastNode = rootNode;
|
|
187
|
+
let depth = 0;
|
|
188
|
+
let nodeShifted = false;
|
|
189
|
+
let i = 0;
|
|
190
|
+
let seenFirstProperty = false;
|
|
191
|
+
let node = Tags.getValues(rootNode.value.tags);
|
|
192
|
+
|
|
193
|
+
outer: while (node) {
|
|
194
|
+
while (i >= node.length) {
|
|
195
|
+
if (stack) {
|
|
196
|
+
let oldAgastNode = agastNode;
|
|
197
|
+
let hadSeenFirst = seenFirstProperty;
|
|
198
|
+
({ stack, agastNode, node, depth, i, nodeShifted, seenFirstProperty } = stack);
|
|
199
|
+
if (oldAgastNode === agastNode) {
|
|
200
|
+
seenFirstProperty = hadSeenFirst;
|
|
201
|
+
yield buildCloseNodeTag();
|
|
349
202
|
}
|
|
350
203
|
|
|
351
|
-
|
|
352
|
-
|
|
204
|
+
i++;
|
|
205
|
+
} else {
|
|
206
|
+
return;
|
|
353
207
|
}
|
|
354
208
|
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
if (path && path.node.type) {
|
|
358
|
-
throw new Error('imbalanced tag stack');
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
return rootPath.node;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
export const buildNullNode = () => {
|
|
365
|
-
return treeFromStreamSync([buildNullTag()]);
|
|
366
|
-
};
|
|
367
209
|
|
|
368
|
-
|
|
210
|
+
let child = node[i];
|
|
369
211
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
};
|
|
373
|
-
|
|
374
|
-
export const treeFromStreamAsync = async (tokens, options = {}) => {
|
|
375
|
-
return evaluateReturnAsync(treeFromStream(tokens, options));
|
|
376
|
-
};
|
|
212
|
+
if (isArray(child)) {
|
|
213
|
+
stack = { stack, agastNode, node, depth, i, nodeShifted, seenFirstProperty };
|
|
377
214
|
|
|
378
|
-
|
|
379
|
-
const co = new Coroutine(generator[Symbol.iterator]());
|
|
380
|
-
while (!co.done) co.advance();
|
|
381
|
-
return co.value;
|
|
382
|
-
};
|
|
215
|
+
yield buildOpenFragmentTag();
|
|
383
216
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
217
|
+
node = Tags.getValues(child);
|
|
218
|
+
depth++;
|
|
219
|
+
i = 0;
|
|
220
|
+
} else {
|
|
221
|
+
let wrappedTag = child;
|
|
388
222
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
223
|
+
if (wrappedTag.type === Property) {
|
|
224
|
+
for (let tag of wrappedTag.value.tags) {
|
|
225
|
+
switch (tag.type) {
|
|
226
|
+
case TreeNode:
|
|
227
|
+
case NullNode:
|
|
228
|
+
case GapNode: {
|
|
229
|
+
let replaceWithGap = nodeShifted && !seenFirstProperty;
|
|
395
230
|
|
|
396
|
-
|
|
397
|
-
|
|
231
|
+
if (replaceWithGap) {
|
|
232
|
+
yield buildGapTag();
|
|
398
233
|
|
|
399
|
-
|
|
234
|
+
seenFirstProperty = true;
|
|
400
235
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
236
|
+
break;
|
|
237
|
+
} else {
|
|
238
|
+
stack = { stack, agastNode, node, depth, i, nodeShifted, seenFirstProperty: true };
|
|
239
|
+
node = Tags.getValues(tag.value.tags);
|
|
240
|
+
|
|
241
|
+
depth++;
|
|
242
|
+
i = 0;
|
|
243
|
+
agastNode = tag.value;
|
|
244
|
+
nodeShifted = wrappedTag.value.tags[0].type === ShiftTag;
|
|
245
|
+
seenFirstProperty = false;
|
|
246
|
+
continue outer;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
405
249
|
|
|
406
|
-
|
|
250
|
+
default: {
|
|
251
|
+
yield tag;
|
|
407
252
|
|
|
408
|
-
|
|
409
|
-
|
|
253
|
+
if (tag.type === OpenNodeTag && tag.value.literalValue) {
|
|
254
|
+
({ stack, agastNode, node, depth, i, nodeShifted } = stack);
|
|
255
|
+
seenFirstProperty = true;
|
|
256
|
+
}
|
|
410
257
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
(isArray(property) && property.length) ||
|
|
414
|
-
!isNullNode(property.node)
|
|
415
|
-
) {
|
|
416
|
-
return false;
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
417
260
|
}
|
|
418
261
|
}
|
|
419
|
-
|
|
420
|
-
|
|
262
|
+
} else {
|
|
263
|
+
yield wrappedTag;
|
|
421
264
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
265
|
+
if (wrappedTag.type === OpenNodeTag && wrappedTag.value.literalValue) {
|
|
266
|
+
({ stack, agastNode, node, depth, i, nodeShifted } = stack);
|
|
267
|
+
seenFirstProperty = true;
|
|
425
268
|
}
|
|
426
|
-
break;
|
|
427
269
|
}
|
|
428
|
-
|
|
429
|
-
case LiteralTag:
|
|
430
|
-
case GapTag:
|
|
431
|
-
return false;
|
|
270
|
+
i++;
|
|
432
271
|
}
|
|
433
272
|
}
|
|
434
|
-
return true;
|
|
435
|
-
};
|
|
436
|
-
|
|
437
|
-
export const buildStubNode = (tag) => {
|
|
438
|
-
return freeze({
|
|
439
|
-
flags: nodeFlags,
|
|
440
|
-
type: null,
|
|
441
|
-
children: freeze([tag]),
|
|
442
|
-
properties: freeze({}),
|
|
443
|
-
attributes: freeze({}),
|
|
444
|
-
});
|
|
445
|
-
};
|
|
446
|
-
|
|
447
|
-
export const streamFromTree = (rootNode, options = {}) => {
|
|
448
|
-
let rootNode_ = isPlainObject(rootNode) ? rootNode : rootNode.node;
|
|
449
|
-
|
|
450
|
-
return __streamFromTree(rootNode_, options);
|
|
451
|
-
};
|
|
452
|
-
|
|
453
|
-
function* __streamFromTree(rootNode, options) {
|
|
454
|
-
const { unshift = false } = options;
|
|
455
|
-
if (!rootNode || !Children.getSize(rootNode.children)) return;
|
|
456
|
-
|
|
457
|
-
let tagPath = TagPath.fromNode(rootNode, 0);
|
|
458
|
-
|
|
459
|
-
let count = 0;
|
|
460
|
-
|
|
461
|
-
do {
|
|
462
|
-
if (tagPath.tag.type === OpenNodeTag) count++;
|
|
463
|
-
if (tagPath.tag.type === CloseNodeTag) count--;
|
|
464
|
-
|
|
465
|
-
if (
|
|
466
|
-
!(
|
|
467
|
-
tagPath.tag.type === AttributeDefinition ||
|
|
468
|
-
(tagPath.tag.type === BindingTag && !tagPath.tag.value.languagePath?.length)
|
|
469
|
-
)
|
|
470
|
-
) {
|
|
471
|
-
yield tagPath.tag;
|
|
472
|
-
}
|
|
473
|
-
} while ((tagPath = unshift ? tagPath.nextUnshifted : tagPath.next));
|
|
474
|
-
|
|
475
|
-
if (count !== 0) throw new Error();
|
|
476
273
|
}
|
|
477
274
|
|
|
478
275
|
export const getCooked = (cookable) => {
|
|
479
|
-
if (!cookable || isGapNode(cookable
|
|
276
|
+
if (!cookable || isGapNode(cookable)) {
|
|
480
277
|
return '';
|
|
481
278
|
}
|
|
482
279
|
|
|
483
|
-
const
|
|
280
|
+
const tags = getTags(cookable) || cookable;
|
|
484
281
|
|
|
485
282
|
let cooked = '';
|
|
486
283
|
|
|
@@ -489,7 +286,7 @@ export const getCooked = (cookable) => {
|
|
|
489
286
|
|
|
490
287
|
let referenceTag = null;
|
|
491
288
|
|
|
492
|
-
for (let tag of
|
|
289
|
+
for (let tag of Tags.traverse(tags)) {
|
|
493
290
|
switch (tag.type) {
|
|
494
291
|
case ReferenceTag: {
|
|
495
292
|
let { type } = tag.value;
|
|
@@ -507,7 +304,7 @@ export const getCooked = (cookable) => {
|
|
|
507
304
|
|
|
508
305
|
case Property: {
|
|
509
306
|
let { node, reference } = tag.value;
|
|
510
|
-
let { attributes } = node;
|
|
307
|
+
let { attributes } = node.value;
|
|
511
308
|
|
|
512
309
|
if (reference.type === '@') {
|
|
513
310
|
let { cooked: cookedValue } = attributes;
|
|
@@ -521,6 +318,10 @@ export const getCooked = (cookable) => {
|
|
|
521
318
|
break;
|
|
522
319
|
}
|
|
523
320
|
|
|
321
|
+
case GapTag: {
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
|
|
524
325
|
case LiteralTag: {
|
|
525
326
|
cooked += tag.value;
|
|
526
327
|
break;
|
|
@@ -543,54 +344,20 @@ export const getCooked = (cookable) => {
|
|
|
543
344
|
return cooked;
|
|
544
345
|
};
|
|
545
346
|
|
|
546
|
-
export const printCSTML = (
|
|
547
|
-
return printCSTMLFromStream(streamFromTree(
|
|
347
|
+
export const printCSTML = (tree) => {
|
|
348
|
+
return printCSTMLFromStream(streamFromTree(tree));
|
|
548
349
|
};
|
|
549
350
|
|
|
550
|
-
export const printPrettyCSTML = (
|
|
551
|
-
return printPrettyCSTMLFromStream(streamFromTree(
|
|
351
|
+
export const printPrettyCSTML = (tree, options = {}) => {
|
|
352
|
+
return printPrettyCSTMLFromStream(streamFromTree(tree), options);
|
|
552
353
|
};
|
|
553
354
|
|
|
554
|
-
export const printSource = (
|
|
555
|
-
return printSourceFromStream(streamFromTree(
|
|
355
|
+
export const printSource = (tree) => {
|
|
356
|
+
return printSourceFromStream(streamFromTree(tree, { unshift: true }));
|
|
556
357
|
};
|
|
557
358
|
|
|
558
359
|
export const sourceTextFor = printSource;
|
|
559
360
|
|
|
560
|
-
export const getRange = (node) => {
|
|
561
|
-
const { children } = node;
|
|
562
|
-
let path = Path.from(node);
|
|
563
|
-
return Children.getSize(children) ? [TagPath.from(path, 0), TagPath.from(path, -1)] : null;
|
|
564
|
-
};
|
|
565
|
-
|
|
566
|
-
export const createNode = (openTag) => {
|
|
567
|
-
if (!openTag || openTag.type === GapTag || openTag.type === NullTag) {
|
|
568
|
-
return {
|
|
569
|
-
flags: nodeFlags,
|
|
570
|
-
type: openTag && ([NullTag, GapTag].includes(openTag.type) ? null : openTag.type),
|
|
571
|
-
children: [],
|
|
572
|
-
properties: {},
|
|
573
|
-
attributes: openTag?.attributes || {},
|
|
574
|
-
};
|
|
575
|
-
} else {
|
|
576
|
-
const { flags, type, attributes = {} } = openTag.value || {};
|
|
577
|
-
return {
|
|
578
|
-
flags,
|
|
579
|
-
type,
|
|
580
|
-
children: [],
|
|
581
|
-
properties: {},
|
|
582
|
-
attributes,
|
|
583
|
-
};
|
|
584
|
-
}
|
|
585
|
-
};
|
|
586
|
-
|
|
587
|
-
export const finalizeNode = (node) => {
|
|
588
|
-
freeze(node);
|
|
589
|
-
freeze(node.properties);
|
|
590
|
-
freeze(node.attributes);
|
|
591
|
-
return node;
|
|
592
|
-
};
|
|
593
|
-
|
|
594
361
|
export const notNull = (node) => {
|
|
595
362
|
return node != null && !isNullNode(node);
|
|
596
363
|
};
|
|
@@ -598,292 +365,3 @@ export const notNull = (node) => {
|
|
|
598
365
|
export const isNull = (node) => {
|
|
599
366
|
return node == null || isNullNode(node);
|
|
600
367
|
};
|
|
601
|
-
|
|
602
|
-
export const branchProperties = (properties) => {
|
|
603
|
-
const copy = { ...properties };
|
|
604
|
-
|
|
605
|
-
for (const { 0: key, 1: value } of Object.entries(copy)) {
|
|
606
|
-
if (isArray(value)) {
|
|
607
|
-
copy[key] = btree.fromValues(value);
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
return copy;
|
|
612
|
-
};
|
|
613
|
-
|
|
614
|
-
export const branchNode = (node) => {
|
|
615
|
-
const { flags, type, children, properties, attributes } = node;
|
|
616
|
-
return {
|
|
617
|
-
flags,
|
|
618
|
-
type,
|
|
619
|
-
children,
|
|
620
|
-
properties: branchProperties(properties),
|
|
621
|
-
attributes: { ...attributes },
|
|
622
|
-
};
|
|
623
|
-
};
|
|
624
|
-
|
|
625
|
-
export const acceptNode = (node, accepted) => {
|
|
626
|
-
const { children, properties, attributes } = accepted;
|
|
627
|
-
node.children = children;
|
|
628
|
-
node.properties = properties;
|
|
629
|
-
node.attributes = attributes;
|
|
630
|
-
return node;
|
|
631
|
-
};
|
|
632
|
-
|
|
633
|
-
export function* traverseProperties(properties) {
|
|
634
|
-
for (const value of Object.values(properties)) {
|
|
635
|
-
if (isArray(value)) {
|
|
636
|
-
for (let item of btree.traverse(value)) {
|
|
637
|
-
if (isArray(item.node)) {
|
|
638
|
-
yield btree.getAt(-1, item.node);
|
|
639
|
-
} else {
|
|
640
|
-
yield item.node;
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
} else {
|
|
644
|
-
yield value.node;
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
export const addToProperties = (properties, property) => {
|
|
650
|
-
let { reference, node: value } = property;
|
|
651
|
-
let { flags, name, isArray } = reference;
|
|
652
|
-
|
|
653
|
-
if (!name) throw new Error();
|
|
654
|
-
if (value === null) throw new Error();
|
|
655
|
-
if (!hasOwn(property, 'binding')) throw new Error();
|
|
656
|
-
|
|
657
|
-
if (Object.isFrozen(properties)) {
|
|
658
|
-
throw new Error('not implemented');
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
let isInitializer = value === undefined || Array.isArray(value);
|
|
662
|
-
|
|
663
|
-
let outerProperty = property;
|
|
664
|
-
|
|
665
|
-
if (flags.expression && !isInitializer) {
|
|
666
|
-
let shiftStack =
|
|
667
|
-
getFirstNodeShiftStack(value) ||
|
|
668
|
-
btree.fromValues([buildProperty(reference, null, buildStubNode(buildGapTag()))]);
|
|
669
|
-
|
|
670
|
-
shiftStack = btree.push(shiftStack, property);
|
|
671
|
-
outerProperty = buildProperty(reference, null, shiftStack);
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
if (isArray && !isInitializer) {
|
|
675
|
-
properties[name] = buildProperty(
|
|
676
|
-
reference,
|
|
677
|
-
null,
|
|
678
|
-
btree.push(properties[name]?.node || btree.fromValues([]), outerProperty),
|
|
679
|
-
);
|
|
680
|
-
} else {
|
|
681
|
-
properties[name] = outerProperty;
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
return properties;
|
|
685
|
-
};
|
|
686
|
-
|
|
687
|
-
export const shiftToProperties = (properties, property) => {
|
|
688
|
-
let { reference, node: value } = property;
|
|
689
|
-
let { flags, name, isArray } = reference;
|
|
690
|
-
|
|
691
|
-
if (!name) throw new Error();
|
|
692
|
-
|
|
693
|
-
if (Object.isFrozen(properties)) {
|
|
694
|
-
throw new Error('not implemented');
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
if (!flags.expression) {
|
|
698
|
-
return addToProperties(properties, property);
|
|
699
|
-
}
|
|
700
|
-
let isInitializer = value === undefined || Array.isArray(value);
|
|
701
|
-
|
|
702
|
-
let outerProperty;
|
|
703
|
-
if (flags.expression && !isInitializer) {
|
|
704
|
-
let shiftStack =
|
|
705
|
-
getFirstNodeShiftStack(value) ||
|
|
706
|
-
btree.fromValues([buildProperty(reference, null, buildStubNode(buildGapTag()))]);
|
|
707
|
-
|
|
708
|
-
shiftStack = btree.push(shiftStack, property);
|
|
709
|
-
outerProperty = buildProperty(reference, null, shiftStack);
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
if (isArray) {
|
|
713
|
-
properties[name] = buildProperty(
|
|
714
|
-
reference,
|
|
715
|
-
null,
|
|
716
|
-
btree.replaceAt(-1, properties[name].node, outerProperty),
|
|
717
|
-
);
|
|
718
|
-
} else {
|
|
719
|
-
properties[name] = outerProperty;
|
|
720
|
-
}
|
|
721
|
-
return properties;
|
|
722
|
-
};
|
|
723
|
-
|
|
724
|
-
export const addProperty = (node, property) => {
|
|
725
|
-
if (!node || !property) throw new Error();
|
|
726
|
-
if (!Object.isFrozen(property)) throw new Error();
|
|
727
|
-
|
|
728
|
-
let back1 = Children.getAt(-1, node.children);
|
|
729
|
-
let back2 = Children.getAt(-2, node.children);
|
|
730
|
-
|
|
731
|
-
let referenceTag;
|
|
732
|
-
let bindingTag = null;
|
|
733
|
-
|
|
734
|
-
if (property.node === null) {
|
|
735
|
-
throw new Error();
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
let { node: value } = property;
|
|
739
|
-
|
|
740
|
-
let isArrayInitializer = isArray(value);
|
|
741
|
-
let isInitializer = value === undefined || isArrayInitializer;
|
|
742
|
-
|
|
743
|
-
if (isArrayInitializer && value.length) throw new Error();
|
|
744
|
-
|
|
745
|
-
if (!isInitializer && property.node.type && !property.binding) {
|
|
746
|
-
throw new Error();
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
let foundShift = false;
|
|
750
|
-
let foundBinding = false;
|
|
751
|
-
if (back1.type === BindingTag) {
|
|
752
|
-
bindingTag = property.binding && back1;
|
|
753
|
-
referenceTag = back2;
|
|
754
|
-
foundShift = foundBinding = true;
|
|
755
|
-
} else if (back1.type === ReferenceTag) {
|
|
756
|
-
bindingTag = property.binding && buildChild(BindingTag, property.binding);
|
|
757
|
-
referenceTag = back1;
|
|
758
|
-
foundShift = true;
|
|
759
|
-
} else {
|
|
760
|
-
bindingTag = property.binding && buildChild(BindingTag, property.binding);
|
|
761
|
-
referenceTag = buildChild(ReferenceTag, property.reference);
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
if (!referenceTag) throw new Error();
|
|
765
|
-
|
|
766
|
-
if (isInitializer) {
|
|
767
|
-
if (property.reference.name) {
|
|
768
|
-
addToProperties(node.properties, property);
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
if (!foundShift) {
|
|
772
|
-
node.children = Children.push(node.children, referenceTag);
|
|
773
|
-
}
|
|
774
|
-
node.children = Children.push(node.children, buildInitializerTag(isArrayInitializer));
|
|
775
|
-
|
|
776
|
-
return;
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
if (property.reference.name) {
|
|
780
|
-
addToProperties(node.properties, property);
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
if (!foundShift) {
|
|
784
|
-
node.children = Children.push(node.children, referenceTag);
|
|
785
|
-
}
|
|
786
|
-
if (!foundBinding && bindingTag) {
|
|
787
|
-
node.children = Children.push(node.children, bindingTag);
|
|
788
|
-
}
|
|
789
|
-
node.children = Children.push(node.children, buildChild(Property, property));
|
|
790
|
-
|
|
791
|
-
return node;
|
|
792
|
-
};
|
|
793
|
-
|
|
794
|
-
export const shiftProperty = (node, property) => {
|
|
795
|
-
if (!node || !property) throw new Error();
|
|
796
|
-
if (!property.reference) throw new Error();
|
|
797
|
-
if (!Object.isFrozen(property)) throw new Error();
|
|
798
|
-
|
|
799
|
-
let back1 = Children.getAt(-1, node.children);
|
|
800
|
-
let back2 = Children.getAt(-2, node.children);
|
|
801
|
-
|
|
802
|
-
let shiftTag;
|
|
803
|
-
let bindingTag = null;
|
|
804
|
-
|
|
805
|
-
if (property.node === null) {
|
|
806
|
-
property.node = buildNullNode();
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
let { node: value } = property;
|
|
810
|
-
|
|
811
|
-
let isArrayInitializer = isArray(value);
|
|
812
|
-
let isInitializer = value === undefined || isArrayInitializer;
|
|
813
|
-
|
|
814
|
-
if (!isInitializer && !property.binding) {
|
|
815
|
-
throw new Error();
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
let foundShift = false;
|
|
819
|
-
let foundBinding = false;
|
|
820
|
-
if (back1.type === BindingTag) {
|
|
821
|
-
bindingTag = back1;
|
|
822
|
-
shiftTag = back2;
|
|
823
|
-
foundShift = foundBinding = true;
|
|
824
|
-
|
|
825
|
-
if (bindingTag.value !== property.binding) throw new Error();
|
|
826
|
-
} else if ([ShiftTag, ReferenceTag].includes(back1.type)) {
|
|
827
|
-
bindingTag = buildChild(BindingTag, property.binding);
|
|
828
|
-
shiftTag = back1;
|
|
829
|
-
foundShift = true;
|
|
830
|
-
} else {
|
|
831
|
-
bindingTag = buildChild(BindingTag, property.binding);
|
|
832
|
-
shiftTag = buildChild(ReferenceTag, property.reference);
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
if (!shiftTag) throw new Error();
|
|
836
|
-
|
|
837
|
-
if (isInitializer) {
|
|
838
|
-
shiftToProperties(node.properties, property);
|
|
839
|
-
|
|
840
|
-
if (!foundShift) {
|
|
841
|
-
node.children = Children.push(node.children, shiftTag);
|
|
842
|
-
}
|
|
843
|
-
node.children = Children.push(node.children, buildInitializerTag(isArrayInitializer));
|
|
844
|
-
|
|
845
|
-
return;
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
let shiftStack = node.properties[property.reference.name]?.node || btree.fromValues([]);
|
|
849
|
-
let stackSize = shiftStack && property.reference.flags.expression ? btree.getSize(shiftStack) : 0;
|
|
850
|
-
|
|
851
|
-
shiftToProperties(node.properties, property);
|
|
852
|
-
|
|
853
|
-
let index = shiftTag.type === ReferenceTag ? 1 : shiftTag.value.index + 1;
|
|
854
|
-
let height = btree.getSize(shiftStack) + 1;
|
|
855
|
-
|
|
856
|
-
let newShiftTag = stackSize ? buildShiftTag(index, height) : shiftTag;
|
|
857
|
-
|
|
858
|
-
if (!foundShift) {
|
|
859
|
-
node.children = Children.push(node.children, newShiftTag);
|
|
860
|
-
}
|
|
861
|
-
if (!foundBinding) {
|
|
862
|
-
node.children = Children.push(node.children, bindingTag);
|
|
863
|
-
}
|
|
864
|
-
node.children = Children.push(node.children, buildChild(Property, property));
|
|
865
|
-
|
|
866
|
-
return node;
|
|
867
|
-
};
|
|
868
|
-
|
|
869
|
-
export const add = (node, referenceTag, value, bindingTag) => {
|
|
870
|
-
let lastChild = Children.getAt(-1, node.children);
|
|
871
|
-
let reference = referenceTag.value;
|
|
872
|
-
let binding = bindingTag
|
|
873
|
-
? bindingTag.value
|
|
874
|
-
: lastChild.type === BindingTag
|
|
875
|
-
? lastChild.value
|
|
876
|
-
: buildBindingTag().value;
|
|
877
|
-
return addProperty(node, buildProperty(reference, binding, value));
|
|
878
|
-
};
|
|
879
|
-
|
|
880
|
-
export const shift = (node, referenceTag, value, bindingTag) => {
|
|
881
|
-
let lastChild = Children.getAt(-1, node.children);
|
|
882
|
-
let reference = referenceTag.value;
|
|
883
|
-
let binding = bindingTag
|
|
884
|
-
? bindingTag.value
|
|
885
|
-
: lastChild.type === BindingTag
|
|
886
|
-
? lastChild.value
|
|
887
|
-
: buildBindingTag().value;
|
|
888
|
-
return shiftProperty(node, buildProperty(reference, binding, value));
|
|
889
|
-
};
|