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