tutuca 0.13.3 → 0.15.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/dist/tutuca-cli.js +1079 -1254
- package/dist/tutuca-dev.ext.js +1086 -1216
- package/dist/tutuca-dev.js +1095 -1225
- package/dist/tutuca-dev.min.js +4 -4
- package/dist/tutuca-extra.ext.js +1055 -1133
- package/dist/tutuca-extra.js +1061 -1139
- package/dist/tutuca-extra.min.js +3 -3
- package/dist/tutuca.ext.js +1054 -1116
- package/dist/tutuca.js +1060 -1122
- package/dist/tutuca.min.js +3 -3
- package/package.json +1 -1
- package/skill/tutuca/SKILL.md +2 -2
- package/skill/tutuca/advanced.md +48 -17
- package/skill/tutuca/component-design.md +2 -2
- package/skill/tutuca/core.md +5 -4
- package/skill/tutuca/messages-and-intents.md +9 -11
- package/skill/tutuca/patterns/README.md +1 -1
- package/skill/tutuca/patterns/edit-through-a-dynamic-target.md +11 -6
- package/skill/tutuca/patterns/share-state-across-the-tree.md +18 -3
- package/skill/tutuca/semantics.md +63 -39
- package/skill/tutuca-source/tutuca.ext.js +1054 -1116
package/dist/tutuca-cli.js
CHANGED
|
@@ -1039,8 +1039,68 @@ var init_immer2 = __esm({
|
|
|
1039
1039
|
});
|
|
1040
1040
|
|
|
1041
1041
|
// src/path.js
|
|
1042
|
-
function
|
|
1043
|
-
|
|
1042
|
+
function stepToJson(step) {
|
|
1043
|
+
if (step instanceof SeqStep) return { f: step.field, k: step.key };
|
|
1044
|
+
if (step instanceof FieldStep) return { f: step.field };
|
|
1045
|
+
if (step instanceof SeqAccessStep) return { f: step.seqField, a: step.keyField };
|
|
1046
|
+
return null;
|
|
1047
|
+
}
|
|
1048
|
+
function stepFromJson(j) {
|
|
1049
|
+
if (j == null || typeof j.f !== "string") return null;
|
|
1050
|
+
if (j.k !== void 0) return new SeqStep(j.f, j.k);
|
|
1051
|
+
if (j.a !== void 0) return new SeqAccessStep(j.f, j.a);
|
|
1052
|
+
return new FieldStep(j.f);
|
|
1053
|
+
}
|
|
1054
|
+
function pathToJson(path) {
|
|
1055
|
+
const out = [];
|
|
1056
|
+
for (const step of path.steps) {
|
|
1057
|
+
const j = stepToJson(step);
|
|
1058
|
+
if (j === null) return null;
|
|
1059
|
+
out.push(j);
|
|
1060
|
+
}
|
|
1061
|
+
return out;
|
|
1062
|
+
}
|
|
1063
|
+
function pathFromJson(j) {
|
|
1064
|
+
if (!Array.isArray(j)) return null;
|
|
1065
|
+
const steps = [];
|
|
1066
|
+
for (const item of j) {
|
|
1067
|
+
const step = stepFromJson(item);
|
|
1068
|
+
if (step === null) return null;
|
|
1069
|
+
steps.push(step);
|
|
1070
|
+
}
|
|
1071
|
+
return new Path(steps);
|
|
1072
|
+
}
|
|
1073
|
+
function walkItems(stack, items, renderPath, path) {
|
|
1074
|
+
let prev = stack.it;
|
|
1075
|
+
for (const step of items) {
|
|
1076
|
+
const next = step.lookup(prev);
|
|
1077
|
+
if (next === NONE) {
|
|
1078
|
+
console.warn("bad PathItem", { root: stack.it, step, path });
|
|
1079
|
+
return null;
|
|
1080
|
+
}
|
|
1081
|
+
renderPath = renderPath.pushItem(step);
|
|
1082
|
+
stack = step.enterFrame(stack, next, renderPath);
|
|
1083
|
+
prev = next;
|
|
1084
|
+
}
|
|
1085
|
+
return [stack, renderPath];
|
|
1086
|
+
}
|
|
1087
|
+
function keyedPath(path, key) {
|
|
1088
|
+
const steps = path.steps;
|
|
1089
|
+
const last = steps[steps.length - 1];
|
|
1090
|
+
if (last instanceof SeqStep || last instanceof FieldStep)
|
|
1091
|
+
return new Path(steps.slice(0, -1).concat(new SeqStep(last.field, key)));
|
|
1092
|
+
return null;
|
|
1093
|
+
}
|
|
1094
|
+
function renderPathText(path) {
|
|
1095
|
+
return JSON.stringify(pathToJson(path));
|
|
1096
|
+
}
|
|
1097
|
+
function parseRenderPath(text) {
|
|
1098
|
+
try {
|
|
1099
|
+
return pathFromJson(JSON.parse(text));
|
|
1100
|
+
} catch (err) {
|
|
1101
|
+
console.warn("bad render path", err, text);
|
|
1102
|
+
return null;
|
|
1103
|
+
}
|
|
1044
1104
|
}
|
|
1045
1105
|
function metaChain(n) {
|
|
1046
1106
|
const out = [];
|
|
@@ -1061,26 +1121,23 @@ function findHandlers(comp, eventIds, vid, eventName) {
|
|
|
1061
1121
|
}
|
|
1062
1122
|
return null;
|
|
1063
1123
|
}
|
|
1064
|
-
function
|
|
1065
|
-
for (let i = 0; i <
|
|
1066
|
-
const
|
|
1067
|
-
|
|
1068
|
-
if (
|
|
1124
|
+
function resolvePathPart(comp, nodeRefs, vid) {
|
|
1125
|
+
for (let i = 0; i < nodeRefs.length; i++) {
|
|
1126
|
+
const ref = nodeRefs[i];
|
|
1127
|
+
if (ref.base != null) return { base: ref.base };
|
|
1128
|
+
if (ref.nid === void 0 || ref.nid === null) continue;
|
|
1129
|
+
const ctx = new StepCtx(comp, nodeRefs, i, vid);
|
|
1130
|
+
const step = ctx.resolveNode()?.toPathStep(ctx) ?? null;
|
|
1131
|
+
if (step !== null) return { step };
|
|
1069
1132
|
}
|
|
1070
1133
|
return null;
|
|
1071
1134
|
}
|
|
1072
|
-
var NONE,
|
|
1135
|
+
var NONE, writeKey, writeSeqKey, Step, BindStep, ScopeBindStep, FieldStep, SeqStep, SeqAccessStep, EachBindStep, EachRenderItStep, Path, EMPTY_PATH, DispatchPath, StepCtx, NO_EVENT_INFO, BUBBLING_EVENTS, PathBuilder;
|
|
1073
1136
|
var init_path = __esm({
|
|
1074
1137
|
"src/path.js"() {
|
|
1075
1138
|
init_collection();
|
|
1076
1139
|
init_immer2();
|
|
1077
1140
|
NONE = /* @__PURE__ */ Symbol("NONE");
|
|
1078
|
-
readKey = (value, key, dval = null) => {
|
|
1079
|
-
if (value == null) return dval;
|
|
1080
|
-
if (value instanceof Map) return value.has(key) ? value.get(key) : dval;
|
|
1081
|
-
if (value instanceof Set) return value.has(key) ? key : dval;
|
|
1082
|
-
return Object.hasOwn(value, key) ? value[key] : dval;
|
|
1083
|
-
};
|
|
1084
1141
|
writeKey = (value, key, next) => {
|
|
1085
1142
|
if (value instanceof Map) value.set(key, next);
|
|
1086
1143
|
else if (value instanceof Set) {
|
|
@@ -1088,20 +1145,15 @@ var init_path = __esm({
|
|
|
1088
1145
|
value.add(next);
|
|
1089
1146
|
} else value[key] = next;
|
|
1090
1147
|
};
|
|
1091
|
-
writeSeqKey = (value, key, next) =>
|
|
1092
|
-
if (value instanceof Map || value instanceof Set || Array.isArray(value) || Object.hasOwn(value, key))
|
|
1093
|
-
writeKey(value, key, next);
|
|
1094
|
-
else if (typeof value?.set === "function") value.set(key, next);
|
|
1095
|
-
else writeKey(value, key, next);
|
|
1096
|
-
};
|
|
1148
|
+
writeSeqKey = (value, key, next) => !(value instanceof Map || value instanceof Set || Array.isArray(value)) && !Object.hasOwn(value, key) && typeof value?.set === "function" ? value.set(key, next) : writeKey(value, key, next);
|
|
1097
1149
|
Step = class {
|
|
1098
|
-
lookup(_v, dval = null) {
|
|
1099
|
-
return dval;
|
|
1100
|
-
}
|
|
1101
1150
|
setDraftValue(_root, _v) {
|
|
1102
1151
|
}
|
|
1103
|
-
|
|
1104
|
-
|
|
1152
|
+
// Re-enter this step while rebuilding a stack. `renderPath` is the dispatch
|
|
1153
|
+
// position AFTER this step: a rebuilt frame must carry the same render path
|
|
1154
|
+
// the renderer had there, or the provides it publishes would be located wrong.
|
|
1155
|
+
enterFrame(stack, next, renderPath) {
|
|
1156
|
+
return stack.enter(next, {}, true, renderPath);
|
|
1105
1157
|
}
|
|
1106
1158
|
toAbstractPathStep() {
|
|
1107
1159
|
return this;
|
|
@@ -1118,41 +1170,29 @@ var init_path = __esm({
|
|
|
1118
1170
|
return null;
|
|
1119
1171
|
}
|
|
1120
1172
|
};
|
|
1121
|
-
BindStep = class
|
|
1173
|
+
BindStep = class extends Step {
|
|
1122
1174
|
constructor(binds) {
|
|
1123
1175
|
super();
|
|
1124
1176
|
this.binds = binds;
|
|
1125
1177
|
}
|
|
1126
|
-
lookup(v
|
|
1178
|
+
lookup(v) {
|
|
1127
1179
|
return v;
|
|
1128
1180
|
}
|
|
1129
|
-
enterFrame(stack, next) {
|
|
1130
|
-
return stack.enter(next, { ...this.binds }, false);
|
|
1131
|
-
}
|
|
1132
|
-
withIndex(i) {
|
|
1133
|
-
return new _BindStep({ ...this.binds, key: i });
|
|
1134
|
-
}
|
|
1135
|
-
withKey(key) {
|
|
1136
|
-
return new _BindStep({ ...this.binds, key });
|
|
1181
|
+
enterFrame(stack, next, renderPath) {
|
|
1182
|
+
return stack.enter(next, { ...this.binds }, false, renderPath);
|
|
1137
1183
|
}
|
|
1138
1184
|
toAbstractPathStep() {
|
|
1139
1185
|
return null;
|
|
1140
1186
|
}
|
|
1141
1187
|
};
|
|
1142
|
-
ScopeBindStep = class
|
|
1188
|
+
ScopeBindStep = class extends BindStep {
|
|
1143
1189
|
constructor(val, binds = {}) {
|
|
1144
1190
|
super(binds);
|
|
1145
1191
|
this.val = val;
|
|
1146
1192
|
}
|
|
1147
|
-
enterFrame(stack, next) {
|
|
1193
|
+
enterFrame(stack, next, renderPath) {
|
|
1148
1194
|
const dyn = this.val.evalAsHandler(stack)?.call(stack.it) ?? {};
|
|
1149
|
-
return stack.enter(next, { ...this.binds, ...dyn }, false);
|
|
1150
|
-
}
|
|
1151
|
-
withIndex(i) {
|
|
1152
|
-
return new _ScopeBindStep(this.val, { ...this.binds, key: i });
|
|
1153
|
-
}
|
|
1154
|
-
withKey(key) {
|
|
1155
|
-
return new _ScopeBindStep(this.val, { ...this.binds, key });
|
|
1195
|
+
return stack.enter(next, { ...this.binds, ...dyn }, false, renderPath);
|
|
1156
1196
|
}
|
|
1157
1197
|
};
|
|
1158
1198
|
FieldStep = class extends Step {
|
|
@@ -1160,18 +1200,12 @@ var init_path = __esm({
|
|
|
1160
1200
|
super();
|
|
1161
1201
|
this.field = field;
|
|
1162
1202
|
}
|
|
1163
|
-
lookup(v
|
|
1164
|
-
return
|
|
1203
|
+
lookup(v) {
|
|
1204
|
+
return seqGet(v, this.field, NONE);
|
|
1165
1205
|
}
|
|
1166
1206
|
setDraftValue(root, v) {
|
|
1167
1207
|
writeKey(root, this.field, v);
|
|
1168
1208
|
}
|
|
1169
|
-
withIndex(i) {
|
|
1170
|
-
return new SeqStep(this.field, i);
|
|
1171
|
-
}
|
|
1172
|
-
withKey(k) {
|
|
1173
|
-
return new SeqStep(this.field, k);
|
|
1174
|
-
}
|
|
1175
1209
|
toKey() {
|
|
1176
1210
|
return { field: this.field };
|
|
1177
1211
|
}
|
|
@@ -1182,15 +1216,15 @@ var init_path = __esm({
|
|
|
1182
1216
|
this.field = field;
|
|
1183
1217
|
this.key = key;
|
|
1184
1218
|
}
|
|
1185
|
-
lookup(v
|
|
1186
|
-
return seqGet(
|
|
1219
|
+
lookup(v) {
|
|
1220
|
+
return seqGet(seqGet(v, this.field, null), this.key, NONE);
|
|
1187
1221
|
}
|
|
1188
1222
|
setDraftValue(root, v) {
|
|
1189
|
-
const seq =
|
|
1223
|
+
const seq = seqGet(root, this.field, null);
|
|
1190
1224
|
if (seq != null) writeSeqKey(seq, this.key, v);
|
|
1191
1225
|
}
|
|
1192
|
-
enterFrame(stack, next) {
|
|
1193
|
-
return stack.enter(next, { key: this.key }, true);
|
|
1226
|
+
enterFrame(stack, next, renderPath) {
|
|
1227
|
+
return stack.enter(next, { key: this.key }, true, renderPath);
|
|
1194
1228
|
}
|
|
1195
1229
|
toKey() {
|
|
1196
1230
|
return { field: this.field, key: this.key };
|
|
@@ -1202,20 +1236,20 @@ var init_path = __esm({
|
|
|
1202
1236
|
this.seqField = seqField;
|
|
1203
1237
|
this.keyField = keyField;
|
|
1204
1238
|
}
|
|
1205
|
-
lookup(v
|
|
1206
|
-
const seq =
|
|
1207
|
-
const key =
|
|
1208
|
-
return key !== NONE && seq !== NONE ? seqGet(seq, key,
|
|
1239
|
+
lookup(v) {
|
|
1240
|
+
const seq = seqGet(v, this.seqField, NONE);
|
|
1241
|
+
const key = seqGet(v, this.keyField, NONE);
|
|
1242
|
+
return key !== NONE && seq !== NONE ? seqGet(seq, key, NONE) : NONE;
|
|
1209
1243
|
}
|
|
1210
1244
|
setDraftValue(root, v) {
|
|
1211
|
-
const seq =
|
|
1212
|
-
const key =
|
|
1245
|
+
const seq = seqGet(root, this.seqField, NONE);
|
|
1246
|
+
const key = seqGet(root, this.keyField, NONE);
|
|
1213
1247
|
if (seq !== NONE && key !== NONE) writeSeqKey(seq, key, v);
|
|
1214
1248
|
}
|
|
1215
1249
|
// Resolve `keyField` against `v` now and freeze it as a literal-key `SeqStep`, so a
|
|
1216
1250
|
// later lookup/setValue lands on this same item even if `keyField` changes meanwhile.
|
|
1217
1251
|
pinKey(v) {
|
|
1218
|
-
const key =
|
|
1252
|
+
const key = seqGet(v, this.keyField, NONE);
|
|
1219
1253
|
return key === NONE ? this : new SeqStep(this.seqField, key);
|
|
1220
1254
|
}
|
|
1221
1255
|
// The key is a *field reference* resolved live, so it is unknown without a value;
|
|
@@ -1226,67 +1260,31 @@ var init_path = __esm({
|
|
|
1226
1260
|
}
|
|
1227
1261
|
};
|
|
1228
1262
|
EachBindStep = class extends Step {
|
|
1229
|
-
constructor(
|
|
1263
|
+
constructor(eachNode, key) {
|
|
1230
1264
|
super();
|
|
1231
|
-
this.
|
|
1265
|
+
this.eachNode = eachNode;
|
|
1232
1266
|
this.key = key;
|
|
1233
1267
|
}
|
|
1234
|
-
lookup(v
|
|
1268
|
+
lookup(v) {
|
|
1235
1269
|
return v;
|
|
1236
1270
|
}
|
|
1237
1271
|
// Replay the renderer's per-item binds (key, value + any @enrich-with binds)
|
|
1238
1272
|
// so a rebuilt stack matches the one @each rendered with.
|
|
1239
|
-
enterFrame(stack, next) {
|
|
1240
|
-
return stack.enter(next, this.
|
|
1273
|
+
enterFrame(stack, next, renderPath) {
|
|
1274
|
+
return stack.enter(next, this.eachNode.enrichBinds(stack, this.key), false, renderPath);
|
|
1241
1275
|
}
|
|
1242
1276
|
toAbstractPathStep() {
|
|
1243
1277
|
return null;
|
|
1244
1278
|
}
|
|
1245
1279
|
};
|
|
1246
1280
|
EachRenderItStep = class extends SeqStep {
|
|
1247
|
-
enterFrame(stack, next) {
|
|
1248
|
-
return stack.enter(next, { key: this.key, value: next }, false).enter(next, {}, true);
|
|
1281
|
+
enterFrame(stack, next, renderPath) {
|
|
1282
|
+
return stack.enter(next, { key: this.key, value: next }, false, renderPath).enter(next, {}, true, renderPath);
|
|
1249
1283
|
}
|
|
1250
1284
|
toAbstractPathStep() {
|
|
1251
1285
|
return new SeqStep(this.field, this.key);
|
|
1252
1286
|
}
|
|
1253
1287
|
};
|
|
1254
|
-
DynStep = class extends Step {
|
|
1255
|
-
constructor(producerCompId, producerSteps) {
|
|
1256
|
-
super();
|
|
1257
|
-
this.producerCompId = producerCompId;
|
|
1258
|
-
this.producerSteps = producerSteps;
|
|
1259
|
-
this.interiorCids = /* @__PURE__ */ new Set();
|
|
1260
|
-
}
|
|
1261
|
-
// Steps spliced into the transaction path in place of this marker.
|
|
1262
|
-
teleportSteps() {
|
|
1263
|
-
return this.producerSteps;
|
|
1264
|
-
}
|
|
1265
|
-
lookup(_v, dval = null) {
|
|
1266
|
-
warnRawDynStep("lookup", this);
|
|
1267
|
-
return dval;
|
|
1268
|
-
}
|
|
1269
|
-
enterFrame(stack, _next) {
|
|
1270
|
-
warnRawDynStep("enterFrame", this);
|
|
1271
|
-
return stack;
|
|
1272
|
-
}
|
|
1273
|
-
};
|
|
1274
|
-
DynEachStep = class extends DynStep {
|
|
1275
|
-
constructor(producerCompId, producerSteps, key) {
|
|
1276
|
-
super(producerCompId, producerSteps);
|
|
1277
|
-
this.key = key;
|
|
1278
|
-
}
|
|
1279
|
-
teleportSteps() {
|
|
1280
|
-
const { producerSteps, key } = this;
|
|
1281
|
-
if (producerSteps.length === 0) return producerSteps;
|
|
1282
|
-
const last = producerSteps[producerSteps.length - 1];
|
|
1283
|
-
if (!(last instanceof FieldStep)) {
|
|
1284
|
-
console.warn("DynEachStep: seq-access dynamic cannot be iterated", this);
|
|
1285
|
-
return producerSteps;
|
|
1286
|
-
}
|
|
1287
|
-
return producerSteps.slice(0, -1).concat(new SeqStep(last.field, key));
|
|
1288
|
-
}
|
|
1289
|
-
};
|
|
1290
1288
|
Path = class _Path {
|
|
1291
1289
|
constructor(steps = []) {
|
|
1292
1290
|
this.steps = steps;
|
|
@@ -1294,43 +1292,13 @@ var init_path = __esm({
|
|
|
1294
1292
|
concat(steps) {
|
|
1295
1293
|
return new _Path(this.steps.concat(steps));
|
|
1296
1294
|
}
|
|
1297
|
-
popStep
|
|
1298
|
-
|
|
1299
|
-
}
|
|
1300
|
-
// The dispatch path: frame-only steps removed, one step per crossed component
|
|
1301
|
-
// (DynStep included). `popStep` over it bubbles through every component.
|
|
1295
|
+
// Frame-only steps removed, one step per crossed component: `popStep` over the
|
|
1296
|
+
// result bubbles through every component.
|
|
1302
1297
|
compact() {
|
|
1303
1298
|
const out = [];
|
|
1304
1299
|
for (const step of this.steps) {
|
|
1305
1300
|
const s = step.toAbstractPathStep();
|
|
1306
|
-
if (s !== null)
|
|
1307
|
-
if (s !== step) s._originCid = step._originCid;
|
|
1308
|
-
out.push(s);
|
|
1309
|
-
}
|
|
1310
|
-
}
|
|
1311
|
-
return new _Path(out);
|
|
1312
|
-
}
|
|
1313
|
-
// The abstract path used to apply a transaction: every DynStep is teleported —
|
|
1314
|
-
// the steps interior to its producer..consumer span are dropped and the
|
|
1315
|
-
// producer's own path spliced in — so a mutation lands on the data's real
|
|
1316
|
-
// location. A path with no DynStep is returned unchanged.
|
|
1317
|
-
toTransactionPath() {
|
|
1318
|
-
let hasDyn = false;
|
|
1319
|
-
for (const step of this.steps)
|
|
1320
|
-
if (step instanceof DynStep) {
|
|
1321
|
-
hasDyn = true;
|
|
1322
|
-
break;
|
|
1323
|
-
}
|
|
1324
|
-
if (!hasDyn) return this;
|
|
1325
|
-
const out = [];
|
|
1326
|
-
for (const step of this.steps) {
|
|
1327
|
-
if (step instanceof DynStep) {
|
|
1328
|
-
while (out.length > 0 && step.interiorCids.has(out[out.length - 1]._originCid)) out.pop();
|
|
1329
|
-
for (const ts of step.teleportSteps()) {
|
|
1330
|
-
ts._originCid = step.producerCompId;
|
|
1331
|
-
out.push(ts);
|
|
1332
|
-
}
|
|
1333
|
-
} else out.push(step);
|
|
1301
|
+
if (s !== null) out.push(s);
|
|
1334
1302
|
}
|
|
1335
1303
|
return new _Path(out);
|
|
1336
1304
|
}
|
|
@@ -1338,7 +1306,6 @@ var init_path = __esm({
|
|
|
1338
1306
|
// key as it is *now* so a later lookup/setValue lands on the same item even if the
|
|
1339
1307
|
// keyField changed meanwhile (e.g. the selected tab moved while an intent was in
|
|
1340
1308
|
// flight). Returns a new Path with those steps replaced; `this` if nothing pinned.
|
|
1341
|
-
// Must be called on a transaction path (no DynSteps — call toTransactionPath first).
|
|
1342
1309
|
pinKeys(root) {
|
|
1343
1310
|
let curVal = root;
|
|
1344
1311
|
let out = null;
|
|
@@ -1346,7 +1313,7 @@ var init_path = __esm({
|
|
|
1346
1313
|
const step = this.steps[i];
|
|
1347
1314
|
const pinned = step.pinKey(curVal);
|
|
1348
1315
|
if (pinned !== step) (out ??= this.steps.slice())[i] = pinned;
|
|
1349
|
-
curVal = step.lookup(curVal
|
|
1316
|
+
curVal = step.lookup(curVal);
|
|
1350
1317
|
if (curVal === NONE) break;
|
|
1351
1318
|
}
|
|
1352
1319
|
return out ? new _Path(out) : this;
|
|
@@ -1354,20 +1321,20 @@ var init_path = __esm({
|
|
|
1354
1321
|
lookup(v, dval = null) {
|
|
1355
1322
|
let curVal = v;
|
|
1356
1323
|
for (const step of this.steps) {
|
|
1357
|
-
curVal = step.lookup(curVal
|
|
1324
|
+
curVal = step.lookup(curVal);
|
|
1358
1325
|
if (curVal === NONE) return dval;
|
|
1359
1326
|
}
|
|
1360
1327
|
return curVal;
|
|
1361
1328
|
}
|
|
1362
1329
|
// The values entered along the path, root→leaf (root included): index 0 is `root`,
|
|
1363
1330
|
// the last entry is the leaf this path resolves to. Stops early at the first
|
|
1364
|
-
// unresolvable step.
|
|
1365
|
-
//
|
|
1331
|
+
// unresolvable step. Used to walk the component instances on a dispatch path
|
|
1332
|
+
// (filter via Components.getCompFor).
|
|
1366
1333
|
resolveChain(root) {
|
|
1367
1334
|
const out = [root];
|
|
1368
1335
|
let curVal = root;
|
|
1369
1336
|
for (const step of this.steps) {
|
|
1370
|
-
curVal = step.lookup(curVal
|
|
1337
|
+
curVal = step.lookup(curVal);
|
|
1371
1338
|
if (curVal === NONE) break;
|
|
1372
1339
|
out.push(curVal);
|
|
1373
1340
|
}
|
|
@@ -1376,7 +1343,7 @@ var init_path = __esm({
|
|
|
1376
1343
|
// A flat `[{ field, key? }]` list of the addressing steps, skipping frame-only
|
|
1377
1344
|
// steps (binds). Generic path introspection so tooling (e.g. the storybook
|
|
1378
1345
|
// activity log) can identify which subtree a transaction touched without
|
|
1379
|
-
// depending on Step internals.
|
|
1346
|
+
// depending on Step internals.
|
|
1380
1347
|
toKeys() {
|
|
1381
1348
|
const out = [];
|
|
1382
1349
|
for (const step of this.steps) {
|
|
@@ -1390,69 +1357,132 @@ var init_path = __esm({
|
|
|
1390
1357
|
return produce(root, (draft) => {
|
|
1391
1358
|
let parent = draft;
|
|
1392
1359
|
for (let i = 0; i < this.steps.length - 1; i++) {
|
|
1393
|
-
parent = this.steps[i].lookup(parent
|
|
1360
|
+
parent = this.steps[i].lookup(parent);
|
|
1394
1361
|
if (parent === NONE) return;
|
|
1395
1362
|
}
|
|
1396
1363
|
this.steps.at(-1).setDraftValue(parent, v);
|
|
1397
1364
|
});
|
|
1398
1365
|
}
|
|
1366
|
+
};
|
|
1367
|
+
EMPTY_PATH = new Path([]);
|
|
1368
|
+
DispatchPath = class _DispatchPath {
|
|
1369
|
+
constructor(frames = [{ base: EMPTY_PATH, items: [] }]) {
|
|
1370
|
+
this.frames = frames;
|
|
1371
|
+
}
|
|
1372
|
+
// Plain addressing steps in one frame based at the root: what a caller means
|
|
1373
|
+
// by "this position" when it has no continuation of its own.
|
|
1374
|
+
static ofSteps(steps) {
|
|
1375
|
+
return new _DispatchPath([{ base: EMPTY_PATH, items: steps.slice() }]);
|
|
1376
|
+
}
|
|
1377
|
+
get top() {
|
|
1378
|
+
return this.frames[this.frames.length - 1];
|
|
1379
|
+
}
|
|
1380
|
+
_withTopItems(items) {
|
|
1381
|
+
const frames = this.frames.slice();
|
|
1382
|
+
frames[frames.length - 1] = { base: this.top.base, items };
|
|
1383
|
+
return new _DispatchPath(frames);
|
|
1384
|
+
}
|
|
1385
|
+
concat(steps) {
|
|
1386
|
+
return this._withTopItems(this.top.items.concat(steps));
|
|
1387
|
+
}
|
|
1388
|
+
pushItem(step) {
|
|
1389
|
+
return this.concat([step]);
|
|
1390
|
+
}
|
|
1391
|
+
pushFrame(base) {
|
|
1392
|
+
return new _DispatchPath(this.frames.concat({ base, items: [] }));
|
|
1393
|
+
}
|
|
1394
|
+
// Whether bubbling has anywhere left to go: another step in this frame, or a
|
|
1395
|
+
// visual caller underneath it. (A path always has at least one frame.)
|
|
1396
|
+
canPop() {
|
|
1397
|
+
return this.frames.length > 1 || this.frames[0].items.length > 0;
|
|
1398
|
+
}
|
|
1399
|
+
// One component closer to the root. At the top of a frame that is popping back
|
|
1400
|
+
// to the visual caller, not to the producer's own parent — the caller is where
|
|
1401
|
+
// the `*name` was written, and where an unhandled message should keep going.
|
|
1402
|
+
popStep() {
|
|
1403
|
+
const { top } = this;
|
|
1404
|
+
if (top.items.length > 0) return this._withTopItems(top.items.slice(0, -1));
|
|
1405
|
+
if (this.frames.length > 1) return new _DispatchPath(this.frames.slice(0, -1));
|
|
1406
|
+
return this;
|
|
1407
|
+
}
|
|
1408
|
+
// Drop frame-only steps inside every frame independently; a frame's base is
|
|
1409
|
+
// already addressing-only.
|
|
1410
|
+
compact() {
|
|
1411
|
+
return new _DispatchPath(
|
|
1412
|
+
this.frames.map(({ base, items }) => ({ base, items: new Path(items).compact().steps }))
|
|
1413
|
+
);
|
|
1414
|
+
}
|
|
1415
|
+
// A stable string for the ADDRESS this path denotes, for the render cache. The
|
|
1416
|
+
// same immutable value can sit at two places in the tree, and a subtree rendered
|
|
1417
|
+
// at one of them bakes that address in — the provides it publishes are located
|
|
1418
|
+
// there. Frame-only steps address nothing, so they are compacted out: two sites
|
|
1419
|
+
// that differ only in binds do render the same subtree.
|
|
1420
|
+
get addressKey() {
|
|
1421
|
+
this._addressKey ??= renderPathText(this.toTransactionPath().compact());
|
|
1422
|
+
return this._addressKey;
|
|
1423
|
+
}
|
|
1424
|
+
// The active transaction address: the top frame's absolute base followed by
|
|
1425
|
+
// its ordinary descendant steps. This is where a mutation lands.
|
|
1426
|
+
toTransactionPath() {
|
|
1427
|
+
const { base, items } = this.top;
|
|
1428
|
+
return base.concat(items);
|
|
1429
|
+
}
|
|
1430
|
+
// Rebuild the render stack this path was dispatched from. A frame with a base
|
|
1431
|
+
// re-enters at that absolute value first — replaying the resume a `*name`
|
|
1432
|
+
// render performed — and then walks its ordinary items.
|
|
1399
1433
|
buildStack(stack) {
|
|
1400
|
-
let
|
|
1401
|
-
for (
|
|
1402
|
-
const
|
|
1403
|
-
if (
|
|
1404
|
-
|
|
1405
|
-
|
|
1434
|
+
let renderPath = new _DispatchPath();
|
|
1435
|
+
for (let i = 0; i < this.frames.length; i++) {
|
|
1436
|
+
const { base, items } = this.frames[i];
|
|
1437
|
+
if (i > 0 || base.steps.length > 0) {
|
|
1438
|
+
const baseValue = base.lookup(stack.root, NONE);
|
|
1439
|
+
if (baseValue === NONE) {
|
|
1440
|
+
console.warn("bad frame base", { base, path: this });
|
|
1441
|
+
return null;
|
|
1442
|
+
}
|
|
1443
|
+
renderPath = renderPath.pushFrame(base);
|
|
1444
|
+
stack = stack.enter(baseValue, {}, true, renderPath);
|
|
1406
1445
|
}
|
|
1407
|
-
|
|
1408
|
-
|
|
1446
|
+
const walked = walkItems(stack, items, renderPath, this);
|
|
1447
|
+
if (walked === null) return null;
|
|
1448
|
+
[stack, renderPath] = walked;
|
|
1409
1449
|
}
|
|
1410
1450
|
return stack;
|
|
1411
1451
|
}
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1452
|
+
// Reconstruct the dispatch position of a DOM event from the `data-*` stamps and
|
|
1453
|
+
// `§…§` meta comments the renderer left on the way down. `stopOnNoEvent` is off for
|
|
1454
|
+
// drag events, whose path is needed even where no handler is registered.
|
|
1455
|
+
static fromNodeAndEventName(node, eventName, rootNode, comps, stopOnNoEvent = true) {
|
|
1456
|
+
const parts = [];
|
|
1415
1457
|
const bubbles = BUBBLING_EVENTS.has(eventName);
|
|
1416
|
-
let depth = 0;
|
|
1417
1458
|
let eventIds = [];
|
|
1418
1459
|
let handlers = null;
|
|
1419
|
-
let
|
|
1460
|
+
let nodeRefs = [];
|
|
1420
1461
|
let isLeafComponent = true;
|
|
1421
1462
|
const crossComponent = (cidNum, vid) => {
|
|
1422
1463
|
const comp = comps.getComponentForId(cidNum);
|
|
1423
|
-
let
|
|
1464
|
+
let pushPart = true;
|
|
1424
1465
|
if (handlers === null && (isLeafComponent || bubbles)) {
|
|
1425
1466
|
handlers = findHandlers(comp, eventIds, vid, eventName);
|
|
1426
1467
|
if (handlers === null) {
|
|
1427
1468
|
if (isLeafComponent && stopOnNoEvent && !bubbles) return false;
|
|
1428
1469
|
} else if (!isLeafComponent) {
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
pushStep = false;
|
|
1470
|
+
parts.length = 0;
|
|
1471
|
+
pushPart = false;
|
|
1432
1472
|
}
|
|
1433
1473
|
}
|
|
1434
1474
|
isLeafComponent = false;
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
if (step) {
|
|
1439
|
-
step._originCid = cidNum;
|
|
1440
|
-
pathSteps.push(step);
|
|
1441
|
-
if (step instanceof DynStep) {
|
|
1442
|
-
step.interiorCids.add(cidNum);
|
|
1443
|
-
pendingDyns.push(step);
|
|
1444
|
-
}
|
|
1445
|
-
}
|
|
1475
|
+
if (pushPart) {
|
|
1476
|
+
const part = resolvePathPart(comp, nodeRefs, vid);
|
|
1477
|
+
if (part) parts.push(part);
|
|
1446
1478
|
}
|
|
1447
|
-
for (let i = pendingDyns.length - 1; i >= 0; i--)
|
|
1448
|
-
if (pendingDyns[i].producerCompId === cidNum) pendingDyns.splice(i, 1);
|
|
1449
1479
|
eventIds = [];
|
|
1450
|
-
|
|
1480
|
+
nodeRefs = [];
|
|
1451
1481
|
return true;
|
|
1452
1482
|
};
|
|
1453
|
-
while (node && node !== rootNode
|
|
1483
|
+
while (node && node !== rootNode) {
|
|
1454
1484
|
if (node?.dataset) {
|
|
1455
|
-
const { eid, cid, vid } = node.dataset;
|
|
1485
|
+
const { eid, cid, vid, rp } = node.dataset;
|
|
1456
1486
|
if (eid !== void 0) eventIds.push(eid);
|
|
1457
1487
|
const metas = metaChain(node.previousSibling);
|
|
1458
1488
|
let sawComp = false;
|
|
@@ -1460,19 +1490,26 @@ var init_path = __esm({
|
|
|
1460
1490
|
if (m.$ === "Comp") {
|
|
1461
1491
|
sawComp = true;
|
|
1462
1492
|
if (!crossComponent(m.cid, m.vid)) return NO_EVENT_INFO;
|
|
1463
|
-
|
|
1493
|
+
nodeRefs.push({ nid: m.nid, base: pathFromJson(m.base) });
|
|
1464
1494
|
} else {
|
|
1465
|
-
|
|
1495
|
+
nodeRefs.push({ nid: m.nid, si: m.si, sk: m.sk });
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
if (!sawComp && cid !== void 0) {
|
|
1499
|
+
if (!crossComponent(+cid, vid)) return NO_EVENT_INFO;
|
|
1500
|
+
if (rp !== void 0) {
|
|
1501
|
+
const base = parseRenderPath(rp);
|
|
1502
|
+
if (base !== null) nodeRefs.push({ base });
|
|
1466
1503
|
}
|
|
1467
1504
|
}
|
|
1468
|
-
if (!sawComp && cid !== void 0 && !crossComponent(+cid, vid)) return NO_EVENT_INFO;
|
|
1469
1505
|
}
|
|
1470
|
-
depth += 1;
|
|
1471
1506
|
node = node.parentNode;
|
|
1472
1507
|
}
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1508
|
+
parts.reverse();
|
|
1509
|
+
let path = new _DispatchPath();
|
|
1510
|
+
for (const part of parts)
|
|
1511
|
+
path = part.base !== void 0 ? path.pushFrame(part.base) : path.pushItem(part.step);
|
|
1512
|
+
return [path, handlers];
|
|
1476
1513
|
}
|
|
1477
1514
|
};
|
|
1478
1515
|
StepCtx = class _StepCtx {
|
|
@@ -1500,13 +1537,6 @@ var init_path = __esm({
|
|
|
1500
1537
|
resolveNode() {
|
|
1501
1538
|
return this.comp.getNodeForId(+this.meta.nid, this.vid);
|
|
1502
1539
|
}
|
|
1503
|
-
applyKey(pi) {
|
|
1504
|
-
if (pi === null) return null;
|
|
1505
|
-
const m = this.meta;
|
|
1506
|
-
if (m.si !== void 0) return pi.withIndex(+m.si);
|
|
1507
|
-
if (m.sk !== void 0) return pi.withKey(m.sk);
|
|
1508
|
-
return pi;
|
|
1509
|
-
}
|
|
1510
1540
|
};
|
|
1511
1541
|
NO_EVENT_INFO = [null, null];
|
|
1512
1542
|
BUBBLING_EVENTS = /* @__PURE__ */ new Set(["drop"]);
|
|
@@ -1514,6 +1544,9 @@ var init_path = __esm({
|
|
|
1514
1544
|
constructor() {
|
|
1515
1545
|
this.pathChanges = [];
|
|
1516
1546
|
}
|
|
1547
|
+
toPath() {
|
|
1548
|
+
return new Path(this.pathChanges);
|
|
1549
|
+
}
|
|
1517
1550
|
add(pathChange) {
|
|
1518
1551
|
this.pathChanges.push(pathChange);
|
|
1519
1552
|
return this;
|
|
@@ -1531,14 +1564,6 @@ var init_path = __esm({
|
|
|
1531
1564
|
}
|
|
1532
1565
|
});
|
|
1533
1566
|
|
|
1534
|
-
// src/util/env.js
|
|
1535
|
-
var isMac;
|
|
1536
|
-
var init_env = __esm({
|
|
1537
|
-
"src/util/env.js"() {
|
|
1538
|
-
isMac = (globalThis.navigator?.userAgent ?? "").toLowerCase().includes("mac");
|
|
1539
|
-
}
|
|
1540
|
-
});
|
|
1541
|
-
|
|
1542
1567
|
// src/value.js
|
|
1543
1568
|
function sizeOf(v) {
|
|
1544
1569
|
if (v == null) return null;
|
|
@@ -1675,25 +1700,12 @@ function _parsePredicate(s, tokens, px) {
|
|
|
1675
1700
|
}
|
|
1676
1701
|
return new PredicateVal(pred, args);
|
|
1677
1702
|
}
|
|
1678
|
-
|
|
1679
|
-
if (val === null) return 0;
|
|
1680
|
-
if (val instanceof ConstVal) return val.kind;
|
|
1681
|
-
if (val instanceof StrTplVal) return val.kind;
|
|
1682
|
-
if (val instanceof SeqAccessVal) return K_SEQ;
|
|
1683
|
-
if (val instanceof FieldVal) return K_FIELD;
|
|
1684
|
-
if (val instanceof MethodVal) return K_METHOD;
|
|
1685
|
-
if (val instanceof BindVal) return K_BIND;
|
|
1686
|
-
if (val instanceof DynVal) return K_DYN;
|
|
1687
|
-
if (val instanceof NameVal) return K_NAME;
|
|
1688
|
-
if (val instanceof EventMemberVal) return K_EVENT;
|
|
1689
|
-
return 0;
|
|
1690
|
-
}
|
|
1691
|
-
var VALID_VAL_ID_RE, isValidValId, VALID_FLOAT_RE, STR_TPL_SPLIT_RE, mkVal, VAL_TOKEN_RE, tokenizeValue, unescapeStr, K_CONST, K_STRTPL, K_FIELD, K_BIND, K_DYN, K_NAME, K_SEQ, K_METHOD, K_EVENT, G_BOOL, G_TEXT, G_COMPONENT, G_SEQUENCE, G_PROVIDE, G_FIELD, G_VALUE, G_HANDLER_ARG, G_ALL, toNullIfNaN, predTruthy, PREDICATES, parseText, parseComponent, parseSequence, parseField, parseProvide, parseMacroAttr, parseReceiveHandler, parseAlterHandler, BaseVal, ConstVal, NULL_CONST_VAL, PredicateVal, VarVal, StrTplVal, NameVal, HandlerNameVal, mk404Handler, keyIs, macCtrl, nullSafe, EVENT_CONVENIENCES, EventMemberVal, RenderVal, RenderNameVal, BindVal, BindMemberVal, DynVal, FieldVal, MethodVal, SeqAccessVal;
|
|
1703
|
+
var isMac, VALID_VAL_ID_RE, isValidValId, VALID_FLOAT_RE, STR_TPL_SPLIT_RE, mkVal, VAL_TOKEN_RE, tokenizeValue, unescapeStr, K_CONST, K_STRTPL, K_FIELD, K_BIND, K_DYN, K_NAME, K_SEQ, K_METHOD, K_EVENT, G_BOOL, G_TEXT, G_COMPONENT, G_SEQUENCE, G_PROVIDE, G_FIELD, G_VALUE, G_HANDLER_ARG, G_ALL, toNullIfNaN, predTruthy, PREDICATES, parseText, parseComponent, parseSequence, parseField, parseProvide, parseMacroAttr, parseReceiveHandler, parseAlterHandler, kindOf, BaseVal, ConstVal, NULL_CONST_VAL, PredicateVal, StrTplVal, NameVal, HandlerNameVal, mk404Handler, keyIs, macCtrl, nullSafe, EVENT_CONVENIENCES, EventMemberVal, SigilNameVal, BindVal, BindMemberVal, DynVal, FieldVal, MethodVal, SeqAccessVal;
|
|
1692
1704
|
var init_value = __esm({
|
|
1693
1705
|
"src/value.js"() {
|
|
1694
1706
|
init_collection();
|
|
1695
1707
|
init_path();
|
|
1696
|
-
|
|
1708
|
+
isMac = (globalThis.navigator?.userAgent ?? "").toLowerCase().includes("mac");
|
|
1697
1709
|
VALID_VAL_ID_RE = /^[a-zA-Z][a-zA-Z0-9_]*\??$/;
|
|
1698
1710
|
isValidValId = (name) => VALID_VAL_ID_RE.test(name);
|
|
1699
1711
|
VALID_FLOAT_RE = /^-?[0-9]+(\.[0-9]+)?$/;
|
|
@@ -1740,9 +1752,10 @@ var init_value = __esm({
|
|
|
1740
1752
|
parseMacroAttr = (s, px) => _parseSingle(s, px, G_ALL);
|
|
1741
1753
|
parseReceiveHandler = (s, px) => _parseHandler(s, px, "receive", true, true, false);
|
|
1742
1754
|
parseAlterHandler = (s, px) => _parseHandler(s, px, "alter", false, false, true)?.handlerVal ?? null;
|
|
1755
|
+
kindOf = (val) => val?.kind ?? 0;
|
|
1743
1756
|
BaseVal = class {
|
|
1744
|
-
|
|
1745
|
-
|
|
1757
|
+
// No kind: never accepted by a group (PredicateVal, which only parseBool builds).
|
|
1758
|
+
kind = 0;
|
|
1746
1759
|
eval(_stack) {
|
|
1747
1760
|
}
|
|
1748
1761
|
toPathItem() {
|
|
@@ -1762,9 +1775,6 @@ var init_value = __esm({
|
|
|
1762
1775
|
this.val = val;
|
|
1763
1776
|
this.kind = kind;
|
|
1764
1777
|
}
|
|
1765
|
-
render(_stack, _rx) {
|
|
1766
|
-
return this.val;
|
|
1767
|
-
}
|
|
1768
1778
|
eval(_stack) {
|
|
1769
1779
|
return this.val;
|
|
1770
1780
|
}
|
|
@@ -1790,9 +1800,7 @@ var init_value = __esm({
|
|
|
1790
1800
|
return `${this.pred.name} ${this.args.map(String).join(" ")}`;
|
|
1791
1801
|
}
|
|
1792
1802
|
};
|
|
1793
|
-
|
|
1794
|
-
};
|
|
1795
|
-
StrTplVal = class _StrTplVal extends VarVal {
|
|
1803
|
+
StrTplVal = class _StrTplVal extends BaseVal {
|
|
1796
1804
|
constructor(vals) {
|
|
1797
1805
|
super();
|
|
1798
1806
|
this.vals = vals;
|
|
@@ -1805,9 +1813,6 @@ var init_value = __esm({
|
|
|
1805
1813
|
for (const v of this.vals) if (!(v instanceof ConstVal) || v.fromMacroVar) return false;
|
|
1806
1814
|
return true;
|
|
1807
1815
|
}
|
|
1808
|
-
render(stack, _rx) {
|
|
1809
|
-
return this.eval(stack);
|
|
1810
|
-
}
|
|
1811
1816
|
eval(stack) {
|
|
1812
1817
|
const strs = new Array(this.vals.length);
|
|
1813
1818
|
for (let i = 0; i < this.vals.length; i++) strs[i] = this.vals[i]?.eval(stack, "");
|
|
@@ -1844,7 +1849,8 @@ var init_value = __esm({
|
|
|
1844
1849
|
return new _StrTplVal(lo === 0 && hi === vals.length ? vals : vals.slice(lo, hi));
|
|
1845
1850
|
}
|
|
1846
1851
|
};
|
|
1847
|
-
NameVal = class extends
|
|
1852
|
+
NameVal = class extends BaseVal {
|
|
1853
|
+
kind = K_NAME;
|
|
1848
1854
|
constructor(name) {
|
|
1849
1855
|
super();
|
|
1850
1856
|
this.name = name;
|
|
@@ -1894,6 +1900,7 @@ var init_value = __esm({
|
|
|
1894
1900
|
dragKey: nullSafe((info) => info.lookupBind("key"))
|
|
1895
1901
|
};
|
|
1896
1902
|
EventMemberVal = class extends BaseVal {
|
|
1903
|
+
kind = K_EVENT;
|
|
1897
1904
|
constructor(members) {
|
|
1898
1905
|
super();
|
|
1899
1906
|
this.members = members;
|
|
@@ -1916,24 +1923,21 @@ var init_value = __esm({
|
|
|
1916
1923
|
return `e.${this.members.join(".")}`;
|
|
1917
1924
|
}
|
|
1918
1925
|
};
|
|
1919
|
-
|
|
1920
|
-
render(stack, _rx) {
|
|
1921
|
-
return this.eval(stack);
|
|
1922
|
-
}
|
|
1923
|
-
};
|
|
1924
|
-
RenderNameVal = class extends RenderVal {
|
|
1926
|
+
SigilNameVal = class extends BaseVal {
|
|
1925
1927
|
constructor(name) {
|
|
1926
1928
|
super();
|
|
1927
1929
|
this.name = name;
|
|
1928
1930
|
}
|
|
1931
|
+
toString() {
|
|
1932
|
+
return this.sigil + this.name;
|
|
1933
|
+
}
|
|
1929
1934
|
};
|
|
1930
|
-
BindVal = class extends
|
|
1935
|
+
BindVal = class extends SigilNameVal {
|
|
1936
|
+
kind = K_BIND;
|
|
1937
|
+
sigil = "@";
|
|
1931
1938
|
eval(stack) {
|
|
1932
1939
|
return stack.lookupBind(this.name);
|
|
1933
1940
|
}
|
|
1934
|
-
toString() {
|
|
1935
|
-
return `@${this.name}`;
|
|
1936
|
-
}
|
|
1937
1941
|
};
|
|
1938
1942
|
BindMemberVal = class extends BindVal {
|
|
1939
1943
|
constructor(name, member) {
|
|
@@ -1948,37 +1952,35 @@ var init_value = __esm({
|
|
|
1948
1952
|
return `@${this.name}.${this.member}`;
|
|
1949
1953
|
}
|
|
1950
1954
|
};
|
|
1951
|
-
DynVal = class extends
|
|
1955
|
+
DynVal = class extends SigilNameVal {
|
|
1956
|
+
kind = K_DYN;
|
|
1957
|
+
sigil = "*";
|
|
1952
1958
|
eval(stack) {
|
|
1953
1959
|
return stack.lookupDynamic(this.name);
|
|
1954
1960
|
}
|
|
1955
|
-
toString() {
|
|
1956
|
-
return `*${this.name}`;
|
|
1957
|
-
}
|
|
1958
1961
|
};
|
|
1959
|
-
FieldVal = class extends
|
|
1962
|
+
FieldVal = class extends SigilNameVal {
|
|
1963
|
+
kind = K_FIELD;
|
|
1964
|
+
sigil = ".";
|
|
1960
1965
|
eval(stack) {
|
|
1961
1966
|
return stack.lookupFieldRaw(this.name);
|
|
1962
1967
|
}
|
|
1963
1968
|
toPathItem() {
|
|
1964
1969
|
return new FieldStep(this.name);
|
|
1965
1970
|
}
|
|
1966
|
-
toString() {
|
|
1967
|
-
return `.${this.name}`;
|
|
1968
|
-
}
|
|
1969
1971
|
};
|
|
1970
|
-
MethodVal = class extends
|
|
1972
|
+
MethodVal = class extends SigilNameVal {
|
|
1973
|
+
kind = K_METHOD;
|
|
1974
|
+
sigil = "$";
|
|
1971
1975
|
eval(stack) {
|
|
1972
1976
|
return stack.lookupMethod(this.name);
|
|
1973
1977
|
}
|
|
1974
1978
|
evalAsHandler(stack) {
|
|
1975
1979
|
return stack.lookupFieldRaw(this.name);
|
|
1976
1980
|
}
|
|
1977
|
-
toString() {
|
|
1978
|
-
return `$${this.name}`;
|
|
1979
|
-
}
|
|
1980
1981
|
};
|
|
1981
|
-
SeqAccessVal = class extends
|
|
1982
|
+
SeqAccessVal = class extends BaseVal {
|
|
1983
|
+
kind = K_SEQ;
|
|
1982
1984
|
constructor(seqVal, keyVal) {
|
|
1983
1985
|
super();
|
|
1984
1986
|
this.seqVal = seqVal;
|
|
@@ -2013,11 +2015,11 @@ function parseDirectiveValue(px, directiveName, source, parser) {
|
|
|
2013
2015
|
function parseIterationDirectives(attributes, px) {
|
|
2014
2016
|
const parseNamed = (name) => {
|
|
2015
2017
|
const attr = attributes.getNamedItem(`@${name}`);
|
|
2016
|
-
return attr ?
|
|
2018
|
+
return attr ? parseIterDirective(px, name, attr.value) : null;
|
|
2017
2019
|
};
|
|
2018
2020
|
return { whenVal: parseNamed("when"), loopWithVal: parseNamed("loop-with") };
|
|
2019
2021
|
}
|
|
2020
|
-
var Attributes, booleanAttrsRaw, booleanAttrs, AttrParser, ConstAttrs, DynAttrs, BaseAttr, Attr, ConstAttr, RawHtmlAttr, NOT_SET_VAL, IfAttr, EventHandler;
|
|
2022
|
+
var Attributes, booleanAttrsRaw, booleanAttrs, ITER_DIRECTIVES, parseIterDirective, AttrParser, ConstAttrs, DynAttrs, BaseAttr, Attr, ConstAttr, RawHtmlAttr, NOT_SET_VAL, IfAttr, EventHandler;
|
|
2021
2023
|
var init_attribute = __esm({
|
|
2022
2024
|
"src/attribute.js"() {
|
|
2023
2025
|
init_value();
|
|
@@ -2025,15 +2027,18 @@ var init_attribute = __esm({
|
|
|
2025
2027
|
constructor(items) {
|
|
2026
2028
|
this.items = items;
|
|
2027
2029
|
}
|
|
2028
|
-
static parse(attributes, px, parseAll = false) {
|
|
2029
|
-
return new AttrParser(px).parse(attributes, parseAll);
|
|
2030
|
-
}
|
|
2031
2030
|
isConstant() {
|
|
2032
2031
|
return false;
|
|
2033
2032
|
}
|
|
2034
2033
|
};
|
|
2035
2034
|
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";
|
|
2036
2035
|
booleanAttrs = new Set(booleanAttrsRaw.split(","));
|
|
2036
|
+
ITER_DIRECTIVES = {
|
|
2037
|
+
when: "whenVal",
|
|
2038
|
+
"loop-with": "loopWithVal",
|
|
2039
|
+
"enrich-with": "enrichWithVal"
|
|
2040
|
+
};
|
|
2041
|
+
parseIterDirective = (px, name, s) => parseDirectiveValue(px, name, s, parseAlterHandler);
|
|
2037
2042
|
AttrParser = class {
|
|
2038
2043
|
constructor(px) {
|
|
2039
2044
|
this.px = px;
|
|
@@ -2071,11 +2076,22 @@ var init_attribute = __esm({
|
|
|
2071
2076
|
this.px.onParseIssue("bad-value", info);
|
|
2072
2077
|
}
|
|
2073
2078
|
}
|
|
2074
|
-
|
|
2075
|
-
|
|
2079
|
+
// `@then` / `@else` fill the branches of the `@if.<attr>` on the same element.
|
|
2080
|
+
parseBranch(slot, name, s) {
|
|
2081
|
+
if (this.ifAttr === null) return this._orphan(name, s, "if");
|
|
2082
|
+
this.ifAttr[slot] = parseText(s, this.px) ?? NOT_SET_VAL;
|
|
2083
|
+
}
|
|
2084
|
+
// `@when` / `@loop-with` / `@enrich-with` amend the `@each` on the same element. A
|
|
2085
|
+
// loop-less `@enrich-with` is a scope of its own; the other two need the loop.
|
|
2086
|
+
parseIter(name, s) {
|
|
2087
|
+
const val = parseIterDirective(this.px, name, s);
|
|
2088
|
+
if (this.eachAttr !== null) this.eachAttr[ITER_DIRECTIVES[name]] = val;
|
|
2089
|
+
else if (name === "enrich-with") this.pushWrapper("scope", s, val);
|
|
2090
|
+
else this._orphan(name, s, "each");
|
|
2076
2091
|
}
|
|
2077
|
-
|
|
2078
|
-
|
|
2092
|
+
// A directive that only means something next to another one, written alone.
|
|
2093
|
+
_orphan(name, value, needs) {
|
|
2094
|
+
this.px.onParseIssue("orphan-directive", { name, value, needs });
|
|
2079
2095
|
}
|
|
2080
2096
|
parseEvent(directiveName, value) {
|
|
2081
2097
|
const [eventName, ...modifiers] = directiveName.slice(3).split("+");
|
|
@@ -2089,77 +2105,51 @@ var init_attribute = __esm({
|
|
|
2089
2105
|
this.events.add(eventName, handler, modifiers);
|
|
2090
2106
|
}
|
|
2091
2107
|
}
|
|
2092
|
-
_parseDirectiveValue(directiveName, s, parserFn) {
|
|
2093
|
-
return parseDirectiveValue(this.px, directiveName, s, parserFn);
|
|
2094
|
-
}
|
|
2095
2108
|
parseDirective(s, directiveName) {
|
|
2096
2109
|
switch (directiveName) {
|
|
2097
2110
|
case "dangerouslysetinnerhtml":
|
|
2098
2111
|
this.attrs ??= [];
|
|
2099
|
-
this.attrs.push(new RawHtmlAttr(this.
|
|
2112
|
+
this.attrs.push(new RawHtmlAttr(parseDirectiveValue(this.px, directiveName, s, parseText)));
|
|
2100
2113
|
this.hasDynamic = true;
|
|
2101
2114
|
return;
|
|
2102
2115
|
case "push-view":
|
|
2103
|
-
this.pushWrapper("push-view", s, this.
|
|
2116
|
+
this.pushWrapper("push-view", s, parseDirectiveValue(this.px, directiveName, s, parseText));
|
|
2104
2117
|
return;
|
|
2105
2118
|
case "text":
|
|
2106
|
-
this.textChild = this.
|
|
2119
|
+
this.textChild = parseDirectiveValue(this.px, directiveName, s, parseText);
|
|
2107
2120
|
return;
|
|
2108
2121
|
case "show":
|
|
2109
|
-
this.pushWrapper("show", s, this.
|
|
2122
|
+
this.pushWrapper("show", s, parseDirectiveValue(this.px, directiveName, s, parseBool));
|
|
2110
2123
|
return;
|
|
2111
2124
|
case "hide":
|
|
2112
|
-
this.pushWrapper("hide", s, this.
|
|
2125
|
+
this.pushWrapper("hide", s, parseDirectiveValue(this.px, directiveName, s, parseBool));
|
|
2113
2126
|
return;
|
|
2114
2127
|
case "each": {
|
|
2115
|
-
const val = this.
|
|
2128
|
+
const val = parseDirectiveValue(this.px, directiveName, s, parseSequence);
|
|
2116
2129
|
this.eachAttr = this.pushWrapper("each", s, val);
|
|
2117
2130
|
return;
|
|
2118
2131
|
}
|
|
2119
|
-
case "enrich-with":
|
|
2120
|
-
if (this.eachAttr !== null)
|
|
2121
|
-
this.eachAttr.enrichWithVal = this._parseDirectiveValue(
|
|
2122
|
-
directiveName,
|
|
2123
|
-
s,
|
|
2124
|
-
parseAlterHandler
|
|
2125
|
-
);
|
|
2126
|
-
else
|
|
2127
|
-
this.pushWrapper(
|
|
2128
|
-
"scope",
|
|
2129
|
-
s,
|
|
2130
|
-
this._parseDirectiveValue(directiveName, s, parseAlterHandler)
|
|
2131
|
-
);
|
|
2132
|
-
return;
|
|
2133
2132
|
case "when":
|
|
2134
|
-
this._parseWhen(s);
|
|
2135
|
-
return;
|
|
2136
2133
|
case "loop-with":
|
|
2137
|
-
|
|
2134
|
+
case "enrich-with":
|
|
2135
|
+
this.parseIter(directiveName, s);
|
|
2138
2136
|
return;
|
|
2139
2137
|
case "then":
|
|
2140
|
-
this.
|
|
2138
|
+
this.parseBranch("thenVal", directiveName, s);
|
|
2141
2139
|
return;
|
|
2142
2140
|
case "else":
|
|
2143
|
-
this.
|
|
2141
|
+
this.parseBranch("elseVal", directiveName, s);
|
|
2144
2142
|
return;
|
|
2145
2143
|
}
|
|
2146
2144
|
if (directiveName.startsWith("on.")) this.parseEvent(directiveName, s);
|
|
2147
2145
|
else if (directiveName.startsWith("if.")) this.parseIf(directiveName, s);
|
|
2148
|
-
else if (directiveName.startsWith("then.")) this.
|
|
2149
|
-
else if (directiveName.startsWith("else.")) this.
|
|
2146
|
+
else if (directiveName.startsWith("then.")) this.parseBranch("thenVal", directiveName, s);
|
|
2147
|
+
else if (directiveName.startsWith("else.")) this.parseBranch("elseVal", directiveName, s);
|
|
2150
2148
|
else {
|
|
2151
2149
|
const info = { name: directiveName, value: s };
|
|
2152
2150
|
this.px.onParseIssue("unknown-directive", info);
|
|
2153
2151
|
}
|
|
2154
2152
|
}
|
|
2155
|
-
_parseWhen(s) {
|
|
2156
|
-
if (this.eachAttr !== null)
|
|
2157
|
-
this.eachAttr.whenVal = this._parseDirectiveValue("when", s, parseAlterHandler);
|
|
2158
|
-
}
|
|
2159
|
-
_parseLoopWith(s) {
|
|
2160
|
-
if (this.eachAttr !== null)
|
|
2161
|
-
this.eachAttr.loopWithVal = this._parseDirectiveValue("loop-with", s, parseAlterHandler);
|
|
2162
|
-
}
|
|
2163
2153
|
parse(attributes, parseAll = false) {
|
|
2164
2154
|
for (const { name, value } of attributes) {
|
|
2165
2155
|
const charCode = name.charCodeAt(0);
|
|
@@ -2420,6 +2410,17 @@ function addChild(normalizedChildren, child) {
|
|
|
2420
2410
|
else normalizedChildren.push(child);
|
|
2421
2411
|
} else normalizedChildren.push(new VText(child));
|
|
2422
2412
|
}
|
|
2413
|
+
function applyAttrs(node, attrs, placeChildren) {
|
|
2414
|
+
const hasValue = "value" in attrs;
|
|
2415
|
+
const hasChecked = "checked" in attrs;
|
|
2416
|
+
if (hasValue || hasChecked) {
|
|
2417
|
+
const { value: _v, checked: _c, ...rest } = attrs;
|
|
2418
|
+
applyProperties(node, rest);
|
|
2419
|
+
} else applyProperties(node, attrs);
|
|
2420
|
+
placeChildren();
|
|
2421
|
+
if (hasValue) applyValueLast(node, attrs.value);
|
|
2422
|
+
if (hasChecked) setProp(node, "checked", attrs.checked, isNamespaced(node));
|
|
2423
|
+
}
|
|
2423
2424
|
function diffProps(a, b) {
|
|
2424
2425
|
if (a === b) return null;
|
|
2425
2426
|
let diff = null;
|
|
@@ -2450,22 +2451,16 @@ function morphNode(domNode, source, target, opts) {
|
|
|
2450
2451
|
}
|
|
2451
2452
|
if (type3 === 1 && source.isSameKind(target)) {
|
|
2452
2453
|
const propsDiff = diffProps(source.attrs, target.attrs);
|
|
2453
|
-
const
|
|
2454
|
-
|
|
2455
|
-
if (propsDiff) {
|
|
2456
|
-
if (hasValue || hasChecked) {
|
|
2457
|
-
const { value: _v, checked: _c, ...rest } = propsDiff;
|
|
2458
|
-
applyProperties(domNode, rest);
|
|
2459
|
-
} else applyProperties(domNode, propsDiff);
|
|
2460
|
-
}
|
|
2461
|
-
if (!target.attrs.dangerouslySetInnerHTML) {
|
|
2454
|
+
const placeChildren = () => {
|
|
2455
|
+
if (target.attrs.dangerouslySetInnerHTML) return;
|
|
2462
2456
|
const ns = effectiveNs(target, opts);
|
|
2463
2457
|
morphChildren(domNode, source.childs, target.childs, childOpts(target, ns, opts));
|
|
2458
|
+
};
|
|
2459
|
+
if (propsDiff) applyAttrs(domNode, propsDiff, placeChildren);
|
|
2460
|
+
else placeChildren();
|
|
2461
|
+
if (!(propsDiff && "value" in propsDiff) && source.tag === "SELECT") {
|
|
2462
|
+
if (target.attrs.value !== void 0) applyValueLast(domNode, target.attrs.value);
|
|
2464
2463
|
}
|
|
2465
|
-
if (hasValue) applyValueLast(domNode, propsDiff.value);
|
|
2466
|
-
else if (source.tag === "SELECT" && target.attrs.value !== void 0)
|
|
2467
|
-
applyValueLast(domNode, target.attrs.value);
|
|
2468
|
-
if (hasChecked) setProp(domNode, "checked", propsDiff.checked, false);
|
|
2469
2464
|
return domNode;
|
|
2470
2465
|
}
|
|
2471
2466
|
if (type3 === 11) {
|
|
@@ -2685,16 +2680,7 @@ var init_vdom = __esm({
|
|
|
2685
2680
|
const createOpts = attrs.is != null ? { is: attrs.is } : void 0;
|
|
2686
2681
|
const node = ns === null ? doc.createElement(tag, createOpts) : doc.createElementNS(ns, tag, createOpts);
|
|
2687
2682
|
const cOpts = childOpts(this, ns, opts);
|
|
2688
|
-
|
|
2689
|
-
const { value, checked, ...rest } = attrs;
|
|
2690
|
-
applyProperties(node, rest);
|
|
2691
|
-
appendChildNodes(node, this.childs, cOpts);
|
|
2692
|
-
if (value !== void 0) applyValueLast(node, value);
|
|
2693
|
-
if (checked !== void 0) setProp(node, "checked", checked, false);
|
|
2694
|
-
} else {
|
|
2695
|
-
applyProperties(node, attrs);
|
|
2696
|
-
appendChildNodes(node, this.childs, cOpts);
|
|
2697
|
-
}
|
|
2683
|
+
applyAttrs(node, attrs, () => appendChildNodes(node, this.childs, cOpts));
|
|
2698
2684
|
return node;
|
|
2699
2685
|
}
|
|
2700
2686
|
};
|
|
@@ -2702,20 +2688,16 @@ var init_vdom = __esm({
|
|
|
2702
2688
|
});
|
|
2703
2689
|
|
|
2704
2690
|
// src/anode.js
|
|
2705
|
-
function
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
const pi = producerProvide.val?.toPathItem?.() ?? null;
|
|
2711
|
-
return { producerCompId: producerComp.id, producerSteps: pi ? [pi] : [] };
|
|
2712
|
-
}
|
|
2713
|
-
function optimizeChilds(childs) {
|
|
2714
|
-
for (let i = 0; i < childs.length; i++) {
|
|
2715
|
-
const child = childs[i];
|
|
2716
|
-
if (child.isConstant()) childs[i] = new RenderOnceNode(child);
|
|
2717
|
-
else child.optimize();
|
|
2691
|
+
function renderTarget(val, stack) {
|
|
2692
|
+
if (val instanceof DynVal) {
|
|
2693
|
+
const loc = stack.lookupDynamicLocated(val.name);
|
|
2694
|
+
if (loc?.path == null) return [loc?.value ?? null, stack.renderPath, null];
|
|
2695
|
+
return [loc.value, stack.renderPath.pushFrame(loc.path), loc.path];
|
|
2718
2696
|
}
|
|
2697
|
+
const step = val.toPathItem?.() ?? null;
|
|
2698
|
+
if (step === null) return [val.eval(stack), stack.renderPath, null];
|
|
2699
|
+
const path = stack.renderPath.pushItem(step);
|
|
2700
|
+
return [val.eval(stack), path, stack.pendingFrame ? path.toTransactionPath() : null];
|
|
2719
2701
|
}
|
|
2720
2702
|
function optimizeNode(node) {
|
|
2721
2703
|
if (node.isConstant()) return new RenderOnceNode(node);
|
|
@@ -2816,11 +2798,6 @@ function makeWrapperNode(data, px) {
|
|
|
2816
2798
|
}
|
|
2817
2799
|
return node;
|
|
2818
2800
|
}
|
|
2819
|
-
function dynRenderStep(comp, name, key) {
|
|
2820
|
-
const p = resolveDynProducer(comp, name);
|
|
2821
|
-
if (!p) return null;
|
|
2822
|
-
return key === void 0 ? new DynStep(p.producerCompId, p.producerSteps) : new DynEachStep(p.producerCompId, p.producerSteps, key);
|
|
2823
|
-
}
|
|
2824
2801
|
function parseRenderEach(px, value, as, attrs) {
|
|
2825
2802
|
const seqVal = parseXOpVal("render-each", value, px, parseSequence);
|
|
2826
2803
|
if (seqVal === null) return null;
|
|
@@ -2837,7 +2814,7 @@ function xOp(consumed = [], { wrappable = false, wrapper = null, ignoresChildren
|
|
|
2837
2814
|
return { consumed: new Set(consumed), wrappable, wrapper, ignoresChildren };
|
|
2838
2815
|
}
|
|
2839
2816
|
function trimEdgeWhite(node) {
|
|
2840
|
-
if (!node.isWhiteSpace
|
|
2817
|
+
if (!node.isWhiteSpace()) return false;
|
|
2841
2818
|
node.condenseWhiteSpace();
|
|
2842
2819
|
return true;
|
|
2843
2820
|
}
|
|
@@ -2848,7 +2825,7 @@ function condenseChildsWhites(childs) {
|
|
|
2848
2825
|
if (last > 0 && trimEdgeWhite(childs[last])) emptied = true;
|
|
2849
2826
|
for (let i = 1; i < last; i++) {
|
|
2850
2827
|
const cur = childs[i];
|
|
2851
|
-
if (!(cur.isWhiteSpace
|
|
2828
|
+
if (!(cur.isWhiteSpace() && cur.hasNewLine())) continue;
|
|
2852
2829
|
const bothBlock = isBlockDomNode(childs[i - 1]) && isBlockDomNode(childs[i + 1]);
|
|
2853
2830
|
cur.condenseWhiteSpace(bothBlock ? "" : " ");
|
|
2854
2831
|
if (bothBlock) emptied = true;
|
|
@@ -2875,7 +2852,7 @@ function compileModifiers(eventName, names) {
|
|
|
2875
2852
|
return w(this, f, args, ctx);
|
|
2876
2853
|
};
|
|
2877
2854
|
}
|
|
2878
|
-
var BaseNode, TextNode, CommentNode, ChildsNode, DomNode, FragmentNode, maybeFragment, VALID_NODE_RE, ANode, MacroNode, RenderViewId, RenderNode, RenderItNode, RenderTextNode, RenderOnceNode, WrapperNode, ShowNode, HideNode, PushViewNameNode, SlotNode, ScopeNode, EachNode, IterInfo, X_OPS, WRAPPER_NODES, ParseContext, _htmlBlockTags, HTML_BLOCK_TAGS, isBlockDomNode, isEmptyText, isIgnorableXChild, hasMeaningfulChilds,
|
|
2855
|
+
var BaseNode, TextNode, CommentNode, ChildsNode, DomNode, FragmentNode, maybeFragment, VALID_NODE_RE, ANode, MacroNode, RenderViewId, RenderNode, RenderItNode, RenderTextNode, RenderOnceNode, WrapperNode, ShowNode, HideNode, PushViewNameNode, SlotNode, ScopeNode, EachNode, IterInfo, X_OPS, WRAPPER_NODES, ParseContext, _htmlBlockTags, HTML_BLOCK_TAGS, isBlockDomNode, isEmptyText, isIgnorableXChild, hasMeaningfulChilds, NodeEvents, NodeEvent, fwdIfCtxPred, fwdIfEventPred, fwdIfKey, fwdCtrl, fwdMeta, fwdAlt, MOD_WRAPPERS_FOR_ANY_EVENT, MOD_WRAPPERS_BY_EVENT, MOD_EFFECTS, NO_WRAPPERS, identityModifierWrapper;
|
|
2879
2856
|
var init_anode = __esm({
|
|
2880
2857
|
"src/anode.js"() {
|
|
2881
2858
|
init_attribute();
|
|
@@ -2887,8 +2864,11 @@ var init_anode = __esm({
|
|
|
2887
2864
|
render(_stack, _rx) {
|
|
2888
2865
|
return null;
|
|
2889
2866
|
}
|
|
2890
|
-
|
|
2891
|
-
|
|
2867
|
+
// Stamp a `data-*` attribute on the element(s) this node renders. A no-op for
|
|
2868
|
+
// nodes that produce no element of their own (text, `<x render*>`): a view whose
|
|
2869
|
+
// root is one of those records its component boundary in the `§Comp§` meta
|
|
2870
|
+
// comment instead (see Renderer._rValComp).
|
|
2871
|
+
setDataAttr(_key, _val) {
|
|
2892
2872
|
}
|
|
2893
2873
|
isConstant() {
|
|
2894
2874
|
return false;
|
|
@@ -2927,8 +2907,6 @@ var init_anode = __esm({
|
|
|
2927
2907
|
isConstant() {
|
|
2928
2908
|
return true;
|
|
2929
2909
|
}
|
|
2930
|
-
setDataAttr(_key, _val) {
|
|
2931
|
-
}
|
|
2932
2910
|
};
|
|
2933
2911
|
CommentNode = class extends TextNode {
|
|
2934
2912
|
render(_stack, rx) {
|
|
@@ -2944,7 +2922,8 @@ var init_anode = __esm({
|
|
|
2944
2922
|
return this.childs.every((v) => v.isConstant());
|
|
2945
2923
|
}
|
|
2946
2924
|
optimize() {
|
|
2947
|
-
|
|
2925
|
+
const { childs } = this;
|
|
2926
|
+
for (let i = 0; i < childs.length; i++) childs[i] = optimizeNode(childs[i]);
|
|
2948
2927
|
}
|
|
2949
2928
|
};
|
|
2950
2929
|
DomNode = class extends ChildsNode {
|
|
@@ -2956,8 +2935,7 @@ var init_anode = __esm({
|
|
|
2956
2935
|
}
|
|
2957
2936
|
render(stack, rx) {
|
|
2958
2937
|
const childNodes = new Array(this.childs.length);
|
|
2959
|
-
for (let i = 0; i < childNodes.length; i++)
|
|
2960
|
-
childNodes[i] = this.childs[i]?.render?.(stack, rx) ?? null;
|
|
2938
|
+
for (let i = 0; i < childNodes.length; i++) childNodes[i] = this.childs[i].render(stack, rx);
|
|
2961
2939
|
return rx.renderTag(this.tagName, this.attrs.eval(stack), childNodes, this.namespace);
|
|
2962
2940
|
}
|
|
2963
2941
|
setDataAttr(key, val) {
|
|
@@ -2969,7 +2947,7 @@ var init_anode = __esm({
|
|
|
2969
2947
|
};
|
|
2970
2948
|
FragmentNode = class extends ChildsNode {
|
|
2971
2949
|
render(stack, rx) {
|
|
2972
|
-
return rx.renderFragment(this.childs.map((c) => c
|
|
2950
|
+
return rx.renderFragment(this.childs.map((c) => c.render(stack, rx)));
|
|
2973
2951
|
}
|
|
2974
2952
|
setDataAttr(key, val) {
|
|
2975
2953
|
for (const child of this.childs) child.setDataAttr(key, val);
|
|
@@ -2983,8 +2961,10 @@ var init_anode = __esm({
|
|
|
2983
2961
|
this.nodeId = nodeId;
|
|
2984
2962
|
this.val = val;
|
|
2985
2963
|
}
|
|
2986
|
-
|
|
2987
|
-
|
|
2964
|
+
// The addressing step this node contributes to an event's dispatch path, given
|
|
2965
|
+
// the `StepCtx` of the meta that named it; null when it addresses nothing.
|
|
2966
|
+
toPathStep(_ctx) {
|
|
2967
|
+
return this.val?.toPathItem?.() ?? null;
|
|
2988
2968
|
}
|
|
2989
2969
|
static parse(html, px) {
|
|
2990
2970
|
const nodes = px.parseHTML(html);
|
|
@@ -3000,8 +2980,8 @@ var init_anode = __esm({
|
|
|
3000
2980
|
return maybeFragment(trimmed);
|
|
3001
2981
|
}
|
|
3002
2982
|
static fromDOM(node, px) {
|
|
3003
|
-
if (node
|
|
3004
|
-
|
|
2983
|
+
if (node.nodeType === 3) return new TextNode(node.textContent);
|
|
2984
|
+
if (node.nodeType === 8) return new CommentNode(node.textContent);
|
|
3005
2985
|
const { childNodes, attributes: attrs, tagName: tag } = node;
|
|
3006
2986
|
const childs = [];
|
|
3007
2987
|
for (let i = 0; i < childNodes.length; i++) {
|
|
@@ -3019,11 +2999,11 @@ var init_anode = __esm({
|
|
|
3019
2999
|
const slotName = attrs.getNamedItem("name")?.value ?? "_";
|
|
3020
3000
|
return px.frame.macroSlots[slotName] ?? maybeFragment(childs);
|
|
3021
3001
|
}
|
|
3022
|
-
const [nAttrs, wrappers] =
|
|
3002
|
+
const [nAttrs, wrappers] = new AttrParser(px).parse(attrs, true);
|
|
3023
3003
|
px.onAttributes(nAttrs, wrappers, null, true, tag);
|
|
3024
3004
|
return wrap(px.newMacroNode(macroName, nAttrs.toMacroVars(), childs), px, wrappers);
|
|
3025
3005
|
} else if (VALID_NODE_RE.test(tag)) {
|
|
3026
|
-
const [nAttrs, wrappers, textChild] =
|
|
3006
|
+
const [nAttrs, wrappers, textChild] = new AttrParser(px).parse(attrs);
|
|
3027
3007
|
px.onAttributes(nAttrs, wrappers, textChild, false, tag);
|
|
3028
3008
|
if (textChild) childs.unshift(new RenderTextNode(null, textChild));
|
|
3029
3009
|
const domChilds = tag !== "PRE" ? condenseChildsWhites(childs) : childs;
|
|
@@ -3082,34 +3062,32 @@ var init_anode = __esm({
|
|
|
3082
3062
|
evalViewName(stack) {
|
|
3083
3063
|
return this.viewVal ? this.viewVal.eval(stack) : null;
|
|
3084
3064
|
}
|
|
3085
|
-
// A `<x render*>` produces no DOM element of its own to carry `data-cid`;
|
|
3086
|
-
// when it is a view's root the component boundary is recorded in the `Comp`
|
|
3087
|
-
// meta comment instead (see Renderer._rValComp), so this is a no-op.
|
|
3088
|
-
setDataAttr(_key, _val) {
|
|
3089
|
-
}
|
|
3090
3065
|
};
|
|
3091
3066
|
RenderNode = class extends RenderViewId {
|
|
3092
3067
|
render(stack, rx) {
|
|
3093
|
-
const
|
|
3094
|
-
|
|
3068
|
+
const [value, renderPath, base] = renderTarget(this.val, stack);
|
|
3069
|
+
const newStack = stack.enter(value, {}, true, renderPath, false);
|
|
3070
|
+
return rx.renderIt(newStack, this, this.evalViewName(stack), base);
|
|
3095
3071
|
}
|
|
3072
|
+
// A `*name` target contributes no step: the site recorded the absolute base it
|
|
3073
|
+
// resumed at, and event reconstruction turns that into a continuation frame.
|
|
3096
3074
|
toPathStep(ctx) {
|
|
3097
|
-
if (this.val instanceof DynVal) return
|
|
3075
|
+
if (this.val instanceof DynVal) return null;
|
|
3098
3076
|
return super.toPathStep(ctx);
|
|
3099
3077
|
}
|
|
3100
3078
|
};
|
|
3101
3079
|
RenderItNode = class extends RenderViewId {
|
|
3102
3080
|
render(stack, rx) {
|
|
3103
|
-
const
|
|
3104
|
-
|
|
3081
|
+
const base = stack.pendingFrame ? stack.renderPath.toTransactionPath() : null;
|
|
3082
|
+
const newStack = stack.enter(stack.it, {}, true, stack.renderPath, false);
|
|
3083
|
+
return rx.renderIt(newStack, this, this.evalViewName(stack), base);
|
|
3105
3084
|
}
|
|
3106
3085
|
toPathStep(ctx) {
|
|
3107
3086
|
const next = ctx.next();
|
|
3108
3087
|
if (next === null) return null;
|
|
3109
3088
|
const nextNode = next.resolveNode();
|
|
3110
3089
|
if (nextNode instanceof EachNode && next.hasKey) {
|
|
3111
|
-
if (nextNode.val instanceof DynVal)
|
|
3112
|
-
return dynRenderStep(ctx.comp, nextNode.val.name, next.key);
|
|
3090
|
+
if (nextNode.val instanceof DynVal) return null;
|
|
3113
3091
|
return new EachRenderItStep(nextNode.val.name, next.key);
|
|
3114
3092
|
}
|
|
3115
3093
|
return null;
|
|
@@ -3119,9 +3097,6 @@ var init_anode = __esm({
|
|
|
3119
3097
|
render(stack, _rx) {
|
|
3120
3098
|
return this.val.eval(stack);
|
|
3121
3099
|
}
|
|
3122
|
-
// Renders to a text node, which can't carry `data-cid`.
|
|
3123
|
-
setDataAttr(_key, _val) {
|
|
3124
|
-
}
|
|
3125
3100
|
};
|
|
3126
3101
|
RenderOnceNode = class extends BaseNode {
|
|
3127
3102
|
constructor(node) {
|
|
@@ -3196,36 +3171,46 @@ var init_anode = __esm({
|
|
|
3196
3171
|
EachNode = class extends WrapperNode {
|
|
3197
3172
|
constructor(nodeId, val) {
|
|
3198
3173
|
super(nodeId, val);
|
|
3199
|
-
this.iterInfo = new IterInfo(
|
|
3174
|
+
this.iterInfo = new IterInfo();
|
|
3200
3175
|
}
|
|
3201
3176
|
render(stack, rx) {
|
|
3202
|
-
return rx.renderEachWhen(stack, this
|
|
3203
|
-
}
|
|
3204
|
-
toPathStep(ctx) {
|
|
3205
|
-
return ctx.hasKey ? new EachBindStep(this.iterInfo, ctx.key) : null;
|
|
3177
|
+
return rx.renderEachWhen(stack, this);
|
|
3206
3178
|
}
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
eval(stack) {
|
|
3217
|
-
const seq = this.val.eval(stack) ?? [];
|
|
3218
|
-
const filter = this.whenVal?.evalAsHandler(stack) ?? filterAlwaysTrue;
|
|
3219
|
-
const loopWith = this.loopWithVal?.evalAsHandler(stack) ?? nullLoopWith;
|
|
3220
|
-
const enricher = this.enrichWithVal?.evalAsHandler(stack) ?? null;
|
|
3221
|
-
return { seq, filter, loopWith, enricher };
|
|
3179
|
+
// The sequence and the three loop handlers, resolved against `stack`.
|
|
3180
|
+
evalIter(stack) {
|
|
3181
|
+
const { whenVal, loopWithVal, enrichWithVal } = this.iterInfo;
|
|
3182
|
+
return {
|
|
3183
|
+
seq: this.val.eval(stack) ?? [],
|
|
3184
|
+
filter: whenVal?.evalAsHandler(stack) ?? filterAlwaysTrue,
|
|
3185
|
+
loopWith: loopWithVal?.evalAsHandler(stack) ?? nullLoopWith,
|
|
3186
|
+
enricher: enrichWithVal?.evalAsHandler(stack) ?? null
|
|
3187
|
+
};
|
|
3222
3188
|
}
|
|
3223
3189
|
// Rebuild the per-item binds for `key` (see iteration.js bindsForKey).
|
|
3224
3190
|
enrichBinds(stack, key) {
|
|
3225
|
-
const { seq, filter, loopWith, enricher } = this.
|
|
3191
|
+
const { seq, filter, loopWith, enricher } = this.evalIter(stack);
|
|
3226
3192
|
const ctx = makeLoopCtx(stack, filter);
|
|
3227
3193
|
return bindsForKey({ seq, it: stack.it, loopWith, enricher, ctx }, key);
|
|
3228
3194
|
}
|
|
3195
|
+
toPathStep(ctx) {
|
|
3196
|
+
return ctx.hasKey ? new EachBindStep(this, ctx.key) : null;
|
|
3197
|
+
}
|
|
3198
|
+
// Where one item lives, for the render path. `@each` re-binds `it` to the item
|
|
3199
|
+
// whether or not the body is a component, so the position moves either way and
|
|
3200
|
+
// the step has to address it — `.rows` iterated at `key` IS `rows[key]`.
|
|
3201
|
+
// Null for a dynamic sequence: `*rows` carries its own absolute path and enters
|
|
3202
|
+
// a continuation frame instead (see Renderer.renderEachWhen).
|
|
3203
|
+
itemStep(key) {
|
|
3204
|
+
return this.val instanceof FieldVal ? new SeqStep(this.val.name, key) : null;
|
|
3205
|
+
}
|
|
3206
|
+
static register = true;
|
|
3207
|
+
};
|
|
3208
|
+
IterInfo = class {
|
|
3209
|
+
constructor() {
|
|
3210
|
+
this.whenVal = null;
|
|
3211
|
+
this.loopWithVal = null;
|
|
3212
|
+
this.enrichWithVal = null;
|
|
3213
|
+
}
|
|
3229
3214
|
};
|
|
3230
3215
|
X_OPS = {
|
|
3231
3216
|
slot: xOp(),
|
|
@@ -3249,26 +3234,31 @@ var init_anode = __esm({
|
|
|
3249
3234
|
scope: ScopeNode,
|
|
3250
3235
|
"push-view": PushViewNameNode
|
|
3251
3236
|
};
|
|
3252
|
-
ParseContext = class
|
|
3253
|
-
constructor(document2
|
|
3254
|
-
this.
|
|
3255
|
-
this.
|
|
3256
|
-
this.
|
|
3257
|
-
this.
|
|
3258
|
-
this.
|
|
3259
|
-
this.
|
|
3260
|
-
this.Text = Text ?? globalThis.Text;
|
|
3261
|
-
this.Comment = Comment ?? globalThis.Comment;
|
|
3262
|
-
this.cacheConstNodes = true;
|
|
3237
|
+
ParseContext = class {
|
|
3238
|
+
constructor(document2 = globalThis.document) {
|
|
3239
|
+
this.document = document2;
|
|
3240
|
+
this.nodes = [];
|
|
3241
|
+
this.events = [];
|
|
3242
|
+
this.macroNodes = [];
|
|
3243
|
+
this.parent = null;
|
|
3244
|
+
this.frame = {};
|
|
3263
3245
|
this.currentTag = null;
|
|
3264
3246
|
}
|
|
3265
3247
|
isInsideMacro(name) {
|
|
3266
3248
|
return this.frame.macroName === name || this.parent?.isInsideMacro(name);
|
|
3267
3249
|
}
|
|
3250
|
+
// A macro body parses in a child context that shares every accumulator with
|
|
3251
|
+
// its parent (nodes, events, macroNodes, and whatever a subclass collects) and
|
|
3252
|
+
// differs only in its frame. Cloned rather than constructed so a subclass
|
|
3253
|
+
// keeps collecting inside macro bodies without re-implementing this — the
|
|
3254
|
+
// lint and class-set contexts used to lose (or had to copy) exactly that.
|
|
3268
3255
|
enterMacro(macroName, macroVars, macroSlots) {
|
|
3269
|
-
const
|
|
3270
|
-
|
|
3271
|
-
|
|
3256
|
+
const child = Object.create(Object.getPrototypeOf(this));
|
|
3257
|
+
return Object.assign(child, this, {
|
|
3258
|
+
frame: { macroName, macroVars, macroSlots },
|
|
3259
|
+
parent: this,
|
|
3260
|
+
currentTag: null
|
|
3261
|
+
});
|
|
3272
3262
|
}
|
|
3273
3263
|
parseHTML(html) {
|
|
3274
3264
|
const t = this.document.createElement("template");
|
|
@@ -3333,33 +3323,8 @@ var init_anode = __esm({
|
|
|
3333
3323
|
return node instanceof DomNode && HTML_BLOCK_TAGS.has(node.tagName);
|
|
3334
3324
|
};
|
|
3335
3325
|
isEmptyText = (c) => c instanceof TextNode && c.val === "";
|
|
3336
|
-
isIgnorableXChild = (c) => c instanceof CommentNode ||
|
|
3326
|
+
isIgnorableXChild = (c) => c instanceof CommentNode || c.isWhiteSpace();
|
|
3337
3327
|
hasMeaningfulChilds = (childs) => childs.some((c) => !isIgnorableXChild(c));
|
|
3338
|
-
View = class {
|
|
3339
|
-
constructor(name, rawView = "No View Defined", style = "", anode = null, ctx = null) {
|
|
3340
|
-
this.name = name;
|
|
3341
|
-
this.anode = anode;
|
|
3342
|
-
this.style = style;
|
|
3343
|
-
this.ctx = ctx;
|
|
3344
|
-
this.rawView = rawView;
|
|
3345
|
-
}
|
|
3346
|
-
compile(ctx, scope, cid) {
|
|
3347
|
-
this.ctx = ctx;
|
|
3348
|
-
this.anode = ANode.parse(this.rawView, ctx);
|
|
3349
|
-
this.anode.setDataAttr("data-cid", cid);
|
|
3350
|
-
this.anode.setDataAttr("data-vid", this.name);
|
|
3351
|
-
this.ctx.compile(scope);
|
|
3352
|
-
if (ctx.cacheConstNodes) this.anode = optimizeNode(this.anode);
|
|
3353
|
-
}
|
|
3354
|
-
render(stack, rx) {
|
|
3355
|
-
if (this.anode === null) {
|
|
3356
|
-
throw new Error(
|
|
3357
|
-
`tutuca: view "${this.name}" was rendered before it was compiled — its component is not registered in this app/scope. Source: ${String(this.rawView).slice(0, 80).replace(/\s+/g, " ")}…`
|
|
3358
|
-
);
|
|
3359
|
-
}
|
|
3360
|
-
return this.anode.render(stack, rx);
|
|
3361
|
-
}
|
|
3362
|
-
};
|
|
3363
3328
|
NodeEvents = class {
|
|
3364
3329
|
constructor(id) {
|
|
3365
3330
|
this.id = id;
|
|
@@ -3374,7 +3339,7 @@ var init_anode = __esm({
|
|
|
3374
3339
|
getHandlersFor(eventName) {
|
|
3375
3340
|
let r = null;
|
|
3376
3341
|
for (const handler of this.handlers)
|
|
3377
|
-
if (handler.
|
|
3342
|
+
if (handler.name === eventName) {
|
|
3378
3343
|
r ??= [];
|
|
3379
3344
|
r.push(handler);
|
|
3380
3345
|
}
|
|
@@ -3388,9 +3353,6 @@ var init_anode = __esm({
|
|
|
3388
3353
|
this.modifierWrapper = compileModifiers(name, modifiers);
|
|
3389
3354
|
this.modifiers = modifiers;
|
|
3390
3355
|
}
|
|
3391
|
-
handlesEventName(name) {
|
|
3392
|
-
return this.name === name;
|
|
3393
|
-
}
|
|
3394
3356
|
getHandlerAndArgs(stack, event) {
|
|
3395
3357
|
const r = this.handlerCall.getHandlerAndArgs(stack, event);
|
|
3396
3358
|
r[0] = this.modifierWrapper(r[0], event);
|
|
@@ -3424,11 +3386,212 @@ var init_anode = __esm({
|
|
|
3424
3386
|
}
|
|
3425
3387
|
});
|
|
3426
3388
|
|
|
3389
|
+
// src/stack.js
|
|
3390
|
+
function lookup(chain, name, dv = null) {
|
|
3391
|
+
let n = chain;
|
|
3392
|
+
while (n !== null) {
|
|
3393
|
+
const r = n[0].lookup(name);
|
|
3394
|
+
if (r === STOP) return dv;
|
|
3395
|
+
if (r !== NEXT) return r;
|
|
3396
|
+
n = n[1];
|
|
3397
|
+
}
|
|
3398
|
+
return dv;
|
|
3399
|
+
}
|
|
3400
|
+
function computeViewsId(views) {
|
|
3401
|
+
let s = "";
|
|
3402
|
+
let n = views;
|
|
3403
|
+
while (n !== null) {
|
|
3404
|
+
s += n[0];
|
|
3405
|
+
n = n[1];
|
|
3406
|
+
}
|
|
3407
|
+
return s === "main" ? "" : s;
|
|
3408
|
+
}
|
|
3409
|
+
var STOP, NEXT, DEFAULT_ROUTE, isTypeName, BindFrame, DynFrame, Stack, NOT_FOUND;
|
|
3410
|
+
var init_stack = __esm({
|
|
3411
|
+
"src/stack.js"() {
|
|
3412
|
+
init_path();
|
|
3413
|
+
STOP = /* @__PURE__ */ Symbol("STOP");
|
|
3414
|
+
NEXT = /* @__PURE__ */ Symbol("NEXT");
|
|
3415
|
+
DEFAULT_ROUTE = ["dyn", "lex"];
|
|
3416
|
+
isTypeName = (s) => {
|
|
3417
|
+
const c = s.charCodeAt(0);
|
|
3418
|
+
return c >= 65 && c <= 90;
|
|
3419
|
+
};
|
|
3420
|
+
BindFrame = class {
|
|
3421
|
+
constructor(it, binds, isFrame) {
|
|
3422
|
+
this.it = it;
|
|
3423
|
+
this.binds = binds;
|
|
3424
|
+
this.isFrame = isFrame;
|
|
3425
|
+
}
|
|
3426
|
+
lookup(name) {
|
|
3427
|
+
const v = this.binds[name];
|
|
3428
|
+
return v === void 0 ? this.isFrame ? STOP : NEXT : v;
|
|
3429
|
+
}
|
|
3430
|
+
};
|
|
3431
|
+
DynFrame = class {
|
|
3432
|
+
constructor(binds, types) {
|
|
3433
|
+
this.binds = binds;
|
|
3434
|
+
this.types = types;
|
|
3435
|
+
}
|
|
3436
|
+
lookup(name) {
|
|
3437
|
+
const v = (isTypeName(name) ? this.types : this.binds)[name];
|
|
3438
|
+
return v === void 0 ? NEXT : v;
|
|
3439
|
+
}
|
|
3440
|
+
};
|
|
3441
|
+
Stack = class _Stack {
|
|
3442
|
+
constructor(fields) {
|
|
3443
|
+
Object.assign(this, fields);
|
|
3444
|
+
}
|
|
3445
|
+
_with(patch) {
|
|
3446
|
+
return new _Stack({ ...this, ...patch });
|
|
3447
|
+
}
|
|
3448
|
+
// Evaluate every provide the entered component publishes and push them as one
|
|
3449
|
+
// dynBinds frame, keyed by NAME. A value is published together with the absolute
|
|
3450
|
+
// path it lives at: the same declaration is read as `*name` AND resumed at by
|
|
3451
|
+
// `<x render="*name">`, so a consumer needs both halves. Types go in the same
|
|
3452
|
+
// frame's other map. No-op with no provides.
|
|
3453
|
+
_pushProvides() {
|
|
3454
|
+
const comp = this.comps.getCompFor(this.it);
|
|
3455
|
+
if (comp == null) return this;
|
|
3456
|
+
const { provide, provideType } = comp;
|
|
3457
|
+
const binds = {};
|
|
3458
|
+
const types = {};
|
|
3459
|
+
let has2 = false;
|
|
3460
|
+
const base = this._publishBase();
|
|
3461
|
+
for (const k in provide) {
|
|
3462
|
+
const step = provide[k].toPathItem?.() ?? null;
|
|
3463
|
+
if (step === null) continue;
|
|
3464
|
+
const value = provide[k].eval(this);
|
|
3465
|
+
binds[k] = { value, path: base === null ? null : base.concat([step]) };
|
|
3466
|
+
has2 = true;
|
|
3467
|
+
}
|
|
3468
|
+
for (const k in provideType) {
|
|
3469
|
+
types[k] = provideType[k];
|
|
3470
|
+
has2 = true;
|
|
3471
|
+
}
|
|
3472
|
+
if (!has2) return this;
|
|
3473
|
+
return this._with({ dynBinds: [new DynFrame(binds, types), this.dynBinds] });
|
|
3474
|
+
}
|
|
3475
|
+
// The absolute address of the component being entered, or null when this
|
|
3476
|
+
// position cannot be written down as one. Frame-only steps carry bindings and
|
|
3477
|
+
// address nothing, so they are compacted away first; what is left is checked
|
|
3478
|
+
// against the value actually being rendered, because a scope CAN move the
|
|
3479
|
+
// render position without contributing an addressing step (a plain `@each`
|
|
3480
|
+
// body re-binds `it` to the item while its rebuild step is an identity).
|
|
3481
|
+
//
|
|
3482
|
+
// A null base still publishes the VALUE — `*name` reads it fine — but there is
|
|
3483
|
+
// nowhere to resume, so `<x render="*name">` renders nothing rather than
|
|
3484
|
+
// editing whatever happens to live at the address we guessed.
|
|
3485
|
+
_publishBase() {
|
|
3486
|
+
const base = this.renderPath.toTransactionPath().compact();
|
|
3487
|
+
return base.lookup(this.root, NOT_FOUND) === this.it ? base : null;
|
|
3488
|
+
}
|
|
3489
|
+
static root(comps, it, ctx = null) {
|
|
3490
|
+
return new _Stack({
|
|
3491
|
+
comps,
|
|
3492
|
+
root: it,
|
|
3493
|
+
it,
|
|
3494
|
+
binds: [new BindFrame(it, {}, true), null],
|
|
3495
|
+
dynBinds: [new DynFrame({}, {}), null],
|
|
3496
|
+
views: ["main", null],
|
|
3497
|
+
viewsId: "",
|
|
3498
|
+
renderPath: new DispatchPath(),
|
|
3499
|
+
pendingFrame: false,
|
|
3500
|
+
ctx
|
|
3501
|
+
})._pushProvides();
|
|
3502
|
+
}
|
|
3503
|
+
// `renderPath` defaults to this stack's own: an ordinary scope does not move.
|
|
3504
|
+
// `pendingFrame` clears on a component frame (which emits the base) and is
|
|
3505
|
+
// inherited by transparent scopes, which have to carry it to the next boundary.
|
|
3506
|
+
enter(it, bindings = {}, isFrame = true, renderPath = this.renderPath, pendingFrame = null) {
|
|
3507
|
+
const stack = this._with({
|
|
3508
|
+
it,
|
|
3509
|
+
binds: [new BindFrame(it, bindings, isFrame), this.binds],
|
|
3510
|
+
renderPath,
|
|
3511
|
+
pendingFrame: pendingFrame ?? (isFrame ? false : this.pendingFrame)
|
|
3512
|
+
});
|
|
3513
|
+
return isFrame ? stack._pushProvides() : stack;
|
|
3514
|
+
}
|
|
3515
|
+
pushViewName(name) {
|
|
3516
|
+
const views = [name, this.views];
|
|
3517
|
+
return this._with({ views, viewsId: computeViewsId(views) });
|
|
3518
|
+
}
|
|
3519
|
+
// Published types are stable per scope and would only churn the render cache, so
|
|
3520
|
+
// the cache key covers values alone.
|
|
3521
|
+
_pushDynBindValuesToArray(arr, comp) {
|
|
3522
|
+
for (const k in comp.provide) arr.push(this.lookupDynamic(k));
|
|
3523
|
+
for (const k in comp.lookup) arr.push(this.lookupDynamic(k));
|
|
3524
|
+
}
|
|
3525
|
+
// `*name`: the nearest binding above (including this component's own provides,
|
|
3526
|
+
// pushed on entering it), else a path registered in the component's lexical
|
|
3527
|
+
// scope, else this component's declared default, else null.
|
|
3528
|
+
//
|
|
3529
|
+
// One chain walk and no producer resolution: a lookup names what it WANTS, so the
|
|
3530
|
+
// frame it wants is keyed by that name. The default belongs to the CONSUMER's
|
|
3531
|
+
// declaration and is evaluated against the consumer's stack, which is why it is
|
|
3532
|
+
// consulted only after the whole chain has missed.
|
|
3533
|
+
lookupDynamicLocated(name) {
|
|
3534
|
+
if (isTypeName(name)) return null;
|
|
3535
|
+
const v = lookup(this.dynBinds, name);
|
|
3536
|
+
if (v != null) return v;
|
|
3537
|
+
const comp = this.comps.getCompFor(this.it);
|
|
3538
|
+
if (comp == null) return null;
|
|
3539
|
+
const path = comp.scope?.lookupPath?.(name) ?? null;
|
|
3540
|
+
if (path !== null) {
|
|
3541
|
+
const value2 = path.lookup(this.root, NOT_FOUND);
|
|
3542
|
+
if (value2 !== NOT_FOUND) return { value: value2, path };
|
|
3543
|
+
}
|
|
3544
|
+
const dval = comp.lookup[name] ?? null;
|
|
3545
|
+
if (dval === null) return null;
|
|
3546
|
+
const step = dval.toPathItem?.() ?? null;
|
|
3547
|
+
const value = dval.eval(this);
|
|
3548
|
+
return step === null ? { value, path: null } : { value, path: this.renderPath.toTransactionPath().concat([step]) };
|
|
3549
|
+
}
|
|
3550
|
+
lookupDynamic(name) {
|
|
3551
|
+
if (isTypeName(name)) return lookup(this.dynBinds, name);
|
|
3552
|
+
return this.lookupDynamicLocated(name)?.value ?? null;
|
|
3553
|
+
}
|
|
3554
|
+
lookupBind(name) {
|
|
3555
|
+
return lookup(this.binds, name);
|
|
3556
|
+
}
|
|
3557
|
+
lookupFieldRaw(name) {
|
|
3558
|
+
return this.it[name] ?? null;
|
|
3559
|
+
}
|
|
3560
|
+
lookupMethod(name) {
|
|
3561
|
+
const fn = this.it[name];
|
|
3562
|
+
return fn instanceof Function ? fn.call(this.it) : null;
|
|
3563
|
+
}
|
|
3564
|
+
// The dispatched DOM event / drag info, read only by EventMemberVal's
|
|
3565
|
+
// `e.<member>` handler args. Null outside a live event transaction (`ctx` is
|
|
3566
|
+
// then a send/intent transaction, which carries no `e`).
|
|
3567
|
+
lookupEvent() {
|
|
3568
|
+
return this.ctx?.e ?? null;
|
|
3569
|
+
}
|
|
3570
|
+
lookupDragInfo() {
|
|
3571
|
+
return this.ctx?.dragInfo ?? null;
|
|
3572
|
+
}
|
|
3573
|
+
getHandlerFor(name, key) {
|
|
3574
|
+
return this.comps.getHandlerFor(this.it, name, key);
|
|
3575
|
+
}
|
|
3576
|
+
lookupBestView(views, defaultViewName) {
|
|
3577
|
+
let n = this.views;
|
|
3578
|
+
while (n !== null) {
|
|
3579
|
+
const view = views[n[0]];
|
|
3580
|
+
if (view !== void 0) return view;
|
|
3581
|
+
n = n[1];
|
|
3582
|
+
}
|
|
3583
|
+
return views[defaultViewName];
|
|
3584
|
+
}
|
|
3585
|
+
};
|
|
3586
|
+
NOT_FOUND = /* @__PURE__ */ Symbol("NOT_FOUND");
|
|
3587
|
+
}
|
|
3588
|
+
});
|
|
3589
|
+
|
|
3427
3590
|
// src/components.js
|
|
3428
|
-
var COMPONENT, Components, ComponentStack,
|
|
3591
|
+
var COMPONENT, Components, ComponentStack, isString, _rawSpecKeys, KNOWN_SPEC_KEYS, COMPONENT_METHODS;
|
|
3429
3592
|
var init_components = __esm({
|
|
3430
3593
|
"src/components.js"() {
|
|
3431
|
-
|
|
3594
|
+
init_stack();
|
|
3432
3595
|
init_value();
|
|
3433
3596
|
COMPONENT = /* @__PURE__ */ Symbol.for("tutuca.component");
|
|
3434
3597
|
Components = class {
|
|
@@ -3436,7 +3599,7 @@ var init_components = __esm({
|
|
|
3436
3599
|
this.byId = /* @__PURE__ */ new Map();
|
|
3437
3600
|
}
|
|
3438
3601
|
registerComponent(Comp) {
|
|
3439
|
-
this.byId.set(Comp
|
|
3602
|
+
this.byId.set(Comp.id, Comp);
|
|
3440
3603
|
}
|
|
3441
3604
|
getComponentForId(id) {
|
|
3442
3605
|
return this.byId.get(id) ?? null;
|
|
@@ -3456,7 +3619,7 @@ var init_components = __esm({
|
|
|
3456
3619
|
}
|
|
3457
3620
|
compileStyles() {
|
|
3458
3621
|
const styles2 = [];
|
|
3459
|
-
for (const Comp of this.byId.values()) styles2.push(Comp
|
|
3622
|
+
for (const Comp of this.byId.values()) styles2.push(Comp.compileStyle());
|
|
3460
3623
|
return styles2.join("\n");
|
|
3461
3624
|
}
|
|
3462
3625
|
};
|
|
@@ -3467,15 +3630,17 @@ var init_components = __esm({
|
|
|
3467
3630
|
this.byName = {};
|
|
3468
3631
|
this.intentsByName = {};
|
|
3469
3632
|
this.macros = {};
|
|
3633
|
+
this.paths = {};
|
|
3470
3634
|
}
|
|
3471
3635
|
enter() {
|
|
3472
3636
|
return new _ComponentStack(this.comps, this);
|
|
3473
3637
|
}
|
|
3474
3638
|
registerComponents(comps, opts) {
|
|
3475
|
-
const { aliases: aliases2 = {} } = opts ?? {};
|
|
3639
|
+
const { aliases: aliases2 = {}, paths } = opts ?? {};
|
|
3640
|
+
if (paths) this.registerPaths(paths);
|
|
3476
3641
|
for (let i = 0; i < comps.length; i++) {
|
|
3477
3642
|
const Comp = comps[i];
|
|
3478
|
-
Comp
|
|
3643
|
+
Comp.scope = this.enter();
|
|
3479
3644
|
this.comps.registerComponent(Comp);
|
|
3480
3645
|
this.byName[Comp.name] = Comp;
|
|
3481
3646
|
}
|
|
@@ -3486,6 +3651,27 @@ var init_components = __esm({
|
|
|
3486
3651
|
else console.warn("alias", alias, "to inexistent component", aliases2[alias]);
|
|
3487
3652
|
}
|
|
3488
3653
|
}
|
|
3654
|
+
// Register lowercase names as absolute paths from the app state root. A
|
|
3655
|
+
// descendant that declares one in its `lookup` reads and renders `*name` without
|
|
3656
|
+
// anything above it publishing one — which is what makes a session, a theme or a
|
|
3657
|
+
// host-owned value available in its natural registration scope, instead of forcing
|
|
3658
|
+
// an application root whose only job is to `provide` it. Register on a nested
|
|
3659
|
+
// scope to narrow a name; nearest registration wins.
|
|
3660
|
+
//
|
|
3661
|
+
// Uppercase names are ignored: a component TYPE is what `lookupComponent` already
|
|
3662
|
+
// answers, and a type has no path.
|
|
3663
|
+
registerPaths(paths) {
|
|
3664
|
+
for (const name in paths) {
|
|
3665
|
+
if (isTypeName(name)) {
|
|
3666
|
+
console.warn("registerPaths: a type name has no path", name);
|
|
3667
|
+
continue;
|
|
3668
|
+
}
|
|
3669
|
+
this.paths[name] = paths[name].toPath();
|
|
3670
|
+
}
|
|
3671
|
+
}
|
|
3672
|
+
lookupPath(name) {
|
|
3673
|
+
return this.paths[name] ?? this.parent?.lookupPath(name) ?? null;
|
|
3674
|
+
}
|
|
3489
3675
|
registerMacros(macros) {
|
|
3490
3676
|
for (const key in macros) {
|
|
3491
3677
|
const lower = key.toLowerCase();
|
|
@@ -3517,97 +3703,56 @@ var init_components = __esm({
|
|
|
3517
3703
|
lookupComponent(name) {
|
|
3518
3704
|
return this.byName[name] ?? this.parent?.lookupComponent(name) ?? null;
|
|
3519
3705
|
}
|
|
3520
|
-
//
|
|
3521
|
-
// names
|
|
3522
|
-
//
|
|
3523
|
-
//
|
|
3524
|
-
//
|
|
3525
|
-
|
|
3706
|
+
// Whether anything in this scope chain provides `name`. Existence only: a lookup
|
|
3707
|
+
// names what it WANTS and takes whoever is nearest above it at render time, so
|
|
3708
|
+
// there is no producer to identify — several components may publish one name and
|
|
3709
|
+
// the live render ancestry decides. Used by the linter to tell a lookup that can
|
|
3710
|
+
// be satisfied from one that never will be.
|
|
3711
|
+
hasProvider(name) {
|
|
3526
3712
|
for (const compName in this.byName) {
|
|
3527
|
-
|
|
3528
|
-
if (Comp.provide?.[name] !== void 0) return Comp;
|
|
3713
|
+
if (this.byName[compName].provide?.[name] !== void 0) return true;
|
|
3529
3714
|
}
|
|
3530
|
-
return this.parent?.
|
|
3715
|
+
return this.parent?.hasProvider(name) ?? false;
|
|
3531
3716
|
}
|
|
3532
3717
|
lookupMacro(name) {
|
|
3533
3718
|
return this.macros[name] ?? this.parent?.lookupMacro(name) ?? null;
|
|
3534
3719
|
}
|
|
3535
3720
|
};
|
|
3536
|
-
ProvideInfo = class {
|
|
3537
|
-
constructor(val) {
|
|
3538
|
-
this.val = val;
|
|
3539
|
-
}
|
|
3540
|
-
};
|
|
3541
|
-
LookupInfo = class {
|
|
3542
|
-
constructor(val) {
|
|
3543
|
-
this.val = val;
|
|
3544
|
-
}
|
|
3545
|
-
};
|
|
3546
3721
|
isString = (v) => typeof v === "string";
|
|
3547
|
-
isTypeName = (s) => {
|
|
3548
|
-
const c = s.charCodeAt(0);
|
|
3549
|
-
return c >= 65 && c <= 90;
|
|
3550
|
-
};
|
|
3551
3722
|
_rawSpecKeys = "name view style commonStyle globalStyle receive intent alter views provide lookup fields methods statics";
|
|
3552
3723
|
KNOWN_SPEC_KEYS = new Set(_rawSpecKeys.split(" "));
|
|
3553
|
-
|
|
3554
|
-
Component = class {
|
|
3555
|
-
constructor(Class, o) {
|
|
3556
|
-
this.id = _compId++;
|
|
3557
|
-
this.name = o.name ?? "UnkComp";
|
|
3558
|
-
this.Class = Class;
|
|
3559
|
-
this.views = { main: new View("main", o.view, o.style) };
|
|
3560
|
-
this.commonStyle = o.commonStyle ?? "";
|
|
3561
|
-
this.globalStyle = o.globalStyle ?? "";
|
|
3562
|
-
this.receive = o.receive ?? {};
|
|
3563
|
-
this.intent = o.intent ?? {};
|
|
3564
|
-
this.alter = o.alter ?? {};
|
|
3565
|
-
for (const name in o.views ?? {}) {
|
|
3566
|
-
const v = o.views[name];
|
|
3567
|
-
const { view, style } = isString(v) ? { view: v } : v;
|
|
3568
|
-
this.views[name] = new View(name, view, style);
|
|
3569
|
-
}
|
|
3570
|
-
this._rawProvide = o.provide ?? {};
|
|
3571
|
-
this._rawLookup = o.lookup ?? [];
|
|
3572
|
-
this.provide = {};
|
|
3573
|
-
this.provideType = {};
|
|
3574
|
-
this.lookup = {};
|
|
3575
|
-
this.scope = null;
|
|
3576
|
-
this.spec = o;
|
|
3577
|
-
this.extra = {};
|
|
3578
|
-
for (const key of Object.keys(o)) if (!KNOWN_SPEC_KEYS.has(key)) this.extra[key] = o[key];
|
|
3579
|
-
}
|
|
3724
|
+
COMPONENT_METHODS = {
|
|
3580
3725
|
compile(ParseContext2) {
|
|
3581
3726
|
for (const name in this.views)
|
|
3582
3727
|
this.views[name].compile(new ParseContext2(), this.scope, this.id);
|
|
3583
3728
|
const ctx = this.views.main.ctx;
|
|
3584
3729
|
for (const key in this._rawProvide) {
|
|
3585
3730
|
if (isTypeName(key)) {
|
|
3586
|
-
if (this._rawProvide[key] === "self") this.provideType[key] = this
|
|
3731
|
+
if (this._rawProvide[key] === "self") this.provideType[key] = this;
|
|
3587
3732
|
continue;
|
|
3588
3733
|
}
|
|
3589
3734
|
const val = parseProvide(this._rawProvide[key], ctx);
|
|
3590
|
-
if (val) this.provide[key] =
|
|
3735
|
+
if (val) this.provide[key] = val;
|
|
3591
3736
|
}
|
|
3592
3737
|
for (const entry of this._rawLookup) {
|
|
3593
3738
|
const name = isString(entry) ? entry : isString(entry?.name) ? entry.name : null;
|
|
3594
3739
|
if (name === null) continue;
|
|
3595
3740
|
const defStr = isString(entry?.default) ? entry.default : null;
|
|
3596
|
-
this.lookup[name] =
|
|
3741
|
+
this.lookup[name] = defStr === null ? null : parseField(defStr, ctx);
|
|
3597
3742
|
}
|
|
3598
3743
|
for (const key in this.lookup)
|
|
3599
3744
|
if (this.provide[key] !== void 0)
|
|
3600
3745
|
console.warn("name declared in both provide and lookup", this.name, key);
|
|
3601
|
-
}
|
|
3746
|
+
},
|
|
3602
3747
|
getView(name) {
|
|
3603
3748
|
return this.views[name] ?? this.views.main;
|
|
3604
|
-
}
|
|
3605
|
-
getEventForId(id,
|
|
3606
|
-
return this.getView(
|
|
3607
|
-
}
|
|
3608
|
-
getNodeForId(id,
|
|
3609
|
-
return this.getView(
|
|
3610
|
-
}
|
|
3749
|
+
},
|
|
3750
|
+
getEventForId(id, viewName) {
|
|
3751
|
+
return this.getView(viewName).ctx.getEventForId(id);
|
|
3752
|
+
},
|
|
3753
|
+
getNodeForId(id, viewName) {
|
|
3754
|
+
return this.getView(viewName).ctx.getNodeForId(id);
|
|
3755
|
+
},
|
|
3611
3756
|
compileStyle() {
|
|
3612
3757
|
const { id, commonStyle, globalStyle, views } = this;
|
|
3613
3758
|
const styles2 = commonStyle ? [`[data-cid="${id}"]{${commonStyle}}`] : [];
|
|
@@ -3622,6 +3767,63 @@ var init_components = __esm({
|
|
|
3622
3767
|
}
|
|
3623
3768
|
});
|
|
3624
3769
|
|
|
3770
|
+
// src/util/parsectx.js
|
|
3771
|
+
var ParseCtxClassSetCollector;
|
|
3772
|
+
var init_parsectx = __esm({
|
|
3773
|
+
"src/util/parsectx.js"() {
|
|
3774
|
+
init_anode();
|
|
3775
|
+
init_value();
|
|
3776
|
+
ParseCtxClassSetCollector = class extends ParseContext {
|
|
3777
|
+
constructor(...args) {
|
|
3778
|
+
super(...args);
|
|
3779
|
+
this.classes = /* @__PURE__ */ new Set();
|
|
3780
|
+
}
|
|
3781
|
+
_addClasses(s) {
|
|
3782
|
+
for (const v of s.split(/\s+/)) {
|
|
3783
|
+
this.classes.add(v);
|
|
3784
|
+
}
|
|
3785
|
+
}
|
|
3786
|
+
onAttributes(attrs, _wrapperAttrs, _textChild, _isMacroCall, _tag) {
|
|
3787
|
+
if (Array.isArray(attrs.items)) {
|
|
3788
|
+
for (const attr of attrs.items) {
|
|
3789
|
+
if (attr.name !== "class") {
|
|
3790
|
+
continue;
|
|
3791
|
+
}
|
|
3792
|
+
const { val, thenVal, elseVal } = attr;
|
|
3793
|
+
if (thenVal !== void 0) {
|
|
3794
|
+
this._maybeAddVal(thenVal);
|
|
3795
|
+
this._maybeAddVal(elseVal);
|
|
3796
|
+
} else {
|
|
3797
|
+
this._maybeAddVal(val);
|
|
3798
|
+
}
|
|
3799
|
+
}
|
|
3800
|
+
} else {
|
|
3801
|
+
const attr = attrs.items.class;
|
|
3802
|
+
if (attr) {
|
|
3803
|
+
this._addClasses(attr);
|
|
3804
|
+
}
|
|
3805
|
+
}
|
|
3806
|
+
}
|
|
3807
|
+
_maybeAddVal(value) {
|
|
3808
|
+
if (!this._maybeAddStrTpl(value) && typeof value?.val === "string") {
|
|
3809
|
+
this._addClasses(value.val);
|
|
3810
|
+
}
|
|
3811
|
+
}
|
|
3812
|
+
_maybeAddStrTpl(value) {
|
|
3813
|
+
if (value?.vals !== void 0) {
|
|
3814
|
+
for (const val of value.vals) {
|
|
3815
|
+
if (val instanceof ConstVal && val.val !== "") {
|
|
3816
|
+
this._addClasses(val.val);
|
|
3817
|
+
}
|
|
3818
|
+
}
|
|
3819
|
+
return true;
|
|
3820
|
+
}
|
|
3821
|
+
return false;
|
|
3822
|
+
}
|
|
3823
|
+
};
|
|
3824
|
+
}
|
|
3825
|
+
});
|
|
3826
|
+
|
|
3625
3827
|
// tools/core/html-tokenizer.js
|
|
3626
3828
|
function isWhitespace(c) {
|
|
3627
3829
|
return c === CharCodes.Space || c === CharCodes.NewLine || c === CharCodes.Tab || c === CharCodes.FormFeed || c === CharCodes.CarriageReturn;
|
|
@@ -5958,7 +6160,6 @@ function checkComponent(Comp, lx = new LintContext(), { wellKnownExtras = EMPTY_
|
|
|
5958
6160
|
checkFieldMethodNameCollisions(lx, Comp);
|
|
5959
6161
|
checkProvidesAreAddressable(lx, Comp);
|
|
5960
6162
|
checkProvidedTypes(lx, Comp);
|
|
5961
|
-
checkProvideNameCollisions(lx, Comp);
|
|
5962
6163
|
checkLookupShapes(lx, Comp);
|
|
5963
6164
|
checkLookupTypesResolve(lx, Comp);
|
|
5964
6165
|
checkLookupsHaveProviders(lx, Comp);
|
|
@@ -6533,19 +6734,6 @@ function checkProvidedTypes(lx, Comp) {
|
|
|
6533
6734
|
if (raw !== "self") lx.error(PROVIDE_TYPE_BAD_SHAPE, { name, value: raw });
|
|
6534
6735
|
}
|
|
6535
6736
|
}
|
|
6536
|
-
function checkProvideNameCollisions(lx, Comp) {
|
|
6537
|
-
const scope = Comp.scope;
|
|
6538
|
-
if (!scope) return;
|
|
6539
|
-
for (const name in Comp.provide) {
|
|
6540
|
-
for (let s = scope; s; s = s.parent) {
|
|
6541
|
-
for (const otherName in s.byName) {
|
|
6542
|
-
const Other = s.byName[otherName];
|
|
6543
|
-
if (Other !== Comp && Other.provide?.[name] !== void 0)
|
|
6544
|
-
lx.error(PROVIDE_NAME_COLLISION, { name, other: Other.name });
|
|
6545
|
-
}
|
|
6546
|
-
}
|
|
6547
|
-
}
|
|
6548
|
-
}
|
|
6549
6737
|
function checkLookupShapes(lx, Comp) {
|
|
6550
6738
|
const raw = Comp._rawLookup;
|
|
6551
6739
|
if (!Array.isArray(raw)) {
|
|
@@ -6586,8 +6774,8 @@ function checkLookupsHaveProviders(lx, Comp) {
|
|
|
6586
6774
|
if (!scope) return;
|
|
6587
6775
|
for (const name in Comp.lookup) {
|
|
6588
6776
|
if (isTypeName2(name)) continue;
|
|
6589
|
-
if (scope.
|
|
6590
|
-
const info = { name, hasDefault: Comp.lookup[name]
|
|
6777
|
+
if (scope.hasProvider?.(name) || scope.lookupPath?.(name)) continue;
|
|
6778
|
+
const info = { name, hasDefault: Comp.lookup[name] != null };
|
|
6591
6779
|
if (info.hasDefault) lx.hint(LOOKUP_NO_PROVIDER, info);
|
|
6592
6780
|
else lx.error(LOOKUP_NO_PROVIDER, info);
|
|
6593
6781
|
}
|
|
@@ -6608,11 +6796,12 @@ function checkUnreferencedDynamics(lx, Comp, referencedDynamics) {
|
|
|
6608
6796
|
}
|
|
6609
6797
|
}
|
|
6610
6798
|
}
|
|
6611
|
-
var KNOWN_COMPONENT_SPEC_KEYS, EMPTY_SET, FRAMEWORK_WELL_KNOWN_EXTRAS, KNOWN_DIRECTIVE_NAMES, isTypeName2, ALT_HANDLER_NOT_DEFINED, ALT_HANDLER_NOT_REFERENCED, DYN_VAL_NOT_DEFINED, DYN_ALIAS_NOT_REFERENCED, PROVIDE_NOT_ADDRESSABLE, PROVIDE_TYPE_BAD_SHAPE,
|
|
6799
|
+
var KNOWN_COMPONENT_SPEC_KEYS, EMPTY_SET, FRAMEWORK_WELL_KNOWN_EXTRAS, KNOWN_DIRECTIVE_NAMES, isTypeName2, ALT_HANDLER_NOT_DEFINED, ALT_HANDLER_NOT_REFERENCED, DYN_VAL_NOT_DEFINED, DYN_ALIAS_NOT_REFERENCED, PROVIDE_NOT_ADDRESSABLE, PROVIDE_TYPE_BAD_SHAPE, LOOKUP_BAD_SHAPE, LOOKUP_NO_PROVIDER, RENDER_IT_OUTSIDE_OF_LOOP, UNKNOWN_EVENT_MODIFIER, RECEIVE_HANDLER_NOT_IMPLEMENTED, EVENT_HANDLER_METHOD_NOT_ALLOWED, HANDLER_NAME_COLLISION, FIELD_VAL_NOT_DEFINED, FIELD_VAL_IS_METHOD, METHOD_VAL_NOT_DEFINED, METHOD_VAL_IS_FIELD, DUPLICATE_ATTR_DEFINITION, IF_NO_BRANCH_SET, UNKNOWN_COMPONENT_NAME, UNKNOWN_MACRO_ARG, UNKNOWN_DIRECTIVE, ORPHAN_DIRECTIVE, UNKNOWN_X_OP, UNKNOWN_X_ATTR, X_OP_IGNORES_CHILDREN, MAYBE_DROP_AT_PREFIX, MAYBE_ADD_AT_PREFIX, BAD_VALUE, UNSUPPORTED_EXPR_SYNTAX, BINDING_MEMBER_TOO_DEEP, SUGGEST_BINDING_MEMBER, REDUNDANT_TEMPLATE_STRING, PLACEHOLDERLESS_TEMPLATE_STRING, CONSTANT_CONDITION, UNKNOWN_COMPONENT_SPEC_KEY, COMP_FIELD_BAD_SHAPE, ASYNC_HANDLER, TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE, GLOBAL_SELECTOR_IN_SCOPED_STYLE, FIELD_METHOD_NAME_COLLISION, X_KNOWN_OP_NAMES, X_KNOWN_ATTR_NAMES, HOST_DIRECTIVE_ONLY_NAMES, LEVEL_WARN2, LEVEL_ERROR2, LEVEL_HINT, PARSE_ISSUES, BINDING_MEMBER_TOO_DEEP_RE, UNSUPPORTED_EXPR_GUIDANCE, HTML_LINT_OPTS, NO_WRAPPERS2, ANY_EVENT_MODIFIERS, fixTo, BOOL_CONDITION_ORIGINS, isBoolConditionCtx, ATTR_VAL_CHECKERS, NODE_KIND_TO_CTX, HANDLER_CHANNELS, ASYNC_HANDLER_HELP, NON_NESTABLE_AT_RULE, GLOBAL_LEADING_SELECTOR, IGNORE_DIRECTIVE, blankRun, STYLE_TO_GLOBAL_HELP, KNOWN_LOOKUP_KEYS, LintContext, LintParseContext;
|
|
6612
6800
|
var init_lint_check = __esm({
|
|
6613
6801
|
"tools/core/lint-check.js"() {
|
|
6614
6802
|
init_anode();
|
|
6615
6803
|
init_components();
|
|
6804
|
+
init_parsectx();
|
|
6616
6805
|
init_htmllinter();
|
|
6617
6806
|
init_closest_name();
|
|
6618
6807
|
KNOWN_COMPONENT_SPEC_KEYS = new Set(
|
|
@@ -6646,7 +6835,6 @@ var init_lint_check = __esm({
|
|
|
6646
6835
|
DYN_ALIAS_NOT_REFERENCED = "DYN_ALIAS_NOT_REFERENCED";
|
|
6647
6836
|
PROVIDE_NOT_ADDRESSABLE = "PROVIDE_NOT_ADDRESSABLE";
|
|
6648
6837
|
PROVIDE_TYPE_BAD_SHAPE = "PROVIDE_TYPE_BAD_SHAPE";
|
|
6649
|
-
PROVIDE_NAME_COLLISION = "PROVIDE_NAME_COLLISION";
|
|
6650
6838
|
LOOKUP_BAD_SHAPE = "LOOKUP_BAD_SHAPE";
|
|
6651
6839
|
LOOKUP_NO_PROVIDER = "LOOKUP_NO_PROVIDER";
|
|
6652
6840
|
RENDER_IT_OUTSIDE_OF_LOOP = "RENDER_IT_OUTSIDE_OF_LOOP";
|
|
@@ -6663,6 +6851,7 @@ var init_lint_check = __esm({
|
|
|
6663
6851
|
UNKNOWN_COMPONENT_NAME = "UNKNOWN_COMPONENT_NAME";
|
|
6664
6852
|
UNKNOWN_MACRO_ARG = "UNKNOWN_MACRO_ARG";
|
|
6665
6853
|
UNKNOWN_DIRECTIVE = "UNKNOWN_DIRECTIVE";
|
|
6854
|
+
ORPHAN_DIRECTIVE = "ORPHAN_DIRECTIVE";
|
|
6666
6855
|
UNKNOWN_X_OP = "UNKNOWN_X_OP";
|
|
6667
6856
|
UNKNOWN_X_ATTR = "UNKNOWN_X_ATTR";
|
|
6668
6857
|
X_OP_IGNORES_CHILDREN = "X_OP_IGNORES_CHILDREN";
|
|
@@ -6697,6 +6886,7 @@ var init_lint_check = __esm({
|
|
|
6697
6886
|
LEVEL_HINT = "hint";
|
|
6698
6887
|
PARSE_ISSUES = {
|
|
6699
6888
|
"unknown-directive": { id: UNKNOWN_DIRECTIVE, candidates: KNOWN_DIRECTIVE_NAMES },
|
|
6889
|
+
"orphan-directive": { id: ORPHAN_DIRECTIVE },
|
|
6700
6890
|
"unknown-x-op": { id: UNKNOWN_X_OP, candidates: X_KNOWN_OP_NAMES, atPrefix: X_KNOWN_OP_NAMES },
|
|
6701
6891
|
"unknown-x-attr": {
|
|
6702
6892
|
id: UNKNOWN_X_ATTR,
|
|
@@ -6851,13 +7041,14 @@ var init_lint_check = __esm({
|
|
|
6851
7041
|
this.reports.push({ id, info, level, context: { ...this.frame }, suggestion });
|
|
6852
7042
|
}
|
|
6853
7043
|
};
|
|
6854
|
-
LintParseContext = class extends
|
|
6855
|
-
constructor(document2
|
|
6856
|
-
super(document2
|
|
7044
|
+
LintParseContext = class extends ParseCtxClassSetCollector {
|
|
7045
|
+
constructor(document2) {
|
|
7046
|
+
super(document2);
|
|
6857
7047
|
this.attrs = [];
|
|
6858
7048
|
this.parseIssues = [];
|
|
6859
7049
|
}
|
|
6860
7050
|
onAttributes(attrs, wrapperAttrs, textChild, isMacroCall = false, tag = null) {
|
|
7051
|
+
super.onAttributes(attrs, wrapperAttrs, textChild, isMacroCall, tag);
|
|
6861
7052
|
this.attrs.push({ attrs, wrapperAttrs, textChild, isMacroCall, tag });
|
|
6862
7053
|
}
|
|
6863
7054
|
onParseIssue(kind, info) {
|
|
@@ -6974,7 +7165,7 @@ var init_lint_rules = __esm({
|
|
|
6974
7165
|
code: LOOKUP_NO_PROVIDER,
|
|
6975
7166
|
level: "error",
|
|
6976
7167
|
group: "Dynamic bindings",
|
|
6977
|
-
summary: "`lookup` name is provided
|
|
7168
|
+
summary: "`lookup` name is neither provided in scope nor a registered path."
|
|
6978
7169
|
},
|
|
6979
7170
|
{
|
|
6980
7171
|
code: PROVIDE_TYPE_BAD_SHAPE,
|
|
@@ -6982,12 +7173,6 @@ var init_lint_rules = __esm({
|
|
|
6982
7173
|
group: "Dynamic bindings",
|
|
6983
7174
|
summary: 'A PascalCase `provide` publishes a component type; its value must be `"self"`.'
|
|
6984
7175
|
},
|
|
6985
|
-
{
|
|
6986
|
-
code: PROVIDE_NAME_COLLISION,
|
|
6987
|
-
level: "error",
|
|
6988
|
-
group: "Dynamic bindings",
|
|
6989
|
-
summary: "Two components in one scope chain `provide` the same name."
|
|
6990
|
-
},
|
|
6991
7176
|
// Templates / events
|
|
6992
7177
|
{
|
|
6993
7178
|
code: RENDER_IT_OUTSIDE_OF_LOOP,
|
|
@@ -7019,6 +7204,12 @@ var init_lint_rules = __esm({
|
|
|
7019
7204
|
group: "Templates / events",
|
|
7020
7205
|
summary: "`@directive` name is not recognized (typo or unsupported)."
|
|
7021
7206
|
},
|
|
7207
|
+
{
|
|
7208
|
+
code: ORPHAN_DIRECTIVE,
|
|
7209
|
+
level: "error",
|
|
7210
|
+
group: "Templates / events",
|
|
7211
|
+
summary: "`@when` / `@loop-with` without an `@each`, or `@then` / `@else` without an `@if`, on the same element — the directive is ignored."
|
|
7212
|
+
},
|
|
7022
7213
|
{
|
|
7023
7214
|
code: UNKNOWN_X_OP,
|
|
7024
7215
|
level: "error",
|
|
@@ -7276,19 +7467,19 @@ function lintIdToMessage(id, info) {
|
|
|
7276
7467
|
case "DYN_ALIAS_NOT_REFERENCED":
|
|
7277
7468
|
return `Lookup '${info.name}' is defined but never used — remove it or reference it as '*${info.name}' in a view`;
|
|
7278
7469
|
case "PROVIDE_NOT_ADDRESSABLE":
|
|
7279
|
-
return `Provide '${info.name}' value '${info.value}' must be a field ('.f') or seq-access ('.s[.k]') — a
|
|
7470
|
+
return `Provide '${info.name}' value '${info.value}' must be a field ('.f') or seq-access ('.s[.k]') — a provide doubles as the path '<x render="*${info.name}">' resumes at, so this one is dropped and '*${info.name}' resolves to nothing`;
|
|
7280
7471
|
case "LOOKUP_BAD_SHAPE":
|
|
7281
7472
|
return `Lookup '${info.name}' has an invalid shape: ${info.problem}`;
|
|
7282
7473
|
case "LOOKUP_NO_PROVIDER":
|
|
7283
|
-
return info.hasDefault ? `Lookup '${info.name}' is provided by no component in scope, so it always resolves to its default` : `Lookup '${info.name}' is provided by no component in scope — add a 'provide' for it, or give this lookup a default`;
|
|
7474
|
+
return info.hasDefault ? `Lookup '${info.name}' is provided by no component in scope and matches no registered path, so it always resolves to its default` : `Lookup '${info.name}' is provided by no component in scope and matches no registered path — add a 'provide' for it, register a path under that name, or give this lookup a default`;
|
|
7284
7475
|
case "PROVIDE_TYPE_BAD_SHAPE":
|
|
7285
7476
|
return `Provide '${info.name}' starts uppercase, so it publishes a component type — its value must be 'self', not '${info.value}'`;
|
|
7286
|
-
case "PROVIDE_NAME_COLLISION":
|
|
7287
|
-
return `Provide '${info.name}' is also provided by '${info.other}' in the same scope — one name, one provider, so a lookup can find it`;
|
|
7288
7477
|
case "UNKNOWN_MACRO_ARG":
|
|
7289
7478
|
return `Argument '${info.name}' is not declared in macro '${info.macroName}'`;
|
|
7290
7479
|
case "UNKNOWN_DIRECTIVE":
|
|
7291
7480
|
return `Unknown directive '@${info.name}=${JSON.stringify(info.value)}'${fmtTagSuffix(info)}`;
|
|
7481
|
+
case "ORPHAN_DIRECTIVE":
|
|
7482
|
+
return `'@${info.name}=${JSON.stringify(info.value)}' needs an '@${info.needs}' on the same element — it was ignored${fmtTagSuffix(info)}`;
|
|
7292
7483
|
case "UNKNOWN_X_OP":
|
|
7293
7484
|
return `Unknown <x> op '${info.name}=${JSON.stringify(info.value)}'${fmtTagSuffix(info)}`;
|
|
7294
7485
|
case "UNKNOWN_X_ATTR":
|
|
@@ -12661,303 +12852,105 @@ function getComponentDoc(comp) {
|
|
|
12661
12852
|
});
|
|
12662
12853
|
}
|
|
12663
12854
|
return {
|
|
12664
|
-
name,
|
|
12665
|
-
methods: userMethods,
|
|
12666
|
-
receive: receiveHandlers,
|
|
12667
|
-
intent: intentHandlers,
|
|
12668
|
-
fields: fieldDocs
|
|
12669
|
-
};
|
|
12670
|
-
}
|
|
12671
|
-
function docComponents(normalized, { name = null } = {}) {
|
|
12672
|
-
const comps = normalized.components;
|
|
12673
|
-
const picked = name === null ? comps : comps.filter((c) => c.name === name);
|
|
12674
|
-
return new ComponentDocs({ items: picked.map((comp) => getComponentDoc(comp)) });
|
|
12675
|
-
}
|
|
12676
|
-
var init_docs = __esm({
|
|
12677
|
-
"tools/core/docs.js"() {
|
|
12678
|
-
init_results();
|
|
12679
|
-
}
|
|
12680
|
-
});
|
|
12681
|
-
|
|
12682
|
-
// tools/core/lint.js
|
|
12683
|
-
function lintComponents(normalized, { name = null, LintParseContextClass, wellKnownExtras = /* @__PURE__ */ new Set() }) {
|
|
12684
|
-
const comps = normalized.components;
|
|
12685
|
-
const picked = name === null ? comps : comps.filter((c) => c.name === name);
|
|
12686
|
-
const stack = new ComponentStack();
|
|
12687
|
-
stack.registerComponents(comps);
|
|
12688
|
-
if (normalized.macros) stack.registerMacros(normalized.macros);
|
|
12689
|
-
if (normalized.intentHandlers) stack.registerIntentHandlers(normalized.intentHandlers);
|
|
12690
|
-
const results = [];
|
|
12691
|
-
for (const comp of picked) {
|
|
12692
|
-
comp.compile(LintParseContextClass);
|
|
12693
|
-
const lx = checkComponent(comp, void 0, { wellKnownExtras });
|
|
12694
|
-
results.push(
|
|
12695
|
-
new LintComponentResult({
|
|
12696
|
-
componentName: comp.name,
|
|
12697
|
-
findings: lx.reports.map((r) => new LintFinding(r))
|
|
12698
|
-
})
|
|
12699
|
-
);
|
|
12700
|
-
}
|
|
12701
|
-
return new LintReport({ components: results });
|
|
12702
|
-
}
|
|
12703
|
-
var init_lint2 = __esm({
|
|
12704
|
-
"tools/core/lint.js"() {
|
|
12705
|
-
init_components();
|
|
12706
|
-
init_lint_check();
|
|
12707
|
-
init_results();
|
|
12708
|
-
}
|
|
12709
|
-
});
|
|
12710
|
-
|
|
12711
|
-
// tools/core/list.js
|
|
12712
|
-
function summarize(comp) {
|
|
12713
|
-
const { fields: fieldMap, name } = comp;
|
|
12714
|
-
const fields = [];
|
|
12715
|
-
for (const fieldName in fieldMap) {
|
|
12716
|
-
const f = fieldMap[fieldName];
|
|
12717
|
-
fields.push({ name: fieldName, type: f.type });
|
|
12718
|
-
}
|
|
12719
|
-
return new ComponentSummary({
|
|
12720
|
-
name,
|
|
12721
|
-
views: Object.keys(comp.views ?? {}),
|
|
12722
|
-
fields
|
|
12723
|
-
});
|
|
12724
|
-
}
|
|
12725
|
-
function listComponents(normalized, { name = null, limit = 0 } = {}) {
|
|
12726
|
-
const comps = normalized.components;
|
|
12727
|
-
const picked = name === null ? comps : comps.filter((c) => c.name === name);
|
|
12728
|
-
const total = picked.length;
|
|
12729
|
-
const capped = limit > 0 ? picked.slice(0, limit) : picked;
|
|
12730
|
-
return new ComponentList({
|
|
12731
|
-
items: capped.map(summarize),
|
|
12732
|
-
total,
|
|
12733
|
-
truncated: capped.length < total
|
|
12734
|
-
});
|
|
12735
|
-
}
|
|
12736
|
-
function listExamples(normalized, { limit = 0 } = {}) {
|
|
12737
|
-
const sections = normalized.sections;
|
|
12738
|
-
const total = sections.reduce((n, s) => n + (s.items?.length ?? 0), 0);
|
|
12739
|
-
if (limit <= 0) {
|
|
12740
|
-
return new ExampleIndex({ sections, total, truncated: false });
|
|
12741
|
-
}
|
|
12742
|
-
const capped = [];
|
|
12743
|
-
let remaining = limit;
|
|
12744
|
-
for (const s of sections) {
|
|
12745
|
-
if (remaining <= 0) break;
|
|
12746
|
-
const items = s.items.slice(0, remaining);
|
|
12747
|
-
capped.push({ ...s, items });
|
|
12748
|
-
remaining -= items.length;
|
|
12749
|
-
}
|
|
12750
|
-
return new ExampleIndex({
|
|
12751
|
-
sections: capped,
|
|
12752
|
-
total,
|
|
12753
|
-
truncated: capped.reduce((n, s) => n + s.items.length, 0) < total
|
|
12754
|
-
});
|
|
12755
|
-
}
|
|
12756
|
-
var init_list = __esm({
|
|
12757
|
-
"tools/core/list.js"() {
|
|
12758
|
-
init_results();
|
|
12759
|
-
}
|
|
12760
|
-
});
|
|
12761
|
-
|
|
12762
|
-
// src/stack.js
|
|
12763
|
-
function routeLookup(route, lex, dyn) {
|
|
12764
|
-
for (let i = 0; i < route.length; i++) {
|
|
12765
|
-
const leg = route[i];
|
|
12766
|
-
if (leg === "dyn") {
|
|
12767
|
-
const v = dyn();
|
|
12768
|
-
if (v != null) return v;
|
|
12769
|
-
} else if (leg === "lex") {
|
|
12770
|
-
const v = lex();
|
|
12771
|
-
if (v != null) return v;
|
|
12772
|
-
} else {
|
|
12773
|
-
console.warn("unknown lookup route leg", leg, '- expected "dyn" or "lex"');
|
|
12774
|
-
}
|
|
12775
|
-
}
|
|
12776
|
-
return null;
|
|
12777
|
-
}
|
|
12778
|
-
function lookup(chain, name, dv = null) {
|
|
12779
|
-
let n = chain;
|
|
12780
|
-
while (n !== null) {
|
|
12781
|
-
const r = n[0].lookup(name);
|
|
12782
|
-
if (r === STOP) return dv;
|
|
12783
|
-
if (r !== NEXT) return r;
|
|
12784
|
-
n = n[1];
|
|
12785
|
-
}
|
|
12786
|
-
return dv;
|
|
12787
|
-
}
|
|
12788
|
-
function computeViewsId(views) {
|
|
12789
|
-
let s = "";
|
|
12790
|
-
let n = views;
|
|
12791
|
-
while (n !== null) {
|
|
12792
|
-
s += n[0];
|
|
12793
|
-
n = n[1];
|
|
12794
|
-
}
|
|
12795
|
-
return s === "main" ? "" : s;
|
|
12796
|
-
}
|
|
12797
|
-
var STOP, NEXT, DEFAULT_ROUTE, BindFrame, ObjectFrame, Stack;
|
|
12798
|
-
var init_stack = __esm({
|
|
12799
|
-
"src/stack.js"() {
|
|
12800
|
-
STOP = /* @__PURE__ */ Symbol("STOP");
|
|
12801
|
-
NEXT = /* @__PURE__ */ Symbol("NEXT");
|
|
12802
|
-
DEFAULT_ROUTE = ["dyn", "lex"];
|
|
12803
|
-
BindFrame = class {
|
|
12804
|
-
constructor(it, binds, isFrame) {
|
|
12805
|
-
this.it = it;
|
|
12806
|
-
this.binds = binds;
|
|
12807
|
-
this.isFrame = isFrame;
|
|
12808
|
-
}
|
|
12809
|
-
lookup(name) {
|
|
12810
|
-
const v = this.binds[name];
|
|
12811
|
-
return v === void 0 ? this.isFrame ? STOP : NEXT : v;
|
|
12812
|
-
}
|
|
12813
|
-
};
|
|
12814
|
-
ObjectFrame = class {
|
|
12815
|
-
constructor(binds) {
|
|
12816
|
-
this.binds = binds;
|
|
12817
|
-
}
|
|
12818
|
-
lookup(key) {
|
|
12819
|
-
const v = this.binds[key];
|
|
12820
|
-
return v === void 0 ? NEXT : v;
|
|
12821
|
-
}
|
|
12822
|
-
};
|
|
12823
|
-
Stack = class _Stack {
|
|
12824
|
-
constructor(comps, it, binds, dynBinds, views, viewsId, ctx = null) {
|
|
12825
|
-
this.comps = comps;
|
|
12826
|
-
this.it = it;
|
|
12827
|
-
this.binds = binds;
|
|
12828
|
-
this.dynBinds = dynBinds;
|
|
12829
|
-
this.views = views;
|
|
12830
|
-
this.viewsId = viewsId;
|
|
12831
|
-
this.ctx = ctx;
|
|
12832
|
-
}
|
|
12833
|
-
// Evaluate every provide the entered component publishes and push them as one
|
|
12834
|
-
// dynBinds frame, keyed by NAME. Published types go in the same frame: a type name
|
|
12835
|
-
// starts A-Z and a value name does not, so the two namespaces cannot collide and
|
|
12836
|
-
// nearest-ancestor-wins falls out of frame order for both. No-op with no provides.
|
|
12837
|
-
_pushProvides() {
|
|
12838
|
-
const comp = this.comps.getCompFor(this.it);
|
|
12839
|
-
if (comp == null) return this;
|
|
12840
|
-
const { provide, provideType } = comp;
|
|
12841
|
-
const dynObj = {};
|
|
12842
|
-
let has2 = false;
|
|
12843
|
-
for (const k in provide) {
|
|
12844
|
-
dynObj[k] = provide[k].val.eval(this);
|
|
12845
|
-
has2 = true;
|
|
12846
|
-
}
|
|
12847
|
-
for (const k in provideType) {
|
|
12848
|
-
dynObj[k] = provideType[k];
|
|
12849
|
-
has2 = true;
|
|
12850
|
-
}
|
|
12851
|
-
if (!has2) return this;
|
|
12852
|
-
const newDynBinds = [new ObjectFrame(dynObj), this.dynBinds];
|
|
12853
|
-
const { comps, it, binds, views, viewsId, ctx } = this;
|
|
12854
|
-
return new _Stack(comps, it, binds, newDynBinds, views, viewsId, ctx);
|
|
12855
|
-
}
|
|
12856
|
-
static root(comps, it, ctx) {
|
|
12857
|
-
const binds = [new BindFrame(it, {}, true), null];
|
|
12858
|
-
const dynBinds = [new ObjectFrame({}), null];
|
|
12859
|
-
const views = ["main", null];
|
|
12860
|
-
return new _Stack(comps, it, binds, dynBinds, views, "", ctx)._pushProvides();
|
|
12861
|
-
}
|
|
12862
|
-
enter(it, bindings = {}, isFrame = true) {
|
|
12863
|
-
const { comps, binds, dynBinds, views, viewsId, ctx } = this;
|
|
12864
|
-
const newBinds = [new BindFrame(it, bindings, isFrame), binds];
|
|
12865
|
-
const stack = new _Stack(comps, it, newBinds, dynBinds, views, viewsId, ctx);
|
|
12866
|
-
return isFrame ? stack._pushProvides() : stack;
|
|
12867
|
-
}
|
|
12868
|
-
pushViewName(name) {
|
|
12869
|
-
const { comps, it, binds, dynBinds, views, ctx } = this;
|
|
12870
|
-
const newViews = [name, views];
|
|
12871
|
-
return new _Stack(comps, it, binds, dynBinds, newViews, computeViewsId(newViews), ctx);
|
|
12872
|
-
}
|
|
12873
|
-
// Published types are stable per scope and would only churn the render cache, so
|
|
12874
|
-
// the cache key covers values alone.
|
|
12875
|
-
_pushDynBindValuesToArray(arr, comp) {
|
|
12876
|
-
for (const k in comp.provide) arr.push(this.lookupDynamic(k));
|
|
12877
|
-
for (const k in comp.lookup) arr.push(this.lookupDynamic(k));
|
|
12878
|
-
}
|
|
12879
|
-
// `*name`: the nearest binding above (including this component's own provides,
|
|
12880
|
-
// pushed on entering it), else this component's declared default, else null.
|
|
12881
|
-
lookupDynamic(name) {
|
|
12882
|
-
const v = lookup(this.dynBinds, name);
|
|
12883
|
-
if (v != null) return v;
|
|
12884
|
-
const comp = this.comps.getCompFor(this.it);
|
|
12885
|
-
return comp?.lookup[name]?.val?.eval(this) ?? null;
|
|
12886
|
-
}
|
|
12887
|
-
lookupBind(name) {
|
|
12888
|
-
return lookup(this.binds, name);
|
|
12889
|
-
}
|
|
12890
|
-
lookupFieldRaw(name) {
|
|
12891
|
-
return this.it[name] ?? null;
|
|
12892
|
-
}
|
|
12893
|
-
lookupMethod(name) {
|
|
12894
|
-
const fn = this.it[name];
|
|
12895
|
-
return fn instanceof Function ? fn.call(this.it) : null;
|
|
12896
|
-
}
|
|
12897
|
-
// The dispatched DOM event / drag info, read only by EventMemberVal's
|
|
12898
|
-
// `e.<member>` handler args. Null outside a live event transaction.
|
|
12899
|
-
lookupEvent() {
|
|
12900
|
-
return this.ctx?.event ?? null;
|
|
12901
|
-
}
|
|
12902
|
-
lookupDragInfo() {
|
|
12903
|
-
return this.ctx?.dragInfo ?? null;
|
|
12904
|
-
}
|
|
12905
|
-
getHandlerFor(name, key) {
|
|
12906
|
-
return this.comps.getHandlerFor(this.it, name, key);
|
|
12907
|
-
}
|
|
12908
|
-
lookupBestView(views, defaultViewName) {
|
|
12909
|
-
let n = this.views;
|
|
12910
|
-
while (n !== null) {
|
|
12911
|
-
const view = views[n[0]];
|
|
12912
|
-
if (view !== void 0) return view;
|
|
12913
|
-
n = n[1];
|
|
12914
|
-
}
|
|
12915
|
-
return views[defaultViewName];
|
|
12916
|
-
}
|
|
12917
|
-
};
|
|
12855
|
+
name,
|
|
12856
|
+
methods: userMethods,
|
|
12857
|
+
receive: receiveHandlers,
|
|
12858
|
+
intent: intentHandlers,
|
|
12859
|
+
fields: fieldDocs
|
|
12860
|
+
};
|
|
12861
|
+
}
|
|
12862
|
+
function docComponents(normalized, { name = null } = {}) {
|
|
12863
|
+
const comps = normalized.components;
|
|
12864
|
+
const picked = name === null ? comps : comps.filter((c) => c.name === name);
|
|
12865
|
+
return new ComponentDocs({ items: picked.map((comp) => getComponentDoc(comp)) });
|
|
12866
|
+
}
|
|
12867
|
+
var init_docs = __esm({
|
|
12868
|
+
"tools/core/docs.js"() {
|
|
12869
|
+
init_results();
|
|
12918
12870
|
}
|
|
12919
12871
|
});
|
|
12920
12872
|
|
|
12921
|
-
//
|
|
12922
|
-
function
|
|
12923
|
-
const
|
|
12924
|
-
|
|
12925
|
-
|
|
12926
|
-
|
|
12873
|
+
// tools/core/lint.js
|
|
12874
|
+
function lintComponents(normalized, { name = null, LintParseContextClass, wellKnownExtras = /* @__PURE__ */ new Set() }) {
|
|
12875
|
+
const comps = normalized.components;
|
|
12876
|
+
const picked = name === null ? comps : comps.filter((c) => c.name === name);
|
|
12877
|
+
const stack = new ComponentStack();
|
|
12878
|
+
stack.registerComponents(comps);
|
|
12879
|
+
if (normalized.macros) stack.registerMacros(normalized.macros);
|
|
12880
|
+
if (normalized.intentHandlers) stack.registerIntentHandlers(normalized.intentHandlers);
|
|
12881
|
+
const results = [];
|
|
12882
|
+
for (const comp of picked) {
|
|
12883
|
+
comp.compile(LintParseContextClass);
|
|
12884
|
+
const lx = checkComponent(comp, void 0, { wellKnownExtras });
|
|
12885
|
+
results.push(
|
|
12886
|
+
new LintComponentResult({
|
|
12887
|
+
componentName: comp.name,
|
|
12888
|
+
findings: lx.reports.map((r) => new LintFinding(r))
|
|
12889
|
+
})
|
|
12927
12890
|
);
|
|
12928
|
-
return Comp?.make({ ...field.args, ...args }, { scope }) ?? null;
|
|
12929
|
-
}
|
|
12930
|
-
function fieldFromDescriptor(name, value) {
|
|
12931
|
-
const FieldCls = fieldsByTypeName[value.type] ?? FieldAny;
|
|
12932
|
-
const probe = new FieldCls(name);
|
|
12933
|
-
return [FieldCls, probe.coerceOr(value.defaultValue, probe.defaultValue)];
|
|
12934
|
-
}
|
|
12935
|
-
function classFromData(name, { fields = {}, methods, statics }) {
|
|
12936
|
-
const b = new ClassBuilder(name);
|
|
12937
|
-
for (const field in fields) {
|
|
12938
|
-
const value = fields[field];
|
|
12939
|
-
const type3 = typeof value;
|
|
12940
|
-
if (type3 === "string") b.addField(field, value, FieldString);
|
|
12941
|
-
else if (type3 === "number") b.addField(field, value, FieldFloat);
|
|
12942
|
-
else if (type3 === "boolean") b.addField(field, value, FieldBool);
|
|
12943
|
-
else if (Array.isArray(value)) b.addField(field, [...value], FieldList);
|
|
12944
|
-
else if (value instanceof Set) b.addField(field, new Set(value), FieldSet);
|
|
12945
|
-
else if (value instanceof Map) b.addField(field, new Map(value), FieldMap);
|
|
12946
|
-
else if (value?.type && Object.hasOwn(value, "defaultValue")) {
|
|
12947
|
-
const [FieldCls, dval] = fieldFromDescriptor(field, value);
|
|
12948
|
-
b.addField(field, dval, FieldCls);
|
|
12949
|
-
} else if (value?.component && value?.args !== void 0)
|
|
12950
|
-
b.addCompField(field, value.component, value.args);
|
|
12951
|
-
else if (isPlainObject(value)) b.addField(field, { ...value }, FieldObject);
|
|
12952
|
-
else {
|
|
12953
|
-
const FieldCls = value?.[FIELD_CLASS] ?? FieldAny;
|
|
12954
|
-
b.addField(field, value, FieldCls);
|
|
12955
|
-
}
|
|
12956
12891
|
}
|
|
12957
|
-
|
|
12958
|
-
|
|
12959
|
-
|
|
12892
|
+
return new LintReport({ components: results });
|
|
12893
|
+
}
|
|
12894
|
+
var init_lint2 = __esm({
|
|
12895
|
+
"tools/core/lint.js"() {
|
|
12896
|
+
init_components();
|
|
12897
|
+
init_lint_check();
|
|
12898
|
+
init_results();
|
|
12899
|
+
}
|
|
12900
|
+
});
|
|
12901
|
+
|
|
12902
|
+
// tools/core/list.js
|
|
12903
|
+
function summarize(comp) {
|
|
12904
|
+
const { fields: fieldMap, name } = comp;
|
|
12905
|
+
const fields = [];
|
|
12906
|
+
for (const fieldName in fieldMap) {
|
|
12907
|
+
const f = fieldMap[fieldName];
|
|
12908
|
+
fields.push({ name: fieldName, type: f.type });
|
|
12909
|
+
}
|
|
12910
|
+
return new ComponentSummary({
|
|
12911
|
+
name,
|
|
12912
|
+
views: Object.keys(comp.views ?? {}),
|
|
12913
|
+
fields
|
|
12914
|
+
});
|
|
12915
|
+
}
|
|
12916
|
+
function listComponents(normalized, { name = null, limit = 0 } = {}) {
|
|
12917
|
+
const comps = normalized.components;
|
|
12918
|
+
const picked = name === null ? comps : comps.filter((c) => c.name === name);
|
|
12919
|
+
const total = picked.length;
|
|
12920
|
+
const capped = limit > 0 ? picked.slice(0, limit) : picked;
|
|
12921
|
+
return new ComponentList({
|
|
12922
|
+
items: capped.map(summarize),
|
|
12923
|
+
total,
|
|
12924
|
+
truncated: capped.length < total
|
|
12925
|
+
});
|
|
12926
|
+
}
|
|
12927
|
+
function listExamples(normalized, { limit = 0 } = {}) {
|
|
12928
|
+
const sections = normalized.sections;
|
|
12929
|
+
const total = sections.reduce((n, s) => n + (s.items?.length ?? 0), 0);
|
|
12930
|
+
if (limit <= 0) {
|
|
12931
|
+
return new ExampleIndex({ sections, total, truncated: false });
|
|
12932
|
+
}
|
|
12933
|
+
const capped = [];
|
|
12934
|
+
let remaining = limit;
|
|
12935
|
+
for (const s of sections) {
|
|
12936
|
+
if (remaining <= 0) break;
|
|
12937
|
+
const items = s.items.slice(0, remaining);
|
|
12938
|
+
capped.push({ ...s, items });
|
|
12939
|
+
remaining -= items.length;
|
|
12940
|
+
}
|
|
12941
|
+
return new ExampleIndex({
|
|
12942
|
+
sections: capped,
|
|
12943
|
+
total,
|
|
12944
|
+
truncated: capped.reduce((n, s) => n + s.items.length, 0) < total
|
|
12945
|
+
});
|
|
12960
12946
|
}
|
|
12947
|
+
var init_list = __esm({
|
|
12948
|
+
"tools/core/list.js"() {
|
|
12949
|
+
init_results();
|
|
12950
|
+
}
|
|
12951
|
+
});
|
|
12952
|
+
|
|
12953
|
+
// src/oo.js
|
|
12961
12954
|
function validateDraftFields(current2, draft) {
|
|
12962
12955
|
const meta = metaOf(current2);
|
|
12963
12956
|
if (!meta) return;
|
|
@@ -12972,226 +12965,41 @@ function validateDraftFields(current2, draft) {
|
|
|
12972
12965
|
}
|
|
12973
12966
|
}
|
|
12974
12967
|
}
|
|
12975
|
-
|
|
12976
|
-
for (const name in statics) {
|
|
12977
|
-
if (RESERVED_COMPONENT_STATICS.has(name)) {
|
|
12978
|
-
throw new TypeError(`component static "${name}" is reserved by the framework`);
|
|
12979
|
-
}
|
|
12980
|
-
}
|
|
12981
|
-
}
|
|
12982
|
-
var BAD_VALUE2, nullCoercer, Field, CHECK_TYPE_ANY, CHECK_TYPE_INT, CHECK_TYPE_FLOAT, CHECK_TYPE_BOOL, CHECK_TYPE_STRING, CHECK_TYPE_LIST, CHECK_TYPE_OBJECT, CHECK_TYPE_MAP, CHECK_TYPE_SET, COERCE_NONE, COERCE_BOOL, COERCE_STRING, COERCE_INT, COERCE_LIST, COERCE_OBJECT, COERCE_MAP, COERCE_SET, FieldBool, FieldAny, FieldString, FieldInt, FieldFloat, metaOf, getTypeName, FieldComp, FieldList, FieldObject, FieldMap, FieldSet, ClassBuilder, FIELD_CLASS, fieldsByTypeName, META_KEYS, RESERVED_COMPONENT_STATICS;
|
|
12968
|
+
var BAD_VALUE2, COERCE_NONE, COERCE_MAP, FIELD_TYPES, metaOf, RESERVED_COMPONENT_STATICS;
|
|
12983
12969
|
var init_oo = __esm({
|
|
12984
12970
|
"src/oo.js"() {
|
|
12985
12971
|
init_collection();
|
|
12986
12972
|
init_components();
|
|
12987
|
-
init_immer2();
|
|
12988
12973
|
BAD_VALUE2 = /* @__PURE__ */ Symbol("BadValue");
|
|
12989
|
-
nullCoercer = (v) => v;
|
|
12990
|
-
Field = class {
|
|
12991
|
-
constructor(type3, name, typeCheck, coercer, defaultValue = null) {
|
|
12992
|
-
this.type = type3;
|
|
12993
|
-
this.name = name;
|
|
12994
|
-
this.typeCheck = typeCheck;
|
|
12995
|
-
this.coercer = coercer;
|
|
12996
|
-
this.defaultValue = defaultValue;
|
|
12997
|
-
}
|
|
12998
|
-
isValid(v) {
|
|
12999
|
-
return this.typeCheck(v);
|
|
13000
|
-
}
|
|
13001
|
-
coerceOr(v, defaultValue = null) {
|
|
13002
|
-
if (this.isValid(v)) return v;
|
|
13003
|
-
const v1 = this.coercer(v);
|
|
13004
|
-
return this.isValid(v1) ? v1 : defaultValue;
|
|
13005
|
-
}
|
|
13006
|
-
coerceOrDefault(v) {
|
|
13007
|
-
return this.coerceOr(v, this.defaultValue);
|
|
13008
|
-
}
|
|
13009
|
-
};
|
|
13010
|
-
CHECK_TYPE_ANY = (_v) => true;
|
|
13011
|
-
CHECK_TYPE_INT = Number.isInteger;
|
|
13012
|
-
CHECK_TYPE_FLOAT = Number.isFinite;
|
|
13013
|
-
CHECK_TYPE_BOOL = (v) => typeof v === "boolean";
|
|
13014
|
-
CHECK_TYPE_STRING = (v) => typeof v === "string";
|
|
13015
|
-
CHECK_TYPE_LIST = Array.isArray;
|
|
13016
|
-
CHECK_TYPE_OBJECT = isPlainObject;
|
|
13017
|
-
CHECK_TYPE_MAP = (v) => v instanceof Map;
|
|
13018
|
-
CHECK_TYPE_SET = (v) => v instanceof Set;
|
|
13019
12974
|
COERCE_NONE = (_v) => null;
|
|
13020
|
-
COERCE_BOOL = (v) => !!v;
|
|
13021
|
-
COERCE_STRING = (v) => v?.toString?.() ?? "";
|
|
13022
|
-
COERCE_INT = (v) => Number.isFinite(v) ? Math.trunc(v) : null;
|
|
13023
|
-
COERCE_LIST = (v) => Array.isArray(v) ? [...v] : null;
|
|
13024
|
-
COERCE_OBJECT = (v) => isPlainObject(v) ? { ...v } : null;
|
|
13025
12975
|
COERCE_MAP = (v) => {
|
|
13026
12976
|
if (v instanceof Map) return new Map(v);
|
|
13027
12977
|
if (Array.isArray(v) || isPlainObject(v))
|
|
13028
12978
|
return new Map(Array.isArray(v) ? v : Object.entries(v));
|
|
13029
12979
|
return null;
|
|
13030
12980
|
};
|
|
13031
|
-
|
|
13032
|
-
|
|
13033
|
-
|
|
13034
|
-
|
|
13035
|
-
|
|
13036
|
-
|
|
13037
|
-
|
|
13038
|
-
|
|
13039
|
-
|
|
13040
|
-
|
|
13041
|
-
|
|
13042
|
-
|
|
13043
|
-
|
|
13044
|
-
|
|
13045
|
-
}
|
|
13046
|
-
};
|
|
13047
|
-
FieldInt = class extends Field {
|
|
13048
|
-
constructor(name, defaultValue = 0) {
|
|
13049
|
-
super("int", name, CHECK_TYPE_INT, COERCE_INT, defaultValue);
|
|
13050
|
-
}
|
|
13051
|
-
};
|
|
13052
|
-
FieldFloat = class extends Field {
|
|
13053
|
-
constructor(name, defaultValue = 0) {
|
|
13054
|
-
super("float", name, CHECK_TYPE_FLOAT, COERCE_NONE, defaultValue);
|
|
13055
|
-
}
|
|
13056
|
-
};
|
|
13057
|
-
metaOf = (v) => v?.constructor?.[COMPONENT] ?? v?.constructor?.getMetaClass?.();
|
|
13058
|
-
getTypeName = (v) => metaOf(v)?.name ?? null;
|
|
13059
|
-
FieldComp = class extends Field {
|
|
13060
|
-
constructor(type3, name, args) {
|
|
13061
|
-
super(type3, name, (v) => getTypeName(v) === type3, nullCoercer, null);
|
|
13062
|
-
this.args = args;
|
|
13063
|
-
}
|
|
13064
|
-
};
|
|
13065
|
-
FieldList = class extends Field {
|
|
13066
|
-
constructor(name, defaultValue = []) {
|
|
13067
|
-
super("list", name, CHECK_TYPE_LIST, COERCE_LIST, defaultValue);
|
|
13068
|
-
}
|
|
13069
|
-
};
|
|
13070
|
-
FieldObject = class extends Field {
|
|
13071
|
-
constructor(name, defaultValue = {}) {
|
|
13072
|
-
super("object", name, CHECK_TYPE_OBJECT, COERCE_OBJECT, defaultValue);
|
|
13073
|
-
}
|
|
13074
|
-
};
|
|
13075
|
-
FieldMap = class extends Field {
|
|
13076
|
-
constructor(name, defaultValue = /* @__PURE__ */ new Map()) {
|
|
13077
|
-
super("map", name, CHECK_TYPE_MAP, COERCE_MAP, defaultValue);
|
|
13078
|
-
}
|
|
13079
|
-
};
|
|
13080
|
-
FieldSet = class extends Field {
|
|
13081
|
-
constructor(name, defaultValue = /* @__PURE__ */ new Set()) {
|
|
13082
|
-
super("set", name, CHECK_TYPE_SET, COERCE_SET, defaultValue);
|
|
13083
|
-
}
|
|
12981
|
+
FIELD_TYPES = {
|
|
12982
|
+
any: [(_v) => true, COERCE_NONE, () => null],
|
|
12983
|
+
text: [(v) => typeof v === "string", (v) => v?.toString?.() ?? "", () => ""],
|
|
12984
|
+
int: [Number.isInteger, (v) => Number.isFinite(v) ? Math.trunc(v) : null, () => 0],
|
|
12985
|
+
float: [Number.isFinite, COERCE_NONE, () => 0],
|
|
12986
|
+
bool: [(v) => typeof v === "boolean", (v) => !!v, () => false],
|
|
12987
|
+
list: [Array.isArray, (v) => Array.isArray(v) ? [...v] : null, () => []],
|
|
12988
|
+
object: [isPlainObject, (v) => isPlainObject(v) ? { ...v } : null, () => ({})],
|
|
12989
|
+
map: [(v) => v instanceof Map, COERCE_MAP, () => /* @__PURE__ */ new Map()],
|
|
12990
|
+
set: [
|
|
12991
|
+
(v) => v instanceof Set,
|
|
12992
|
+
(v) => v instanceof Set || Array.isArray(v) ? new Set(v) : null,
|
|
12993
|
+
() => /* @__PURE__ */ new Set()
|
|
12994
|
+
]
|
|
13084
12995
|
};
|
|
13085
|
-
|
|
13086
|
-
constructor(name) {
|
|
13087
|
-
this.name = name;
|
|
13088
|
-
this.fields = {};
|
|
13089
|
-
this.compFields = /* @__PURE__ */ new Set();
|
|
13090
|
-
this._methods = {};
|
|
13091
|
-
this._statics = {};
|
|
13092
|
-
}
|
|
13093
|
-
build() {
|
|
13094
|
-
const { name, fields, compFields, _methods } = this;
|
|
13095
|
-
const defaults = Object.fromEntries(
|
|
13096
|
-
Object.entries(fields).map(([fieldName, field]) => [fieldName, field.defaultValue])
|
|
13097
|
-
);
|
|
13098
|
-
const Class = {
|
|
13099
|
-
[name]: class {
|
|
13100
|
-
constructor(values = {}) {
|
|
13101
|
-
Object.assign(this, defaults, values);
|
|
13102
|
-
}
|
|
13103
|
-
}
|
|
13104
|
-
}[name];
|
|
13105
|
-
Class[DRAFTABLE] = true;
|
|
13106
|
-
Object.assign(Class.prototype, _methods);
|
|
13107
|
-
const metaClass = { fields, name, methods: _methods };
|
|
13108
|
-
Object.assign(
|
|
13109
|
-
Class,
|
|
13110
|
-
{
|
|
13111
|
-
getMetaClass: () => metaClass,
|
|
13112
|
-
make(inArgs = {}, opts = {}) {
|
|
13113
|
-
const args = {};
|
|
13114
|
-
const scope = opts.scope ?? this[COMPONENT]?.scope ?? this.scope;
|
|
13115
|
-
for (const key in inArgs) {
|
|
13116
|
-
const field = fields[key];
|
|
13117
|
-
if (compFields.has(key)) args[key] = mkCompField(field, scope, inArgs[key]);
|
|
13118
|
-
else if (field === void 0)
|
|
13119
|
-
console.warn("extra argument to constructor:", name, key, inArgs);
|
|
13120
|
-
else args[key] = field.coerceOrDefault(inArgs[key]);
|
|
13121
|
-
}
|
|
13122
|
-
for (const key of compFields)
|
|
13123
|
-
if (args[key] === void 0) args[key] = mkCompField(fields[key], scope, inArgs[key]);
|
|
13124
|
-
return freeze(new this(args), true);
|
|
13125
|
-
}
|
|
13126
|
-
},
|
|
13127
|
-
this._statics
|
|
13128
|
-
);
|
|
13129
|
-
return Class;
|
|
13130
|
-
}
|
|
13131
|
-
methods(proto) {
|
|
13132
|
-
for (const k in proto) this._methods[k] = proto[k];
|
|
13133
|
-
}
|
|
13134
|
-
statics(proto) {
|
|
13135
|
-
for (const k in proto) this._statics[k] = proto[k];
|
|
13136
|
-
}
|
|
13137
|
-
addField(name, dval, FieldCls) {
|
|
13138
|
-
const field = new FieldCls(name, dval);
|
|
13139
|
-
this.fields[name] = field;
|
|
13140
|
-
return field;
|
|
13141
|
-
}
|
|
13142
|
-
addCompField(name, type3, args) {
|
|
13143
|
-
const field = new FieldComp(type3, name, args);
|
|
13144
|
-
this.compFields.add(name);
|
|
13145
|
-
this.fields[name] = field;
|
|
13146
|
-
return field;
|
|
13147
|
-
}
|
|
13148
|
-
};
|
|
13149
|
-
FIELD_CLASS = /* @__PURE__ */ Symbol.for("tutuca.fieldClass");
|
|
13150
|
-
fieldsByTypeName = {
|
|
13151
|
-
text: FieldString,
|
|
13152
|
-
int: FieldInt,
|
|
13153
|
-
float: FieldFloat,
|
|
13154
|
-
bool: FieldBool,
|
|
13155
|
-
list: FieldList,
|
|
13156
|
-
object: FieldObject,
|
|
13157
|
-
map: FieldMap,
|
|
13158
|
-
set: FieldSet,
|
|
13159
|
-
any: FieldAny
|
|
13160
|
-
};
|
|
13161
|
-
META_KEYS = "name id fields methods views receive intent alter provide provideType lookup spec extra commonStyle globalStyle scope _rawProvide _rawLookup".split(
|
|
13162
|
-
" "
|
|
13163
|
-
);
|
|
12996
|
+
metaOf = (v) => v?.constructor?.getMetaClass?.();
|
|
13164
12997
|
RESERVED_COMPONENT_STATICS = /* @__PURE__ */ new Set([
|
|
13165
|
-
...
|
|
13166
|
-
|
|
13167
|
-
|
|
13168
|
-
...Object.
|
|
12998
|
+
..."name id fields methods views receive intent alter provide provideType lookup spec extra commonStyle globalStyle scope _rawProvide _rawLookup make getMetaClass".split(
|
|
12999
|
+
" "
|
|
13000
|
+
),
|
|
13001
|
+
...Object.keys(COMPONENT_METHODS)
|
|
13169
13002
|
]);
|
|
13170
|
-
Component.fromSpec = (opts) => {
|
|
13171
|
-
assertNoReservedComponentStatics(opts.statics);
|
|
13172
|
-
const Class = classFromData(opts.name, opts);
|
|
13173
|
-
const comp = new Component(Class, opts);
|
|
13174
|
-
const metaClass = Class.getMetaClass();
|
|
13175
|
-
comp.fields = metaClass.fields;
|
|
13176
|
-
comp.methods = metaClass.methods;
|
|
13177
|
-
Class.getMetaClass = () => comp;
|
|
13178
|
-
Class[COMPONENT] = comp;
|
|
13179
|
-
for (const key of META_KEYS)
|
|
13180
|
-
if (!Object.hasOwn(Class, key))
|
|
13181
|
-
Object.defineProperty(Class, key, {
|
|
13182
|
-
get() {
|
|
13183
|
-
return comp[key];
|
|
13184
|
-
},
|
|
13185
|
-
set(v) {
|
|
13186
|
-
comp[key] = v;
|
|
13187
|
-
},
|
|
13188
|
-
configurable: true
|
|
13189
|
-
});
|
|
13190
|
-
for (const key of Object.getOwnPropertyNames(Component.prototype))
|
|
13191
|
-
if (key !== "constructor" && !Object.hasOwn(Class, key))
|
|
13192
|
-
Class[key] = (...args) => comp[key](...args);
|
|
13193
|
-
return Class;
|
|
13194
|
-
};
|
|
13195
13003
|
}
|
|
13196
13004
|
});
|
|
13197
13005
|
|
|
@@ -13199,11 +13007,22 @@ var init_oo = __esm({
|
|
|
13199
13007
|
function nullHandler() {
|
|
13200
13008
|
return this;
|
|
13201
13009
|
}
|
|
13010
|
+
function subscribe(list, cb) {
|
|
13011
|
+
list.push(cb);
|
|
13012
|
+
return () => {
|
|
13013
|
+
const i = list.indexOf(cb);
|
|
13014
|
+
if (i !== -1) list.splice(i, 1);
|
|
13015
|
+
};
|
|
13016
|
+
}
|
|
13017
|
+
function warnUnknownLeg(what, leg) {
|
|
13018
|
+
console.warn(`unknown ${what} route leg`, leg, '- expected "dyn" or "lex"');
|
|
13019
|
+
return null;
|
|
13020
|
+
}
|
|
13202
13021
|
function warnNotIntent(verb) {
|
|
13203
13022
|
console.warn(`ctx.${verb}() is only meaningful in an "intent" handler - ignored`);
|
|
13204
13023
|
}
|
|
13205
13024
|
function rootDispatcher(transactor) {
|
|
13206
|
-
return new Dispatcher(new
|
|
13025
|
+
return new Dispatcher(new DispatchPath(), transactor, null);
|
|
13207
13026
|
}
|
|
13208
13027
|
var State2, Transactor, Transaction, InputEvent, NameArgsTransaction, SendEvent, IntentEvent, PASS, REFUSAL_RING_CAP, INTENT_DEPTH, IntentWalk, Completion, Dispatcher, EventContext, PathChanges;
|
|
13209
13028
|
var init_transactor = __esm({
|
|
@@ -13251,14 +13070,7 @@ var init_transactor = __esm({
|
|
|
13251
13070
|
// carry: kind, name, args, path, pathKeys, targetPath, handler, handlerName,
|
|
13252
13071
|
// matched, before, after, parent, timestamp. Purely observational.
|
|
13253
13072
|
observe(cb) {
|
|
13254
|
-
this._observers
|
|
13255
|
-
return () => {
|
|
13256
|
-
const i = this._observers.indexOf(cb);
|
|
13257
|
-
if (i !== -1) this._observers.splice(i, 1);
|
|
13258
|
-
};
|
|
13259
|
-
}
|
|
13260
|
-
_emit(record) {
|
|
13261
|
-
for (const cb of this._observers) cb(record);
|
|
13073
|
+
return subscribe(this._observers, cb);
|
|
13262
13074
|
}
|
|
13263
13075
|
// Record a refusal: a dispatch the runtime could not carry out. Kinds are
|
|
13264
13076
|
// open strings; today the runtime raises NO_HANDLER (a receive name with no
|
|
@@ -13277,11 +13089,7 @@ var init_transactor = __esm({
|
|
|
13277
13089
|
// Subscribe to refusal records as they happen. Returns an unsubscribe fn,
|
|
13278
13090
|
// like observe().
|
|
13279
13091
|
observeRefusals(cb) {
|
|
13280
|
-
this._refusalObservers
|
|
13281
|
-
return () => {
|
|
13282
|
-
const i = this._refusalObservers.indexOf(cb);
|
|
13283
|
-
if (i !== -1) this._refusalObservers.splice(i, 1);
|
|
13284
|
-
};
|
|
13092
|
+
return subscribe(this._refusalObservers, cb);
|
|
13285
13093
|
}
|
|
13286
13094
|
// Build and dispatch one observer record. Pins field-resolved keys (e.g. a
|
|
13287
13095
|
// `.a[.selId]` render target reconstructed from a DOM event) against the root the
|
|
@@ -13290,7 +13098,7 @@ var init_transactor = __esm({
|
|
|
13290
13098
|
_emitRecord(root, { kind, name, args, path, targetPath, handler, handlerName, matched, before, after, parent }) {
|
|
13291
13099
|
if (this._observers.length === 0) return;
|
|
13292
13100
|
const pinned = path.pinKeys(root);
|
|
13293
|
-
|
|
13101
|
+
const record = {
|
|
13294
13102
|
kind,
|
|
13295
13103
|
name,
|
|
13296
13104
|
args: args ?? null,
|
|
@@ -13304,14 +13112,14 @@ var init_transactor = __esm({
|
|
|
13304
13112
|
after,
|
|
13305
13113
|
parent,
|
|
13306
13114
|
timestamp: Date.now()
|
|
13307
|
-
}
|
|
13115
|
+
};
|
|
13116
|
+
for (const cb of this._observers) cb(record);
|
|
13308
13117
|
}
|
|
13309
13118
|
// The observer record for a settled transaction. The resolved handler
|
|
13310
13119
|
// (`_resolvedHandler`/`_matched`) and per-leaf before/after (`_before`/`_after`)
|
|
13311
13120
|
// were captured while the handler ran (see callHandler / Transaction.run).
|
|
13312
13121
|
_emitTransaction(transaction, root) {
|
|
13313
13122
|
if (this._observers.length === 0) return;
|
|
13314
|
-
if (transaction._resolvedHandler === void 0) return;
|
|
13315
13123
|
this._emitRecord(root, {
|
|
13316
13124
|
kind: transaction.observeKind,
|
|
13317
13125
|
name: transaction.observeName,
|
|
@@ -13325,26 +13133,22 @@ var init_transactor = __esm({
|
|
|
13325
13133
|
parent: transaction.parentTransaction
|
|
13326
13134
|
});
|
|
13327
13135
|
}
|
|
13328
|
-
// Make `child` a tracked unit of `parent`'s subtree: the parent's completion stays open
|
|
13329
|
-
// until the child's *whole* subtree settles. Tracking happens at dispatch time — during
|
|
13330
|
-
// the parent's handler or afterTransaction — while the parent's self-unit is still held,
|
|
13331
|
-
// so the parent counter can't reach zero before the child is registered. Returns `child`.
|
|
13332
|
-
_link(child, parent) {
|
|
13333
|
-
if (parent) {
|
|
13334
|
-
const release = parent.completion.track();
|
|
13335
|
-
child.completion.whenSubtreeSettled().then(release);
|
|
13336
|
-
}
|
|
13337
|
-
return child;
|
|
13338
|
-
}
|
|
13339
13136
|
// `origin` is where the message came FROM, pinned now for the same reason an
|
|
13340
13137
|
// intent's answerPath is: a reply must reach the sender that asked even if a key
|
|
13341
13138
|
// moved while the message was in flight. Null when nobody is waiting — a host
|
|
13342
13139
|
// sendAtRoot or a view's own `@on.*` — and ctx.sendReply refuses on that.
|
|
13343
|
-
|
|
13140
|
+
//
|
|
13141
|
+
// The parent's subtree stays open until this message's whole subtree settles. The
|
|
13142
|
+
// unit is taken now, at dispatch — during the parent's handler or afterTransaction,
|
|
13143
|
+
// while the parent's self-unit is still held — so its counter can't reach zero first.
|
|
13144
|
+
pushSend(path, name, args = [], parent = null, origin = null, txnPath = null) {
|
|
13344
13145
|
const t = new SendEvent(path, this, name, args, parent);
|
|
13345
|
-
t.
|
|
13146
|
+
t.txnPath = txnPath;
|
|
13147
|
+
t.origin = origin;
|
|
13148
|
+
t.originPinned = origin === null ? null : origin.toTransactionPath().pinKeys(this.state.val);
|
|
13346
13149
|
this.pushTransaction(t);
|
|
13347
|
-
|
|
13150
|
+
if (parent) t.completion.carry(parent.completion.track());
|
|
13151
|
+
return t;
|
|
13348
13152
|
}
|
|
13349
13153
|
// Raise an intent: a job the sender did not address, walked along a route until
|
|
13350
13154
|
// something answers. `opts.route` is a list of legs (see DEFAULT_ROUTE) and
|
|
@@ -13368,7 +13172,7 @@ var init_transactor = __esm({
|
|
|
13368
13172
|
return this.transactions.length > 0;
|
|
13369
13173
|
}
|
|
13370
13174
|
transactNext() {
|
|
13371
|
-
|
|
13175
|
+
this.transact(this.transactions.shift());
|
|
13372
13176
|
}
|
|
13373
13177
|
transact(transaction) {
|
|
13374
13178
|
try {
|
|
@@ -13381,8 +13185,7 @@ var init_transactor = __esm({
|
|
|
13381
13185
|
} else console.warn("undefined new state", { curState, transaction });
|
|
13382
13186
|
} finally {
|
|
13383
13187
|
transaction.ensureWalkAdvanced?.();
|
|
13384
|
-
transaction._completion?.
|
|
13385
|
-
transaction._completion?.releaseSelf();
|
|
13188
|
+
transaction._completion?.finish();
|
|
13386
13189
|
}
|
|
13387
13190
|
}
|
|
13388
13191
|
transactInputNow(path, event, eventHandler, dragInfo) {
|
|
@@ -13392,6 +13195,7 @@ var init_transactor = __esm({
|
|
|
13392
13195
|
Transaction = class {
|
|
13393
13196
|
constructor(path, transactor, parentTransaction = null) {
|
|
13394
13197
|
this.path = path;
|
|
13198
|
+
this.txnPath = null;
|
|
13395
13199
|
this.transactor = transactor;
|
|
13396
13200
|
this.parentTransaction = parentTransaction;
|
|
13397
13201
|
this._completion = null;
|
|
@@ -13411,39 +13215,41 @@ var init_transactor = __esm({
|
|
|
13411
13215
|
whenSubtreeSettled() {
|
|
13412
13216
|
return this.completion.whenSubtreeSettled();
|
|
13413
13217
|
}
|
|
13414
|
-
|
|
13415
|
-
|
|
13416
|
-
//
|
|
13417
|
-
// rather than throwing, so a stray call from the wrong place is a message and not a
|
|
13418
|
-
// crash. `walk` is undefined here, which is how ctx.reply/ctx.fail tell the two apart.
|
|
13419
|
-
stop() {
|
|
13420
|
-
warnNotIntent("stop");
|
|
13421
|
-
}
|
|
13422
|
-
forward(_opts) {
|
|
13423
|
-
console.warn('ctx.forward() needs a "receive" or "intent" handler - ignored');
|
|
13424
|
-
}
|
|
13425
|
-
// The kind reported to observers (see Transactor.observe); null on the base.
|
|
13426
|
-
get observeKind() {
|
|
13427
|
-
return null;
|
|
13428
|
-
}
|
|
13429
|
-
// The name reported to observers; null on the base. Overridden by NameArgs (the
|
|
13430
|
-
// dispatched message name) and InputEvent (the DOM event type). Kept separate from
|
|
13431
|
-
// `name`/`ctx.name` so it can't change handler-visible behavior.
|
|
13432
|
-
get observeName() {
|
|
13433
|
-
return null;
|
|
13434
|
-
}
|
|
13218
|
+
// Every transaction kind defines `observeKind` / `observeName` (what observers see;
|
|
13219
|
+
// kept apart from `name`/`ctx.name` so they can't change handler-visible behavior),
|
|
13220
|
+
// `getHandlerAndArgs(root, instance, comps)`, and the three `_forward*` hooks below.
|
|
13435
13221
|
callHandler(root, instance, draft, comps) {
|
|
13436
13222
|
const [handler, args] = this.getHandlerAndArgs(root, instance, comps);
|
|
13437
13223
|
this._resolvedHandler = handler;
|
|
13438
13224
|
return handler.apply(instance, [draft, ...args]);
|
|
13439
13225
|
}
|
|
13440
|
-
|
|
13441
|
-
|
|
13226
|
+
// `forward` is where a name can LEAVE the component: the message being handled is
|
|
13227
|
+
// raised again as an INTENT under the same name (`_forwardName()`) with the same
|
|
13228
|
+
// arguments unless `opts.args` says otherwise, from the position `_forwardPath()`
|
|
13229
|
+
// names. Deferred to afterTransaction so the state the handler produced is in place
|
|
13230
|
+
// before the walk starts. (`IntentEvent` overrides both: in an intent body, forward
|
|
13231
|
+
// amends the walk that is already running.)
|
|
13232
|
+
forward(opts) {
|
|
13233
|
+
this._forward = opts ?? {};
|
|
13234
|
+
}
|
|
13235
|
+
afterTransaction() {
|
|
13236
|
+
const f = this._forward;
|
|
13237
|
+
if (f === void 0) return;
|
|
13238
|
+
this._forward = void 0;
|
|
13239
|
+
const name = this._forwardName();
|
|
13240
|
+
if (name === void 0) {
|
|
13241
|
+
this.transactor.refuse("FORWARD_NO_NAME", {});
|
|
13242
|
+
return;
|
|
13243
|
+
}
|
|
13244
|
+
const { args = this._forwardArgs(), ...rest } = f;
|
|
13245
|
+
this.transactor.pushIntent(this._forwardPath(), name, args, rest, this);
|
|
13442
13246
|
}
|
|
13443
|
-
// The path used to apply the mutation
|
|
13444
|
-
//
|
|
13247
|
+
// The path used to apply the mutation: the ACTIVE frame of the dispatch path, so
|
|
13248
|
+
// an event inside a `<x render="*name">` subtree updates the value where it
|
|
13249
|
+
// really lives (the dispatch `this.path` keeps the visual callers, for bubbling).
|
|
13250
|
+
// `txnPath`, when pinned by the sender, wins.
|
|
13445
13251
|
getTransactionPath() {
|
|
13446
|
-
return this.path.toTransactionPath()
|
|
13252
|
+
return this.txnPath ?? this.path.toTransactionPath();
|
|
13447
13253
|
}
|
|
13448
13254
|
run(curRoot, comps) {
|
|
13449
13255
|
const txnPath = this.getTransactionPath();
|
|
@@ -13467,12 +13273,20 @@ var init_transactor = __esm({
|
|
|
13467
13273
|
this.dragInfo = dragInfo;
|
|
13468
13274
|
this._dispatchPath = null;
|
|
13469
13275
|
}
|
|
13470
|
-
// Frame steps removed,
|
|
13471
|
-
//
|
|
13276
|
+
// Frame-only steps removed, one step per crossed component kept — inside every
|
|
13277
|
+
// continuation frame independently, so bubbling it visits every component and
|
|
13278
|
+
// then returns to the caller that wrote the `*name`.
|
|
13472
13279
|
get dispatchPath() {
|
|
13473
13280
|
this._dispatchPath ??= this.path.compact();
|
|
13474
13281
|
return this._dispatchPath;
|
|
13475
13282
|
}
|
|
13283
|
+
// Only a DOM event's path carries frame-only bind steps (they replay the handler's
|
|
13284
|
+
// arguments, but address no state); the compacted path is where the mutation lands,
|
|
13285
|
+
// so a handler inside @each still updates the component that owns the view. Every
|
|
13286
|
+
// other transaction is dispatched at an already-compacted position.
|
|
13287
|
+
getTransactionPath() {
|
|
13288
|
+
return this.dispatchPath.toTransactionPath();
|
|
13289
|
+
}
|
|
13476
13290
|
// A DOM event is an ADDRESSED message like any other — it reaches the component that
|
|
13477
13291
|
// owns the view and stops. It keeps its own class only because it resolves its handler
|
|
13478
13292
|
// from the compiled view and runs synchronously, not because it is a different channel.
|
|
@@ -13482,40 +13296,29 @@ var init_transactor = __esm({
|
|
|
13482
13296
|
get observeName() {
|
|
13483
13297
|
return this.e?.type ?? null;
|
|
13484
13298
|
}
|
|
13485
|
-
// A view's name is a message
|
|
13486
|
-
//
|
|
13487
|
-
//
|
|
13488
|
-
//
|
|
13489
|
-
|
|
13490
|
-
|
|
13491
|
-
}
|
|
13492
|
-
afterTransaction() {
|
|
13493
|
-
const f = this._forward;
|
|
13494
|
-
if (f === void 0) return;
|
|
13495
|
-
this._forward = void 0;
|
|
13496
|
-
const { args = this._handlerArgs ?? [], ...rest } = f;
|
|
13299
|
+
// A view's name is a message, and forwarding it means a view that says
|
|
13300
|
+
// `@on.click="saveDraft .text"` never has to change when an ancestor takes the job
|
|
13301
|
+
// over. (A `$method` handler has a name too, so forwarding one raises an intent under
|
|
13302
|
+
// it.) `handler` is a NodeEvent, whose own `name` is the DOM event type; the MESSAGE
|
|
13303
|
+
// name is the one the view wrote, on the handler call it wraps.
|
|
13304
|
+
_forwardName() {
|
|
13497
13305
|
const hv = this.handler?.handlerCall?.handlerVal ?? this.handler?.handlerVal;
|
|
13498
|
-
|
|
13499
|
-
|
|
13500
|
-
|
|
13501
|
-
|
|
13502
|
-
|
|
13503
|
-
|
|
13306
|
+
return hv?.name;
|
|
13307
|
+
}
|
|
13308
|
+
_forwardArgs() {
|
|
13309
|
+
return this._handlerArgs ?? [];
|
|
13310
|
+
}
|
|
13311
|
+
_forwardPath() {
|
|
13312
|
+
return this.dispatchPath;
|
|
13504
13313
|
}
|
|
13505
13314
|
getHandlerAndArgs(root, _instance, comps) {
|
|
13506
|
-
const stack = this.path.
|
|
13315
|
+
const stack = this.path.buildStack(Stack.root(comps, root, this));
|
|
13507
13316
|
const [handler, args] = this.handler.getHandlerAndArgs(stack, this);
|
|
13508
13317
|
this._handlerArgs = [...args];
|
|
13509
13318
|
const path = this.dispatchPath;
|
|
13510
13319
|
args.push(new EventContext(path, this.transactor, this));
|
|
13511
13320
|
return [handler, args];
|
|
13512
13321
|
}
|
|
13513
|
-
// The dispatched DOM event, read only through `e.<member>` handler args
|
|
13514
|
-
// (src/value.js EventMemberVal via Stack.lookupEvent). There is no bare
|
|
13515
|
-
// implicit-name vocabulary anymore: every arg carries a sigil.
|
|
13516
|
-
get event() {
|
|
13517
|
-
return this.e;
|
|
13518
|
-
}
|
|
13519
13322
|
};
|
|
13520
13323
|
NameArgsTransaction = class extends Transaction {
|
|
13521
13324
|
constructor(path, transactor, name, args, parentTransaction) {
|
|
@@ -13533,6 +13336,17 @@ var init_transactor = __esm({
|
|
|
13533
13336
|
get observeName() {
|
|
13534
13337
|
return this.name;
|
|
13535
13338
|
}
|
|
13339
|
+
// `forward` in a RECEIVE body starts a walk: the message that arrived becomes an
|
|
13340
|
+
// intent, keeping its name and payload.
|
|
13341
|
+
_forwardName() {
|
|
13342
|
+
return this.name;
|
|
13343
|
+
}
|
|
13344
|
+
_forwardArgs() {
|
|
13345
|
+
return this.args;
|
|
13346
|
+
}
|
|
13347
|
+
_forwardPath() {
|
|
13348
|
+
return this.path;
|
|
13349
|
+
}
|
|
13536
13350
|
getHandlerForName(comp) {
|
|
13537
13351
|
const handlers = comp?.[this.handlerProp];
|
|
13538
13352
|
const exact = handlers?.[this.name];
|
|
@@ -13563,19 +13377,6 @@ var init_transactor = __esm({
|
|
|
13563
13377
|
get observeKind() {
|
|
13564
13378
|
return this._isAnswer ? "answer" : "receive";
|
|
13565
13379
|
}
|
|
13566
|
-
// `forward` in a RECEIVE body starts a walk: the message that arrived becomes an
|
|
13567
|
-
// intent, keeping its name and payload. This is what lets a view's name leave the
|
|
13568
|
-
// component without the view changing.
|
|
13569
|
-
forward(opts) {
|
|
13570
|
-
this._forward = opts ?? {};
|
|
13571
|
-
}
|
|
13572
|
-
afterTransaction() {
|
|
13573
|
-
const f = this._forward;
|
|
13574
|
-
if (f === void 0) return;
|
|
13575
|
-
this._forward = void 0;
|
|
13576
|
-
const { args = this.args, ...rest } = f;
|
|
13577
|
-
this.transactor.pushIntent(this.path, this.name, args, rest, this);
|
|
13578
|
-
}
|
|
13579
13380
|
};
|
|
13580
13381
|
IntentEvent = class extends NameArgsTransaction {
|
|
13581
13382
|
handlerProp = "intent";
|
|
@@ -13589,9 +13390,6 @@ var init_transactor = __esm({
|
|
|
13589
13390
|
forward(opts) {
|
|
13590
13391
|
this.walk.amend(opts, this.path);
|
|
13591
13392
|
}
|
|
13592
|
-
stop() {
|
|
13593
|
-
this.walk.finish(null, null);
|
|
13594
|
-
}
|
|
13595
13393
|
afterTransaction() {
|
|
13596
13394
|
this.ensureWalkAdvanced();
|
|
13597
13395
|
}
|
|
@@ -13629,7 +13427,7 @@ var init_transactor = __esm({
|
|
|
13629
13427
|
while (this.legIndex < this.route.length) {
|
|
13630
13428
|
const leg = this.route[this.legIndex];
|
|
13631
13429
|
if (leg === "dyn") {
|
|
13632
|
-
if (this.dynAt.
|
|
13430
|
+
if (!this.dynAt.canPop()) {
|
|
13633
13431
|
this.legIndex++;
|
|
13634
13432
|
continue;
|
|
13635
13433
|
}
|
|
@@ -13641,7 +13439,7 @@ var init_transactor = __esm({
|
|
|
13641
13439
|
this.legIndex++;
|
|
13642
13440
|
return this._tryLex();
|
|
13643
13441
|
}
|
|
13644
|
-
|
|
13442
|
+
warnUnknownLeg("intent", leg);
|
|
13645
13443
|
this.legIndex++;
|
|
13646
13444
|
}
|
|
13647
13445
|
this.exhaust("noHandler");
|
|
@@ -13726,11 +13524,11 @@ var init_transactor = __esm({
|
|
|
13726
13524
|
if (this.ended) return;
|
|
13727
13525
|
this.ended = true;
|
|
13728
13526
|
if (name === null) return this.release?.();
|
|
13729
|
-
const
|
|
13730
|
-
|
|
13527
|
+
const t = new SendEvent(this.origin, this.transactor, name, args, this.parent);
|
|
13528
|
+
t.txnPath = this.answerPath;
|
|
13731
13529
|
t._isAnswer = true;
|
|
13732
13530
|
this.transactor.pushTransaction(t);
|
|
13733
|
-
if (this.release) t.completion.
|
|
13531
|
+
if (this.release) t.completion.carry(this.release);
|
|
13734
13532
|
}
|
|
13735
13533
|
};
|
|
13736
13534
|
Completion = class {
|
|
@@ -13738,12 +13536,12 @@ var init_transactor = __esm({
|
|
|
13738
13536
|
this.val = void 0;
|
|
13739
13537
|
this.selfSettled = false;
|
|
13740
13538
|
this.subtreeSettled = false;
|
|
13741
|
-
this.pending =
|
|
13539
|
+
this.pending = 0;
|
|
13742
13540
|
this._selfResolve = null;
|
|
13743
13541
|
this._selfPromise = null;
|
|
13744
13542
|
this._subtreeResolve = null;
|
|
13745
13543
|
this._subtreePromise = null;
|
|
13746
|
-
this.
|
|
13544
|
+
this._releaseSelf = this.track();
|
|
13747
13545
|
}
|
|
13748
13546
|
whenSettled() {
|
|
13749
13547
|
if (this.selfSettled) return Promise.resolve(this.val);
|
|
@@ -13766,38 +13564,38 @@ var init_transactor = __esm({
|
|
|
13766
13564
|
this.val = val;
|
|
13767
13565
|
this._selfResolve?.(val);
|
|
13768
13566
|
}
|
|
13769
|
-
//
|
|
13770
|
-
|
|
13771
|
-
|
|
13567
|
+
// The transaction is done processing: self is settled (with the value the handler
|
|
13568
|
+
// produced, or none on the undefined-state / throw paths) and the self-unit goes.
|
|
13569
|
+
finish() {
|
|
13570
|
+
this.markSelfSettled(this.val);
|
|
13571
|
+
this._releaseSelf();
|
|
13772
13572
|
}
|
|
13773
|
-
// Register an outstanding unit; returns
|
|
13573
|
+
// Register an outstanding unit; returns its one-shot release. The subtree settles
|
|
13574
|
+
// when the last unit is released.
|
|
13774
13575
|
track() {
|
|
13775
13576
|
this.pending++;
|
|
13776
13577
|
let done = false;
|
|
13777
13578
|
return () => {
|
|
13778
13579
|
if (done) return;
|
|
13779
13580
|
done = true;
|
|
13780
|
-
this.
|
|
13581
|
+
if (--this.pending === 0) {
|
|
13582
|
+
this.subtreeSettled = true;
|
|
13583
|
+
this._subtreeResolve?.(this.val);
|
|
13584
|
+
}
|
|
13781
13585
|
};
|
|
13782
13586
|
}
|
|
13783
|
-
|
|
13784
|
-
|
|
13785
|
-
|
|
13786
|
-
this.
|
|
13787
|
-
}
|
|
13788
|
-
_release() {
|
|
13789
|
-
if (--this.pending === 0) {
|
|
13790
|
-
this.subtreeSettled = true;
|
|
13791
|
-
this._subtreeResolve?.(this.val);
|
|
13792
|
-
}
|
|
13587
|
+
// Hand a unit held elsewhere to this subtree: `release` runs once this transaction
|
|
13588
|
+
// and everything it spawned have settled.
|
|
13589
|
+
carry(release) {
|
|
13590
|
+
this.whenSubtreeSettled().then(release);
|
|
13793
13591
|
}
|
|
13794
13592
|
};
|
|
13795
13593
|
Dispatcher = class {
|
|
13796
|
-
constructor(path, transactor, parentTransaction
|
|
13594
|
+
constructor(path, transactor, parentTransaction) {
|
|
13797
13595
|
this.path = path;
|
|
13798
13596
|
this.transactor = transactor;
|
|
13799
13597
|
this.parent = parentTransaction;
|
|
13800
|
-
this.root =
|
|
13598
|
+
this.root = transactor.state.val;
|
|
13801
13599
|
}
|
|
13802
13600
|
// Walk the component instances on this ctx's path, leaf→root, calling
|
|
13803
13601
|
// callback(Component, instance). Return false from the callback to stop early.
|
|
@@ -13822,28 +13620,37 @@ var init_transactor = __esm({
|
|
|
13822
13620
|
// replayed; provides are pushed on every component frame either way, so a provide
|
|
13823
13621
|
// that reads a loop binding is the one case this cannot reproduce faithfully.
|
|
13824
13622
|
_stack() {
|
|
13825
|
-
this._stackMemo ??= this.path.
|
|
13623
|
+
this._stackMemo ??= this.path.buildStack(
|
|
13624
|
+
Stack.root(this.transactor.comps, this.root, this.parent)
|
|
13625
|
+
);
|
|
13826
13626
|
return this._stackMemo;
|
|
13827
13627
|
}
|
|
13828
13628
|
// Resolve a name the way the renderer would. `opts.route` takes the same legs in
|
|
13829
13629
|
// the same spelling as `ctx.intent` — `["dyn"]` the render ancestry, `["lex"]` the
|
|
13830
13630
|
// registration scope, default both.
|
|
13631
|
+
// Legs are tried in route order, like the intent walker's; an unknown leg warns and
|
|
13632
|
+
// is skipped, and an empty route resolves to null.
|
|
13831
13633
|
lookup(name, opts) {
|
|
13832
|
-
|
|
13833
|
-
|
|
13834
|
-
()
|
|
13835
|
-
|
|
13836
|
-
|
|
13634
|
+
for (const leg of opts?.route ?? DEFAULT_ROUTE) {
|
|
13635
|
+
const v = leg === "dyn" ? this._stack()?.lookupDynamic(name) ?? null : leg === "lex" ? this._lookupLex(name) : warnUnknownLeg("lookup", leg);
|
|
13636
|
+
if (v != null) return v;
|
|
13637
|
+
}
|
|
13638
|
+
return null;
|
|
13837
13639
|
}
|
|
13838
13640
|
// The `lex` leg without a Stack: the scope of the component whose handler is
|
|
13839
|
-
// running, which is the leaf of this ctx's path.
|
|
13641
|
+
// running, which is the leaf of this ctx's path. A type name resolves to the
|
|
13642
|
+
// component registered under it; a value name to a path registered under it
|
|
13643
|
+
// (see ComponentStack.registerPaths), read against the current root.
|
|
13840
13644
|
_lookupLex(name) {
|
|
13841
13645
|
let Comp = null;
|
|
13842
13646
|
this.walkPath((c) => {
|
|
13843
13647
|
Comp = c;
|
|
13844
13648
|
return false;
|
|
13845
13649
|
});
|
|
13846
|
-
|
|
13650
|
+
const scope = Comp?.scope;
|
|
13651
|
+
if (scope == null) return null;
|
|
13652
|
+
if (isTypeName(name)) return scope.lookupComponent(name) ?? null;
|
|
13653
|
+
return scope.lookupPath(name)?.lookup(this.root) ?? null;
|
|
13847
13654
|
}
|
|
13848
13655
|
// A component lookup is a value lookup constrained to a component. The `lex` leg
|
|
13849
13656
|
// can only ever answer with one; the `dyn` leg reads a binding an ancestor
|
|
@@ -13904,11 +13711,19 @@ var init_transactor = __esm({
|
|
|
13904
13711
|
this.transactor.refuse("NO_SENDER", { name });
|
|
13905
13712
|
return null;
|
|
13906
13713
|
}
|
|
13907
|
-
return this.
|
|
13714
|
+
return this.transactor.pushSend(
|
|
13715
|
+
origin,
|
|
13716
|
+
name,
|
|
13717
|
+
args,
|
|
13718
|
+
this.parent,
|
|
13719
|
+
this.path,
|
|
13720
|
+
this.parent.originPinned
|
|
13721
|
+
);
|
|
13908
13722
|
}
|
|
13909
|
-
// End the walk answering nothing — "served, and no answer".
|
|
13723
|
+
// End the walk answering nothing — "served, and no answer". Like reply/fail,
|
|
13724
|
+
// legal only in an `intent` handler.
|
|
13910
13725
|
stop() {
|
|
13911
|
-
return this.parent.stop();
|
|
13726
|
+
return this.parent.walk === void 0 ? warnNotIntent("stop") : this.parent.walk.finish(null, null);
|
|
13912
13727
|
}
|
|
13913
13728
|
// From an `intent` body: hand the intent to the next hop, optionally amending it.
|
|
13914
13729
|
// From a `receive` body: turn the message that arrived into an intent. One word from
|
|
@@ -13987,7 +13802,6 @@ var init_app = __esm({
|
|
|
13987
13802
|
this.transactor = new Transactor(comps, null);
|
|
13988
13803
|
this.ParseContext = ParseContext2;
|
|
13989
13804
|
this.renderer = renderer;
|
|
13990
|
-
this.maxEventNodeDepth = Infinity;
|
|
13991
13805
|
this._transactNextBatchId = this._evictCacheId = null;
|
|
13992
13806
|
this._eventNames = new Set(_evs);
|
|
13993
13807
|
this.dragInfo = this.curDragOver = null;
|
|
@@ -14014,12 +13828,11 @@ var init_app = __esm({
|
|
|
14014
13828
|
_dispatchEvent(e) {
|
|
14015
13829
|
const { type: type3 } = e;
|
|
14016
13830
|
const isDrag = type3 === "dragover" || type3 === "dragstart" || type3 === "dragend" || type3 === "drop";
|
|
14017
|
-
const { rootNode
|
|
14018
|
-
const [path, handlers] =
|
|
13831
|
+
const { rootNode, comps, transactor } = this;
|
|
13832
|
+
const [path, handlers] = DispatchPath.fromNodeAndEventName(
|
|
14019
13833
|
e.target,
|
|
14020
13834
|
type3,
|
|
14021
|
-
|
|
14022
|
-
maxDepth,
|
|
13835
|
+
rootNode,
|
|
14023
13836
|
comps,
|
|
14024
13837
|
!isDrag
|
|
14025
13838
|
);
|
|
@@ -14083,7 +13896,7 @@ var init_app = __esm({
|
|
|
14083
13896
|
const txnPath = path.compact().toTransactionPath();
|
|
14084
13897
|
const value = txnPath.lookup(rootValue);
|
|
14085
13898
|
const dragType = e.target.dataset.dragtype ?? "?";
|
|
14086
|
-
const stack = path.
|
|
13899
|
+
const stack = path.buildStack(this.makeStack(rootValue));
|
|
14087
13900
|
this.dragInfo = new DragInfo(stack, value, dragType, e.target);
|
|
14088
13901
|
} else if (type3 === "drop") {
|
|
14089
13902
|
e.preventDefault();
|
|
@@ -14128,10 +13941,9 @@ var init_app = __esm({
|
|
|
14128
13941
|
}
|
|
14129
13942
|
compile() {
|
|
14130
13943
|
for (const Comp of this.comps.byId.values()) {
|
|
14131
|
-
|
|
14132
|
-
|
|
14133
|
-
|
|
14134
|
-
for (const name of meta.views[key].ctx.genEventNames()) this._eventNames.add(name);
|
|
13944
|
+
Comp.compile(this.ParseContext);
|
|
13945
|
+
for (const key in Comp.views)
|
|
13946
|
+
for (const name of Comp.views[key].ctx.genEventNames()) this._eventNames.add(name);
|
|
14135
13947
|
}
|
|
14136
13948
|
this._compiled = true;
|
|
14137
13949
|
}
|
|
@@ -14154,11 +13966,13 @@ var init_app = __esm({
|
|
|
14154
13966
|
}
|
|
14155
13967
|
stop() {
|
|
14156
13968
|
this.stopCacheEvictionInterval();
|
|
13969
|
+
clearTimeout(this._transactNextBatchId);
|
|
13970
|
+
this._transactNextBatchId = null;
|
|
14157
13971
|
for (const name of this._eventNames)
|
|
14158
13972
|
this.rootNode.removeEventListener(name, this, listenerOpts(name));
|
|
14159
13973
|
}
|
|
14160
13974
|
sendAtRoot(name, args) {
|
|
14161
|
-
this.transactor.pushSend(new
|
|
13975
|
+
this.transactor.pushSend(new DispatchPath(), name, args);
|
|
14162
13976
|
}
|
|
14163
13977
|
registerComponents(comps, opts) {
|
|
14164
13978
|
const scope = this.compStack.enter();
|
|
@@ -14242,28 +14056,21 @@ var init_cache = __esm({
|
|
|
14242
14056
|
set(_keys, _cacheKey, _v) {
|
|
14243
14057
|
}
|
|
14244
14058
|
evict() {
|
|
14245
|
-
return { hit: 0, miss: 0, badKey: 0 };
|
|
14246
14059
|
}
|
|
14247
14060
|
};
|
|
14248
14061
|
WeakMapDomCache = class {
|
|
14249
14062
|
constructor() {
|
|
14250
|
-
this.hit = this.miss = this.badKey = 0;
|
|
14251
14063
|
this.keysByLen = /* @__PURE__ */ new Map();
|
|
14252
14064
|
}
|
|
14253
|
-
_returnValue(r) {
|
|
14254
|
-
if (r === void 0) this.miss += 1;
|
|
14255
|
-
else this.hit += 1;
|
|
14256
|
-
return r;
|
|
14257
|
-
}
|
|
14258
14065
|
get(keys, cacheKey) {
|
|
14259
14066
|
const len = keys.length;
|
|
14260
14067
|
let cur = this.keysByLen.get(len);
|
|
14261
|
-
if (!cur) return
|
|
14068
|
+
if (!cur) return void 0;
|
|
14262
14069
|
for (let i = 0; i < len - 1; i++) {
|
|
14263
14070
|
cur = cur.get(keys[i]);
|
|
14264
|
-
if (!cur) return
|
|
14071
|
+
if (!cur) return void 0;
|
|
14265
14072
|
}
|
|
14266
|
-
return
|
|
14073
|
+
return cur.get(keys[len - 1])?.[cacheKey];
|
|
14267
14074
|
}
|
|
14268
14075
|
set(keys, cacheKey, v) {
|
|
14269
14076
|
const len = keys.length;
|
|
@@ -14276,10 +14083,7 @@ var init_cache = __esm({
|
|
|
14276
14083
|
const key = keys[i];
|
|
14277
14084
|
let next = cur.get(key);
|
|
14278
14085
|
if (!next) {
|
|
14279
|
-
if (!isWeakKey(key))
|
|
14280
|
-
this.badKey += 1;
|
|
14281
|
-
return;
|
|
14282
|
-
}
|
|
14086
|
+
if (!isWeakKey(key)) return;
|
|
14283
14087
|
next = /* @__PURE__ */ new WeakMap();
|
|
14284
14088
|
cur.set(key, next);
|
|
14285
14089
|
}
|
|
@@ -14289,31 +14093,48 @@ var init_cache = __esm({
|
|
|
14289
14093
|
const leaf = cur.get(lastKey);
|
|
14290
14094
|
if (leaf) leaf[cacheKey] = v;
|
|
14291
14095
|
else if (isWeakKey(lastKey)) cur.set(lastKey, { [cacheKey]: v });
|
|
14292
|
-
else this.badKey += 1;
|
|
14293
14096
|
}
|
|
14294
14097
|
evict() {
|
|
14295
|
-
const { hit, miss, badKey } = this;
|
|
14296
|
-
this.hit = this.miss = this.badKey = 0;
|
|
14297
14098
|
this.keysByLen = /* @__PURE__ */ new Map();
|
|
14298
|
-
return { hit, miss, badKey };
|
|
14299
14099
|
}
|
|
14300
14100
|
};
|
|
14301
14101
|
}
|
|
14302
14102
|
});
|
|
14303
14103
|
|
|
14304
14104
|
// src/renderer.js
|
|
14305
|
-
|
|
14105
|
+
function stampRenderBase(vdom, text) {
|
|
14106
|
+
if (vdom instanceof VNode)
|
|
14107
|
+
return new VNode(
|
|
14108
|
+
vdom.tag,
|
|
14109
|
+
{ ...vdom.attrs, "data-rp": text },
|
|
14110
|
+
vdom.childs,
|
|
14111
|
+
vdom.key,
|
|
14112
|
+
vdom.namespace
|
|
14113
|
+
);
|
|
14114
|
+
if (vdom instanceof VFragment)
|
|
14115
|
+
return new VFragment(vdom.childs.map((c) => stampRenderBase(c, text)));
|
|
14116
|
+
return vdom;
|
|
14117
|
+
}
|
|
14118
|
+
var Renderer;
|
|
14306
14119
|
var init_renderer = __esm({
|
|
14307
14120
|
"src/renderer.js"() {
|
|
14308
14121
|
init_cache();
|
|
14309
14122
|
init_iteration();
|
|
14123
|
+
init_path();
|
|
14124
|
+
init_value();
|
|
14310
14125
|
init_vdom();
|
|
14311
|
-
DATASET_ATTRS = ["nid", "cid", "eid", "vid", "si", "sk"];
|
|
14312
14126
|
Renderer = class {
|
|
14313
14127
|
constructor(comps) {
|
|
14314
14128
|
this.comps = comps;
|
|
14315
14129
|
this.cache = new WeakMapDomCache();
|
|
14316
|
-
|
|
14130
|
+
}
|
|
14131
|
+
// Parse nodes build their VDOM through the renderer, never by importing vdom.js
|
|
14132
|
+
// themselves: a component may have been compiled by ANOTHER copy of the library
|
|
14133
|
+
// (a docs example imports the dist bundle while the host app runs from src), and
|
|
14134
|
+
// `render()` recognizes VNodes by `instanceof` against ITS copy's classes. Going
|
|
14135
|
+
// through `rx` guarantees the rendering copy makes them.
|
|
14136
|
+
renderTag(tag, attrs, childs, namespace) {
|
|
14137
|
+
return h(tag, attrs, childs, namespace);
|
|
14317
14138
|
}
|
|
14318
14139
|
renderFragment(childs) {
|
|
14319
14140
|
return new VFragment(childs);
|
|
@@ -14324,38 +14145,24 @@ var init_renderer = __esm({
|
|
|
14324
14145
|
setNullCache() {
|
|
14325
14146
|
this.cache = new NullDomCache();
|
|
14326
14147
|
}
|
|
14327
|
-
// Library utilities for consumers embedding tutuca: render a value to a detached
|
|
14328
|
-
// DOM node / an HTML string. Not called by the framework itself.
|
|
14329
|
-
renderToDOM(stack, val) {
|
|
14330
|
-
const rootNode = document.createElement("div");
|
|
14331
|
-
const rOpts = { document };
|
|
14332
|
-
render(h("DIV", null, [this.renderRoot(stack, val)]), rootNode, rOpts);
|
|
14333
|
-
return rootNode.childNodes[0];
|
|
14334
|
-
}
|
|
14335
|
-
renderToString(stack, val, cleanAttrs = true) {
|
|
14336
|
-
const dom = this.renderToDOM(stack, val);
|
|
14337
|
-
if (cleanAttrs) {
|
|
14338
|
-
const nodes = dom.querySelectorAll("[data-nid],[data-cid],[data-eid]");
|
|
14339
|
-
for (const { dataset } of nodes) for (const name of DATASET_ATTRS) delete dataset[name];
|
|
14340
|
-
}
|
|
14341
|
-
return dom.innerHTML;
|
|
14342
|
-
}
|
|
14343
14148
|
renderRoot(stack, val, viewName = null) {
|
|
14344
14149
|
const comp = this.comps.getCompFor(val);
|
|
14345
14150
|
if (comp === null) return null;
|
|
14346
14151
|
return this._rValComp(stack, val, comp, comp.getView(viewName).anode, "ROOT", viewName);
|
|
14347
14152
|
}
|
|
14348
|
-
|
|
14153
|
+
// Render `stack.it` at a `<x render*>` site (`node`). `base` is the absolute
|
|
14154
|
+
// path the site resumed at, when it rendered a `*name` (see _rValComp).
|
|
14155
|
+
renderIt(stack, node, viewName, base = null) {
|
|
14349
14156
|
const comp = this.comps.getCompFor(stack.it);
|
|
14350
|
-
return comp ? this._rValComp(stack, stack.it, comp, node,
|
|
14157
|
+
return comp ? this._rValComp(stack, stack.it, comp, node, "", viewName, base) : null;
|
|
14351
14158
|
}
|
|
14352
14159
|
// `node` is the parse node of the render site (`<x render>` / `render-it` /
|
|
14353
14160
|
// `render-each`, or the view's root anode for the app root). It keys the
|
|
14354
14161
|
// cache as a globally-unique object: node ids alone are unique only within a
|
|
14355
14162
|
// single view, so the same value rendered by two components (e.g. through a
|
|
14356
14163
|
// shared dynamic-var sequence) would otherwise collide in the cache.
|
|
14357
|
-
_rValComp(stack, val, comp, node, key, viewName) {
|
|
14358
|
-
const cacheKey = `${viewName ?? ""}${stack.viewsId ?? ""}${key}`;
|
|
14164
|
+
_rValComp(stack, val, comp, node, key, viewName, base = null) {
|
|
14165
|
+
const cacheKey = `${viewName ?? ""}${stack.viewsId ?? ""}${key}${stack.renderPath.addressKey}`;
|
|
14359
14166
|
const cachePath = [node, val];
|
|
14360
14167
|
stack._pushDynBindValuesToArray(cachePath, comp);
|
|
14361
14168
|
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
@@ -14363,30 +14170,43 @@ var init_renderer = __esm({
|
|
|
14363
14170
|
const view = viewName ? comp.getView(viewName) : stack.lookupBestView(comp.views, "main");
|
|
14364
14171
|
const body = this.renderView(view, stack);
|
|
14365
14172
|
if (body == null) return null;
|
|
14173
|
+
const baseJson = base === null ? null : pathToJson(base);
|
|
14366
14174
|
const meta = this._renderMetadata({
|
|
14367
14175
|
$: "Comp",
|
|
14368
14176
|
nid: node?.nodeId ?? null,
|
|
14369
14177
|
cid: comp.id,
|
|
14370
|
-
vid: view.name
|
|
14178
|
+
vid: view.name,
|
|
14179
|
+
...baseJson === null ? null : { base: baseJson }
|
|
14371
14180
|
});
|
|
14372
|
-
const dom = new VFragment([
|
|
14181
|
+
const dom = new VFragment([
|
|
14182
|
+
meta,
|
|
14183
|
+
baseJson === null ? body : stampRenderBase(body, JSON.stringify(baseJson))
|
|
14184
|
+
]);
|
|
14373
14185
|
this.cache.set(cachePath, cacheKey, dom);
|
|
14374
14186
|
return dom;
|
|
14375
14187
|
}
|
|
14376
14188
|
pushEachEntry(r, nid, attrName, key, dom) {
|
|
14377
14189
|
r.push(this._renderMetadata({ $: "Each", nid, [attrName]: key }), dom);
|
|
14378
14190
|
}
|
|
14379
|
-
renderEachWhen(stack,
|
|
14380
|
-
const {
|
|
14191
|
+
renderEachWhen(stack, each2) {
|
|
14192
|
+
const { val: seqVal, node: view, nodeId: nid } = each2;
|
|
14193
|
+
const { seq, filter, loopWith, enricher } = each2.evalIter(stack);
|
|
14194
|
+
const seqPath = seqVal instanceof DynVal ? stack.lookupDynamicLocated(seqVal.name)?.path ?? null : null;
|
|
14381
14195
|
const r = [];
|
|
14382
14196
|
const it = stack.it;
|
|
14383
14197
|
const renderOne = (key, value, attrName, binds) => {
|
|
14198
|
+
const itemBase = seqPath === null ? null : keyedPath(seqPath, key);
|
|
14199
|
+
const itemStep = itemBase === null ? each2.itemStep(key) : null;
|
|
14200
|
+
const itemPath = itemBase !== null ? stack.renderPath.pushFrame(itemBase) : itemStep !== null ? stack.renderPath.pushItem(itemStep) : stack.renderPath;
|
|
14384
14201
|
const cachePath = enricher ? [view, it, value] : [view, value];
|
|
14385
|
-
const cacheKey = `${stack.viewsId ?? ""}${nid}${key}`;
|
|
14202
|
+
const cacheKey = `${stack.viewsId ?? ""}${nid}${key}${itemPath.addressKey}`;
|
|
14386
14203
|
const cachedNode = this.cache.get(cachePath, cacheKey);
|
|
14387
14204
|
if (cachedNode) this.pushEachEntry(r, nid, attrName, key, cachedNode);
|
|
14388
14205
|
else {
|
|
14389
|
-
const dom = this.renderView(
|
|
14206
|
+
const dom = this.renderView(
|
|
14207
|
+
view,
|
|
14208
|
+
stack.enter(value, binds, false, itemPath, itemBase !== null)
|
|
14209
|
+
);
|
|
14390
14210
|
if (dom != null) this.pushEachEntry(r, nid, attrName, key, dom);
|
|
14391
14211
|
this.cache.set(cachePath, cacheKey, dom);
|
|
14392
14212
|
}
|
|
@@ -14424,9 +14244,7 @@ var init_renderer = __esm({
|
|
|
14424
14244
|
|
|
14425
14245
|
// src/util/render.js
|
|
14426
14246
|
function reindexComponents(comps) {
|
|
14427
|
-
for (let i = 0; i < comps.length; i++)
|
|
14428
|
-
comps[i][COMPONENT].id = i;
|
|
14429
|
-
}
|
|
14247
|
+
for (let i = 0; i < comps.length; i++) comps[i].id = i;
|
|
14430
14248
|
}
|
|
14431
14249
|
function serializeContainer(container) {
|
|
14432
14250
|
for (const input of container.querySelectorAll("input")) {
|
|
@@ -14435,19 +14253,19 @@ function serializeContainer(container) {
|
|
|
14435
14253
|
}
|
|
14436
14254
|
return container.innerHTML;
|
|
14437
14255
|
}
|
|
14438
|
-
function renderToHTMLNode(document2, components, macros, rootState, ParseContext2,
|
|
14256
|
+
function renderToHTMLNode(document2, components, macros, rootState, ParseContext2, { noCache = true, paths = null, intentHandlers = null, view = null } = {}) {
|
|
14439
14257
|
const container = document2.createElement("div");
|
|
14440
14258
|
document2.body.appendChild(container);
|
|
14441
14259
|
reindexComponents(components);
|
|
14442
14260
|
const comps = new Components();
|
|
14443
14261
|
const renderer = new Renderer(comps);
|
|
14444
14262
|
const app = new App(container, comps, renderer, ParseContext2);
|
|
14445
|
-
const scope = app.registerComponents(components);
|
|
14263
|
+
const scope = app.registerComponents(components, { paths });
|
|
14446
14264
|
if (macros) scope.registerMacros(macros);
|
|
14447
|
-
if (
|
|
14448
|
-
app.rootViewName =
|
|
14265
|
+
if (intentHandlers) scope.registerIntentHandlers(intentHandlers);
|
|
14266
|
+
app.rootViewName = view;
|
|
14449
14267
|
app.transactor.state.set(rootState);
|
|
14450
|
-
app.start(
|
|
14268
|
+
app.start({ noCache });
|
|
14451
14269
|
return {
|
|
14452
14270
|
container,
|
|
14453
14271
|
app,
|
|
@@ -14457,18 +14275,18 @@ function renderToHTMLNode(document2, components, macros, rootState, ParseContext
|
|
|
14457
14275
|
}
|
|
14458
14276
|
};
|
|
14459
14277
|
}
|
|
14460
|
-
async function renderToHTMLDriven(document2, components, macros, rootState, ParseContext2, { phase = null,
|
|
14278
|
+
async function renderToHTMLDriven(document2, components, macros, rootState, ParseContext2, { phase = null, ...opts } = {}) {
|
|
14461
14279
|
const { container, app, cleanup } = renderToHTMLNode(
|
|
14462
14280
|
document2,
|
|
14463
14281
|
components,
|
|
14464
14282
|
macros,
|
|
14465
14283
|
rootState,
|
|
14466
14284
|
ParseContext2,
|
|
14467
|
-
|
|
14285
|
+
opts
|
|
14468
14286
|
);
|
|
14469
14287
|
try {
|
|
14470
14288
|
if (phase) {
|
|
14471
|
-
dispatchPhase(rootDispatcher(app.transactor), new
|
|
14289
|
+
dispatchPhase(rootDispatcher(app.transactor), new DispatchPath(), phase, app.state.val);
|
|
14472
14290
|
await app.transactor.settle();
|
|
14473
14291
|
}
|
|
14474
14292
|
return serializeContainer(container);
|
|
@@ -14706,7 +14524,7 @@ async function driveStack(stack, value, phase, opts = {}) {
|
|
|
14706
14524
|
val
|
|
14707
14525
|
);
|
|
14708
14526
|
});
|
|
14709
|
-
dispatchPhase(rootDispatcher(transactor), new
|
|
14527
|
+
dispatchPhase(rootDispatcher(transactor), new DispatchPath(), phase, value);
|
|
14710
14528
|
await transactor.settle();
|
|
14711
14529
|
return transactor.state.val;
|
|
14712
14530
|
}
|
|
@@ -15406,23 +15224,30 @@ function installSkill(skill, root, scope, force, dotAgents, dryRun, opts) {
|
|
|
15406
15224
|
});
|
|
15407
15225
|
}
|
|
15408
15226
|
const target = targetDir(scope, skill.name, dotAgents);
|
|
15409
|
-
if (targetHasSkillFiles(target) && !force) {
|
|
15410
|
-
emitError(opts, {
|
|
15411
|
-
code: CODES.SKILL_TARGET_EXISTS,
|
|
15412
|
-
message: `${target} already contains skill files`,
|
|
15413
|
-
hint: "Re-run with --force to overwrite, or --dry-run to see what would change."
|
|
15414
|
-
});
|
|
15415
|
-
}
|
|
15416
15227
|
const baseDir = dotAgents ? ".agents/skills" : ".claude/skills";
|
|
15417
15228
|
const rel = scope === "project" ? `${baseDir}/${skill.name}` : target;
|
|
15229
|
+
const exists = targetHasSkillFiles(target);
|
|
15418
15230
|
if (dryRun) {
|
|
15419
15231
|
const files = walkFiles(src, { match: () => true }).map((f) => relative(src, f));
|
|
15420
15232
|
process.stdout.write(`would install ${skill.name} skill → ${rel}
|
|
15421
15233
|
`);
|
|
15422
15234
|
for (const f of files) process.stdout.write(` + ${f}
|
|
15423
15235
|
`);
|
|
15236
|
+
if (exists) {
|
|
15237
|
+
process.stdout.write(
|
|
15238
|
+
` note: ${rel} already contains skill files; re-run with --force to overwrite them
|
|
15239
|
+
`
|
|
15240
|
+
);
|
|
15241
|
+
}
|
|
15424
15242
|
return;
|
|
15425
15243
|
}
|
|
15244
|
+
if (exists && !force) {
|
|
15245
|
+
emitError(opts, {
|
|
15246
|
+
code: CODES.SKILL_TARGET_EXISTS,
|
|
15247
|
+
message: `${target} already contains skill files`,
|
|
15248
|
+
hint: "Re-run with --force to overwrite, or --dry-run to see what would change."
|
|
15249
|
+
});
|
|
15250
|
+
}
|
|
15426
15251
|
mkdirSync2(target, { recursive: true });
|
|
15427
15252
|
cpSync(src, target, { recursive: true });
|
|
15428
15253
|
process.stdout.write(`installed ${skill.name} skill → ${rel}
|
|
@@ -15520,16 +15345,16 @@ async function createNodeEnv() {
|
|
|
15520
15345
|
const dom = new JSDOM("<!DOCTYPE html><html><head></head><body></body></html>", {
|
|
15521
15346
|
virtualConsole
|
|
15522
15347
|
});
|
|
15523
|
-
const { document: document2
|
|
15348
|
+
const { document: document2 } = dom.window;
|
|
15524
15349
|
globalThis.document = document2;
|
|
15525
15350
|
class HeadlessParseContext extends ParseContext {
|
|
15526
15351
|
constructor() {
|
|
15527
|
-
super(document2
|
|
15352
|
+
super(document2);
|
|
15528
15353
|
}
|
|
15529
15354
|
}
|
|
15530
15355
|
class HeadlessLintParseContext extends LintParseContext {
|
|
15531
15356
|
constructor() {
|
|
15532
|
-
super(document2
|
|
15357
|
+
super(document2);
|
|
15533
15358
|
}
|
|
15534
15359
|
}
|
|
15535
15360
|
return {
|
|
@@ -15538,7 +15363,7 @@ async function createNodeEnv() {
|
|
|
15538
15363
|
LintParseContext: HeadlessLintParseContext
|
|
15539
15364
|
};
|
|
15540
15365
|
}
|
|
15541
|
-
var
|
|
15366
|
+
var init_env = __esm({
|
|
15542
15367
|
"tools/cli/env.js"() {
|
|
15543
15368
|
init_anode();
|
|
15544
15369
|
init_lint_check();
|
|
@@ -16039,7 +15864,7 @@ var init_storybook = __esm({
|
|
|
16039
15864
|
init_chai2();
|
|
16040
15865
|
init_module();
|
|
16041
15866
|
init_test();
|
|
16042
|
-
|
|
15867
|
+
init_env();
|
|
16043
15868
|
init_errors();
|
|
16044
15869
|
init_pkg();
|
|
16045
15870
|
init_walk();
|
|
@@ -16224,7 +16049,7 @@ export async function resolve(specifier, context, nextResolve) {
|
|
|
16224
16049
|
init_errors();
|
|
16225
16050
|
|
|
16226
16051
|
// tools/cli/with-module.js
|
|
16227
|
-
|
|
16052
|
+
init_env();
|
|
16228
16053
|
init_errors();
|
|
16229
16054
|
import { statSync as statSync2 } from "node:fs";
|
|
16230
16055
|
import { parseArgs as parseArgs4 } from "node:util";
|