tutuca 0.9.2 → 0.9.4

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/dist/tutuca.js CHANGED
@@ -1,1215 +1,648 @@
1
- // deps/vdom.js
2
- function isHtmlAttribute(propName) {
3
- return propName[4] === "-" && (propName[0] === "d" || propName[0] === "a");
4
- }
5
- function getDomProp(node, propName) {
6
- return node[propName];
7
- }
8
- function setDomProp(node, propName, value) {
9
- node[propName] = value;
10
- }
11
- function applyProperties(node, props, previous) {
12
- for (const propName in props) {
13
- const propValue = props[propName];
14
- if (propValue === undefined) {
15
- removeProperty(node, propName, previous);
16
- } else if (isHtmlAttribute(propName)) {
17
- node.setAttribute(propName, propValue);
18
- } else {
19
- if (typeof propValue === "object" && propValue !== null) {
20
- patchObject(node, previous, propName, propValue);
21
- } else {
22
- setDomProp(node, propName, propValue);
23
- }
24
- }
25
- }
26
- }
27
- function removeProperty(node, propName, previous) {
28
- const previousValue = previous[propName];
29
- if (isHtmlAttribute(propName)) {
30
- node.removeAttribute(propName);
31
- } else if (typeof previousValue === "string") {
32
- setDomProp(node, propName, "");
33
- const attrName = propName === "className" ? "class" : propName === "htmlFor" ? "for" : propName;
34
- node.removeAttribute(attrName);
35
- } else {
36
- setDomProp(node, propName, null);
37
- }
38
- }
39
- function patchObject(node, previous, propName, propValue) {
40
- const previousValue = previous?.[propName];
41
- if (previousValue && typeof previousValue === "object" && Object.getPrototypeOf(previousValue) !== Object.getPrototypeOf(propValue)) {
42
- setDomProp(node, propName, propValue);
43
- return;
44
- }
45
- let current = getDomProp(node, propName);
46
- if (typeof current !== "object" || current === null) {
47
- setDomProp(node, propName, {});
48
- current = getDomProp(node, propName);
1
+ // src/path.js
2
+ class Step {
3
+ lookup(_v, dval = null) {
4
+ return dval;
49
5
  }
50
- const target = current;
51
- for (const k in propValue) {
52
- target[k] = propValue[k];
6
+ setValue(root, _v) {
7
+ return root;
53
8
  }
9
+ updateBindings(_v, _o) {}
10
+ isFrame = true;
54
11
  }
55
12
 
56
- class Warning {
57
- type;
58
- message;
59
- constructor(type, message) {
60
- this.type = type;
61
- this.message = message;
13
+ class BindStep extends Step {
14
+ constructor(binds) {
15
+ super();
16
+ this.binds = binds;
62
17
  }
63
- }
64
-
65
- class DuplicatedKeysWarning extends Warning {
66
- duplicatedKeys;
67
- parentTag;
68
- parentIndex;
69
- constructor(duplicatedKeys, parentTag, parentIndex) {
70
- const keys = [...duplicatedKeys].join(", ");
71
- super("DuplicatedKeys", `Duplicate keys found: [${keys}] in ${parentTag || "fragment"} at index ${parentIndex}. Nodes with duplicated keys are matched positionally.`);
72
- this.duplicatedKeys = duplicatedKeys;
73
- this.parentTag = parentTag;
74
- this.parentIndex = parentIndex;
18
+ lookup(v, _dval) {
19
+ return v;
75
20
  }
76
- }
77
-
78
- class VBase {
79
- isEqualTo(other) {
80
- return this === other;
21
+ setValue(_root, v) {
22
+ return v;
81
23
  }
82
- toDom(_opts) {
83
- return null;
24
+ withIndex(i) {
25
+ return new BindStep({ ...this.binds, key: i });
84
26
  }
85
- }
86
- function getKey(node) {
87
- return node instanceof VNode ? node.key : undefined;
88
- }
89
- function effectiveKey(node, duplicatedKeys) {
90
- const key = getKey(node);
91
- return key && duplicatedKeys?.has(key) ? undefined : key;
92
- }
93
- function isIterable(obj) {
94
- return obj != null && typeof obj !== "string" && typeof obj[Symbol.iterator] === "function";
95
- }
96
- function addChild(normalizedChildren, child) {
97
- if (child == null) {
98
- return;
27
+ withKey(key) {
28
+ return new BindStep({ ...this.binds, key });
99
29
  }
100
- if (isIterable(child)) {
101
- for (const c of child) {
102
- addChild(normalizedChildren, c);
103
- }
104
- } else if (child instanceof VBase) {
105
- if (child instanceof VFragment) {
106
- normalizedChildren.push(...child.childs);
107
- } else {
108
- normalizedChildren.push(child);
109
- }
110
- } else {
111
- normalizedChildren.push(new VText(child));
30
+ updateBindings(_v, o) {
31
+ Object.assign(o, this.binds);
112
32
  }
33
+ isFrame = false;
113
34
  }
114
35
 
115
- class VText extends VBase {
116
- text;
117
- constructor(text) {
36
+ class FieldStep extends Step {
37
+ constructor(field) {
118
38
  super();
119
- this.text = String(text);
39
+ this.field = field;
120
40
  }
121
- get nodeType() {
122
- return 3;
41
+ lookup(v, dval = null) {
42
+ return v?.get ? v.get(this.field, dval) : dval;
123
43
  }
124
- isEqualTo(other) {
125
- return other instanceof VText && this.text === other.text;
44
+ setValue(root, v) {
45
+ return root.set(this.field, v);
126
46
  }
127
- toDom(opts) {
128
- return opts.document.createTextNode(this.text);
47
+ withIndex(i) {
48
+ return new SeqIndexStep(this.field, i);
49
+ }
50
+ withKey(k) {
51
+ return new SeqKeyStep(this.field, k);
129
52
  }
130
53
  }
131
54
 
132
- class VComment extends VBase {
133
- text;
134
- constructor(text) {
55
+ class FieldSeqStep extends Step {
56
+ constructor(field, key) {
135
57
  super();
136
- this.text = text;
58
+ this.field = field;
59
+ this.key = key;
137
60
  }
138
- get nodeType() {
139
- return 8;
61
+ lookup(v, dval = null) {
62
+ const o = v?.get(this.field, null);
63
+ return o?.get ? o.get(this.key, dval) : dval;
140
64
  }
141
- isEqualTo(other) {
142
- return other instanceof VComment && this.text === other.text;
65
+ setValue(root, v) {
66
+ return root.set(this.field, root.get(this.field).set(this.key, v));
143
67
  }
144
- toDom(opts) {
145
- return opts.document.createComment(this.text);
68
+ updateBindings(_v, o) {
69
+ o.key = this.key;
146
70
  }
147
71
  }
148
72
 
149
- class VFragment extends VBase {
150
- childs;
151
- constructor(childs) {
73
+ class SeqKeyStep extends FieldSeqStep {
74
+ }
75
+
76
+ class SeqIndexStep extends FieldSeqStep {
77
+ }
78
+ var NONE = Symbol("NONE");
79
+
80
+ class SeqAccessStep extends Step {
81
+ constructor(seqField, keyField) {
152
82
  super();
153
- const normalized = [];
154
- addChild(normalized, childs);
155
- this.childs = normalized;
83
+ this.seqField = seqField;
84
+ this.keyField = keyField;
156
85
  }
157
- get nodeType() {
158
- return 11;
86
+ lookup(v, dval = null) {
87
+ const seq = v?.get(this.seqField, NONE);
88
+ const key = v?.get(this.keyField, NONE);
89
+ return key !== NONE && seq?.get ? seq.get(key, dval) : dval;
159
90
  }
160
- isEqualTo(other) {
161
- if (!(other instanceof VFragment) || this.childs.length !== other.childs.length) {
162
- return false;
163
- }
164
- for (let i = 0;i < this.childs.length; i++) {
165
- if (!this.childs[i].isEqualTo(other.childs[i])) {
166
- return false;
167
- }
168
- }
169
- return true;
91
+ setValue(root, v) {
92
+ const seq = root?.get(this.seqField, NONE);
93
+ const key = root?.get(this.keyField, NONE);
94
+ return seq === NONE || key === NONE ? root : root.set(this.seqField, seq.set(key, v));
170
95
  }
171
- toDom(opts) {
172
- const fragment = opts.document.createDocumentFragment();
173
- for (const child of this.childs) {
174
- const childNode = child.toDom(opts);
175
- if (childNode) {
176
- fragment.appendChild(childNode);
177
- }
178
- }
179
- return fragment;
96
+ updateBindings(v, o) {
97
+ o.key = v?.get(this.keyField, null);
180
98
  }
181
99
  }
182
100
 
183
- class VNode extends VBase {
184
- tag;
185
- attrs;
186
- childs;
187
- key;
188
- namespace;
189
- attrCount;
190
- constructor(tag, attrs, childs, key, namespace) {
191
- super();
192
- this.tag = tag;
193
- this.attrs = attrs ?? {};
194
- this.childs = childs ?? [];
195
- this.key = key != null ? String(key) : undefined;
196
- this.namespace = typeof namespace === "string" ? namespace : null;
197
- this.attrCount = Object.keys(this.attrs).length;
101
+ class Path {
102
+ constructor(steps = []) {
103
+ this.steps = steps;
198
104
  }
199
- get nodeType() {
200
- return 1;
105
+ concat(steps) {
106
+ return new Path(this.steps.concat(steps));
201
107
  }
202
- isEqualTo(other) {
203
- if (!(other instanceof VNode) || this.tag !== other.tag || this.key !== other.key || this.namespace !== other.namespace || this.attrCount !== other.attrCount || this.childs.length !== other.childs.length) {
204
- return false;
205
- }
206
- for (const key in this.attrs) {
207
- if (this.attrs[key] !== other.attrs[key]) {
208
- return false;
108
+ popStep() {
109
+ return new Path(this.steps.slice(0, -1));
110
+ }
111
+ lookup(v, dval = null) {
112
+ let curVal = v;
113
+ for (const step of this.steps) {
114
+ curVal = step.lookup(curVal, NONE);
115
+ if (curVal === NONE) {
116
+ return dval;
209
117
  }
210
118
  }
211
- for (let i = 0;i < this.childs.length; i++) {
212
- if (!this.childs[i].isEqualTo(other.childs[i])) {
213
- return false;
119
+ return curVal;
120
+ }
121
+ setValue(root, v) {
122
+ const intermediates = new Array(this.steps.length);
123
+ let curVal = root;
124
+ for (let i = 0;i < this.steps.length; i++) {
125
+ intermediates[i] = curVal;
126
+ curVal = this.steps[i].lookup(curVal, NONE);
127
+ if (curVal === NONE) {
128
+ return root;
214
129
  }
215
130
  }
216
- return true;
131
+ let newVal = v;
132
+ for (let i = this.steps.length - 1;i >= 0; i--) {
133
+ newVal = this.steps[i].setValue(intermediates[i], newVal);
134
+ intermediates[i] = newVal;
135
+ }
136
+ return newVal;
217
137
  }
218
- toDom(opts) {
219
- const doc = opts.document;
220
- const node = this.namespace === null ? doc.createElement(this.tag) : doc.createElementNS(this.namespace, this.tag);
221
- applyProperties(node, this.attrs, {});
222
- for (const child of this.childs) {
223
- const childNode = child.toDom(opts);
224
- if (childNode) {
225
- node.appendChild(childNode);
138
+ buildStack(stack) {
139
+ const root = stack.it;
140
+ let curVal = root;
141
+ for (const step of this.steps) {
142
+ curVal = step.lookup(curVal, NONE);
143
+ if (curVal === NONE) {
144
+ console.warn(`bad PathItem`, { root, curVal, step, path: this });
145
+ return null;
226
146
  }
147
+ step.updateBindings(curVal, stack.binds.head.bindings);
148
+ stack = stack.enter(curVal, {}, step.isFrame);
227
149
  }
228
- return node;
150
+ return stack;
229
151
  }
230
- }
231
- function diffProps(a, b) {
232
- let diff = null;
233
- for (const aKey in a) {
234
- if (!Object.hasOwn(b, aKey)) {
235
- diff ??= {};
236
- diff[aKey] = undefined;
237
- continue;
238
- }
239
- const aValue = a[aKey];
240
- const bValue = b[aKey];
241
- if (aValue === bValue) {} else if (typeof aValue === "object" && aValue !== null && typeof bValue === "object" && bValue !== null) {
242
- if (Object.getPrototypeOf(bValue) !== Object.getPrototypeOf(aValue)) {
243
- diff ??= {};
244
- diff[aKey] = bValue;
245
- } else {
246
- const objectDiff = diffProps(aValue, bValue);
247
- if (objectDiff) {
248
- diff ??= {};
249
- diff[aKey] = objectDiff;
152
+ static fromNodeAndEventName(node, eventName, rootNode, maxDepth, comps, stopOnNoEvent = true) {
153
+ const pathSteps = [];
154
+ let depth = 0;
155
+ let eventIds = [];
156
+ let handlers = null;
157
+ let nodeIds = [];
158
+ let isLeafComponent = true;
159
+ while (node && node !== rootNode && depth < maxDepth) {
160
+ if (node?.dataset) {
161
+ const { nid, si, sk } = parseMetaComment(node.previousSibling);
162
+ const { eid, cid, vid } = node.dataset;
163
+ if (eid !== undefined)
164
+ eventIds.push(eid);
165
+ if (cid !== undefined) {
166
+ const comp = comps.getComponentForId(+cid, vid);
167
+ if (isLeafComponent) {
168
+ handlers = findHandlers(comp, eventIds, vid, eventName);
169
+ if (handlers === null && stopOnNoEvent)
170
+ return NO_EVENT_INFO;
171
+ isLeafComponent = false;
172
+ }
173
+ const step = resolvePathStep(comp, nodeIds, vid);
174
+ if (step)
175
+ pathSteps.push(step);
176
+ eventIds = [];
177
+ nodeIds = [];
250
178
  }
179
+ if (nid !== undefined)
180
+ nodeIds.push({ nid, si, sk });
251
181
  }
252
- } else {
253
- diff ??= {};
254
- diff[aKey] = bValue;
182
+ depth += 1;
183
+ node = node.parentNode;
255
184
  }
185
+ return [new Path(pathSteps.reverse()), handlers];
256
186
  }
257
- for (const bKey in b) {
258
- if (!Object.hasOwn(a, bKey)) {
259
- diff ??= {};
260
- diff[bKey] = b[bKey];
261
- }
187
+ static fromEvent(e, rNode, maxDepth, comps, stopOnNoEvent = true) {
188
+ const { type, target } = e;
189
+ return Path.fromNodeAndEventName(target, type, rNode, maxDepth, comps, stopOnNoEvent);
262
190
  }
263
- return diff;
264
191
  }
265
- function reorder(oldChildren, newChildren) {
266
- const rawNew = keyIndex(newChildren);
267
- if (rawNew.free.length === newChildren.length) {
268
- return {
269
- children: newChildren,
270
- moves: null,
271
- duplicatedKeys: rawNew.duplicatedKeys
272
- };
273
- }
274
- const rawOld = keyIndex(oldChildren);
275
- const duplicatedKeys = rawNew.duplicatedKeys || rawOld.duplicatedKeys ? new Set([...rawNew.duplicatedKeys || [], ...rawOld.duplicatedKeys || []]) : null;
276
- if (rawOld.free.length === oldChildren.length) {
277
- return {
278
- children: newChildren,
279
- moves: null,
280
- duplicatedKeys
281
- };
282
- }
283
- let newKeys;
284
- let newFree;
285
- let oldKeys;
286
- if (duplicatedKeys) {
287
- const updatedNew = keyIndex(newChildren, duplicatedKeys);
288
- newKeys = updatedNew.keys;
289
- newFree = updatedNew.free;
290
- oldKeys = keyIndex(oldChildren, duplicatedKeys).keys;
291
- } else {
292
- newKeys = rawNew.keys;
293
- newFree = rawNew.free;
294
- oldKeys = rawOld.keys;
295
- }
296
- const reordered = [];
297
- let freeIndex = 0;
298
- const freeCount = newFree.length;
299
- let deletedItems = 0;
300
- for (let i = 0;i < oldChildren.length; i++) {
301
- const oldItem = oldChildren[i];
302
- const oldKey = effectiveKey(oldItem, duplicatedKeys);
303
- if (oldKey) {
304
- if (Object.hasOwn(newKeys, oldKey)) {
305
- const itemIndex = newKeys[oldKey];
306
- reordered.push(newChildren[itemIndex]);
307
- } else {
308
- deletedItems++;
309
- reordered.push(null);
310
- }
311
- } else {
312
- if (freeIndex < freeCount) {
313
- const itemIndex = newFree[freeIndex++];
314
- reordered.push(newChildren[itemIndex]);
315
- } else {
316
- deletedItems++;
317
- reordered.push(null);
318
- }
319
- }
320
- }
321
- const lastFreeIndex = freeIndex >= newFree.length ? newChildren.length : newFree[freeIndex];
322
- for (let j = 0;j < newChildren.length; j++) {
323
- const newItem = newChildren[j];
324
- const newKey = effectiveKey(newItem, duplicatedKeys);
325
- if (newKey) {
326
- if (!Object.hasOwn(oldKeys, newKey)) {
327
- reordered.push(newItem);
328
- }
329
- } else if (j >= lastFreeIndex) {
330
- reordered.push(newItem);
331
- }
332
- }
333
- const moves = computeMoves(reordered, newChildren, newKeys, duplicatedKeys, deletedItems);
334
- return { children: reordered, moves, duplicatedKeys };
335
- }
336
- function computeMoves(reordered, newChildren, newKeys, duplicatedKeys, deletedItems) {
337
- const simulate = reordered.slice();
338
- let simulateIndex = 0;
339
- const removes = [];
340
- const inserts = [];
341
- const wantedKeys = new Array(newChildren.length);
342
- for (let i = 0;i < newChildren.length; i++) {
343
- wantedKeys[i] = effectiveKey(newChildren[i], duplicatedKeys);
344
- }
345
- for (let k = 0;k < newChildren.length; ) {
346
- const wantedKey = wantedKeys[k];
347
- let simulateItem = simulate[simulateIndex];
348
- let simulateKey = effectiveKey(simulateItem, duplicatedKeys);
349
- while (simulateItem === null && simulate.length) {
350
- simulate.splice(simulateIndex, 1);
351
- removes.push({ from: simulateIndex, key: null });
352
- simulateItem = simulate[simulateIndex];
353
- simulateKey = effectiveKey(simulateItem, duplicatedKeys);
354
- }
355
- if (simulateItem && simulateKey === wantedKey) {
356
- simulateIndex++;
357
- k++;
358
- continue;
359
- }
360
- if (wantedKey) {
361
- if (simulateKey && newKeys[simulateKey] !== k + 1) {
362
- simulate.splice(simulateIndex, 1);
363
- removes.push({ from: simulateIndex, key: simulateKey });
364
- simulateItem = simulate[simulateIndex];
365
- simulateKey = effectiveKey(simulateItem, duplicatedKeys);
366
- if (simulateItem && simulateKey === wantedKey) {
367
- simulateIndex++;
368
- k++;
369
- continue;
370
- }
371
- }
372
- inserts.push({ key: wantedKey, to: k });
373
- k++;
374
- continue;
192
+ var EMPTY_META = {};
193
+ function parseMetaComment(n) {
194
+ if (n?.nodeType === 8 && n.textContent[0] === "§") {
195
+ const m = parseMetaComment(n.previousSibling);
196
+ if (m !== EMPTY_META) {
197
+ return m;
375
198
  }
376
- if (simulateKey) {
377
- simulate.splice(simulateIndex, 1);
378
- removes.push({ from: simulateIndex, key: simulateKey });
379
- continue;
199
+ try {
200
+ return JSON.parse(n.textContent.slice(1, -1));
201
+ } catch (err) {
202
+ console.warn(err, n);
380
203
  }
381
- k++;
382
204
  }
383
- while (simulateIndex < simulate.length) {
384
- const simulateItem = simulate[simulateIndex];
385
- simulate.splice(simulateIndex, 1);
386
- removes.push({
387
- from: simulateIndex,
388
- key: effectiveKey(simulateItem, duplicatedKeys)
389
- });
390
- }
391
- if (removes.length === deletedItems && !inserts.length) {
392
- return null;
205
+ return EMPTY_META;
206
+ }
207
+ function findHandlers(comp, eventIds, vid, eventName) {
208
+ for (const eid of eventIds) {
209
+ const handlers = comp.getEventForId(+eid, vid).getHandlersFor(eventName);
210
+ if (handlers !== null)
211
+ return handlers;
393
212
  }
394
- return { removes, inserts };
213
+ return null;
395
214
  }
396
- function keyIndex(children, excludeKeys) {
397
- const keys = {};
398
- const free = [];
399
- let duplicatedKeys = null;
400
- for (let i = 0;i < children.length; i++) {
401
- const key = getKey(children[i]);
402
- if (key && !excludeKeys?.has(key)) {
403
- if (key in keys) {
404
- duplicatedKeys ??= new Set;
405
- duplicatedKeys.add(key);
406
- }
407
- keys[key] = i;
408
- } else {
409
- free.push(i);
215
+ function resolvePathStep(comp, nodeIds, vid) {
216
+ for (let i = 0;i < nodeIds.length; i++) {
217
+ const node = comp.getNodeForId(+nodeIds[i].nid, vid);
218
+ const j = node.pathInNext ? i + 1 : i;
219
+ const { si, sk, nid: nodeId } = nodeIds[j];
220
+ const pi = node.pathInNext ? comp.getNodeForId(+nodeId, vid).val.toPathItem() : node.toPathItem();
221
+ if (pi !== null) {
222
+ return si !== undefined ? pi.withIndex(+si) : sk ? pi.withKey(sk) : pi;
410
223
  }
411
224
  }
412
- return { keys, free, duplicatedKeys };
225
+ return null;
413
226
  }
414
- function replaceNode(domNode, vnode, options) {
415
- const parentNode = domNode.parentNode;
416
- const newNode = vnode.toDom(options);
417
- if (parentNode && newNode && newNode !== domNode) {
418
- parentNode.replaceChild(newNode, domNode);
227
+ var NO_EVENT_INFO = [null, null];
228
+
229
+ class PathBuilder {
230
+ constructor() {
231
+ this.pathChanges = [];
419
232
  }
420
- return newNode || domNode;
421
- }
422
- function morphNode(domNode, source, target, opts) {
423
- if (source === target || source.isEqualTo(target))
424
- return domNode;
425
- if (source instanceof VText && target instanceof VText || source instanceof VComment && target instanceof VComment) {
426
- domNode.data = target.text;
427
- return domNode;
233
+ add(pathChange) {
234
+ this.pathChanges.push(pathChange);
235
+ return this;
428
236
  }
429
- if (source instanceof VNode && target instanceof VNode && source.tag === target.tag && source.namespace === target.namespace && source.key === target.key) {
430
- const propsDiff = diffProps(source.attrs, target.attrs);
431
- if (propsDiff) {
432
- applyProperties(domNode, propsDiff, source.attrs);
433
- }
434
- morphChildren(domNode, source.childs, target.childs, source.tag, opts);
435
- return domNode;
237
+ field(name) {
238
+ return this.add(new FieldStep(name));
436
239
  }
437
- if (source instanceof VFragment && target instanceof VFragment) {
438
- morphChildren(domNode, source.childs, target.childs, null, opts);
439
- return domNode;
240
+ index(name, index) {
241
+ return this.add(new SeqIndexStep(name, index));
242
+ }
243
+ key(name, key) {
244
+ return this.add(new SeqKeyStep(name, key));
440
245
  }
441
- return replaceNode(domNode, target, opts);
442
246
  }
443
- function morphChildren(parentDom, oldChilds, newChilds, parentTag, opts) {
444
- if (oldChilds.length === 0) {
445
- for (const child of newChilds) {
446
- const node = child.toDom(opts);
447
- if (node)
448
- parentDom.appendChild(node);
449
- }
450
- return;
247
+
248
+ // src/value.js
249
+ var VALID_VAL_ID_RE = /^[a-zA-Z][a-zA-Z0-9_]*$/;
250
+ var isValidValId = (name) => VALID_VAL_ID_RE.test(name);
251
+ var VALID_FLOAT_RE = /^-?[0-9]+(\.[0-9]+)?$/;
252
+ var parseStrTemplate = (v, px) => StrTplVal.parse(v, px);
253
+ var parseConst = (v, _) => new ConstVal(v);
254
+ var parseName = (v, _) => isValidValId(v) ? new NameVal(v) : null;
255
+ var parseType = (v, _) => isValidValId(v) ? new TypeVal(v) : null;
256
+ var parseBind = (v, _) => isValidValId(v) ? new BindVal(v) : null;
257
+ var parseDyn = (v, _) => isValidValId(v) ? new DynVal(v) : null;
258
+ var parseField = (v, _) => isValidValId(v) ? new FieldVal(v) : null;
259
+ var parseComp = (v, _) => isValidValId(v) ? new ComputedVal(v) : null;
260
+ var parseReq = (v, _) => isValidValId(v) ? new RequestVal(v) : null;
261
+
262
+ class ValParser {
263
+ constructor() {
264
+ this.allowFieldOnly();
265
+ this.bindValIt = new BindVal("it");
266
+ this.nullConstVal = new ConstVal(null);
451
267
  }
452
- if (newChilds.length === 0) {
453
- while (parentDom.firstChild) {
454
- parentDom.removeChild(parentDom.firstChild);
455
- }
456
- return;
268
+ const(v) {
269
+ return new ConstVal(v);
457
270
  }
458
- const orderedSet = reorder(oldChilds, newChilds);
459
- const reorderedChilds = orderedSet.children;
460
- if (orderedSet.duplicatedKeys && opts.onWarning) {
461
- opts.onWarning(new DuplicatedKeysWarning(orderedSet.duplicatedKeys, parentTag, 0));
271
+ allowFieldOnly() {
272
+ this.okField = true;
273
+ this.okBind = false;
274
+ this.okComputed = false;
275
+ this.okDyn = false;
276
+ this.okType = false;
277
+ this.okRequest = false;
278
+ this.okName = false;
279
+ this.okConst = false;
280
+ this.okStrTpl = false;
281
+ this.okSeqAccess = false;
462
282
  }
463
- const domChildren = Array.from(parentDom.childNodes);
464
- const oldLen = oldChilds.length;
465
- const reorderedLen = reorderedChilds.length;
466
- const len = Math.max(oldLen, reorderedLen);
467
- const toRemove = [];
468
- for (let i = 0;i < len; i++) {
469
- const leftNode = oldChilds[i];
470
- const rightNode = reorderedChilds[i];
471
- if (!leftNode && rightNode) {
472
- const newNode = rightNode.toDom(opts);
473
- if (newNode)
474
- parentDom.appendChild(newNode);
475
- } else if (leftNode && rightNode) {
476
- const domChild = domChildren[i];
477
- if (domChild) {
478
- morphNode(domChild, leftNode, rightNode, opts);
479
- }
480
- } else if (leftNode && !rightNode) {
481
- if (!orderedSet.moves && domChildren[i]) {
482
- toRemove.push(domChildren[i]);
483
- }
484
- }
283
+ parseIfOk(s, px, isOk, parseFn) {
284
+ return isOk ? parseFn(s, px) : null;
485
285
  }
486
- for (const node of toRemove) {
487
- if (node.parentNode === parentDom) {
488
- parentDom.removeChild(node);
286
+ _parseSeqAccess(s, px) {
287
+ if (!this.okSeqAccess) {
288
+ return null;
489
289
  }
290
+ const openSquareBracketIndex = s.indexOf("[");
291
+ this.allowFieldOnly();
292
+ const left = this.parse(s.slice(0, openSquareBracketIndex), px);
293
+ const right = this.parse(s.slice(openSquareBracketIndex + 1, -1), px);
294
+ return left && right ? new SeqAccessVal(left, right) : null;
490
295
  }
491
- if (orderedSet.moves) {
492
- applyMoves(parentDom, orderedSet.moves);
296
+ parse(s, px) {
297
+ switch (getValSubType(s)) {
298
+ case VAL_SUB_TYPE_STRING_TEMPLATE:
299
+ return this.parseIfOk(s, px, this.okStrTpl, parseStrTemplate);
300
+ case VAL_SUB_TYPE_CONST_STRING:
301
+ return this.parseIfOk(s, px, this.okStrTpl, parseConst);
302
+ case VAL_SUB_TYPE_SEQ_ACCESS:
303
+ return this._parseSeqAccess(s, px);
304
+ case VAL_SUB_TYPE_INVALID:
305
+ return this.parseIfOk(s, px, this.okStrTpl, parseStrTemplate);
306
+ }
307
+ const charCode = s.charCodeAt(0);
308
+ switch (charCode) {
309
+ case 94: {
310
+ const newS = px.frame.macroVars?.[s.slice(1)];
311
+ if (newS !== undefined) {
312
+ return this.parse(newS, px);
313
+ }
314
+ return null;
315
+ }
316
+ case 126:
317
+ return this.parseIfOk(s.slice(1), px, this.okStrTpl, parseConst);
318
+ case 39:
319
+ return this.parseIfOk(s.slice(1, -1), px, this.okStrTpl, parseConst);
320
+ case 64:
321
+ return this.parseIfOk(s.slice(1), px, this.okBind, parseBind);
322
+ case 42:
323
+ return this.parseIfOk(s.slice(1), px, this.okDyn, parseDyn);
324
+ case 46:
325
+ return this.parseIfOk(s.slice(1), px, this.okField, parseField);
326
+ case 36:
327
+ return this.parseIfOk(s.slice(1), px, this.okComputed, parseComp);
328
+ case 33:
329
+ return this.parseIfOk(s.slice(1), px, this.okRequest, parseReq);
330
+ }
331
+ const num = VALID_FLOAT_RE.test(s) ? parseFloat(s) : null;
332
+ if (Number.isFinite(num)) {
333
+ return this.parseIfOk(num, px, this.okConst, parseConst);
334
+ } else if (s === "true" || s === "false") {
335
+ return this.parseIfOk(s === "true", px, this.okConst, parseConst);
336
+ } else if (charCode >= 97 && charCode <= 122) {
337
+ return this.parseIfOk(s, px, this.okName, parseName);
338
+ } else if (charCode >= 65 && charCode <= 90) {
339
+ return this.parseIfOk(s, px, this.okType, parseType);
340
+ }
341
+ return null;
493
342
  }
494
- }
495
- function applyMoves(domNode, moves) {
496
- const childNodes = domNode.childNodes;
497
- const keyMap = {};
498
- for (const remove of moves.removes) {
499
- const node = childNodes[remove.from];
500
- if (remove.key)
501
- keyMap[remove.key] = node;
502
- domNode.removeChild(node);
343
+ parseDynamic(s, px) {
344
+ this.allowFieldOnly();
345
+ this.okComputed = true;
346
+ return this.parse(s, px);
503
347
  }
504
- let length = childNodes.length;
505
- for (let j = 0;j < moves.inserts.length; j++) {
506
- const insert = moves.inserts[j];
507
- const node = keyMap[insert.key];
508
- if (node) {
509
- domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to]);
510
- }
348
+ parseEach(s, px) {
349
+ this.allowFieldOnly();
350
+ this.okComputed = true;
351
+ this.okDyn = true;
352
+ return this.parse(s, px);
511
353
  }
512
- }
513
- var renderCache = new WeakMap;
514
- function render(vnode, container, options) {
515
- const cached = renderCache.get(container);
516
- const isFragment = vnode instanceof VFragment;
517
- if (cached) {
518
- const wasFragment = cached.vnode instanceof VFragment;
519
- if (wasFragment === isFragment) {
520
- const rootNode = wasFragment ? container : cached.dom;
521
- const newDom = morphNode(rootNode, cached.vnode, vnode, options);
522
- renderCache.set(container, {
523
- vnode,
524
- dom: isFragment ? container : newDom
525
- });
526
- return newDom;
527
- }
528
- renderCache.delete(container);
354
+ allowHandlerArg() {
355
+ this.allowFieldOnly();
356
+ this.okBind = true;
357
+ this.okComputed = true;
358
+ this.okDyn = true;
359
+ this.okType = true;
360
+ this.okRequest = true;
361
+ this.okName = true;
362
+ this.okConst = true;
529
363
  }
530
- const domNode = vnode.toDom(options);
531
- if (domNode) {
532
- container.innerHTML = "";
533
- container.appendChild(domNode);
534
- renderCache.set(container, {
535
- vnode,
536
- dom: isFragment ? container : domNode
537
- });
364
+ parseHandlerArg(s, px) {
365
+ this.allowHandlerArg();
366
+ return this.parse(s, px);
538
367
  }
539
- return domNode;
540
- }
541
- function h(tagName, properties, children) {
542
- const tag = tagName.toUpperCase();
543
- const props = {};
544
- let key;
545
- let namespace;
546
- if (properties) {
547
- for (const propName in properties) {
548
- if (propName === "key") {
549
- key = properties[propName];
550
- } else if (propName === "namespace") {
551
- namespace = properties[propName];
552
- } else if (propName === "class") {
553
- props.className = properties[propName];
554
- } else if (propName === "for") {
555
- props.htmlFor = properties[propName];
556
- } else if (isHtmlAttribute(propName)) {
557
- props[propName] = String(properties[propName]);
558
- } else {
559
- props[propName] = properties[propName];
560
- }
561
- }
368
+ _parseHandler(s, px, HandlerClass) {
369
+ this.allowFieldOnly();
370
+ this.okName = true;
371
+ const val = this.parse(s, px);
372
+ return val.toRawFieldVal ? val.toRawFieldVal() : new HandlerClass(val.name);
373
+ }
374
+ parseHandlerName(s, px) {
375
+ return this._parseHandler(s, px, InputHandlerNameVal);
376
+ }
377
+ parseAlter(s, px) {
378
+ return this._parseHandler(s, px, AlterHandlerNameVal);
379
+ }
380
+ parseAttr(s, px) {
381
+ return this.parseText(s, px);
382
+ }
383
+ parseAll(s, px) {
384
+ this.allowHandlerArg();
385
+ this.okStrTpl = true;
386
+ this.okSeqAccess = true;
387
+ return this.parse(s, px);
388
+ }
389
+ parseCondValue(s, px) {
390
+ this.allowFieldOnly();
391
+ this.okBind = true;
392
+ this.okComputed = true;
393
+ this.okDyn = true;
394
+ this.okConst = true;
395
+ return this.parse(s, px);
396
+ }
397
+ parseText(s, px) {
398
+ this.allowFieldOnly();
399
+ this.okBind = true;
400
+ this.okComputed = true;
401
+ this.okDyn = true;
402
+ this.okConst = true;
403
+ this.okStrTpl = true;
404
+ return this.parse(s, px);
405
+ }
406
+ parseRender(s, px) {
407
+ this.allowFieldOnly();
408
+ this.okSeqAccess = true;
409
+ return this.parse(s, px);
562
410
  }
563
- const normalizedChildren = [];
564
- addChild(normalizedChildren, children);
565
- return new VNode(tag, props, normalizedChildren, key, namespace);
566
411
  }
567
412
 
568
- // src/path.js
569
- class Step {
570
- lookup(_v, dval = null) {
571
- return dval;
572
- }
573
- setValue(root, _v) {
574
- return root;
413
+ class BaseVal {
414
+ render(_stack, _rx) {}
415
+ eval(_stack) {}
416
+ toPathItem() {
417
+ return null;
575
418
  }
576
- updateBindings(_v, _o) {}
577
- isFrame = true;
578
419
  }
579
420
 
580
- class BindStep extends Step {
581
- constructor(binds) {
421
+ class ConstVal extends BaseVal {
422
+ constructor(value) {
582
423
  super();
583
- this.binds = binds;
584
- }
585
- lookup(v, _dval) {
586
- return v;
587
- }
588
- setValue(_root, v) {
589
- return v;
424
+ this.value = value;
590
425
  }
591
- withIndex(i) {
592
- return new BindStep({ ...this.binds, key: i });
426
+ render(_stack, _rx) {
427
+ return this.value;
593
428
  }
594
- withKey(key) {
595
- return new BindStep({ ...this.binds, key });
429
+ eval(_stack) {
430
+ return this.value;
596
431
  }
597
- updateBindings(_v, o) {
598
- Object.assign(o, this.binds);
432
+ toString() {
433
+ const v = this.value;
434
+ return typeof v === "string" ? `'${v}'` : `${v}`;
599
435
  }
600
- isFrame = false;
601
436
  }
602
437
 
603
- class FieldStep extends Step {
604
- constructor(field) {
438
+ class VarVal extends BaseVal {
439
+ }
440
+
441
+ class StrTplVal extends VarVal {
442
+ constructor(vals) {
605
443
  super();
606
- this.field = field;
607
- }
608
- lookup(v, dval = null) {
609
- return v?.get ? v.get(this.field, dval) : dval;
444
+ this.vals = vals;
610
445
  }
611
- setValue(root, v) {
612
- return root.set(this.field, v);
446
+ render(stack, _rx) {
447
+ return this.eval(stack);
613
448
  }
614
- withIndex(i) {
615
- return new SeqIndexStep(this.field, i);
449
+ eval(stack) {
450
+ const strs = new Array(this.vals.length);
451
+ for (let i = 0;i < this.vals.length; i++) {
452
+ strs[i] = this.vals[i]?.eval(stack, "");
453
+ }
454
+ return strs.join("");
616
455
  }
617
- withKey(k) {
618
- return new SeqKeyStep(this.field, k);
456
+ static parse(s, px) {
457
+ const parts = s.split(/(\{[^}]+\})/g);
458
+ const vals = new Array(parts.length);
459
+ let allConsts = true;
460
+ for (let i = 0;i < parts.length; i++) {
461
+ const s2 = parts[i];
462
+ const isExpr = s2[0] === "{" && s2.at(-1) === "}";
463
+ const val = isExpr ? vp.parseText(s2.slice(1, -1), px) : new ConstVal(s2);
464
+ vals[i] = val;
465
+ allConsts &&= val instanceof ConstVal;
466
+ }
467
+ return allConsts ? new ConstVal(vals.map((v) => v.value).join("")) : new StrTplVal(vals);
619
468
  }
620
469
  }
621
470
 
622
- class FieldSeqStep extends Step {
623
- constructor(field, key) {
471
+ class NameVal extends VarVal {
472
+ constructor(name) {
624
473
  super();
625
- this.field = field;
626
- this.key = key;
474
+ this.name = name;
627
475
  }
628
- lookup(v, dval = null) {
629
- const o = v?.get(this.field, null);
630
- return o?.get ? o.get(this.key, dval) : dval;
476
+ eval(stack) {
477
+ return stack.lookupName(this.name);
631
478
  }
632
- setValue(root, v) {
633
- return root.set(this.field, root.get(this.field).set(this.key, v));
479
+ toString() {
480
+ return this.name;
634
481
  }
635
- updateBindings(_v, o) {
636
- o.key = this.key;
482
+ }
483
+
484
+ class InputHandlerNameVal extends NameVal {
485
+ eval(stack) {
486
+ return stack.getInputHandler(this.name) ?? mk404Handler("input", this.name);
637
487
  }
638
488
  }
639
489
 
640
- class SeqKeyStep extends FieldSeqStep {
490
+ class AlterHandlerNameVal extends NameVal {
491
+ eval(stack) {
492
+ return stack.getAlterHandler(this.name) ?? mk404Handler("alter", this.name);
493
+ }
641
494
  }
495
+ var mk404Handler = (type, name) => function(...args) {
496
+ console.warn("handler not found", { type, name, args }, this);
497
+ return this;
498
+ };
642
499
 
643
- class SeqIndexStep extends FieldSeqStep {
500
+ class TypeVal extends NameVal {
501
+ eval(stack) {
502
+ return stack.lookupType(this.name);
503
+ }
644
504
  }
645
- var NONE = Symbol("NONE");
646
505
 
647
- class SeqAccessStep extends Step {
648
- constructor(seqField, keyField) {
649
- super();
650
- this.seqField = seqField;
651
- this.keyField = keyField;
506
+ class RequestVal extends NameVal {
507
+ eval(stack) {
508
+ return stack.lookupRequest(this.name);
652
509
  }
653
- lookup(v, dval = null) {
654
- const seq = v?.get(this.seqField, NONE);
655
- const key = v?.get(this.keyField, NONE);
656
- return key !== NONE && seq?.get ? seq.get(key, dval) : dval;
510
+ toString() {
511
+ return `!${this.name}`;
657
512
  }
658
- setValue(root, v) {
659
- const seq = root?.get(this.seqField, NONE);
660
- const key = root?.get(this.keyField, NONE);
661
- return seq === NONE || key === NONE ? root : root.set(this.seqField, seq.set(key, v));
513
+ }
514
+
515
+ class RawFieldVal extends NameVal {
516
+ eval(stack) {
517
+ return stack.lookupFieldRaw(this.name);
662
518
  }
663
- updateBindings(v, o) {
664
- o.key = v?.get(this.keyField, null);
519
+ toString() {
520
+ return `.${this.name}`;
665
521
  }
666
522
  }
667
523
 
668
- class Path {
669
- constructor(steps = []) {
670
- this.steps = steps;
671
- }
672
- concat(steps) {
673
- return new Path(this.steps.concat(steps));
524
+ class RenderVal extends BaseVal {
525
+ render(stack, _rx) {
526
+ return this.eval(stack);
674
527
  }
675
- popStep() {
676
- return new Path(this.steps.slice(0, -1));
528
+ }
529
+
530
+ class RenderNameVal extends RenderVal {
531
+ constructor(name) {
532
+ super();
533
+ this.name = name;
677
534
  }
678
- lookup(v, dval = null) {
679
- let curVal = v;
680
- for (const step of this.steps) {
681
- curVal = step.lookup(curVal, NONE);
682
- if (curVal === NONE) {
683
- return dval;
684
- }
685
- }
686
- return curVal;
535
+ }
536
+
537
+ class BindVal extends RenderNameVal {
538
+ eval(stack) {
539
+ return stack.lookupBind(this.name);
687
540
  }
688
- setValue(root, v) {
689
- const intermediates = new Array(this.steps.length);
690
- let curVal = root;
691
- for (let i = 0;i < this.steps.length; i++) {
692
- intermediates[i] = curVal;
693
- curVal = this.steps[i].lookup(curVal, NONE);
694
- if (curVal === NONE) {
695
- return root;
696
- }
697
- }
698
- let newVal = v;
699
- for (let i = this.steps.length - 1;i >= 0; i--) {
700
- newVal = this.steps[i].setValue(intermediates[i], newVal);
701
- intermediates[i] = newVal;
702
- }
703
- return newVal;
541
+ toString() {
542
+ return `@${this.name}`;
704
543
  }
705
- buildStack(stack) {
706
- const root = stack.it;
707
- let curVal = root;
708
- for (const step of this.steps) {
709
- curVal = step.lookup(curVal, NONE);
710
- if (curVal === NONE) {
711
- console.warn(`bad PathItem`, { root, curVal, step, path: this });
712
- return null;
713
- }
714
- step.updateBindings(curVal, stack.binds.head.bindings);
715
- stack = stack.enter(curVal, {}, step.isFrame);
716
- }
717
- return stack;
544
+ }
545
+
546
+ class DynVal extends RenderNameVal {
547
+ eval(stack) {
548
+ return stack.lookupDynamic(this.name);
718
549
  }
719
- static fromNodeAndEventName(node, eventName, rootNode, maxDepth, comps, stopOnNoEvent = true) {
720
- const pathSteps = [];
721
- let depth = 0;
722
- let eventIds = [];
723
- let handlers = null;
724
- let nodeIds = [];
725
- let isLeafComponent = true;
726
- while (node && node !== rootNode && depth < maxDepth) {
727
- if (node?.dataset) {
728
- const { nid, si, sk } = parseMetaComment(node.previousSibling);
729
- const { eid, cid, vid } = node.dataset;
730
- if (eid !== undefined)
731
- eventIds.push(eid);
732
- if (cid !== undefined) {
733
- const comp = comps.getComponentForId(+cid, vid);
734
- if (isLeafComponent) {
735
- handlers = findHandlers(comp, eventIds, vid, eventName);
736
- if (handlers === null && stopOnNoEvent)
737
- return NO_EVENT_INFO;
738
- isLeafComponent = false;
739
- }
740
- const step = resolvePathStep(comp, nodeIds, vid);
741
- if (step)
742
- pathSteps.push(step);
743
- eventIds = [];
744
- nodeIds = [];
745
- }
746
- if (nid !== undefined)
747
- nodeIds.push({ nid, si, sk });
748
- }
749
- depth += 1;
750
- node = node.parentNode;
751
- }
752
- return [new Path(pathSteps.reverse()), handlers];
550
+ toPathItem() {
551
+ return null;
753
552
  }
754
- static fromEvent(e, rNode, maxDepth, comps, stopOnNoEvent = true) {
755
- const { type, target } = e;
756
- return Path.fromNodeAndEventName(target, type, rNode, maxDepth, comps, stopOnNoEvent);
553
+ toString() {
554
+ return `*${this.name}`;
757
555
  }
758
556
  }
759
- var EMPTY_META = {};
760
- function parseMetaComment(n) {
761
- if (n?.nodeType === 8 && n.textContent[0] === "§") {
762
- const m = parseMetaComment(n.previousSibling);
763
- if (m !== EMPTY_META) {
764
- return m;
765
- }
766
- try {
767
- return JSON.parse(n.textContent.slice(1, -1));
768
- } catch (err) {
769
- console.warn(err, n);
770
- }
557
+
558
+ class FieldVal extends RenderNameVal {
559
+ eval(stack) {
560
+ return stack.lookupField(this.name);
771
561
  }
772
- return EMPTY_META;
773
- }
774
- function findHandlers(comp, eventIds, vid, eventName) {
775
- for (const eid of eventIds) {
776
- const handlers = comp.getEventForId(+eid, vid).getHandlersFor(eventName);
777
- if (handlers !== null)
778
- return handlers;
562
+ toPathItem() {
563
+ return new FieldStep(this.name);
564
+ }
565
+ toRawFieldVal() {
566
+ return new RawFieldVal(this.name);
567
+ }
568
+ toString() {
569
+ return `.${this.name}`;
779
570
  }
780
- return null;
781
571
  }
782
- function resolvePathStep(comp, nodeIds, vid) {
783
- for (let i = 0;i < nodeIds.length; i++) {
784
- const node = comp.getNodeForId(+nodeIds[i].nid, vid);
785
- const j = node.pathInNext ? i + 1 : i;
786
- const { si, sk, nid: nodeId } = nodeIds[j];
787
- const pi = node.pathInNext ? comp.getNodeForId(+nodeId, vid).val.toPathItem() : node.toPathItem();
788
- if (pi !== null) {
789
- return si !== undefined ? pi.withIndex(+si) : sk ? pi.withKey(sk) : pi;
790
- }
572
+
573
+ class ComputedVal extends RenderNameVal {
574
+ eval(stack) {
575
+ return stack.lookupComputed(this.name);
576
+ }
577
+ toString() {
578
+ return `$${this.name}`;
791
579
  }
792
- return null;
793
580
  }
794
- var NO_EVENT_INFO = [null, null];
795
581
 
796
- class PathBuilder {
797
- constructor() {
798
- this.pathChanges = [];
582
+ class SeqAccessVal extends RenderVal {
583
+ constructor(seqVal, keyVal) {
584
+ super();
585
+ this.seqVal = seqVal;
586
+ this.keyVal = keyVal;
799
587
  }
800
- add(pathChange) {
801
- this.pathChanges.push(pathChange);
802
- return this;
588
+ toPathItem() {
589
+ return new SeqAccessStep(this.seqVal.name, this.keyVal.name);
803
590
  }
804
- field(name) {
805
- return this.add(new FieldStep(name));
591
+ eval(stack) {
592
+ const key = this.keyVal.eval(stack);
593
+ return this.seqVal.eval(stack).get(key, null);
806
594
  }
807
- index(name, index) {
808
- return this.add(new SeqIndexStep(name, index));
595
+ toString() {
596
+ return `${this.seqVal}[${this.keyVal}]`;
809
597
  }
810
- key(name, key) {
811
- return this.add(new SeqKeyStep(name, key));
598
+ }
599
+ var VAL_SUB_TYPE_STRING_TEMPLATE = 0;
600
+ var VAL_SUB_TYPE_SEQ_ACCESS = 1;
601
+ var VAL_SUB_TYPE_INVALID = 2;
602
+ var VAL_SUB_TYPE_CONST_STRING = 3;
603
+ function getValSubType(s) {
604
+ let open = 0;
605
+ let close = 0;
606
+ for (let i = 0;i < s.length; i++) {
607
+ switch (s.charCodeAt(i)) {
608
+ case 91:
609
+ if (open > 0) {
610
+ return VAL_SUB_TYPE_INVALID;
611
+ }
612
+ open += 1;
613
+ break;
614
+ case 93:
615
+ if (close > 0 || open === 0) {
616
+ return VAL_SUB_TYPE_INVALID;
617
+ }
618
+ close += 1;
619
+ break;
620
+ case 123:
621
+ return VAL_SUB_TYPE_STRING_TEMPLATE;
622
+ case 125:
623
+ return VAL_SUB_TYPE_CONST_STRING;
624
+ }
625
+ }
626
+ if (open > 0 || close > 0) {
627
+ return open === 1 && close === 1 ? VAL_SUB_TYPE_SEQ_ACCESS : VAL_SUB_TYPE_INVALID;
812
628
  }
629
+ return -1;
813
630
  }
631
+ var vp = new ValParser;
814
632
 
815
- // src/value.js
816
- var VALID_VAL_ID_RE = /^[a-zA-Z][a-zA-Z0-9_]*$/;
817
- var isValidValId = (name) => VALID_VAL_ID_RE.test(name);
818
- var VALID_FLOAT_RE = /^-?[0-9]+(\.[0-9]+)?$/;
819
- var parseStrTemplate = (v, px) => StrTplVal.parse(v, px);
820
- var parseConst = (v, _) => new ConstVal(v);
821
- var parseName = (v, _) => isValidValId(v) ? new NameVal(v) : null;
822
- var parseType = (v, _) => isValidValId(v) ? new TypeVal(v) : null;
823
- var parseBind = (v, _) => isValidValId(v) ? new BindVal(v) : null;
824
- var parseDyn = (v, _) => isValidValId(v) ? new DynVal(v) : null;
825
- var parseField = (v, _) => isValidValId(v) ? new FieldVal(v) : null;
826
- var parseComp = (v, _) => isValidValId(v) ? new ComputedVal(v) : null;
827
- var parseReq = (v, _) => isValidValId(v) ? new RequestVal(v) : null;
828
-
829
- class ValParser {
830
- constructor() {
831
- this.allowFieldOnly();
832
- this.bindValIt = new BindVal("it");
833
- this.nullConstVal = new ConstVal(null);
633
+ // src/attribute.js
634
+ class Attributes {
635
+ constructor(items) {
636
+ this.items = items;
834
637
  }
835
- const(v) {
836
- return new ConstVal(v);
638
+ eval(_stack) {
639
+ return {};
837
640
  }
838
- allowFieldOnly() {
839
- this.okField = true;
840
- this.okBind = false;
841
- this.okComputed = false;
842
- this.okDyn = false;
843
- this.okType = false;
844
- this.okRequest = false;
845
- this.okName = false;
846
- this.okConst = false;
847
- this.okStrTpl = false;
848
- this.okSeqAccess = false;
641
+ static parse(attributes, px, parseAll = false) {
642
+ return getAttrParser(px).parse(attributes, parseAll);
849
643
  }
850
- parseIfOk(s, px, isOk, parseFn) {
851
- return isOk ? parseFn(s, px) : null;
852
- }
853
- _parseSeqAccess(s, px) {
854
- if (!this.okSeqAccess) {
855
- return null;
856
- }
857
- const openSquareBracketIndex = s.indexOf("[");
858
- this.allowFieldOnly();
859
- const left = this.parse(s.slice(0, openSquareBracketIndex), px);
860
- const right = this.parse(s.slice(openSquareBracketIndex + 1, -1), px);
861
- return left && right ? new SeqAccessVal(left, right) : null;
862
- }
863
- parse(s, px) {
864
- switch (getValSubType(s)) {
865
- case VAL_SUB_TYPE_STRING_TEMPLATE:
866
- return this.parseIfOk(s, px, this.okStrTpl, parseStrTemplate);
867
- case VAL_SUB_TYPE_CONST_STRING:
868
- return this.parseIfOk(s, px, this.okStrTpl, parseConst);
869
- case VAL_SUB_TYPE_SEQ_ACCESS:
870
- return this._parseSeqAccess(s, px);
871
- case VAL_SUB_TYPE_INVALID:
872
- return this.parseIfOk(s, px, this.okStrTpl, parseStrTemplate);
873
- }
874
- const charCode = s.charCodeAt(0);
875
- switch (charCode) {
876
- case 94: {
877
- const newS = px.frame.macroVars?.[s.slice(1)];
878
- if (newS !== undefined) {
879
- return this.parse(newS, px);
880
- }
881
- return null;
882
- }
883
- case 126:
884
- return this.parseIfOk(s.slice(1), px, this.okStrTpl, parseConst);
885
- case 39:
886
- return this.parseIfOk(s.slice(1, -1), px, this.okStrTpl, parseConst);
887
- case 64:
888
- return this.parseIfOk(s.slice(1), px, this.okBind, parseBind);
889
- case 42:
890
- return this.parseIfOk(s.slice(1), px, this.okDyn, parseDyn);
891
- case 46:
892
- return this.parseIfOk(s.slice(1), px, this.okField, parseField);
893
- case 36:
894
- return this.parseIfOk(s.slice(1), px, this.okComputed, parseComp);
895
- case 33:
896
- return this.parseIfOk(s.slice(1), px, this.okRequest, parseReq);
897
- }
898
- const num = VALID_FLOAT_RE.test(s) ? parseFloat(s) : null;
899
- if (Number.isFinite(num)) {
900
- return this.parseIfOk(num, px, this.okConst, parseConst);
901
- } else if (s === "true" || s === "false") {
902
- return this.parseIfOk(s === "true", px, this.okConst, parseConst);
903
- } else if (charCode >= 97 && charCode <= 122) {
904
- return this.parseIfOk(s, px, this.okName, parseName);
905
- } else if (charCode >= 65 && charCode <= 90) {
906
- return this.parseIfOk(s, px, this.okType, parseType);
907
- }
908
- return null;
909
- }
910
- parseDynamic(s, px) {
911
- this.allowFieldOnly();
912
- this.okComputed = true;
913
- return this.parse(s, px);
914
- }
915
- parseEach(s, px) {
916
- this.allowFieldOnly();
917
- this.okComputed = true;
918
- this.okDyn = true;
919
- return this.parse(s, px);
920
- }
921
- allowHandlerArg() {
922
- this.allowFieldOnly();
923
- this.okBind = true;
924
- this.okComputed = true;
925
- this.okDyn = true;
926
- this.okType = true;
927
- this.okRequest = true;
928
- this.okName = true;
929
- this.okConst = true;
930
- }
931
- parseHandlerArg(s, px) {
932
- this.allowHandlerArg();
933
- return this.parse(s, px);
934
- }
935
- _parseHandler(s, px, HandlerClass) {
936
- this.allowFieldOnly();
937
- this.okName = true;
938
- const val = this.parse(s, px);
939
- return val.toRawFieldVal ? val.toRawFieldVal() : new HandlerClass(val.name);
940
- }
941
- parseHandlerName(s, px) {
942
- return this._parseHandler(s, px, InputHandlerNameVal);
943
- }
944
- parseAlter(s, px) {
945
- return this._parseHandler(s, px, AlterHandlerNameVal);
946
- }
947
- parseAttr(s, px) {
948
- return this.parseText(s, px);
949
- }
950
- parseAll(s, px) {
951
- this.allowHandlerArg();
952
- this.okStrTpl = true;
953
- this.okSeqAccess = true;
954
- return this.parse(s, px);
955
- }
956
- parseCondValue(s, px) {
957
- this.allowFieldOnly();
958
- this.okBind = true;
959
- this.okComputed = true;
960
- this.okDyn = true;
961
- this.okConst = true;
962
- return this.parse(s, px);
963
- }
964
- parseText(s, px) {
965
- this.allowFieldOnly();
966
- this.okBind = true;
967
- this.okComputed = true;
968
- this.okDyn = true;
969
- this.okConst = true;
970
- this.okStrTpl = true;
971
- return this.parse(s, px);
972
- }
973
- parseRender(s, px) {
974
- this.allowFieldOnly();
975
- this.okSeqAccess = true;
976
- return this.parse(s, px);
977
- }
978
- }
979
-
980
- class BaseVal {
981
- render(_stack, _rx) {}
982
- eval(_stack) {}
983
- toPathItem() {
984
- return null;
985
- }
986
- }
987
-
988
- class ConstVal extends BaseVal {
989
- constructor(value) {
990
- super();
991
- this.value = value;
992
- }
993
- render(_stack, _rx) {
994
- return this.value;
995
- }
996
- eval(_stack) {
997
- return this.value;
998
- }
999
- toString() {
1000
- const v = this.value;
1001
- return typeof v === "string" ? `'${v}'` : `${v}`;
1002
- }
1003
- }
1004
-
1005
- class VarVal extends BaseVal {
1006
- }
1007
-
1008
- class StrTplVal extends VarVal {
1009
- constructor(vals) {
1010
- super();
1011
- this.vals = vals;
1012
- }
1013
- render(stack, _rx) {
1014
- return this.eval(stack);
1015
- }
1016
- eval(stack) {
1017
- const strs = new Array(this.vals.length);
1018
- for (let i = 0;i < this.vals.length; i++) {
1019
- strs[i] = this.vals[i]?.eval(stack, "");
1020
- }
1021
- return strs.join("");
1022
- }
1023
- static parse(s, px) {
1024
- const parts = s.split(/(\{[^}]+\})/g);
1025
- const vals = new Array(parts.length);
1026
- let allConsts = true;
1027
- for (let i = 0;i < parts.length; i++) {
1028
- const s2 = parts[i];
1029
- const isExpr = s2[0] === "{" && s2.at(-1) === "}";
1030
- const val = isExpr ? vp.parseText(s2.slice(1, -1), px) : new ConstVal(s2);
1031
- vals[i] = val;
1032
- allConsts &&= val instanceof ConstVal;
1033
- }
1034
- return allConsts ? new ConstVal(vals.map((v) => v.value).join("")) : new StrTplVal(vals);
1035
- }
1036
- }
1037
-
1038
- class NameVal extends VarVal {
1039
- constructor(name) {
1040
- super();
1041
- this.name = name;
1042
- }
1043
- eval(stack) {
1044
- return stack.lookupName(this.name);
1045
- }
1046
- toString() {
1047
- return this.name;
1048
- }
1049
- }
1050
-
1051
- class InputHandlerNameVal extends NameVal {
1052
- eval(stack) {
1053
- return stack.getInputHandler(this.name) ?? mk404Handler("input", this.name);
1054
- }
1055
- }
1056
-
1057
- class AlterHandlerNameVal extends NameVal {
1058
- eval(stack) {
1059
- return stack.getAlterHandler(this.name) ?? mk404Handler("alter", this.name);
1060
- }
1061
- }
1062
- var mk404Handler = (type, name) => function(...args) {
1063
- console.warn("handler not found", { type, name, args }, this);
1064
- return this;
1065
- };
1066
-
1067
- class TypeVal extends NameVal {
1068
- eval(stack) {
1069
- return stack.lookupType(this.name);
1070
- }
1071
- }
1072
-
1073
- class RequestVal extends NameVal {
1074
- eval(stack) {
1075
- return stack.lookupRequest(this.name);
1076
- }
1077
- toString() {
1078
- return `!${this.name}`;
1079
- }
1080
- }
1081
-
1082
- class RawFieldVal extends NameVal {
1083
- eval(stack) {
1084
- return stack.lookupFieldRaw(this.name);
1085
- }
1086
- toString() {
1087
- return `.${this.name}`;
1088
- }
1089
- }
1090
-
1091
- class RenderVal extends BaseVal {
1092
- render(stack, _rx) {
1093
- return this.eval(stack);
1094
- }
1095
- }
1096
-
1097
- class RenderNameVal extends RenderVal {
1098
- constructor(name) {
1099
- super();
1100
- this.name = name;
1101
- }
1102
- }
1103
-
1104
- class BindVal extends RenderNameVal {
1105
- eval(stack) {
1106
- return stack.lookupBind(this.name);
1107
- }
1108
- toString() {
1109
- return `@${this.name}`;
1110
- }
1111
- }
1112
-
1113
- class DynVal extends RenderNameVal {
1114
- eval(stack) {
1115
- return stack.lookupDynamic(this.name);
1116
- }
1117
- toPathItem() {
1118
- return null;
1119
- }
1120
- toString() {
1121
- return `*${this.name}`;
1122
- }
1123
- }
1124
-
1125
- class FieldVal extends RenderNameVal {
1126
- eval(stack) {
1127
- return stack.lookupField(this.name);
1128
- }
1129
- toPathItem() {
1130
- return new FieldStep(this.name);
1131
- }
1132
- toRawFieldVal() {
1133
- return new RawFieldVal(this.name);
1134
- }
1135
- toString() {
1136
- return `.${this.name}`;
1137
- }
1138
- }
1139
-
1140
- class ComputedVal extends RenderNameVal {
1141
- eval(stack) {
1142
- return stack.lookupComputed(this.name);
1143
- }
1144
- toString() {
1145
- return `$${this.name}`;
1146
- }
1147
- }
1148
-
1149
- class SeqAccessVal extends RenderVal {
1150
- constructor(seqVal, keyVal) {
1151
- super();
1152
- this.seqVal = seqVal;
1153
- this.keyVal = keyVal;
1154
- }
1155
- toPathItem() {
1156
- return new SeqAccessStep(this.seqVal.name, this.keyVal.name);
1157
- }
1158
- eval(stack) {
1159
- const key = this.keyVal.eval(stack);
1160
- return this.seqVal.eval(stack).get(key, null);
1161
- }
1162
- toString() {
1163
- return `${this.seqVal}[${this.keyVal}]`;
1164
- }
1165
- }
1166
- var VAL_SUB_TYPE_STRING_TEMPLATE = 0;
1167
- var VAL_SUB_TYPE_SEQ_ACCESS = 1;
1168
- var VAL_SUB_TYPE_INVALID = 2;
1169
- var VAL_SUB_TYPE_CONST_STRING = 3;
1170
- function getValSubType(s) {
1171
- let open = 0;
1172
- let close = 0;
1173
- for (let i = 0;i < s.length; i++) {
1174
- switch (s.charCodeAt(i)) {
1175
- case 91:
1176
- if (open > 0) {
1177
- return VAL_SUB_TYPE_INVALID;
1178
- }
1179
- open += 1;
1180
- break;
1181
- case 93:
1182
- if (close > 0 || open === 0) {
1183
- return VAL_SUB_TYPE_INVALID;
1184
- }
1185
- close += 1;
1186
- break;
1187
- case 123:
1188
- return VAL_SUB_TYPE_STRING_TEMPLATE;
1189
- case 125:
1190
- return VAL_SUB_TYPE_CONST_STRING;
1191
- }
1192
- }
1193
- if (open > 0 || close > 0) {
1194
- return open === 1 && close === 1 ? VAL_SUB_TYPE_SEQ_ACCESS : VAL_SUB_TYPE_INVALID;
1195
- }
1196
- return -1;
1197
- }
1198
- var vp = new ValParser;
1199
-
1200
- // src/attribute.js
1201
- class Attributes {
1202
- constructor(items) {
1203
- this.items = items;
1204
- }
1205
- eval(_stack) {
1206
- return {};
1207
- }
1208
- static parse(attributes, px, parseAll = false) {
1209
- return getAttrParser(px).parse(attributes, parseAll);
1210
- }
1211
- isConstant() {
1212
- return false;
644
+ isConstant() {
645
+ return false;
1213
646
  }
1214
647
  }
1215
648
  var booleanAttrsRaw = "itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly,async,autofocus,autoplay,controls,default,defer,disabled,hidden,inert,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected";
@@ -2956,7 +2389,7 @@ class App {
2956
2389
  this.render();
2957
2390
  }
2958
2391
  });
2959
- injectCss("tutuca-app", this.comps.compileStyles());
2392
+ injectCss("tutuca-app", this.comps.compileStyles(), opts?.head ?? document.head);
2960
2393
  if (opts?.noCache) {
2961
2394
  this.renderer.setNullCache();
2962
2395
  this.comps.setNullComputedCache();
@@ -3001,15 +2434,15 @@ class App {
3001
2434
  this._evictCacheId = null;
3002
2435
  }
3003
2436
  }
3004
- function injectCss(nodeId, style) {
2437
+ function injectCss(nodeId, style, styleTarget = document.head) {
3005
2438
  const styleNode = document.createElement("style");
3006
- const currentNodeWithId = document.head.querySelector(`#${nodeId}`);
2439
+ const currentNodeWithId = styleTarget.querySelector(`#${nodeId}`);
3007
2440
  if (currentNodeWithId) {
3008
- document.head.removeChild(currentNodeWithId);
2441
+ styleTarget.removeChild(currentNodeWithId);
3009
2442
  }
3010
2443
  styleNode.id = nodeId;
3011
2444
  styleNode.innerHTML = style;
3012
- document.head.appendChild(styleNode);
2445
+ styleTarget.appendChild(styleNode);
3013
2446
  }
3014
2447
  function getClosestDropTarget(target, rootNode, count) {
3015
2448
  let node = target;
@@ -3701,28 +3134,28 @@ function hashCollection(collection) {
3701
3134
  }
3702
3135
  const ordered = isOrdered(collection);
3703
3136
  const keyed = isKeyed(collection);
3704
- let h2 = ordered ? 1 : 0;
3137
+ let h = ordered ? 1 : 0;
3705
3138
  collection.__iterate(keyed ? ordered ? (v, k) => {
3706
- h2 = 31 * h2 + hashMerge(hash(v), hash(k)) | 0;
3139
+ h = 31 * h + hashMerge(hash(v), hash(k)) | 0;
3707
3140
  } : (v, k) => {
3708
- h2 = h2 + hashMerge(hash(v), hash(k)) | 0;
3141
+ h = h + hashMerge(hash(v), hash(k)) | 0;
3709
3142
  } : ordered ? (v) => {
3710
- h2 = 31 * h2 + hash(v) | 0;
3143
+ h = 31 * h + hash(v) | 0;
3711
3144
  } : (v) => {
3712
- h2 = h2 + hash(v) | 0;
3145
+ h = h + hash(v) | 0;
3713
3146
  });
3714
- return murmurHashOfSize(collection.size, h2);
3147
+ return murmurHashOfSize(collection.size, h);
3715
3148
  }
3716
3149
  var hashMerge = (a, b) => a ^ b + 2654435769 + (a << 6) + (a >> 2) | 0;
3717
- function murmurHashOfSize(size, h2) {
3718
- h2 = Math.imul(h2, 3432918353);
3719
- h2 = Math.imul(h2 << 15 | h2 >>> -15, 461845907);
3720
- h2 = Math.imul(h2 << 13 | h2 >>> -13, 5);
3721
- h2 = (h2 + 3864292196 | 0) ^ size;
3722
- h2 = Math.imul(h2 ^ h2 >>> 16, 2246822507);
3723
- h2 = Math.imul(h2 ^ h2 >>> 13, 3266489909);
3724
- h2 = smi(h2 ^ h2 >>> 16);
3725
- return h2;
3150
+ function murmurHashOfSize(size, h) {
3151
+ h = Math.imul(h, 3432918353);
3152
+ h = Math.imul(h << 15 | h >>> -15, 461845907);
3153
+ h = Math.imul(h << 13 | h >>> -13, 5);
3154
+ h = (h + 3864292196 | 0) ^ size;
3155
+ h = Math.imul(h ^ h >>> 16, 2246822507);
3156
+ h = Math.imul(h ^ h >>> 13, 3266489909);
3157
+ h = smi(h ^ h >>> 16);
3158
+ return h;
3726
3159
  }
3727
3160
  function quoteString(value) {
3728
3161
  try {
@@ -5831,7 +5264,7 @@ var List = (value) => {
5831
5264
  }
5832
5265
  assertNotInfinite(size);
5833
5266
  if (size > 0 && size < SIZE) {
5834
- return makeList(0, size, SHIFT, null, new VNode2(iter.toArray()));
5267
+ return makeList(0, size, SHIFT, null, new VNode(iter.toArray()));
5835
5268
  }
5836
5269
  return empty.withMutations((list) => {
5837
5270
  list.setSize(size);
@@ -6022,7 +5455,7 @@ class ListImpl extends IndexedCollectionImpl {
6022
5455
  }
6023
5456
  List.isList = isList;
6024
5457
 
6025
- class VNode2 {
5458
+ class VNode {
6026
5459
  constructor(array, ownerID) {
6027
5460
  this.array = array;
6028
5461
  this.ownerID = ownerID;
@@ -6033,7 +5466,7 @@ class VNode2 {
6033
5466
  }
6034
5467
  const originIndex = index >>> level & MASK;
6035
5468
  if (originIndex >= this.array.length) {
6036
- return new VNode2([], ownerID);
5469
+ return new VNode([], ownerID);
6037
5470
  }
6038
5471
  const removingFirst = originIndex === 0;
6039
5472
  let newChild;
@@ -6259,7 +5692,7 @@ function editableVNode(node, ownerID) {
6259
5692
  if (ownerID && ownerID === node?.ownerID) {
6260
5693
  return node;
6261
5694
  }
6262
- return new VNode2(node?.array.slice() ?? [], ownerID);
5695
+ return new VNode(node?.array.slice() ?? [], ownerID);
6263
5696
  }
6264
5697
  function listNodeFor(list, rawIndex) {
6265
5698
  if (rawIndex >= getTailOffset(list._capacity)) {
@@ -6297,7 +5730,7 @@ function setListBounds(list, begin, end) {
6297
5730
  let newRoot = list._root;
6298
5731
  let offsetShift = 0;
6299
5732
  while (newOrigin + offsetShift < 0) {
6300
- newRoot = new VNode2(newRoot?.array.length ? [undefined, newRoot] : [], owner);
5733
+ newRoot = new VNode(newRoot?.array.length ? [undefined, newRoot] : [], owner);
6301
5734
  newLevel += SHIFT;
6302
5735
  offsetShift += 1 << newLevel;
6303
5736
  }
@@ -6310,11 +5743,11 @@ function setListBounds(list, begin, end) {
6310
5743
  const oldTailOffset = getTailOffset(oldCapacity);
6311
5744
  const newTailOffset = getTailOffset(newCapacity);
6312
5745
  while (newTailOffset >= 1 << newLevel + SHIFT) {
6313
- newRoot = new VNode2(newRoot?.array.length ? [newRoot] : [], owner);
5746
+ newRoot = new VNode(newRoot?.array.length ? [newRoot] : [], owner);
6314
5747
  newLevel += SHIFT;
6315
5748
  }
6316
5749
  const oldTail = list._tail;
6317
- let newTail = newTailOffset < oldTailOffset ? listNodeFor(list, newCapacity - 1) : newTailOffset > oldTailOffset ? new VNode2([], owner) : oldTail;
5750
+ let newTail = newTailOffset < oldTailOffset ? listNodeFor(list, newCapacity - 1) : newTailOffset > oldTailOffset ? new VNode([], owner) : oldTail;
6318
5751
  if (oldTail && newTailOffset > oldTailOffset && newOrigin < oldCapacity && oldTail.array.length) {
6319
5752
  newRoot = editableVNode(newRoot, owner);
6320
5753
  let node = newRoot;
@@ -7323,9 +6756,9 @@ class RepeatImpl extends IndexedSeqImpl {
7323
6756
  var DATASET_ATTRS = ["nid", "cid", "eid", "vid", "si", "sk"];
7324
6757
 
7325
6758
  class Renderer {
7326
- constructor(comps, h2, fragment, comment, renderFn, getSeqInfo, cache) {
6759
+ constructor(comps, h, fragment, comment, renderFn, getSeqInfo, cache) {
7327
6760
  this.comps = comps;
7328
- this.h = h2;
6761
+ this.h = h;
7329
6762
  this.fragment = fragment;
7330
6763
  this.comment = comment;
7331
6764
  this.renderFn = renderFn;
@@ -7350,114 +6783,494 @@ class Renderer {
7350
6783
  }
7351
6784
  }
7352
6785
  }
7353
- return dom.innerHTML;
6786
+ return dom.innerHTML;
6787
+ }
6788
+ renderRoot(stack, val, viewName = null) {
6789
+ const c = this.comps.getCompFor(val);
6790
+ const nid = c.getView(viewName).anode.nodeId ?? null;
6791
+ return c ? this._rValComp(stack, val, c, nid, "ROOT", viewName) : null;
6792
+ }
6793
+ renderIt(stack, nodeId, key, viewName) {
6794
+ const c = this.comps.getCompFor(stack.it);
6795
+ return c ? this._rValComp(stack, stack.it, c, nodeId, key, viewName) : null;
6796
+ }
6797
+ _rValComp(stack, val, comp, nid, key, viewName) {
6798
+ const cacheKey = `${viewName ?? stack.viewsId ?? ""}${nid}-${key}`;
6799
+ const cachedNode = this.cache.get(val, cacheKey);
6800
+ if (cachedNode) {
6801
+ return cachedNode;
6802
+ }
6803
+ const view = viewName ? comp.getView(viewName) : stack.lookupBestView(comp.views, "main");
6804
+ const meta = this.renderMetadata("Comp", { nid });
6805
+ const dom = this.renderFragment([meta, view.render(stack, this)]);
6806
+ this.cache.set(val, cacheKey, dom);
6807
+ return dom;
6808
+ }
6809
+ renderEach(stack, iterInfo, nodeId, viewName) {
6810
+ const { seq, filter, loopWith } = iterInfo.eval(stack);
6811
+ const [attrName, gen] = this.getSeqInfo(seq);
6812
+ const r = [];
6813
+ const iterData = loopWith.call(stack.it, seq);
6814
+ for (const [key, value] of gen(seq)) {
6815
+ if (filter.call(stack.it, key, value, iterData)) {
6816
+ const newStack = stack.enter(value, { key }, true);
6817
+ const dom = this.renderIt(newStack, nodeId, key, viewName);
6818
+ r.push(this.renderMetadata("Each", { nid: nodeId, [attrName]: key }));
6819
+ r.push(dom);
6820
+ }
6821
+ }
6822
+ return r;
6823
+ }
6824
+ renderEachWhen(stack, iterInfo, node, nid) {
6825
+ const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
6826
+ const [attrName, gen] = this.getSeqInfo(seq);
6827
+ const hasEnricher = !!enricher;
6828
+ const r = [];
6829
+ const iterData = loopWith.call(stack.it, seq);
6830
+ for (const [key, value] of gen(seq)) {
6831
+ if (filter.call(stack.it, key, value, iterData)) {
6832
+ const bindings = { key, value };
6833
+ const cacheKey = `${nid}-${key}`;
6834
+ let cachedNode;
6835
+ if (hasEnricher) {
6836
+ enricher.call(stack.it, bindings, key, value, iterData);
6837
+ cachedNode = this.cache.get2(stack.it, value, cacheKey);
6838
+ } else {
6839
+ cachedNode = this.cache.get(value, cacheKey);
6840
+ }
6841
+ if (cachedNode) {
6842
+ r.push(this.renderMetadata("Each", { nid, [attrName]: key }));
6843
+ r.push(cachedNode);
6844
+ continue;
6845
+ }
6846
+ const newStack = stack.enter(value, bindings, false);
6847
+ const dom = node.render(newStack, this);
6848
+ r.push(this.renderMetadata("Each", { nid, [attrName]: key }));
6849
+ if (hasEnricher) {
6850
+ this.cache.set2(stack.it, value, cacheKey, dom);
6851
+ } else {
6852
+ this.cache.set(value, cacheKey, dom);
6853
+ }
6854
+ r.push(dom);
6855
+ }
6856
+ }
6857
+ return r;
6858
+ }
6859
+ renderText(text) {
6860
+ return text;
6861
+ }
6862
+ renderMetadata(type, info) {
6863
+ info.$ = type;
6864
+ return this.renderComment(`§${JSON.stringify(info)}§`);
6865
+ }
6866
+ renderComment(text) {
6867
+ return this.comment(text);
6868
+ }
6869
+ renderEmpty(_text) {
6870
+ return null;
6871
+ }
6872
+ renderTag(tagName, attrs, childs) {
6873
+ return this.h(tagName, attrs, childs);
6874
+ }
6875
+ renderFragment(childs) {
6876
+ return this.fragment(childs);
6877
+ }
6878
+ }
6879
+ function* imIndexedEntries(seq) {
6880
+ let i = 0;
6881
+ for (const v of seq)
6882
+ yield [i++, v];
6883
+ }
6884
+ function* imKeyedEntries(obj) {
6885
+ for (const [key, value] of obj.toSeq().entries())
6886
+ yield [key, value];
6887
+ }
6888
+ var seqInfoByClass = new Map;
6889
+ var idxInfo = ["si", imIndexedEntries];
6890
+ var keyInfo = ["sk", imKeyedEntries];
6891
+ var unkInfo = ["si", function* nullEntries(_obj) {}];
6892
+ function basicGetSeqInfo(seq) {
6893
+ return isIndexed(seq) ? idxInfo : isKeyed(seq) ? keyInfo : seqInfoByClass.get(seq?.constructor) ?? unkInfo;
6894
+ }
6895
+
6896
+ // src/vdom.js
6897
+ function isHtmlAttribute(propName) {
6898
+ return propName[4] === "-" && (propName[0] === "d" || propName[0] === "a");
6899
+ }
6900
+ function applyProperties(node, props, previous) {
6901
+ for (const propName in props) {
6902
+ const propValue = props[propName];
6903
+ if (propValue === undefined) {
6904
+ removeProperty(node, propName, previous);
6905
+ } else if (isHtmlAttribute(propName)) {
6906
+ node.setAttribute(propName, propValue);
6907
+ } else if (propName === "dangerouslySetInnerHTML") {
6908
+ node.innerHTML = propValue.__html ?? "";
6909
+ } else if (typeof propValue === "object" && propValue !== null) {
6910
+ patchObject(node, previous, propName, propValue);
6911
+ } else if (propName === "className") {
6912
+ node.setAttribute("class", propValue);
6913
+ } else {
6914
+ node[propName] = propValue;
6915
+ }
6916
+ }
6917
+ }
6918
+ function removeProperty(node, propName, previous) {
6919
+ const previousValue = previous[propName];
6920
+ if (propName === "dangerouslySetInnerHTML") {
6921
+ node.innerHTML = "";
6922
+ } else if (isHtmlAttribute(propName)) {
6923
+ node.removeAttribute(propName);
6924
+ } else if (typeof previousValue === "string") {
6925
+ if (propName !== "className")
6926
+ node[propName] = "";
6927
+ const attrName = propName === "className" ? "class" : propName === "htmlFor" ? "for" : propName;
6928
+ node.removeAttribute(attrName);
6929
+ } else {
6930
+ node[propName] = null;
6931
+ }
6932
+ }
6933
+ function patchObject(node, previous, propName, propValue) {
6934
+ const previousValue = previous?.[propName];
6935
+ if (previousValue && typeof previousValue === "object" && Object.getPrototypeOf(previousValue) !== Object.getPrototypeOf(propValue)) {
6936
+ node[propName] = propValue;
6937
+ return;
6938
+ }
6939
+ let current = node[propName];
6940
+ if (typeof current !== "object" || current === null) {
6941
+ node[propName] = {};
6942
+ current = node[propName];
6943
+ }
6944
+ const target = current;
6945
+ for (const k in propValue) {
6946
+ target[k] = propValue[k];
6947
+ }
6948
+ }
6949
+
6950
+ class VBase {
6951
+ isEqualTo(other) {
6952
+ return this === other;
6953
+ }
6954
+ toDom(_opts) {
6955
+ return null;
6956
+ }
6957
+ }
6958
+ function getKey(child) {
6959
+ return child instanceof VNode2 ? child.key : undefined;
6960
+ }
6961
+ function isIterable(obj) {
6962
+ return obj != null && typeof obj !== "string" && typeof obj[Symbol.iterator] === "function";
6963
+ }
6964
+ function addChild(normalizedChildren, child) {
6965
+ if (child == null) {
6966
+ return;
6967
+ }
6968
+ if (isIterable(child)) {
6969
+ for (const c of child) {
6970
+ addChild(normalizedChildren, c);
6971
+ }
6972
+ } else if (child instanceof VBase) {
6973
+ if (child instanceof VFragment) {
6974
+ normalizedChildren.push(...child.childs);
6975
+ } else {
6976
+ normalizedChildren.push(child);
6977
+ }
6978
+ } else {
6979
+ normalizedChildren.push(new VText(child));
6980
+ }
6981
+ }
6982
+
6983
+ class VText extends VBase {
6984
+ constructor(text) {
6985
+ super();
6986
+ this.text = String(text);
6987
+ }
6988
+ get nodeType() {
6989
+ return 3;
6990
+ }
6991
+ isEqualTo(other) {
6992
+ return other instanceof VText && this.text === other.text;
6993
+ }
6994
+ toDom(opts) {
6995
+ return opts.document.createTextNode(this.text);
6996
+ }
6997
+ }
6998
+
6999
+ class VComment extends VBase {
7000
+ constructor(text) {
7001
+ super();
7002
+ this.text = text;
7003
+ }
7004
+ get nodeType() {
7005
+ return 8;
7006
+ }
7007
+ isEqualTo(other) {
7008
+ return other instanceof VComment && this.text === other.text;
7009
+ }
7010
+ toDom(opts) {
7011
+ return opts.document.createComment(this.text);
7012
+ }
7013
+ }
7014
+
7015
+ class VFragment extends VBase {
7016
+ constructor(childs) {
7017
+ super();
7018
+ const normalized = [];
7019
+ addChild(normalized, childs);
7020
+ this.childs = normalized;
7021
+ }
7022
+ get nodeType() {
7023
+ return 11;
7024
+ }
7025
+ isEqualTo(other) {
7026
+ if (!(other instanceof VFragment) || this.childs.length !== other.childs.length) {
7027
+ return false;
7028
+ }
7029
+ for (let i = 0;i < this.childs.length; i++) {
7030
+ if (!this.childs[i].isEqualTo(other.childs[i])) {
7031
+ return false;
7032
+ }
7033
+ }
7034
+ return true;
7035
+ }
7036
+ toDom(opts) {
7037
+ const fragment = opts.document.createDocumentFragment();
7038
+ for (const child of this.childs) {
7039
+ const childNode = child.toDom(opts);
7040
+ if (childNode) {
7041
+ fragment.appendChild(childNode);
7042
+ }
7043
+ }
7044
+ return fragment;
7354
7045
  }
7355
- renderRoot(stack, val, viewName = null) {
7356
- const c = this.comps.getCompFor(val);
7357
- const nid = c.getView(viewName).anode.nodeId ?? null;
7358
- return c ? this._rValComp(stack, val, c, nid, "ROOT", viewName) : null;
7046
+ }
7047
+
7048
+ class VNode2 extends VBase {
7049
+ constructor(tag, attrs, childs, key, namespace) {
7050
+ super();
7051
+ this.tag = tag;
7052
+ this.attrs = attrs ?? {};
7053
+ this.childs = childs ?? [];
7054
+ this.key = key != null ? String(key) : undefined;
7055
+ this.namespace = typeof namespace === "string" ? namespace : null;
7359
7056
  }
7360
- renderIt(stack, nodeId, key, viewName) {
7361
- const c = this.comps.getCompFor(stack.it);
7362
- return c ? this._rValComp(stack, stack.it, c, nodeId, key, viewName) : null;
7057
+ get nodeType() {
7058
+ return 1;
7363
7059
  }
7364
- _rValComp(stack, val, comp, nid, key, viewName) {
7365
- const cacheKey = `${viewName ?? stack.viewsId ?? ""}${nid}-${key}`;
7366
- const cachedNode = this.cache.get(val, cacheKey);
7367
- if (cachedNode) {
7368
- return cachedNode;
7060
+ isEqualTo(other) {
7061
+ if (!(other instanceof VNode2) || this.tag !== other.tag || this.key !== other.key || this.namespace !== other.namespace || this.childs.length !== other.childs.length) {
7062
+ return false;
7369
7063
  }
7370
- const view = viewName ? comp.getView(viewName) : stack.lookupBestView(comp.views, "main");
7371
- const meta = this.renderMetadata("Comp", { nid });
7372
- const dom = this.renderFragment([meta, view.render(stack, this)]);
7373
- this.cache.set(val, cacheKey, dom);
7374
- return dom;
7064
+ for (const key in this.attrs) {
7065
+ if (this.attrs[key] !== other.attrs[key]) {
7066
+ return false;
7067
+ }
7068
+ }
7069
+ for (const key in other.attrs) {
7070
+ if (!Object.hasOwn(this.attrs, key)) {
7071
+ return false;
7072
+ }
7073
+ }
7074
+ for (let i = 0;i < this.childs.length; i++) {
7075
+ if (!this.childs[i].isEqualTo(other.childs[i])) {
7076
+ return false;
7077
+ }
7078
+ }
7079
+ return true;
7375
7080
  }
7376
- renderEach(stack, iterInfo, nodeId, viewName) {
7377
- const { seq, filter, loopWith } = iterInfo.eval(stack);
7378
- const [attrName, gen] = this.getSeqInfo(seq);
7379
- const r = [];
7380
- const iterData = loopWith.call(stack.it, seq);
7381
- for (const [key, value] of gen(seq)) {
7382
- if (filter.call(stack.it, key, value, iterData)) {
7383
- const newStack = stack.enter(value, { key }, true);
7384
- const dom = this.renderIt(newStack, nodeId, key, viewName);
7385
- r.push(this.renderMetadata("Each", { nid: nodeId, [attrName]: key }));
7386
- r.push(dom);
7081
+ toDom(opts) {
7082
+ const doc = opts.document;
7083
+ const node = this.namespace === null ? doc.createElement(this.tag) : doc.createElementNS(this.namespace, this.tag);
7084
+ applyProperties(node, this.attrs, {});
7085
+ for (const child of this.childs) {
7086
+ const childNode = child.toDom(opts);
7087
+ if (childNode) {
7088
+ node.appendChild(childNode);
7387
7089
  }
7388
7090
  }
7389
- return r;
7091
+ return node;
7390
7092
  }
7391
- renderEachWhen(stack, iterInfo, node, nid) {
7392
- const { seq, filter, loopWith, enricher } = iterInfo.eval(stack);
7393
- const [attrName, gen] = this.getSeqInfo(seq);
7394
- const hasEnricher = !!enricher;
7395
- const r = [];
7396
- const iterData = loopWith.call(stack.it, seq);
7397
- for (const [key, value] of gen(seq)) {
7398
- if (filter.call(stack.it, key, value, iterData)) {
7399
- const bindings = { key, value };
7400
- const cacheKey = `${nid}-${key}`;
7401
- let cachedNode;
7402
- if (hasEnricher) {
7403
- enricher.call(stack.it, bindings, key, value, iterData);
7404
- cachedNode = this.cache.get2(stack.it, value, cacheKey);
7405
- } else {
7406
- cachedNode = this.cache.get(value, cacheKey);
7407
- }
7408
- if (cachedNode) {
7409
- r.push(this.renderMetadata("Each", { nid, [attrName]: key }));
7410
- r.push(cachedNode);
7411
- continue;
7412
- }
7413
- const newStack = stack.enter(value, bindings, false);
7414
- const dom = node.render(newStack, this);
7415
- r.push(this.renderMetadata("Each", { nid, [attrName]: key }));
7416
- if (hasEnricher) {
7417
- this.cache.set2(stack.it, value, cacheKey, dom);
7418
- } else {
7419
- this.cache.set(value, cacheKey, dom);
7093
+ }
7094
+ function diffProps(a, b) {
7095
+ let diff = null;
7096
+ for (const aKey in a) {
7097
+ if (!Object.hasOwn(b, aKey)) {
7098
+ diff ??= {};
7099
+ diff[aKey] = undefined;
7100
+ continue;
7101
+ }
7102
+ const aValue = a[aKey];
7103
+ const bValue = b[aKey];
7104
+ if (aValue === bValue) {} else if (typeof aValue === "object" && aValue !== null && typeof bValue === "object" && bValue !== null) {
7105
+ if (Object.getPrototypeOf(bValue) !== Object.getPrototypeOf(aValue)) {
7106
+ diff ??= {};
7107
+ diff[aKey] = bValue;
7108
+ } else {
7109
+ const objectDiff = diffProps(aValue, bValue);
7110
+ if (objectDiff) {
7111
+ diff ??= {};
7112
+ diff[aKey] = objectDiff;
7420
7113
  }
7421
- r.push(dom);
7422
7114
  }
7115
+ } else {
7116
+ diff ??= {};
7117
+ diff[aKey] = bValue;
7423
7118
  }
7424
- return r;
7425
- }
7426
- renderText(text) {
7427
- return text;
7428
7119
  }
7429
- renderMetadata(type, info) {
7430
- info.$ = type;
7431
- return this.renderComment(`§${JSON.stringify(info)}§`);
7120
+ for (const bKey in b) {
7121
+ if (!Object.hasOwn(a, bKey)) {
7122
+ diff ??= {};
7123
+ diff[bKey] = b[bKey];
7124
+ }
7432
7125
  }
7433
- renderComment(text) {
7434
- return this.comment(text);
7126
+ return diff;
7127
+ }
7128
+ function replaceNode(domNode, vnode, options) {
7129
+ const parentNode = domNode.parentNode;
7130
+ const newNode = vnode.toDom(options);
7131
+ if (parentNode && newNode && newNode !== domNode) {
7132
+ parentNode.replaceChild(newNode, domNode);
7435
7133
  }
7436
- renderEmpty(_text) {
7437
- return null;
7134
+ return newNode || domNode;
7135
+ }
7136
+ function morphNode(domNode, source, target, opts) {
7137
+ if (source === target || source.isEqualTo(target))
7138
+ return domNode;
7139
+ if (source instanceof VText && target instanceof VText || source instanceof VComment && target instanceof VComment) {
7140
+ domNode.data = target.text;
7141
+ return domNode;
7438
7142
  }
7439
- renderTag(tagName, attrs, childs) {
7440
- return this.h(tagName, attrs, childs);
7143
+ if (source instanceof VNode2 && target instanceof VNode2 && source.tag === target.tag && source.namespace === target.namespace && source.key === target.key) {
7144
+ const propsDiff = diffProps(source.attrs, target.attrs);
7145
+ if (propsDiff) {
7146
+ applyProperties(domNode, propsDiff, source.attrs);
7147
+ }
7148
+ if (!target.attrs.dangerouslySetInnerHTML) {
7149
+ morphChildren(domNode, source.childs, target.childs, source.tag, opts);
7150
+ }
7151
+ return domNode;
7441
7152
  }
7442
- renderFragment(childs) {
7443
- return this.fragment(childs);
7153
+ if (source instanceof VFragment && target instanceof VFragment) {
7154
+ morphChildren(domNode, source.childs, target.childs, null, opts);
7155
+ return domNode;
7444
7156
  }
7157
+ return replaceNode(domNode, target, opts);
7445
7158
  }
7446
- function* imIndexedEntries(seq) {
7447
- let i = 0;
7448
- for (const v of seq)
7449
- yield [i++, v];
7159
+ function morphChildren(parentDom, oldChilds, newChilds, _parentTag, opts) {
7160
+ if (oldChilds.length === 0) {
7161
+ for (const child of newChilds) {
7162
+ const node = child.toDom(opts);
7163
+ if (node)
7164
+ parentDom.appendChild(node);
7165
+ }
7166
+ return;
7167
+ }
7168
+ if (newChilds.length === 0) {
7169
+ while (parentDom.firstChild) {
7170
+ parentDom.removeChild(parentDom.firstChild);
7171
+ }
7172
+ return;
7173
+ }
7174
+ const domNodes = Array.from(parentDom.childNodes);
7175
+ const oldKeyMap = {};
7176
+ for (let i = 0;i < oldChilds.length; i++) {
7177
+ const key = getKey(oldChilds[i]);
7178
+ if (key != null)
7179
+ oldKeyMap[key] = i;
7180
+ }
7181
+ const used = new Uint8Array(oldChilds.length);
7182
+ let unkeyedCursor = 0;
7183
+ for (let j = 0;j < newChilds.length; j++) {
7184
+ const newChild = newChilds[j];
7185
+ const newKey = getKey(newChild);
7186
+ let oldIdx = -1;
7187
+ if (newKey != null) {
7188
+ if (newKey in oldKeyMap && !used[oldKeyMap[newKey]]) {
7189
+ oldIdx = oldKeyMap[newKey];
7190
+ }
7191
+ } else {
7192
+ while (unkeyedCursor < oldChilds.length) {
7193
+ if (!used[unkeyedCursor] && getKey(oldChilds[unkeyedCursor]) == null) {
7194
+ oldIdx = unkeyedCursor++;
7195
+ break;
7196
+ }
7197
+ unkeyedCursor++;
7198
+ }
7199
+ }
7200
+ if (oldIdx >= 0) {
7201
+ used[oldIdx] = 1;
7202
+ const dom = domNodes[oldIdx];
7203
+ const newDom = morphNode(dom, oldChilds[oldIdx], newChild, opts);
7204
+ const ref = parentDom.childNodes[j] ?? null;
7205
+ if (newDom !== ref)
7206
+ parentDom.insertBefore(newDom, ref);
7207
+ } else {
7208
+ const dom = newChild.toDom(opts);
7209
+ if (dom) {
7210
+ const ref = parentDom.childNodes[j] ?? null;
7211
+ parentDom.insertBefore(dom, ref);
7212
+ }
7213
+ }
7214
+ }
7215
+ for (let i = oldChilds.length - 1;i >= 0; i--) {
7216
+ if (!used[i] && domNodes[i].parentNode === parentDom) {
7217
+ parentDom.removeChild(domNodes[i]);
7218
+ }
7219
+ }
7450
7220
  }
7451
- function* imKeyedEntries(obj) {
7452
- for (const [key, value] of obj.toSeq().entries())
7453
- yield [key, value];
7221
+ var renderCache = new WeakMap;
7222
+ function render(vnode, container, options) {
7223
+ const cached = renderCache.get(container);
7224
+ const isFragment = vnode instanceof VFragment;
7225
+ if (cached) {
7226
+ const wasFragment = cached.vnode instanceof VFragment;
7227
+ if (wasFragment === isFragment) {
7228
+ const rootNode = wasFragment ? container : cached.dom;
7229
+ const newDom = morphNode(rootNode, cached.vnode, vnode, options);
7230
+ renderCache.set(container, {
7231
+ vnode,
7232
+ dom: isFragment ? container : newDom
7233
+ });
7234
+ return newDom;
7235
+ }
7236
+ renderCache.delete(container);
7237
+ }
7238
+ const domNode = vnode.toDom(options);
7239
+ if (domNode) {
7240
+ container.innerHTML = "";
7241
+ container.appendChild(domNode);
7242
+ renderCache.set(container, {
7243
+ vnode,
7244
+ dom: isFragment ? container : domNode
7245
+ });
7246
+ }
7247
+ return domNode;
7454
7248
  }
7455
- var seqInfoByClass = new Map;
7456
- var idxInfo = ["si", imIndexedEntries];
7457
- var keyInfo = ["sk", imKeyedEntries];
7458
- var unkInfo = ["si", function* nullEntries(_obj) {}];
7459
- function basicGetSeqInfo(seq) {
7460
- return isIndexed(seq) ? idxInfo : isKeyed(seq) ? keyInfo : seqInfoByClass.get(seq?.constructor) ?? unkInfo;
7249
+ function h(tagName, properties, children) {
7250
+ const tag = tagName.toUpperCase();
7251
+ const props = {};
7252
+ let key;
7253
+ let namespace;
7254
+ if (properties) {
7255
+ for (const propName in properties) {
7256
+ if (propName === "key") {
7257
+ key = properties[propName];
7258
+ } else if (propName === "namespace") {
7259
+ namespace = properties[propName];
7260
+ } else if (propName === "class") {
7261
+ props.className = properties[propName];
7262
+ } else if (propName === "for") {
7263
+ props.htmlFor = properties[propName];
7264
+ } else if (isHtmlAttribute(propName)) {
7265
+ props[propName] = String(properties[propName]);
7266
+ } else {
7267
+ props[propName] = properties[propName];
7268
+ }
7269
+ }
7270
+ }
7271
+ const normalizedChildren = [];
7272
+ addChild(normalizedChildren, children);
7273
+ return new VNode2(tag, props, normalizedChildren, key, namespace);
7461
7274
  }
7462
7275
  // src/oo.js
7463
7276
  var BAD_VALUE = Symbol("BadValue");
@@ -7899,6 +7712,7 @@ export {
7899
7712
  isKeyed,
7900
7713
  isIndexed,
7901
7714
  isMap as isIMap,
7715
+ injectCss,
7902
7716
  html,
7903
7717
  fieldsByClass,
7904
7718
  css,