@bablr/agast-helpers 0.8.0 → 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 CHANGED
@@ -1,4 +1,4 @@
1
- import * as btree from './btree.js';
1
+ import { isSymbol } from './object.js';
2
2
  import { printType } from './print.js';
3
3
  import {
4
4
  DoctypeTag,
@@ -10,56 +10,48 @@ import {
10
10
  NullTag,
11
11
  InitializerTag,
12
12
  LiteralTag,
13
- TokenGroup,
14
13
  AttributeDefinition,
15
14
  BindingTag,
15
+ Document,
16
16
  } from './symbols.js';
17
17
 
18
18
  const { freeze, hasOwn } = Object;
19
19
  const { isArray } = Array;
20
20
 
21
- function* relatedNodes(properties) {
22
- for (const value of Object.values(properties)) {
23
- if (isArray(value)) {
24
- for (let value of btree.traverse(value)) {
25
- yield value.node;
26
- }
27
- } else {
28
- yield value.node;
29
- }
30
- }
31
- }
32
-
33
- const find = (predicate, iterable) => {
34
- for (const value of iterable) {
35
- if (predicate(value)) return value;
36
- }
37
- };
38
-
39
- export const buildProperty = (reference, binding, node) => {
21
+ export const buildProperty = (reference, binding = null, node = undefined) => {
40
22
  if (node?.binding) throw new Error();
41
23
  if (!reference.flags) throw new Error();
42
- if (!isArray(node) && typeof node === 'object' && !hasOwn(node, 'properties')) throw new Error();
24
+ if (!isArray(node) && typeof node === 'object' && !hasOwn(node, 'tags')) throw new Error();
43
25
 
44
26
  if (reference.value) throw new Error();
45
27
 
46
28
  return freeze({ reference, binding, node });
47
29
  };
48
30
 
31
+ export const buildPropertyWrapper = (tags, property) => {
32
+ freeze(tags);
33
+ freeze(property);
34
+
35
+ if (![ReferenceTag, ShiftTag].includes(tags[0].type)) throw new Error();
36
+ if (property.node && !(tags[1]?.type === InitializerTag || tags.length === 3)) throw new Error();
37
+
38
+ return freeze({ tags, property });
39
+ };
40
+
41
+ export const buildDocument = (doctypeTag, fragment) => {
42
+ return freeze({ type: Document, value: freeze({ doctypeTag, fragment }) });
43
+ };
44
+
49
45
  export const buildFacadeProperty = (reference, binding, node) => {
50
46
  if (node?.binding) throw new Error();
51
47
  if (!reference.flags) throw new Error();
52
- if (!isArray(node) && typeof node === 'object' && !node.properties) throw new Error();
48
+ if (!isArray(node) && typeof node === 'object' && !node.tags) throw new Error();
53
49
 
54
50
  if (reference.value) throw new Error();
55
51
 
56
52
  return freeze({ reference, binding, node });
57
53
  };
58
54
 
59
- export const buildTokenGroup = (tokens) => {
60
- return freeze({ type: TokenGroup, value: tokens });
61
- };
62
-
63
55
  export const buildBeginningOfStreamToken = () => {
64
56
  return freeze({ type: Symbol.for('@bablr/beginning-of-stream'), value: undefined });
65
57
  };
@@ -71,7 +63,7 @@ export const buildReferenceTag = (
71
63
  flags = referenceFlags,
72
64
  index,
73
65
  ) => {
74
- if (type != null && !isString(type)) throw new Error();
66
+ if (type != null && !['.', '#', '@', '_'].includes(type)) throw new Error();
75
67
  if (name != null && !isString(name)) throw new Error();
76
68
  if (name == null && type == null) throw new Error();
77
69
  if (index) throw new Error();
@@ -86,12 +78,31 @@ export const buildReferenceTag = (
86
78
  });
87
79
  };
88
80
 
81
+ export const buildReference = (
82
+ type = null,
83
+ name = null,
84
+ isArray = false,
85
+ flags = referenceFlags,
86
+ index,
87
+ ) => {
88
+ return buildReferenceTag(type, name, isArray, flags, index).value;
89
+ };
90
+
89
91
  export const buildNullTag = () => {
90
92
  return freeze({ type: NullTag, value: undefined });
91
93
  };
92
94
 
95
+ export const buildInitializer = (isArray = false) => {
96
+ return freeze({ isArray });
97
+ };
98
+
93
99
  export const buildInitializerTag = (isArray = false) => {
94
- return freeze({ type: InitializerTag, value: freeze({ isArray }) });
100
+ return freeze({ type: InitializerTag, value: buildInitializer(isArray) });
101
+ };
102
+
103
+ export const buildBinding = (languagePath = []) => {
104
+ if (!isArray(languagePath)) throw new Error();
105
+ return freeze({ languagePath });
95
106
  };
96
107
 
97
108
  export const buildBindingTag = (languagePath = []) => {
@@ -100,6 +111,7 @@ export const buildBindingTag = (languagePath = []) => {
100
111
  };
101
112
 
102
113
  export const buildChild = (type, value) => {
114
+ if (!isSymbol(type)) throw new Error();
103
115
  return freeze({ type, value });
104
116
  };
105
117
 
@@ -113,22 +125,31 @@ export const buildShiftTag = (index, height) => {
113
125
  return freeze({ type: ShiftTag, value: freeze({ index, height }) });
114
126
  };
115
127
 
116
- export const buildDoctypeTag = (attributes = {}, version = 0) => {
128
+ export const buildDoctypeTag = (version = 0) => {
117
129
  return freeze({
118
130
  type: DoctypeTag,
119
- value: freeze({ doctype: 'cstml', version, attributes: freeze(attributes) }),
131
+ value: freeze({ doctype: 'cstml', version }),
120
132
  });
121
133
  };
122
134
 
123
- export const buildOpenNodeTag = (flags = nodeFlags, type = null, attributes = {}) => {
135
+ export const buildOpenNodeTag = (
136
+ flags = nodeFlags,
137
+ type = null,
138
+ attributes = {},
139
+ literalValue = null,
140
+ selfClosing = !!literalValue,
141
+ ) => {
124
142
  if (printType(type).startsWith('https://')) throw new Error();
143
+ if (literalValue && (!isString(literalValue) || !flags.token)) throw new Error();
125
144
 
126
145
  return freeze({
127
146
  type: OpenNodeTag,
128
147
  value: freeze({
129
148
  flags: freeze(flags),
130
149
  type: isString(type) ? Symbol.for(type) : type,
150
+ literalValue,
131
151
  attributes,
152
+ selfClosing,
132
153
  }),
133
154
  });
134
155
  };
@@ -145,6 +166,8 @@ export const buildLiteralTag = (value) => {
145
166
  };
146
167
 
147
168
  export const buildAttributeDefinition = (path, value) => {
169
+ if (!path?.length) throw new Error();
170
+ freeze(path);
148
171
  return freeze({ type: AttributeDefinition, value: freeze({ path, value }) });
149
172
  };
150
173
 
@@ -172,20 +195,15 @@ export const fragmentFlags = freeze({
172
195
  token: false,
173
196
  hasGap: false,
174
197
  fragment: true,
175
- cover: false,
198
+ cover: true,
176
199
  });
177
200
 
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
- };
201
+ export const multiFragmentFlags = freeze({
202
+ token: false,
203
+ hasGap: false,
204
+ fragment: true,
205
+ cover: false,
206
+ });
189
207
 
190
208
  export const tokenFlags = freeze({
191
209
  token: true,
@@ -1,4 +1,4 @@
1
- import { CloseNodeTag, ReferenceTag } from './symbols.js';
1
+ import { CloseNodeTag, OpenNodeTag, ReferenceTag } from './symbols.js';
2
2
 
3
3
  export function* allTagPathsFor(range, options = {}) {
4
4
  if (range == null) return;
@@ -6,29 +6,34 @@ export function* allTagPathsFor(range, options = {}) {
6
6
  const { unshift = false } = options;
7
7
  let startPath = range[0];
8
8
  let endPath = range[1];
9
- let path = startPath;
9
+ let tagPath = startPath;
10
10
 
11
- while (path) {
12
- if (path.inner && path.previousSibling.tag.type === ReferenceTag) {
13
- path = path.inner.tagPathAt(0);
11
+ while (tagPath) {
12
+ if (tagPath.inner && tagPath.previousSibling.tag.type === ReferenceTag) {
13
+ tagPath = tagPath.inner.tagPathAt(0);
14
14
  }
15
15
 
16
- if (path.path.depth < startPath.path.depth) {
16
+ if (tagPath.path.depth < startPath.path.depth) {
17
17
  return;
18
18
  }
19
19
 
20
- yield path;
20
+ yield tagPath;
21
21
 
22
- if (endPath && endPath.equalTo(path)) {
23
- return;
22
+ if (
23
+ tagPath.tag.type === CloseNodeTag ||
24
+ (tagPath.tag.type === OpenNodeTag && tagPath.tag.value.selfClosing)
25
+ ) {
26
+ let propPath = tagPath.path.parentPropertyPath;
27
+ if (endPath && propPath && endPath.equalTo(propPath.path.tagPathAt(propPath.tagsIndex, 2))) {
28
+ return;
29
+ }
24
30
  }
25
31
 
26
- let propPath = path.path.parent && path.path.parent.tagPathAt(path.path.referenceIndex + 2);
27
-
28
- if (endPath && path.tag.type === CloseNodeTag && propPath && endPath.equalTo(propPath)) {
32
+ if (endPath && endPath.equalTo(tagPath)) {
29
33
  return;
30
34
  }
31
- path = unshift ? path.nextUnshifted : path.next;
35
+
36
+ tagPath = unshift ? tagPath.nextUnshifted : tagPath.next;
32
37
  }
33
38
  }
34
39