@bablr/agast-helpers 0.9.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 +148 -95
- package/lib/path.js +1303 -437
- package/lib/print.js +66 -43
- package/lib/shorthand.js +17 -13
- package/lib/stream.js +433 -32
- package/lib/symbols.js +3 -2
- package/lib/tags.js +106 -57
- package/lib/template.js +44 -42
- package/lib/tree.js +59 -513
- package/package.json +3 -3
- package/lib/path-facade.js +0 -44
package/lib/tree.js
CHANGED
|
@@ -1,45 +1,37 @@
|
|
|
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,
|
|
16
|
-
|
|
17
|
-
buildReference,
|
|
18
|
-
multiFragmentFlags,
|
|
19
|
-
buildPropertyWrapper,
|
|
9
|
+
buildOpenFragmentTag,
|
|
20
10
|
} from './builders.js';
|
|
21
11
|
import {
|
|
22
12
|
printPrettyCSTML as printPrettyCSTMLFromStream,
|
|
23
13
|
printCSTML as printCSTMLFromStream,
|
|
24
14
|
printSource as printSourceFromStream,
|
|
25
|
-
|
|
15
|
+
treeFromStream,
|
|
16
|
+
treeFromStreamSync,
|
|
17
|
+
treeFromStreamAsync,
|
|
18
|
+
evaluateReturnSync,
|
|
19
|
+
evaluateReturnAsync,
|
|
26
20
|
} from './stream.js';
|
|
27
21
|
import {
|
|
28
|
-
DoctypeTag,
|
|
29
22
|
OpenNodeTag,
|
|
30
23
|
CloseNodeTag,
|
|
31
24
|
ReferenceTag,
|
|
32
25
|
GapTag,
|
|
33
|
-
NullTag,
|
|
34
|
-
InitializerTag,
|
|
35
26
|
LiteralTag,
|
|
36
27
|
AttributeDefinition,
|
|
37
28
|
BindingTag,
|
|
38
|
-
Property,
|
|
39
29
|
ShiftTag,
|
|
40
|
-
|
|
30
|
+
Property,
|
|
31
|
+
NullNode,
|
|
32
|
+
TreeNode,
|
|
33
|
+
GapNode,
|
|
41
34
|
} from './symbols.js';
|
|
42
|
-
import * as BTree from './btree.js';
|
|
43
35
|
import * as Tags from './tags.js';
|
|
44
36
|
export * from './builders.js';
|
|
45
37
|
export * from './print.js';
|
|
@@ -49,36 +41,37 @@ import {
|
|
|
49
41
|
has,
|
|
50
42
|
list,
|
|
51
43
|
TagPath,
|
|
52
|
-
|
|
53
|
-
isFragmentNode,
|
|
44
|
+
isCover,
|
|
54
45
|
isNullNode,
|
|
55
46
|
isGapNode,
|
|
56
47
|
getOpenTag,
|
|
57
48
|
getCloseTag,
|
|
58
49
|
getRoot,
|
|
59
|
-
|
|
60
|
-
isStubTag,
|
|
61
|
-
wrapperIsFull,
|
|
50
|
+
getTags,
|
|
62
51
|
} from './path.js';
|
|
63
|
-
import { isPlainObject } from './object.js';
|
|
52
|
+
import { freeze, isPlainObject } from './object.js';
|
|
64
53
|
|
|
65
54
|
export {
|
|
66
55
|
get,
|
|
67
56
|
getOr,
|
|
68
57
|
has,
|
|
69
58
|
list,
|
|
70
|
-
|
|
59
|
+
isCover,
|
|
71
60
|
isNullNode,
|
|
72
61
|
isGapNode,
|
|
73
62
|
getOpenTag,
|
|
74
63
|
getCloseTag,
|
|
75
64
|
getRoot,
|
|
76
|
-
|
|
65
|
+
treeFromStream,
|
|
66
|
+
treeFromStreamSync,
|
|
67
|
+
treeFromStreamAsync,
|
|
68
|
+
evaluateReturnSync,
|
|
69
|
+
evaluateReturnAsync,
|
|
77
70
|
};
|
|
78
71
|
|
|
79
|
-
export const buildToken = (
|
|
72
|
+
export const buildToken = (name, value, attributes = {}) => {
|
|
80
73
|
return treeFromStreamSync([
|
|
81
|
-
buildOpenNodeTag(tokenFlags,
|
|
74
|
+
buildOpenNodeTag(tokenFlags, name, null, attributes),
|
|
82
75
|
buildLiteralTag(value),
|
|
83
76
|
buildCloseNodeTag(),
|
|
84
77
|
]);
|
|
@@ -87,10 +80,9 @@ export const buildToken = (type, value, attributes = {}) => {
|
|
|
87
80
|
const isString = (str) => typeof str === 'string';
|
|
88
81
|
|
|
89
82
|
const { isArray } = Array;
|
|
90
|
-
const { freeze, hasOwn } = Object;
|
|
91
83
|
|
|
92
84
|
export const mergeReferences = (outer, inner) => {
|
|
93
|
-
let { type, name,
|
|
85
|
+
let { type, name, index, flags: { array, expression, intrinsic, hasGap } = {} } = outer;
|
|
94
86
|
|
|
95
87
|
if (
|
|
96
88
|
(name != null && inner.name != null && name !== inner.name) ||
|
|
@@ -99,13 +91,15 @@ export const mergeReferences = (outer, inner) => {
|
|
|
99
91
|
return inner;
|
|
100
92
|
}
|
|
101
93
|
|
|
102
|
-
|
|
94
|
+
array = !!(array || inner.flags.array);
|
|
103
95
|
expression = !!(expression || inner.flags.expression);
|
|
96
|
+
intrinsic = !!(intrinsic || inner.flags.intrinsic);
|
|
104
97
|
hasGap = !!(hasGap || inner.flags.hasGap);
|
|
105
98
|
name = type === '.' ? inner.name : name;
|
|
106
99
|
type = type === '.' ? inner.type : type;
|
|
107
100
|
|
|
108
|
-
return buildReferenceTag(type, name,
|
|
101
|
+
return buildReferenceTag(type, name, freeze({ array, expression, intrinsic, hasGap }), index)
|
|
102
|
+
.value;
|
|
109
103
|
};
|
|
110
104
|
|
|
111
105
|
export const mergeReferenceTags = (outer, inner) => {
|
|
@@ -114,297 +108,24 @@ export const mergeReferenceTags = (outer, inner) => {
|
|
|
114
108
|
return buildChild(ReferenceTag, value);
|
|
115
109
|
};
|
|
116
110
|
|
|
117
|
-
export const
|
|
118
|
-
|
|
119
|
-
return type === '.' && !isArray && !(flags.expression || flags.hasGap);
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
function* __treeFromStream(tags, options) {
|
|
123
|
-
let path = null;
|
|
124
|
-
let rootPath = null;
|
|
125
|
-
let held = null;
|
|
126
|
-
let doctype = null;
|
|
127
|
-
const co = new Coroutine(getStreamIterator(tags));
|
|
128
|
-
const expressionsCo = new Coroutine(getStreamIterator(options.expressions || []));
|
|
129
|
-
let referenceTag = null;
|
|
130
|
-
let bindingTag = null;
|
|
131
|
-
|
|
132
|
-
for (;;) {
|
|
133
|
-
co.advance();
|
|
134
|
-
|
|
135
|
-
if (co.current instanceof Promise) {
|
|
136
|
-
co.current = yield co.current;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
if (co.done) break;
|
|
140
|
-
|
|
141
|
-
const tag = co.value;
|
|
142
|
-
|
|
143
|
-
if (tag.type === 'Effect') {
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (tag.type === DoctypeTag) {
|
|
148
|
-
doctype = tag;
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (held && tag.type !== OpenNodeTag && tag.type !== GapTag) {
|
|
153
|
-
throw new Error('cannot eat this type of tag while holding');
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
let suppressTag = false;
|
|
157
|
-
|
|
158
|
-
switch (tag.type) {
|
|
159
|
-
case LiteralTag:
|
|
160
|
-
break;
|
|
161
|
-
|
|
162
|
-
case CloseNodeTag: {
|
|
163
|
-
let { node } = path;
|
|
164
|
-
if (!node.tags[1]) throw new Error();
|
|
165
|
-
break;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
case ReferenceTag: {
|
|
169
|
-
referenceTag = tag;
|
|
170
|
-
suppressTag = true;
|
|
171
|
-
break;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
case BindingTag: {
|
|
175
|
-
bindingTag = tag;
|
|
176
|
-
suppressTag = true;
|
|
177
|
-
break;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
case InitializerTag: {
|
|
181
|
-
add(path.node, referenceTag, []);
|
|
182
|
-
suppressTag = true;
|
|
183
|
-
referenceTag = null;
|
|
184
|
-
break;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
case NullTag:
|
|
188
|
-
case GapTag: {
|
|
189
|
-
if (!path) {
|
|
190
|
-
return buildStubNode(tag);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const isGap = tag.type === GapTag;
|
|
194
|
-
|
|
195
|
-
if (path.parent && referenceTag.type !== ReferenceTag) throw new Error();
|
|
196
|
-
|
|
197
|
-
let node = createNode(tag);
|
|
198
|
-
|
|
199
|
-
suppressTag = true;
|
|
200
|
-
|
|
201
|
-
if (isGap) {
|
|
202
|
-
if (held) {
|
|
203
|
-
node = held;
|
|
204
|
-
add(path.node, referenceTag, node, bindingTag);
|
|
205
|
-
} else if (!expressionsCo.done) {
|
|
206
|
-
expressionsCo.advance();
|
|
207
|
-
|
|
208
|
-
let outerReference = referenceTag;
|
|
209
|
-
|
|
210
|
-
if (!expressionsCo.done) {
|
|
211
|
-
node =
|
|
212
|
-
node == null
|
|
213
|
-
? buildStubNode(buildNullTag())
|
|
214
|
-
: expressionsCo.value == null
|
|
215
|
-
? buildStubNode(buildNullTag())
|
|
216
|
-
: expressionsCo.value;
|
|
217
|
-
|
|
218
|
-
if (isFragmentNode(node)) {
|
|
219
|
-
const parentNode = path.node;
|
|
220
|
-
|
|
221
|
-
let referenceTag;
|
|
222
|
-
let bindingTag;
|
|
223
|
-
|
|
224
|
-
for (const tag of Tags.traverse(node.tags)) {
|
|
225
|
-
switch (tag.type) {
|
|
226
|
-
case DoctypeTag: {
|
|
227
|
-
break;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
case OpenNodeTag: {
|
|
231
|
-
referenceTag = bindingTag = null;
|
|
232
|
-
if (!tag.value.type) {
|
|
233
|
-
break;
|
|
234
|
-
} else {
|
|
235
|
-
throw new Error();
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
case ReferenceTag:
|
|
240
|
-
referenceTag = tag;
|
|
241
|
-
break;
|
|
242
|
-
|
|
243
|
-
case InitializerTag: {
|
|
244
|
-
add(parentNode, mergeReferenceTags(outerReference, referenceTag), []);
|
|
245
|
-
break;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
case BindingTag: {
|
|
249
|
-
bindingTag = tag;
|
|
250
|
-
break;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
case GapTag:
|
|
254
|
-
case NullTag: {
|
|
255
|
-
add(
|
|
256
|
-
parentNode,
|
|
257
|
-
mergeReferenceTags(outerReference, referenceTag),
|
|
258
|
-
buildStubNode(tag),
|
|
259
|
-
bindingTag,
|
|
260
|
-
);
|
|
261
|
-
referenceTag = bindingTag = null;
|
|
262
|
-
break;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
default:
|
|
266
|
-
throw new Error();
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
} else {
|
|
270
|
-
if (path.node.flags.token) {
|
|
271
|
-
throw new Error('not implemented');
|
|
272
|
-
}
|
|
273
|
-
add(path.node, referenceTag, node, bindingTag ?? buildBindingTag());
|
|
274
|
-
}
|
|
275
|
-
} else {
|
|
276
|
-
if (!path.node.flags.token) {
|
|
277
|
-
add(path.node, referenceTag, node, bindingTag ?? buildBindingTag());
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
referenceTag = null;
|
|
284
|
-
held = isGap ? null : held;
|
|
285
|
-
|
|
286
|
-
if (!path.node.flags.token) {
|
|
287
|
-
path = { parent: path, node, depth: (path.depth ?? -1) + 1, arrays: new Set() };
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
break;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// case ShiftTag: {
|
|
294
|
-
// const { tags, properties } = path.node;
|
|
295
|
-
|
|
296
|
-
// let property = properties[ref.value.name];
|
|
297
|
-
// let node;
|
|
298
|
-
|
|
299
|
-
// if (ref.value.isArray) {
|
|
300
|
-
// ({ node } = btree.getAt(-1, property));
|
|
301
|
-
// properties[ref.value.name].pop();
|
|
302
|
-
// } else {
|
|
303
|
-
// ({ node } = property);
|
|
304
|
-
// properties[ref.value.name] = null;
|
|
305
|
-
// }
|
|
306
|
-
|
|
307
|
-
// held = node;
|
|
308
|
-
// break;
|
|
309
|
-
// }
|
|
310
|
-
|
|
311
|
-
case OpenNodeTag: {
|
|
312
|
-
const node = createNode(tag);
|
|
313
|
-
if (path) {
|
|
314
|
-
if (path) {
|
|
315
|
-
add(path.node, referenceTag, node, bindingTag ?? buildBindingTag());
|
|
316
|
-
referenceTag = null;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
path = { parent: path, node, depth: (path ? path.depth : -1) + 1, arrays: new Set() };
|
|
320
|
-
} else {
|
|
321
|
-
path = { parent: null, node, depth: 0, arrays: new Set() };
|
|
322
|
-
|
|
323
|
-
rootPath = path;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
suppressTag = true;
|
|
327
|
-
break;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
default: {
|
|
331
|
-
throw new Error();
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
if (!suppressTag) {
|
|
336
|
-
path.node.tags = Tags.push(path.node.tags, tag);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
switch (tag.type) {
|
|
340
|
-
case NullTag:
|
|
341
|
-
case GapTag:
|
|
342
|
-
case CloseNodeTag: {
|
|
343
|
-
const completedNode = path.node;
|
|
344
|
-
|
|
345
|
-
if (!(tag.type === GapTag && completedNode.flags.token)) {
|
|
346
|
-
finalizeNode(completedNode);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
if (tag.type === GapTag) {
|
|
350
|
-
if (path && completedNode.type === null && completedNode.flags.token) {
|
|
351
|
-
break;
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
path = path.parent;
|
|
356
|
-
break;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
if (path && path.node.type) {
|
|
362
|
-
throw new Error('imbalanced tag stack');
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
return rootPath.node;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
export const buildNullNode = () => {
|
|
369
|
-
return treeFromStreamSync([buildNullTag()]);
|
|
370
|
-
};
|
|
371
|
-
|
|
372
|
-
export const treeFromStream = (tags, options = {}) => __treeFromStream(tags, options);
|
|
111
|
+
export const documentFromStream = (tags, options) => {
|
|
112
|
+
throw new Error('not implemented');
|
|
373
113
|
|
|
374
|
-
|
|
375
|
-
return evaluateReturnSync(treeFromStream(tokens, options));
|
|
376
|
-
};
|
|
377
|
-
|
|
378
|
-
export const treeFromStreamAsync = async (tokens, options = {}) => {
|
|
379
|
-
return evaluateReturnAsync(treeFromStream(tokens, options));
|
|
380
|
-
};
|
|
381
|
-
|
|
382
|
-
export const evaluateReturnSync = (generator) => {
|
|
383
|
-
const co = new Coroutine(generator[Symbol.iterator]());
|
|
384
|
-
while (!co.done) co.advance();
|
|
385
|
-
return co.value;
|
|
386
|
-
};
|
|
114
|
+
// strip doctype tag off
|
|
387
115
|
|
|
388
|
-
|
|
389
|
-
const co = new Coroutine(getStreamIterator(generator));
|
|
390
|
-
while (!co.done) {
|
|
391
|
-
co.advance();
|
|
392
|
-
|
|
393
|
-
if (co.current instanceof Promise) {
|
|
394
|
-
co.current = await co.current;
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
return co.value;
|
|
116
|
+
// return buildChild(Document, freeze({ doctype, tree }));
|
|
398
117
|
};
|
|
399
118
|
|
|
400
119
|
export const isEmpty = (node) => {
|
|
401
|
-
|
|
120
|
+
if (node == null) return true;
|
|
121
|
+
|
|
122
|
+
for (const tag of Tags.traverse(getTags(node))) {
|
|
402
123
|
switch (tag.type) {
|
|
403
124
|
case Property: {
|
|
404
|
-
if (tag.value.reference.type === '@') {
|
|
125
|
+
if (tag.value.property.reference.type === '@') {
|
|
405
126
|
return false;
|
|
406
127
|
} else {
|
|
407
|
-
const property = tag.value;
|
|
128
|
+
const { property } = tag.value;
|
|
408
129
|
|
|
409
130
|
if (!isNullNode(property.node)) {
|
|
410
131
|
return false;
|
|
@@ -421,36 +142,15 @@ export const isEmpty = (node) => {
|
|
|
421
142
|
return true;
|
|
422
143
|
};
|
|
423
144
|
|
|
424
|
-
let buildGapProperty = () =>
|
|
425
|
-
buildProperty(buildReference('.'), buildBinding(), buildStubNode(buildGapTag()));
|
|
426
|
-
|
|
427
|
-
export const buildBounds = (
|
|
428
|
-
openBoundary = BTree.fromValues([buildGapProperty()]),
|
|
429
|
-
closeBoundary = openBoundary,
|
|
430
|
-
) => {
|
|
431
|
-
return freeze([openBoundary, closeBoundary]);
|
|
432
|
-
};
|
|
433
|
-
|
|
434
|
-
export const buildStubNode = (tag) => {
|
|
435
|
-
if (!isStubTag(tag)) throw new Error();
|
|
436
|
-
return freeze({
|
|
437
|
-
flags: nodeFlags,
|
|
438
|
-
type: null,
|
|
439
|
-
bounds: buildBounds(null, null),
|
|
440
|
-
tags: Tags.from(tag),
|
|
441
|
-
attributes: freeze({}),
|
|
442
|
-
});
|
|
443
|
-
};
|
|
444
|
-
|
|
445
145
|
export const streamFromTree = (tree, options = {}) => {
|
|
446
|
-
|
|
146
|
+
if (tree && !isPlainObject(tree)) throw new Error();
|
|
447
147
|
|
|
448
|
-
return __streamFromTree(null,
|
|
148
|
+
return __streamFromTree(null, tree, options);
|
|
449
149
|
};
|
|
450
150
|
|
|
451
151
|
function* __streamFromTree(doctypeTag, rootNode, options) {
|
|
452
152
|
const { unshift = false } = options;
|
|
453
|
-
if (!rootNode || !Tags.getSize(rootNode
|
|
153
|
+
if (!rootNode || !Tags.getSize(getTags(rootNode))) return;
|
|
454
154
|
|
|
455
155
|
let tagPath = TagPath.fromNode(rootNode, 0);
|
|
456
156
|
|
|
@@ -461,26 +161,24 @@ function* __streamFromTree(doctypeTag, rootNode, options) {
|
|
|
461
161
|
}
|
|
462
162
|
|
|
463
163
|
do {
|
|
464
|
-
if (tagPath.tag.type === OpenNodeTag && !tagPath.tag.value.
|
|
164
|
+
if (tagPath.tag.type === OpenNodeTag && !tagPath.tag.value.selfClosing) count++;
|
|
465
165
|
if (tagPath.tag.type === CloseNodeTag) count--;
|
|
466
166
|
|
|
467
167
|
if (
|
|
468
168
|
!(
|
|
469
169
|
tagPath.tag.type === AttributeDefinition ||
|
|
470
|
-
(tagPath.tag.type === BindingTag && !tagPath.tag.value.
|
|
170
|
+
(tagPath.tag.type === BindingTag && !tagPath.tag.value.segments?.length)
|
|
471
171
|
)
|
|
472
172
|
) {
|
|
473
173
|
yield tagPath.tag;
|
|
474
174
|
}
|
|
475
175
|
} while ((tagPath = unshift ? tagPath.nextUnshifted : tagPath.next));
|
|
476
176
|
|
|
477
|
-
if (count !== 0) throw new Error();
|
|
177
|
+
// if (count !== 0) throw new Error();
|
|
478
178
|
}
|
|
479
179
|
|
|
480
180
|
export const vcsStreamFromTree = (rootNode) => {
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
return __vcsStreamFromTree(rootNode_);
|
|
181
|
+
return __vcsStreamFromTree(rootNode);
|
|
484
182
|
};
|
|
485
183
|
|
|
486
184
|
function* __vcsStreamFromTree(rootNode) {
|
|
@@ -490,7 +188,7 @@ function* __vcsStreamFromTree(rootNode) {
|
|
|
490
188
|
let nodeShifted = false;
|
|
491
189
|
let i = 0;
|
|
492
190
|
let seenFirstProperty = false;
|
|
493
|
-
let node = Tags.getValues(rootNode.tags);
|
|
191
|
+
let node = Tags.getValues(rootNode.value.tags);
|
|
494
192
|
|
|
495
193
|
outer: while (node) {
|
|
496
194
|
while (i >= node.length) {
|
|
@@ -514,7 +212,7 @@ function* __vcsStreamFromTree(rootNode) {
|
|
|
514
212
|
if (isArray(child)) {
|
|
515
213
|
stack = { stack, agastNode, node, depth, i, nodeShifted, seenFirstProperty };
|
|
516
214
|
|
|
517
|
-
yield
|
|
215
|
+
yield buildOpenFragmentTag();
|
|
518
216
|
|
|
519
217
|
node = Tags.getValues(child);
|
|
520
218
|
depth++;
|
|
@@ -522,10 +220,12 @@ function* __vcsStreamFromTree(rootNode) {
|
|
|
522
220
|
} else {
|
|
523
221
|
let wrappedTag = child;
|
|
524
222
|
|
|
525
|
-
if (wrappedTag.type ===
|
|
223
|
+
if (wrappedTag.type === Property) {
|
|
526
224
|
for (let tag of wrappedTag.value.tags) {
|
|
527
225
|
switch (tag.type) {
|
|
528
|
-
case
|
|
226
|
+
case TreeNode:
|
|
227
|
+
case NullNode:
|
|
228
|
+
case GapNode: {
|
|
529
229
|
let replaceWithGap = nodeShifted && !seenFirstProperty;
|
|
530
230
|
|
|
531
231
|
if (replaceWithGap) {
|
|
@@ -536,11 +236,11 @@ function* __vcsStreamFromTree(rootNode) {
|
|
|
536
236
|
break;
|
|
537
237
|
} else {
|
|
538
238
|
stack = { stack, agastNode, node, depth, i, nodeShifted, seenFirstProperty: true };
|
|
539
|
-
node = Tags.getValues(tag.value.
|
|
239
|
+
node = Tags.getValues(tag.value.tags);
|
|
540
240
|
|
|
541
241
|
depth++;
|
|
542
242
|
i = 0;
|
|
543
|
-
agastNode = tag.value
|
|
243
|
+
agastNode = tag.value;
|
|
544
244
|
nodeShifted = wrappedTag.value.tags[0].type === ShiftTag;
|
|
545
245
|
seenFirstProperty = false;
|
|
546
246
|
continue outer;
|
|
@@ -573,11 +273,11 @@ function* __vcsStreamFromTree(rootNode) {
|
|
|
573
273
|
}
|
|
574
274
|
|
|
575
275
|
export const getCooked = (cookable) => {
|
|
576
|
-
if (!cookable || isGapNode(cookable
|
|
276
|
+
if (!cookable || isGapNode(cookable)) {
|
|
577
277
|
return '';
|
|
578
278
|
}
|
|
579
279
|
|
|
580
|
-
const tags = cookable
|
|
280
|
+
const tags = getTags(cookable) || cookable;
|
|
581
281
|
|
|
582
282
|
let cooked = '';
|
|
583
283
|
|
|
@@ -602,9 +302,9 @@ export const getCooked = (cookable) => {
|
|
|
602
302
|
case BindingTag:
|
|
603
303
|
break;
|
|
604
304
|
|
|
605
|
-
case
|
|
606
|
-
let { node, reference } = tag.value
|
|
607
|
-
let { attributes } = node;
|
|
305
|
+
case Property: {
|
|
306
|
+
let { node, reference } = tag.value;
|
|
307
|
+
let { attributes } = node.value;
|
|
608
308
|
|
|
609
309
|
if (reference.type === '@') {
|
|
610
310
|
let { cooked: cookedValue } = attributes;
|
|
@@ -618,6 +318,10 @@ export const getCooked = (cookable) => {
|
|
|
618
318
|
break;
|
|
619
319
|
}
|
|
620
320
|
|
|
321
|
+
case GapTag: {
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
|
|
621
325
|
case LiteralTag: {
|
|
622
326
|
cooked += tag.value;
|
|
623
327
|
break;
|
|
@@ -654,34 +358,6 @@ export const printSource = (tree) => {
|
|
|
654
358
|
|
|
655
359
|
export const sourceTextFor = printSource;
|
|
656
360
|
|
|
657
|
-
export const getRange = (node) => {
|
|
658
|
-
const { tags } = node;
|
|
659
|
-
let path = Path.from(node);
|
|
660
|
-
return Tags.getSize(tags) ? [TagPath.from(path, 0), TagPath.from(path, -1)] : null;
|
|
661
|
-
};
|
|
662
|
-
|
|
663
|
-
export const createNode = (openTag) => {
|
|
664
|
-
let bounds = buildBounds();
|
|
665
|
-
let literalTags = [];
|
|
666
|
-
let tags = openTag ? Tags.fromValues([openTag, ...literalTags]) : Tags.fromValues(literalTags);
|
|
667
|
-
let flags, type, attributes;
|
|
668
|
-
|
|
669
|
-
if (!openTag || openTag.type === GapTag || openTag.type === NullTag) {
|
|
670
|
-
flags = nodeFlags;
|
|
671
|
-
type = openTag && ([NullTag, GapTag].includes(openTag.type) ? null : openTag.type);
|
|
672
|
-
attributes = openTag?.attributes || {};
|
|
673
|
-
} else {
|
|
674
|
-
({ flags, type, attributes = {} } = openTag.value || {});
|
|
675
|
-
}
|
|
676
|
-
return { flags, type, bounds, tags, attributes };
|
|
677
|
-
};
|
|
678
|
-
|
|
679
|
-
export const finalizeNode = (node) => {
|
|
680
|
-
freeze(node);
|
|
681
|
-
freeze(node.attributes);
|
|
682
|
-
return node;
|
|
683
|
-
};
|
|
684
|
-
|
|
685
361
|
export const notNull = (node) => {
|
|
686
362
|
return node != null && !isNullNode(node);
|
|
687
363
|
};
|
|
@@ -689,133 +365,3 @@ export const notNull = (node) => {
|
|
|
689
365
|
export const isNull = (node) => {
|
|
690
366
|
return node == null || isNullNode(node);
|
|
691
367
|
};
|
|
692
|
-
|
|
693
|
-
export const addProperty = (node, property) => {
|
|
694
|
-
if (!node || !property) throw new Error();
|
|
695
|
-
if (!Object.isFrozen(property)) throw new Error();
|
|
696
|
-
|
|
697
|
-
if (property.node === null) {
|
|
698
|
-
throw new Error();
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
let { node: value, binding, reference } = property;
|
|
702
|
-
|
|
703
|
-
let isArrayInitializer = reference.type !== '_' && isArray(value);
|
|
704
|
-
let isInitializer = value === undefined || isArrayInitializer;
|
|
705
|
-
|
|
706
|
-
if (isArrayInitializer && value.length) throw new Error();
|
|
707
|
-
|
|
708
|
-
if (!isInitializer && property.node.type && !property.binding) {
|
|
709
|
-
throw new Error();
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
if (reference.type === '_') {
|
|
713
|
-
node.tags = Tags.push(node.tags, value);
|
|
714
|
-
return node;
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
let referenceTag = buildChild(ReferenceTag, reference);
|
|
718
|
-
let propertyWrapper;
|
|
719
|
-
|
|
720
|
-
if (isInitializer) {
|
|
721
|
-
let tags = freeze([referenceTag, buildInitializerTag(isArrayInitializer)]);
|
|
722
|
-
|
|
723
|
-
propertyWrapper = buildPropertyWrapper(
|
|
724
|
-
tags,
|
|
725
|
-
buildProperty(reference, null, isArrayInitializer ? [] : null),
|
|
726
|
-
);
|
|
727
|
-
} else {
|
|
728
|
-
let tags = freeze([
|
|
729
|
-
referenceTag,
|
|
730
|
-
buildChild(BindingTag, binding),
|
|
731
|
-
buildChild(Property, property),
|
|
732
|
-
]);
|
|
733
|
-
|
|
734
|
-
propertyWrapper = buildPropertyWrapper(tags, property);
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
let lastTag = Tags.getAt(-1, node.tags);
|
|
738
|
-
let unboundProperty = lastTag.type === PropertyWrapper && lastTag.value.tags.length < 3;
|
|
739
|
-
|
|
740
|
-
if (unboundProperty) {
|
|
741
|
-
node.tags = Tags.replaceAt(-1, node.tags, buildChild(PropertyWrapper, propertyWrapper));
|
|
742
|
-
} else {
|
|
743
|
-
node.tags = Tags.push(node.tags, buildChild(PropertyWrapper, propertyWrapper));
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
return node;
|
|
747
|
-
};
|
|
748
|
-
|
|
749
|
-
export const shiftProperty = (node, property) => {
|
|
750
|
-
if (!node || !property) throw new Error();
|
|
751
|
-
if (!property.reference) throw new Error();
|
|
752
|
-
if (!Object.isFrozen(property)) throw new Error();
|
|
753
|
-
|
|
754
|
-
if (property.node === null) {
|
|
755
|
-
property.node = buildNullNode();
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
let { node: value } = property;
|
|
759
|
-
|
|
760
|
-
let isArrayInitializer = isArray(value);
|
|
761
|
-
let isInitializer = value === undefined || isArrayInitializer;
|
|
762
|
-
|
|
763
|
-
if (isInitializer || !property.binding) {
|
|
764
|
-
throw new Error();
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
let existingProperty = Tags.getAt(-1, node.tags);
|
|
768
|
-
|
|
769
|
-
if (!wrapperIsFull(existingProperty)) {
|
|
770
|
-
existingProperty = Tags.getAt(-2, node.tags);
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
let existingRef = existingProperty?.value.tags[0];
|
|
774
|
-
|
|
775
|
-
let bindingTag = buildChild(BindingTag, property.binding);
|
|
776
|
-
|
|
777
|
-
let shiftStack = existingProperty?.value.property.node.bounds[0] || BTree.fromValues([]);
|
|
778
|
-
let stackSize = shiftStack && property.reference.flags.expression ? BTree.getSize(shiftStack) : 0;
|
|
779
|
-
|
|
780
|
-
let index = existingRef.type === ReferenceTag ? 1 : existingRef.value.index + 1;
|
|
781
|
-
let height = BTree.getSize(shiftStack) + 1;
|
|
782
|
-
|
|
783
|
-
let shiftTag = stackSize ? buildShiftTag(index, height) : existingRef;
|
|
784
|
-
|
|
785
|
-
let tags = freeze([shiftTag, bindingTag, buildChild(Property, property)]);
|
|
786
|
-
|
|
787
|
-
let lastTag = Tags.getAt(-1, node.tags);
|
|
788
|
-
let unboundProperty = lastTag.type === PropertyWrapper && lastTag.value.tags.length < 3;
|
|
789
|
-
|
|
790
|
-
let propertyWrapper = buildPropertyWrapper(tags, property);
|
|
791
|
-
|
|
792
|
-
if (unboundProperty) {
|
|
793
|
-
node.tags = Tags.replaceAt(-1, node.tags, buildChild(PropertyWrapper, propertyWrapper));
|
|
794
|
-
} else {
|
|
795
|
-
node.tags = Tags.push(node.tags, buildChild(PropertyWrapper, propertyWrapper));
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
return node;
|
|
799
|
-
};
|
|
800
|
-
|
|
801
|
-
export const add = (node, referenceTag, value, bindingTag) => {
|
|
802
|
-
let lastChild = Tags.getAt(-1, node.tags);
|
|
803
|
-
let reference = referenceTag.value;
|
|
804
|
-
let binding = bindingTag
|
|
805
|
-
? bindingTag.value
|
|
806
|
-
: lastChild?.type === BindingTag
|
|
807
|
-
? lastChild.value
|
|
808
|
-
: buildBinding();
|
|
809
|
-
return addProperty(node, buildProperty(reference, binding, value));
|
|
810
|
-
};
|
|
811
|
-
|
|
812
|
-
export const shift = (node, referenceTag, value, bindingTag) => {
|
|
813
|
-
let lastChild = Tags.getAt(-1, node.tags);
|
|
814
|
-
let reference = referenceTag.value;
|
|
815
|
-
let binding = bindingTag
|
|
816
|
-
? bindingTag.value
|
|
817
|
-
: lastChild.type === BindingTag
|
|
818
|
-
? lastChild.value
|
|
819
|
-
: buildBinding();
|
|
820
|
-
return shiftProperty(node, buildProperty(reference, binding, value));
|
|
821
|
-
};
|