@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/builders.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import emptyStack from '@iter-tools/imm-stack';
|
|
2
|
+
import { isObject, isSymbol } from './object.js';
|
|
3
3
|
import {
|
|
4
4
|
DoctypeTag,
|
|
5
5
|
OpenNodeTag,
|
|
@@ -8,98 +8,128 @@ import {
|
|
|
8
8
|
ShiftTag,
|
|
9
9
|
GapTag,
|
|
10
10
|
NullTag,
|
|
11
|
-
InitializerTag,
|
|
12
11
|
LiteralTag,
|
|
13
|
-
TokenGroup,
|
|
14
12
|
AttributeDefinition,
|
|
15
13
|
BindingTag,
|
|
14
|
+
Document,
|
|
15
|
+
Property,
|
|
16
|
+
NullNode,
|
|
17
|
+
GapNode,
|
|
18
|
+
TreeNode,
|
|
16
19
|
} from './symbols.js';
|
|
17
20
|
|
|
18
|
-
const { freeze
|
|
21
|
+
const { freeze } = Object;
|
|
19
22
|
const { isArray } = Array;
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
export const deepFreeze = (object) => {
|
|
25
|
+
let list = emptyStack.push(object);
|
|
26
|
+
while (list.size) {
|
|
27
|
+
let item = list.value;
|
|
28
|
+
list = list.pop();
|
|
29
|
+
|
|
30
|
+
for (const value of Object.values(item)) {
|
|
31
|
+
if (isObject(value)) {
|
|
32
|
+
list = list.push(value);
|
|
26
33
|
}
|
|
27
|
-
} else {
|
|
28
|
-
yield value.node;
|
|
29
34
|
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
35
|
|
|
33
|
-
|
|
34
|
-
for (const value of iterable) {
|
|
35
|
-
if (predicate(value)) return value;
|
|
36
|
+
Object.freeze(item);
|
|
36
37
|
}
|
|
37
38
|
};
|
|
38
39
|
|
|
39
|
-
export const buildProperty = (
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
if (!isArray(node) && typeof node === 'object' && !hasOwn(node, 'properties')) throw new Error();
|
|
40
|
+
export const buildProperty = (tags, shift) => {
|
|
41
|
+
if (shift && !shift.index) throw new Error();
|
|
42
|
+
freeze(tags);
|
|
43
43
|
|
|
44
|
-
if (
|
|
44
|
+
if (tags[0] && ![ReferenceTag, ShiftTag].includes(tags[0].type)) throw new Error();
|
|
45
|
+
if (tags.length > 1 && !isArray(tags[1])) throw new Error();
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
// if (property.node && !(tags.length === 3)) throw new Error();
|
|
48
|
+
// if (tags[0].type === ShiftTag && !property.shift) throw new Error();
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
if (
|
|
51
|
-
if (!reference.flags) throw new Error();
|
|
52
|
-
if (!isArray(node) && typeof node === 'object' && !node.properties) throw new Error();
|
|
50
|
+
if ((tags[0]?.type == ShiftTag) !== !!shift) throw new Error();
|
|
51
|
+
if (tags[2] && ![NullNode, GapNode, TreeNode].includes(tags[2].type)) throw new Error();
|
|
53
52
|
|
|
54
|
-
|
|
53
|
+
return freeze({
|
|
54
|
+
tags,
|
|
55
|
+
reference: tags[0]?.type === ShiftTag ? null : tags[0]?.value || buildReference(),
|
|
56
|
+
bindings: freeze(tags[1]?.map((tag) => tag.value) || []),
|
|
57
|
+
node: tags[2] || null,
|
|
58
|
+
shift: tags[0]?.type == ShiftTag ? shift : null,
|
|
59
|
+
});
|
|
60
|
+
};
|
|
55
61
|
|
|
56
|
-
|
|
62
|
+
export const buildPropertyTag = (tags, shift) => {
|
|
63
|
+
return freeze({ type: Property, value: buildProperty(tags, shift) });
|
|
57
64
|
};
|
|
58
65
|
|
|
59
|
-
export const
|
|
60
|
-
return freeze({ type:
|
|
66
|
+
export const buildDocument = (doctypeTag, tree) => {
|
|
67
|
+
return freeze({ type: Document, value: freeze({ doctypeTag, tree }) });
|
|
61
68
|
};
|
|
62
69
|
|
|
63
70
|
export const buildBeginningOfStreamToken = () => {
|
|
64
71
|
return freeze({ type: Symbol.for('@bablr/beginning-of-stream'), value: undefined });
|
|
65
72
|
};
|
|
66
73
|
|
|
67
|
-
export const buildReferenceTag = (
|
|
68
|
-
|
|
69
|
-
name = null,
|
|
70
|
-
isArray = false,
|
|
71
|
-
flags = referenceFlags,
|
|
72
|
-
index,
|
|
73
|
-
) => {
|
|
74
|
-
if (type != null && !isString(type)) throw new Error();
|
|
75
|
-
if (name != null && !isString(name)) throw new Error();
|
|
76
|
-
if (name == null && type == null) throw new Error();
|
|
77
|
-
if (index) throw new Error();
|
|
78
|
-
let { hasGap, expression } = flags;
|
|
79
|
-
|
|
80
|
-
hasGap = !!hasGap;
|
|
81
|
-
expression = !!expression;
|
|
82
|
-
|
|
74
|
+
export const buildReferenceTag = (type = null, name = null, flags = referenceFlags) => {
|
|
75
|
+
if (!Object.isFrozen(flags)) throw new Error();
|
|
83
76
|
return freeze({
|
|
84
77
|
type: ReferenceTag,
|
|
85
|
-
value:
|
|
78
|
+
value: buildReference(type, name, flags),
|
|
86
79
|
});
|
|
87
80
|
};
|
|
88
81
|
|
|
82
|
+
export const buildReference = (type = null, name = null, flags = referenceFlags) => {
|
|
83
|
+
if (type != null && !['_', '.', '#', '@'].includes(type)) throw new Error();
|
|
84
|
+
if (type && ['_', '#', '@'].includes(type) && (flags.intrinsic || flags.hasGap))
|
|
85
|
+
throw new Error();
|
|
86
|
+
if (name != null && (!isString(name) || !name)) throw new Error();
|
|
87
|
+
let { array, expression, intrinsic, hasGap } = flags;
|
|
88
|
+
|
|
89
|
+
array = !!array;
|
|
90
|
+
expression = !!expression;
|
|
91
|
+
intrinsic = !!intrinsic;
|
|
92
|
+
hasGap = !!hasGap;
|
|
93
|
+
|
|
94
|
+
let type_ = type == null && name == null ? '.' : type;
|
|
95
|
+
|
|
96
|
+
return freeze({ type: type_, name, flags: freeze({ array, expression, intrinsic, hasGap }) });
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const referenceFromMatcher = (matcher) => {
|
|
100
|
+
let { type, name, flags } = matcher;
|
|
101
|
+
return buildReference(type, name, flags);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export const buildShift = (index, height) => {
|
|
105
|
+
if (index == null || height == null) throw new Error();
|
|
106
|
+
return freeze({ index, height });
|
|
107
|
+
};
|
|
108
|
+
|
|
89
109
|
export const buildNullTag = () => {
|
|
90
110
|
return freeze({ type: NullTag, value: undefined });
|
|
91
111
|
};
|
|
92
112
|
|
|
93
|
-
export const
|
|
94
|
-
|
|
113
|
+
export const buildBinding = (segments = []) => {
|
|
114
|
+
// TODO relax this restriction
|
|
115
|
+
if (!isArray(segments) || !segments.length) throw new Error();
|
|
116
|
+
if (segments.includes(undefined)) throw new Error();
|
|
117
|
+
return freeze({
|
|
118
|
+
segments: segments.map((segment) =>
|
|
119
|
+
freeze(isString(segment) ? { type: null, name: segment } : segment),
|
|
120
|
+
),
|
|
121
|
+
});
|
|
95
122
|
};
|
|
96
123
|
|
|
97
|
-
export const buildBindingTag = (
|
|
98
|
-
|
|
99
|
-
|
|
124
|
+
export const buildBindingTag = (segments = []) => {
|
|
125
|
+
return freeze({
|
|
126
|
+
type: BindingTag,
|
|
127
|
+
value: buildBinding(segments),
|
|
128
|
+
});
|
|
100
129
|
};
|
|
101
130
|
|
|
102
131
|
export const buildChild = (type, value) => {
|
|
132
|
+
if (!isSymbol(type)) throw new Error();
|
|
103
133
|
return freeze({ type, value });
|
|
104
134
|
};
|
|
105
135
|
|
|
@@ -107,28 +137,74 @@ export const buildGapTag = () => {
|
|
|
107
137
|
return freeze({ type: GapTag, value: undefined });
|
|
108
138
|
};
|
|
109
139
|
|
|
110
|
-
export const buildShiftTag = (
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
140
|
+
export const buildShiftTag = () => {
|
|
141
|
+
let value = Object.defineProperties(
|
|
142
|
+
{},
|
|
143
|
+
{
|
|
144
|
+
index: {
|
|
145
|
+
get() {
|
|
146
|
+
throw new Error('moved');
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
height: {
|
|
150
|
+
get() {
|
|
151
|
+
throw new Error('moved');
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
);
|
|
156
|
+
return freeze({ type: ShiftTag, value });
|
|
114
157
|
};
|
|
115
158
|
|
|
116
|
-
export const buildDoctypeTag = (
|
|
159
|
+
export const buildDoctypeTag = (version = 0, attributes = Object.freeze({})) => {
|
|
117
160
|
return freeze({
|
|
118
161
|
type: DoctypeTag,
|
|
119
|
-
value: freeze({ doctype: 'cstml', version, attributes
|
|
162
|
+
value: freeze({ doctype: 'cstml', version, attributes }),
|
|
120
163
|
});
|
|
121
164
|
};
|
|
122
165
|
|
|
123
|
-
export const
|
|
124
|
-
|
|
166
|
+
export const buildOpenFragmentTag = (flags = nodeFlags, selfClosing = false) => {
|
|
167
|
+
return buildFullOpenNodeTag(flags, Symbol.for('__'), null, null, {}, selfClosing);
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
export const buildOpenCoverTag = (flags = nodeFlags, name = null, selfClosing = false) => {
|
|
171
|
+
return buildFullOpenNodeTag(flags, Symbol.for('_'), name, null, {}, selfClosing);
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
export const buildOpenNodeTag = (
|
|
175
|
+
flags,
|
|
176
|
+
name,
|
|
177
|
+
literalValue = null,
|
|
178
|
+
attributes = {},
|
|
179
|
+
selfClosing = !!literalValue,
|
|
180
|
+
) => {
|
|
181
|
+
if (!name && !flags.token) throw new Error();
|
|
182
|
+
return buildFullOpenNodeTag(flags, null, name, literalValue, attributes, selfClosing);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
export const buildFullOpenNodeTag = (
|
|
186
|
+
flags = nodeFlags,
|
|
187
|
+
type = Symbol.for('__'),
|
|
188
|
+
name = null,
|
|
189
|
+
literalValue = null,
|
|
190
|
+
attributes = {},
|
|
191
|
+
selfClosing = !!literalValue,
|
|
192
|
+
) => {
|
|
193
|
+
if (!isObject(attributes)) throw new Error();
|
|
194
|
+
if (literalValue && !isString(literalValue)) throw new Error();
|
|
195
|
+
if (!type && !name && !flags.token && !literalValue) throw new Error();
|
|
196
|
+
|
|
197
|
+
deepFreeze(attributes);
|
|
125
198
|
|
|
126
199
|
return freeze({
|
|
127
200
|
type: OpenNodeTag,
|
|
128
201
|
value: freeze({
|
|
129
202
|
flags: freeze(flags),
|
|
203
|
+
name: isString(name) ? Symbol.for(name) : name,
|
|
130
204
|
type: isString(type) ? Symbol.for(type) : type,
|
|
205
|
+
literalValue,
|
|
131
206
|
attributes,
|
|
207
|
+
selfClosing,
|
|
132
208
|
}),
|
|
133
209
|
});
|
|
134
210
|
};
|
|
@@ -144,8 +220,10 @@ export const buildLiteralTag = (value) => {
|
|
|
144
220
|
return freeze({ type: LiteralTag, value });
|
|
145
221
|
};
|
|
146
222
|
|
|
147
|
-
export const buildAttributeDefinition = (
|
|
148
|
-
|
|
223
|
+
export const buildAttributeDefinition = (key, value) => {
|
|
224
|
+
if (!key?.length) throw new Error();
|
|
225
|
+
freeze(key);
|
|
226
|
+
return freeze({ type: AttributeDefinition, value: freeze({ path: key, value }) });
|
|
149
227
|
};
|
|
150
228
|
|
|
151
229
|
const flagsWithGap = new WeakMap();
|
|
@@ -155,7 +233,10 @@ export const getFlagsWithGap = (flags, hasGap = true) => {
|
|
|
155
233
|
|
|
156
234
|
let gapFlags = flagsWithGap.get(flags);
|
|
157
235
|
if (!gapFlags) {
|
|
158
|
-
gapFlags = {
|
|
236
|
+
gapFlags = freeze({
|
|
237
|
+
token: flags.token,
|
|
238
|
+
hasGap,
|
|
239
|
+
});
|
|
159
240
|
flagsWithGap.set(flags, gapFlags);
|
|
160
241
|
}
|
|
161
242
|
return gapFlags;
|
|
@@ -164,47 +245,37 @@ export const getFlagsWithGap = (flags, hasGap = true) => {
|
|
|
164
245
|
export const nodeFlags = freeze({
|
|
165
246
|
token: false,
|
|
166
247
|
hasGap: false,
|
|
167
|
-
fragment: false,
|
|
168
|
-
cover: false,
|
|
169
248
|
});
|
|
170
249
|
|
|
171
|
-
export const fragmentFlags = freeze({
|
|
172
|
-
token: false,
|
|
173
|
-
hasGap: false,
|
|
174
|
-
fragment: true,
|
|
175
|
-
cover: false,
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
const hasGap = (properties) => {
|
|
179
|
-
return find((node) => node.flags.hasGap, relatedNodes(properties));
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
const getFlags = (flags, properties) => {
|
|
183
|
-
if (!hasGap(properties)) {
|
|
184
|
-
return flags;
|
|
185
|
-
} else {
|
|
186
|
-
return getFlagsWithGap(flags);
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
|
|
190
250
|
export const tokenFlags = freeze({
|
|
191
251
|
token: true,
|
|
192
252
|
hasGap: false,
|
|
193
|
-
fragment: false,
|
|
194
|
-
cover: false,
|
|
195
253
|
});
|
|
196
254
|
|
|
197
255
|
export const referenceFlags = freeze({
|
|
256
|
+
array: false,
|
|
257
|
+
expression: false,
|
|
258
|
+
intrinsic: false,
|
|
259
|
+
hasGap: false,
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
export const intrinsicReferenceFlags = freeze({
|
|
263
|
+
array: false,
|
|
198
264
|
expression: false,
|
|
265
|
+
intrinsic: true,
|
|
199
266
|
hasGap: false,
|
|
200
267
|
});
|
|
201
268
|
|
|
202
269
|
export const gapReferenceFlags = freeze({
|
|
270
|
+
array: false,
|
|
203
271
|
expression: false,
|
|
272
|
+
intrinsic: false,
|
|
204
273
|
hasGap: true,
|
|
205
274
|
});
|
|
206
275
|
|
|
207
276
|
export const expressionReferenceFlags = freeze({
|
|
277
|
+
array: false,
|
|
208
278
|
expression: true,
|
|
279
|
+
intrinsic: false,
|
|
209
280
|
hasGap: false,
|
|
210
281
|
});
|