@bablr/agast-helpers 0.7.1 → 0.9.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 +110 -49
- package/lib/object.js +86 -0
- package/lib/path-facade.js +44 -0
- package/lib/path.js +780 -556
- package/lib/print.js +75 -97
- package/lib/shorthand.js +26 -1
- package/lib/stream.js +55 -163
- package/lib/symbols.js +6 -2
- package/lib/tags.js +236 -0
- package/lib/template.js +28 -37
- package/lib/tree.js +391 -213
- package/package.json +11 -6
- package/lib/sumtree.js +0 -62
package/lib/print.js
CHANGED
|
@@ -8,18 +8,17 @@ import {
|
|
|
8
8
|
NullTag,
|
|
9
9
|
InitializerTag,
|
|
10
10
|
LiteralTag,
|
|
11
|
+
AttributeDefinition,
|
|
12
|
+
BindingTag,
|
|
13
|
+
Document,
|
|
11
14
|
} from './symbols.js';
|
|
12
|
-
import {
|
|
15
|
+
import { referenceFlags } from './builders.js';
|
|
13
16
|
|
|
14
17
|
let { isInteger, isFinite } = Number;
|
|
15
18
|
let { isArray } = Array;
|
|
16
19
|
let isString = (val) => typeof val === 'string';
|
|
17
20
|
let isNumber = (val) => typeof val === 'number';
|
|
18
21
|
let isObject = (val) => val && typeof val === 'object' && !isArray(val);
|
|
19
|
-
let isFunction = (val) => typeof val === 'function';
|
|
20
|
-
|
|
21
|
-
let when = (condition, value) =>
|
|
22
|
-
condition ? (isFunction(value) ? value() : value) : { *[Symbol.iterator]() {} };
|
|
23
22
|
|
|
24
23
|
export const printArray = (arr) => `[${arr.map((v) => printExpression(v)).join(', ')}]`;
|
|
25
24
|
|
|
@@ -30,39 +29,6 @@ export const printObject = (obj) => {
|
|
|
30
29
|
: '{}';
|
|
31
30
|
};
|
|
32
31
|
|
|
33
|
-
export const printPropertyMatcher = (matcher) => {
|
|
34
|
-
let { refMatcher, nodeMatcher } = matcher;
|
|
35
|
-
let ref = { type: ReferenceTag, value: refMatcher };
|
|
36
|
-
let refPart = refMatcher && !isEmptyReference(ref) ? `${printReferenceTag(ref)} ` : '';
|
|
37
|
-
let nodePart;
|
|
38
|
-
|
|
39
|
-
if (isArray(nodeMatcher)) {
|
|
40
|
-
if (nodeMatcher.length) throw new Error();
|
|
41
|
-
nodePart = '[]';
|
|
42
|
-
} else if (isGapNode(nodeMatcher)) {
|
|
43
|
-
nodePart = '<//>';
|
|
44
|
-
} else if (isNullNode(nodeMatcher)) {
|
|
45
|
-
nodePart = 'null';
|
|
46
|
-
} else {
|
|
47
|
-
nodePart = printOpenNodeMatcher(nodeMatcher);
|
|
48
|
-
}
|
|
49
|
-
return `${refPart}${nodePart}`;
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
export const printOpenNodeMatcher = (matcher) => {
|
|
53
|
-
let { flags, language: tagLanguage, type, attributes, intrinsicValue } = matcher;
|
|
54
|
-
|
|
55
|
-
let printedAttributes = printAttributes(attributes);
|
|
56
|
-
let attributesFrag = printedAttributes ? ` ${printedAttributes}` : '';
|
|
57
|
-
|
|
58
|
-
let intrinsicFrag = intrinsicValue
|
|
59
|
-
? ` ${isString(intrinsicValue) ? printExpression(intrinsicValue) : printSource(intrinsicValue)}`
|
|
60
|
-
: '';
|
|
61
|
-
let typeFrag = type !== Symbol.for('@bablr/fragment') ? printTagPath(tagLanguage, type) : ' ';
|
|
62
|
-
|
|
63
|
-
return `<${printNodeFlags(flags)}${typeFrag}${intrinsicFrag}${attributesFrag}/>`;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
32
|
export const printExpression = (expr) => {
|
|
67
33
|
if (isString(expr)) {
|
|
68
34
|
return printString(expr);
|
|
@@ -91,19 +57,8 @@ export const printAttributes = (attributes) => {
|
|
|
91
57
|
return !printed || printed === '{}' ? '' : printed;
|
|
92
58
|
};
|
|
93
59
|
|
|
94
|
-
export const
|
|
95
|
-
|
|
96
|
-
return printSingleString(language);
|
|
97
|
-
} else {
|
|
98
|
-
return language.join('.');
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
export const printTagPath = (language, type) => {
|
|
103
|
-
return [
|
|
104
|
-
...when(type && language?.length, () => [printLanguage(language)]),
|
|
105
|
-
...when(type, [printType(type)]),
|
|
106
|
-
].join(':');
|
|
60
|
+
export const printIdentifierPath = (path) => {
|
|
61
|
+
return path.map(printIdentifier).join('.');
|
|
107
62
|
};
|
|
108
63
|
|
|
109
64
|
let escapeReplacer = (esc) => {
|
|
@@ -122,6 +77,14 @@ let escapeReplacer = (esc) => {
|
|
|
122
77
|
}
|
|
123
78
|
};
|
|
124
79
|
|
|
80
|
+
export const printIdentifier = (id) => {
|
|
81
|
+
return /^[a-zA-Z\u{80}-\u{10ffff}][a-zA-Z\u{80}-\u{10ffff}0-9_-]+$/u.test(id)
|
|
82
|
+
? id
|
|
83
|
+
: `\`${id
|
|
84
|
+
.replace(/[`\\]/g, '\\`')
|
|
85
|
+
.replace(/[\x00-\x20\x7f]/g, (value) => `\\u00${value.toString(16)}`)}\``;
|
|
86
|
+
};
|
|
87
|
+
|
|
125
88
|
export const printSingleString = (str) => {
|
|
126
89
|
return `'${str.replace(/['\\\0\r\n\t\u0000-\u001A]/g, escapeReplacer)}'`;
|
|
127
90
|
};
|
|
@@ -156,13 +119,27 @@ export const printShiftTag = (tag) => {
|
|
|
156
119
|
return `^^^`;
|
|
157
120
|
};
|
|
158
121
|
|
|
159
|
-
export const
|
|
160
|
-
|
|
122
|
+
export const printReference = (ref) => {
|
|
123
|
+
let { type, name, isArray, flags } = ref;
|
|
124
|
+
let pathBraces = isArray ? `[]` : '';
|
|
161
125
|
|
|
162
|
-
|
|
163
|
-
|
|
126
|
+
if (type && type !== '#' && name) throw new Error();
|
|
127
|
+
if (type && !['.', '#', '@', '_'].includes(type)) throw new Error();
|
|
164
128
|
|
|
165
|
-
return `${name || ''}${pathBraces}${printReferenceFlags(flags)}:`;
|
|
129
|
+
return `${type || ''}${printIdentifier(name) || ''}${pathBraces}${printReferenceFlags(flags)}:`;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export const printBinding = (binding) => {
|
|
133
|
+
let { languagePath } = binding;
|
|
134
|
+
return `:${languagePath ? printIdentifierPath(languagePath) : ''}:`;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
export const printReferenceTag = (tag) => {
|
|
138
|
+
return printReference(tag.value);
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
export const printBindingTag = (tag) => {
|
|
142
|
+
return printBinding(tag.value);
|
|
166
143
|
};
|
|
167
144
|
|
|
168
145
|
export const printNullTag = (tag) => {
|
|
@@ -177,7 +154,7 @@ export const printType = (type) => {
|
|
|
177
154
|
return typeof type === 'string'
|
|
178
155
|
? type
|
|
179
156
|
: typeof type === 'symbol'
|
|
180
|
-
? type.description
|
|
157
|
+
? printIdentifier(type.description)
|
|
181
158
|
: String(type);
|
|
182
159
|
};
|
|
183
160
|
|
|
@@ -207,40 +184,47 @@ export const printReferenceFlags = (flags = referenceFlags) => {
|
|
|
207
184
|
|
|
208
185
|
export const printNodeFlags = (flags) => {
|
|
209
186
|
if (flags.cover && !flags.fragment) throw new Error();
|
|
187
|
+
|
|
210
188
|
let star = flags.token ? '*' : '';
|
|
211
189
|
let dollar = flags.hasGap ? '$' : '';
|
|
190
|
+
let fragment = flags.fragment ? '_' : '';
|
|
191
|
+
let multiFragment = fragment && !flags.cover ? '_' : '';
|
|
212
192
|
|
|
213
|
-
return `${star}${dollar}`;
|
|
193
|
+
return `${star}${dollar}${fragment}${multiFragment}`;
|
|
214
194
|
};
|
|
215
195
|
|
|
216
196
|
export const printOpenNodeTag = (tag) => {
|
|
217
197
|
if (tag?.type !== OpenNodeTag) throw new Error();
|
|
218
198
|
|
|
219
|
-
let { flags,
|
|
199
|
+
let { flags, type, literalValue, attributes, selfClosing } = tag.value;
|
|
200
|
+
|
|
201
|
+
if (!type && !flags.fragment) throw new Error();
|
|
202
|
+
if (literalValue && !selfClosing) throw new Error();
|
|
220
203
|
|
|
221
204
|
if (!type) {
|
|
222
|
-
return `<${printNodeFlags(flags)}
|
|
205
|
+
return `<${printNodeFlags(flags)}>`;
|
|
223
206
|
}
|
|
224
207
|
|
|
225
208
|
let printedAttributes = printAttributes(attributes);
|
|
226
209
|
let attributesFrag = printedAttributes ? ` ${printedAttributes}` : '';
|
|
210
|
+
let literalFrag = literalValue ? ` ${printString(literalValue)}` : '';
|
|
211
|
+
let selfClosingFrag = selfClosing ? ' /' : '';
|
|
227
212
|
|
|
228
|
-
return `<${printNodeFlags(flags)}${
|
|
213
|
+
return `<${printNodeFlags(flags)}${printType(
|
|
214
|
+
type,
|
|
215
|
+
)}${literalFrag}${attributesFrag}${selfClosingFrag}>`;
|
|
229
216
|
};
|
|
230
217
|
|
|
231
|
-
export const printSelfClosingNodeTag = (tag,
|
|
218
|
+
export const printSelfClosingNodeTag = (tag, literalValue) => {
|
|
232
219
|
if (tag?.type !== OpenNodeTag) throw new Error();
|
|
233
220
|
|
|
234
|
-
let { flags,
|
|
221
|
+
let { flags, type, attributes } = tag.value;
|
|
235
222
|
|
|
236
223
|
let printedAttributes = printAttributes(attributes);
|
|
237
224
|
let attributesFrag = printedAttributes ? ` ${printedAttributes}` : '';
|
|
238
|
-
let intrinsicFrag =
|
|
225
|
+
let intrinsicFrag = literalValue ? ` ${printString(literalValue)}` : '';
|
|
239
226
|
|
|
240
|
-
return `<${printNodeFlags(flags)}${
|
|
241
|
-
tagLanguage,
|
|
242
|
-
type,
|
|
243
|
-
)}${intrinsicFrag}${attributesFrag} />`;
|
|
227
|
+
return `<${printNodeFlags(flags)}${printType(type)}${intrinsicFrag}${attributesFrag} />`;
|
|
244
228
|
};
|
|
245
229
|
|
|
246
230
|
export const printCloseNodeTag = (tag) => {
|
|
@@ -249,38 +233,32 @@ export const printCloseNodeTag = (tag) => {
|
|
|
249
233
|
return `</>`;
|
|
250
234
|
};
|
|
251
235
|
|
|
252
|
-
export const
|
|
253
|
-
if (
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
case NullTag:
|
|
257
|
-
return printNullTag(tag);
|
|
236
|
+
export const printAttributeDefinition = (tag) => {
|
|
237
|
+
if (tag?.type !== AttributeDefinition) throw new Error();
|
|
238
|
+
if (!tag.value.path?.length) throw new Error();
|
|
239
|
+
let { path, value } = tag.value;
|
|
258
240
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
case InitializerTag:
|
|
263
|
-
return printInitializerTag(tag);
|
|
264
|
-
|
|
265
|
-
case ShiftTag:
|
|
266
|
-
return printShiftTag(tag);
|
|
267
|
-
|
|
268
|
-
case LiteralTag:
|
|
269
|
-
return printLiteralTag(tag);
|
|
270
|
-
|
|
271
|
-
case DoctypeTag:
|
|
272
|
-
return printDoctypeTag(tag);
|
|
241
|
+
return `{ ${printIdentifierPath(path)}: ${printExpression(value)} }`;
|
|
242
|
+
};
|
|
273
243
|
|
|
274
|
-
|
|
275
|
-
|
|
244
|
+
const printers = {
|
|
245
|
+
[NullTag]: printNullTag,
|
|
246
|
+
[GapTag]: printGapTag,
|
|
247
|
+
[BindingTag]: printBindingTag,
|
|
248
|
+
[InitializerTag]: printInitializerTag,
|
|
249
|
+
[ShiftTag]: printShiftTag,
|
|
250
|
+
[LiteralTag]: printLiteralTag,
|
|
251
|
+
[DoctypeTag]: printDoctypeTag,
|
|
252
|
+
[ReferenceTag]: printReferenceTag,
|
|
253
|
+
[OpenNodeTag]: printOpenNodeTag,
|
|
254
|
+
[CloseNodeTag]: printCloseNodeTag,
|
|
255
|
+
[AttributeDefinition]: printAttributeDefinition,
|
|
256
|
+
};
|
|
276
257
|
|
|
277
|
-
|
|
278
|
-
|
|
258
|
+
export const printTag = (tag) => {
|
|
259
|
+
if (!isObject(tag)) throw new Error();
|
|
279
260
|
|
|
280
|
-
|
|
281
|
-
return printCloseNodeTag(tag);
|
|
261
|
+
let printer = printers[tag?.type];
|
|
282
262
|
|
|
283
|
-
|
|
284
|
-
throw new Error();
|
|
285
|
-
}
|
|
263
|
+
return printer(tag);
|
|
286
264
|
};
|
package/lib/shorthand.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
buildLiteralTag,
|
|
7
7
|
buildInitializerTag,
|
|
8
8
|
} from './builders.js';
|
|
9
|
-
import {
|
|
9
|
+
import { buildReferenceTag, treeFromStreamSync } from './tree.js';
|
|
10
10
|
|
|
11
11
|
export * from './builders.js';
|
|
12
12
|
|
|
@@ -23,6 +23,31 @@ const stripArray = (val) => {
|
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
+
export const parseReference = (str) => {
|
|
27
|
+
let {
|
|
28
|
+
1: type,
|
|
29
|
+
2: name,
|
|
30
|
+
3: isArray,
|
|
31
|
+
4: index,
|
|
32
|
+
5: expressionToken,
|
|
33
|
+
6: hasGapToken,
|
|
34
|
+
} = /^\s*(?:([.#@_])|([a-zA-Z\u{80}-\u{10ffff}][a-zA-Z0-9_\u{80}-\u{10ffff}-]*))\s*(\[\s*(\d+\s*)?\])?\s*(\+)?(\$)?\s*$/u.exec(
|
|
35
|
+
str,
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
let flags = {
|
|
39
|
+
expression: !!expressionToken,
|
|
40
|
+
hasGap: !!hasGapToken,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
index = index ? parseInt(index, 10) : null;
|
|
44
|
+
isArray = !!isArray;
|
|
45
|
+
type = type || null;
|
|
46
|
+
name = name || null;
|
|
47
|
+
|
|
48
|
+
return buildReferenceTag(type, name, isArray, flags, index);
|
|
49
|
+
};
|
|
50
|
+
|
|
26
51
|
export const ref = (path) => {
|
|
27
52
|
return parseReference(isArray(path) ? path[0] : path);
|
|
28
53
|
};
|
package/lib/stream.js
CHANGED
|
@@ -1,147 +1,25 @@
|
|
|
1
1
|
import { Coroutine } from '@bablr/coroutine';
|
|
2
2
|
import emptyStack from '@iter-tools/imm-stack';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { getStreamIterator, StreamIterable, StreamGenerator } from '@bablr/stream-iterator';
|
|
4
|
+
import { printTag } from './print.js';
|
|
5
|
+
import { buildOpenNodeTag } from './builders.js';
|
|
5
6
|
import {
|
|
6
|
-
DoctypeTag,
|
|
7
7
|
OpenNodeTag,
|
|
8
8
|
CloseNodeTag,
|
|
9
9
|
ReferenceTag,
|
|
10
|
-
ShiftTag,
|
|
11
10
|
GapTag,
|
|
12
11
|
NullTag,
|
|
13
12
|
InitializerTag,
|
|
14
13
|
LiteralTag,
|
|
15
|
-
|
|
14
|
+
BindingTag,
|
|
15
|
+
DoctypeTag,
|
|
16
|
+
ShiftTag,
|
|
17
|
+
AttributeDefinition,
|
|
16
18
|
} from './symbols.js';
|
|
17
19
|
|
|
18
|
-
export
|
|
19
|
-
|
|
20
|
-
export const getStreamIterator = (obj) => {
|
|
21
|
-
return obj[Symbol.for('@@streamIterator')]?.() || obj[Symbol.iterator]?.();
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export class SyncGenerator {
|
|
25
|
-
constructor(embeddedGenerator) {
|
|
26
|
-
if (!embeddedGenerator.next) throw new Error();
|
|
27
|
-
|
|
28
|
-
this.generator = embeddedGenerator;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
next(value) {
|
|
32
|
-
const step = this.generator.next(value);
|
|
33
|
-
|
|
34
|
-
if (step instanceof Promise) {
|
|
35
|
-
throw new Error('invalid embedded generator');
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (step.done) {
|
|
39
|
-
return step;
|
|
40
|
-
} else if (step.value instanceof Promise) {
|
|
41
|
-
throw new Error('sync generators cannot resolve promises');
|
|
42
|
-
} else {
|
|
43
|
-
return step;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return(value) {
|
|
48
|
-
const step = this.generator.return(value);
|
|
49
|
-
if (step instanceof Promise) {
|
|
50
|
-
throw new Error('invalid embedded generator');
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (step.value instanceof Promise) {
|
|
54
|
-
throw new Error('sync generators cannot resolve promises');
|
|
55
|
-
}
|
|
56
|
-
return step;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
[Symbol.iterator]() {
|
|
60
|
-
return this;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export class AsyncGenerator {
|
|
65
|
-
constructor(embeddedGenerator) {
|
|
66
|
-
this.generator = embeddedGenerator;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
next(value) {
|
|
70
|
-
const step = this.generator.next(value);
|
|
71
|
-
|
|
72
|
-
if (step instanceof Promise) {
|
|
73
|
-
throw new Error('invalid embedded generator');
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (step.done) {
|
|
77
|
-
return Promise.resolve(step);
|
|
78
|
-
} else if (step.value instanceof Promise) {
|
|
79
|
-
return step.value.then((value) => {
|
|
80
|
-
return this.next(value);
|
|
81
|
-
});
|
|
82
|
-
} else {
|
|
83
|
-
return Promise.resolve(step);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return(value) {
|
|
88
|
-
const result = this.generator.return(value);
|
|
89
|
-
if (result instanceof Promise) {
|
|
90
|
-
throw new Error('sync generators cannot resolve promises');
|
|
91
|
-
}
|
|
92
|
-
return result;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
[Symbol.asyncIterator]() {
|
|
96
|
-
return this;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export class StreamGenerator {
|
|
101
|
-
constructor(embeddedGenerator) {
|
|
102
|
-
this.generator = embeddedGenerator;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
next(value) {
|
|
106
|
-
const step = this.generator.next(value);
|
|
107
|
-
|
|
108
|
-
if (step.done) {
|
|
109
|
-
return step;
|
|
110
|
-
} else if (step.value instanceof Promise) {
|
|
111
|
-
return step.value.then((value) => {
|
|
112
|
-
return this.next(value);
|
|
113
|
-
});
|
|
114
|
-
} else {
|
|
115
|
-
return step;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return(value) {
|
|
120
|
-
return this.generator.return(value);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
[Symbol.for('@@streamIterator')]() {
|
|
124
|
-
return this;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export class StreamIterable {
|
|
129
|
-
constructor(embeddedStreamIterable) {
|
|
130
|
-
this.iterable = embeddedStreamIterable;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
[Symbol.iterator]() {
|
|
134
|
-
return new SyncGenerator(this.iterable);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
[Symbol.asyncIterator]() {
|
|
138
|
-
return new AsyncGenerator(this.iterable);
|
|
139
|
-
}
|
|
20
|
+
export { getStreamIterator, StreamIterable, StreamGenerator };
|
|
140
21
|
|
|
141
|
-
|
|
142
|
-
return new StreamGenerator(this.iterable);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
22
|
+
export * from './print.js';
|
|
145
23
|
|
|
146
24
|
export const maybeWait = (maybePromise, callback) => {
|
|
147
25
|
if (maybePromise instanceof Promise) {
|
|
@@ -175,7 +53,9 @@ function* __isEmpty(tags) {
|
|
|
175
53
|
case OpenNodeTag:
|
|
176
54
|
++depth;
|
|
177
55
|
|
|
178
|
-
if (
|
|
56
|
+
if (tag.value.literalValue) return false;
|
|
57
|
+
|
|
58
|
+
if (depth === 0 && ref.value.type === '@') {
|
|
179
59
|
return false;
|
|
180
60
|
}
|
|
181
61
|
|
|
@@ -218,9 +98,9 @@ export const asyncStringFromStream = async (stream) => {
|
|
|
218
98
|
|
|
219
99
|
if (co.done) break;
|
|
220
100
|
|
|
221
|
-
const
|
|
101
|
+
const chr = co.value;
|
|
222
102
|
|
|
223
|
-
str +=
|
|
103
|
+
str += chr;
|
|
224
104
|
}
|
|
225
105
|
|
|
226
106
|
return str;
|
|
@@ -271,12 +151,7 @@ function* __generateCSTML(tags, options) {
|
|
|
271
151
|
continue;
|
|
272
152
|
}
|
|
273
153
|
|
|
274
|
-
|
|
275
|
-
const intrinsicValue = getCooked(tag.value);
|
|
276
|
-
yield* printSelfClosingNodeTag(tag.value[0], intrinsicValue);
|
|
277
|
-
} else {
|
|
278
|
-
yield* printTag(tag);
|
|
279
|
-
}
|
|
154
|
+
yield* printTag(tag);
|
|
280
155
|
|
|
281
156
|
prevTag = tag;
|
|
282
157
|
}
|
|
@@ -319,8 +194,17 @@ function* __prettyGroupTags(tags) {
|
|
|
319
194
|
|
|
320
195
|
if (
|
|
321
196
|
(tag.type === 'Effect' && tag.value.verb === 'write') ||
|
|
322
|
-
[
|
|
323
|
-
|
|
197
|
+
[
|
|
198
|
+
ReferenceTag,
|
|
199
|
+
DoctypeTag,
|
|
200
|
+
BindingTag,
|
|
201
|
+
GapTag,
|
|
202
|
+
NullTag,
|
|
203
|
+
InitializerTag,
|
|
204
|
+
ShiftTag,
|
|
205
|
+
AttributeDefinition,
|
|
206
|
+
].includes(tag.type) ||
|
|
207
|
+
(tag.type === OpenNodeTag && (!tag.value.type || ref?.value.type === '@'))
|
|
324
208
|
) {
|
|
325
209
|
state.broken = true;
|
|
326
210
|
|
|
@@ -338,8 +222,14 @@ function* __prettyGroupTags(tags) {
|
|
|
338
222
|
|
|
339
223
|
if (tag.type === CloseNodeTag) {
|
|
340
224
|
if (!state.broken && (isToken(state.open) || state.holding.length === 1)) {
|
|
341
|
-
state.holding.
|
|
342
|
-
|
|
225
|
+
let { flags, type, attributes } = state.holding[0].value;
|
|
226
|
+
|
|
227
|
+
let literal = state.holding
|
|
228
|
+
.slice(1)
|
|
229
|
+
.map((lit) => lit.value)
|
|
230
|
+
.join('');
|
|
231
|
+
|
|
232
|
+
yield buildOpenNodeTag(flags, type, attributes, literal, true);
|
|
343
233
|
} else {
|
|
344
234
|
if (state.holding.length) {
|
|
345
235
|
yield* state.holding;
|
|
@@ -352,14 +242,13 @@ function* __prettyGroupTags(tags) {
|
|
|
352
242
|
}
|
|
353
243
|
|
|
354
244
|
if (tag.type === OpenNodeTag) {
|
|
355
|
-
if (
|
|
356
|
-
states = states.push({ holding: [], broken: false, open: tag });
|
|
245
|
+
if (tag.value.literalValue) {
|
|
357
246
|
yield tag;
|
|
358
247
|
} else {
|
|
359
248
|
states = states.push({ holding: [tag], broken: false, open: tag });
|
|
360
|
-
}
|
|
361
249
|
|
|
362
|
-
|
|
250
|
+
state = states.value;
|
|
251
|
+
}
|
|
363
252
|
}
|
|
364
253
|
}
|
|
365
254
|
}
|
|
@@ -393,14 +282,19 @@ function* __generatePrettyCSTML(tags, options) {
|
|
|
393
282
|
continue;
|
|
394
283
|
}
|
|
395
284
|
|
|
285
|
+
if (tag.type === BindingTag && !tag.value.languagePath?.length) {
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
|
|
396
289
|
inline =
|
|
397
290
|
inlineOption &&
|
|
398
291
|
inline &&
|
|
399
292
|
ref &&
|
|
400
293
|
(tag.type === NullTag ||
|
|
401
294
|
tag.type === GapTag ||
|
|
295
|
+
tag.type === BindingTag ||
|
|
402
296
|
tag.type === InitializerTag ||
|
|
403
|
-
tag.type ===
|
|
297
|
+
(tag.type === OpenNodeTag && tag.value.selfClosing));
|
|
404
298
|
|
|
405
299
|
if (!first && !inline) {
|
|
406
300
|
yield* '\n';
|
|
@@ -413,18 +307,12 @@ function* __generatePrettyCSTML(tags, options) {
|
|
|
413
307
|
}
|
|
414
308
|
|
|
415
309
|
if (!inline) {
|
|
416
|
-
yield* indent.repeat(indentLevel);
|
|
310
|
+
yield* indent.repeat(Math.max(0, indentLevel));
|
|
417
311
|
} else {
|
|
418
312
|
yield* ' ';
|
|
419
313
|
}
|
|
420
314
|
|
|
421
|
-
|
|
422
|
-
ref = null;
|
|
423
|
-
const intrinsicValue = tag.value[0].value.flags.token ? getCooked(tag.value) : null;
|
|
424
|
-
yield* printSelfClosingNodeTag(tag.value[0], intrinsicValue);
|
|
425
|
-
} else {
|
|
426
|
-
yield* printTag(tag);
|
|
427
|
-
}
|
|
315
|
+
yield* printTag(tag);
|
|
428
316
|
|
|
429
317
|
if (tag.type === ReferenceTag) {
|
|
430
318
|
inline = true;
|
|
@@ -432,7 +320,7 @@ function* __generatePrettyCSTML(tags, options) {
|
|
|
432
320
|
}
|
|
433
321
|
|
|
434
322
|
if (tag.type === OpenNodeTag) {
|
|
435
|
-
indentLevel
|
|
323
|
+
indentLevel += tag.value.selfClosing ? 0 : 1;
|
|
436
324
|
}
|
|
437
325
|
|
|
438
326
|
first = false;
|
|
@@ -474,9 +362,9 @@ export const getCooked = (tags) => {
|
|
|
474
362
|
}
|
|
475
363
|
|
|
476
364
|
case OpenNodeTag: {
|
|
477
|
-
const { flags, attributes } = tag.value;
|
|
365
|
+
const { flags, attributes, literalValue, selfClosing } = tag.value;
|
|
478
366
|
|
|
479
|
-
depth
|
|
367
|
+
depth += selfClosing ? 0 : 1;
|
|
480
368
|
|
|
481
369
|
if (first) {
|
|
482
370
|
if (flags.token) {
|
|
@@ -486,16 +374,18 @@ export const getCooked = (tags) => {
|
|
|
486
374
|
}
|
|
487
375
|
}
|
|
488
376
|
|
|
489
|
-
if (!(ref.value.
|
|
377
|
+
if (!(ref.value.type === '#' || (ref.value.type === '@' && attributes.cooked))) {
|
|
490
378
|
throw new Error('cookable nodes must not contain other nodes');
|
|
491
379
|
}
|
|
492
380
|
|
|
493
|
-
if (ref.value.
|
|
381
|
+
if (ref.value.type === '@') {
|
|
494
382
|
const { cooked: cookedValue } = tag.value.attributes;
|
|
495
383
|
|
|
496
384
|
if (!cookedValue) throw new Error('cannot cook string: it contains uncooked escapes');
|
|
497
385
|
|
|
498
386
|
cooked += cookedValue;
|
|
387
|
+
} else if (literalValue) {
|
|
388
|
+
cooked += literalValue;
|
|
499
389
|
}
|
|
500
390
|
|
|
501
391
|
break;
|
|
@@ -533,7 +423,9 @@ export const printSource = (tags) => {
|
|
|
533
423
|
if (!tags) return printed;
|
|
534
424
|
|
|
535
425
|
for (const tag of tags) {
|
|
536
|
-
if (tag.type ===
|
|
426
|
+
if (tag.type === OpenNodeTag && tag.value.literalValue) {
|
|
427
|
+
printed += tag.value.literalValue;
|
|
428
|
+
} else if (tag.type === LiteralTag) {
|
|
537
429
|
printed += tag.value;
|
|
538
430
|
} else if (tag.type === GapTag) {
|
|
539
431
|
throw new Error('use generateSourceTextFor');
|
package/lib/symbols.js
CHANGED
|
@@ -4,10 +4,14 @@ export const CloseNodeTag = Symbol.for('CloseNodeTag');
|
|
|
4
4
|
export const ReferenceTag = Symbol.for('ReferenceTag');
|
|
5
5
|
export const ShiftTag = Symbol.for('ShiftTag');
|
|
6
6
|
export const GapTag = Symbol.for('GapTag');
|
|
7
|
+
export const BindingTag = Symbol.for('BindingTag');
|
|
7
8
|
export const NullTag = Symbol.for('NullTag');
|
|
8
9
|
export const InitializerTag = Symbol.for('InitializerTag');
|
|
10
|
+
export const AttributeDefinition = Symbol.for('AttributeDefinition');
|
|
9
11
|
export const LiteralTag = Symbol.for('LiteralTag');
|
|
10
12
|
|
|
11
|
-
export const
|
|
13
|
+
export const Document = Symbol.for('Document');
|
|
14
|
+
export const Node = Symbol.for('Node');
|
|
12
15
|
|
|
13
|
-
export const
|
|
16
|
+
export const Property = Symbol.for('Property');
|
|
17
|
+
export const PropertyWrapper = Symbol.for('PropertyWrapper');
|