marko 6.1.13 → 6.1.14

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.
@@ -21,8 +21,132 @@ function* attrTagIterator() {
21
21
  yield* this[rest];
22
22
  }
23
23
  //#endregion
24
+ //#region src/common/helpers.ts
25
+ const htmlAttrNameReg = /^[^a-z_]|[^a-z0-9._:-]/i;
26
+ const knownWrongAttrs = {
27
+ className: "class",
28
+ classList: "class",
29
+ htmlFor: "for",
30
+ acceptCharset: "accept-charset",
31
+ httpEquiv: "http-equiv",
32
+ defaultValue: "value",
33
+ defaultChecked: "checked",
34
+ dangerouslySetInnerHTML: "$!{html}",
35
+ key: "<for by>",
36
+ ref: "<tag/ref>",
37
+ "v-if": "<if>",
38
+ "v-else": "<else>",
39
+ "v-else-if": "<else if>",
40
+ "v-for": "<for>",
41
+ "v-show": "<if>",
42
+ "v-model": "value:=state",
43
+ "v-bind": "...attrs",
44
+ "v-html": "$!{html}",
45
+ "v-text": "${text}"
46
+ };
47
+ function getWrongAttrSuggestion(name) {
48
+ const exact = knownWrongAttrs[name];
49
+ if (exact) return exact;
50
+ const colon = name.indexOf(":");
51
+ if (colon > 0) {
52
+ const rest = name.slice(colon + 1);
53
+ switch (name.slice(0, colon)) {
54
+ case "class": return `class={ ${rest}: condition }`;
55
+ case "style": return `style={ ${rest}: value }`;
56
+ case "on":
57
+ case "v-on": return `on${rest.charAt(0).toUpperCase()}${rest.slice(1)}`;
58
+ case "bind":
59
+ case "v-model": return `${rest}:=state`;
60
+ case "v-bind": return rest;
61
+ }
62
+ }
63
+ }
64
+ function stringifyClassObject(name, value) {
65
+ return value ? name : "";
66
+ }
67
+ function stringifyStyleObject(name, value) {
68
+ return value || value === 0 ? name + ":" + value : "";
69
+ }
70
+ const toDelimitedString = function toDelimitedString(val, delimiter, stringify) {
71
+ let str = "";
72
+ let sep = "";
73
+ let part;
74
+ if (val) if (typeof val !== "object") str += val;
75
+ else if (Array.isArray(val)) for (const v of val) {
76
+ part = toDelimitedString(v, delimiter, stringify);
77
+ if (part) {
78
+ str += sep + part;
79
+ sep = delimiter;
80
+ }
81
+ }
82
+ else for (const name in val) {
83
+ part = stringify(name, val[name]);
84
+ if (part) {
85
+ str += sep + part;
86
+ sep = delimiter;
87
+ }
88
+ }
89
+ return str;
90
+ };
91
+ function isEventHandler(name) {
92
+ return /^on[A-Z-]/.test(name);
93
+ }
94
+ function getEventHandlerName(name) {
95
+ return name[2] === "-" ? name.slice(3) : name.slice(2).toLowerCase();
96
+ }
97
+ function isVoid(value) {
98
+ return value == null || value === false;
99
+ }
100
+ function isNotVoid(value) {
101
+ return value != null && value !== false;
102
+ }
103
+ function normalizeDynamicRenderer(value) {
104
+ if (value) {
105
+ if (typeof value === "string") return value;
106
+ const normalized = value.content || value.default || value;
107
+ if ("id" in normalized) return normalized;
108
+ }
109
+ }
110
+ //#endregion
24
111
  //#region src/common/errors.ts
25
112
  const lowercaseEventHandlerReg = /^on[a-z]/;
113
+ function assertValidAttrValue(name, value) {
114
+ if (value && typeof value !== "string" && lowercaseEventHandlerReg.test(name)) throw new Error(`The \`${name}\` attribute must be a string or a falsey value (\`null\`, \`undefined\`, \`false\`, \`0\`, …), but received type "${typeof value}". To attach an event listener, use the \`on${name[2].toUpperCase()}${name.slice(3)}\` event handler instead.`);
115
+ if (typeof value === "function") {
116
+ if (name === "content" || /^on/i.test(name) || /Change$/.test(name)) return;
117
+ throw new Error(`The \`${name}\` attribute cannot be a function.`);
118
+ }
119
+ const unrenderable = describeUnrenderable(value);
120
+ if (unrenderable) throw new Error(`The \`${name}\` attribute cannot be ${unrenderable}.`);
121
+ }
122
+ function assertValidTextValue(value) {
123
+ const unrenderable = describeUnrenderable(value);
124
+ if (unrenderable) throw new Error(`Text content cannot be ${unrenderable}.`);
125
+ }
126
+ function describeUnrenderable(value) {
127
+ if (typeof value === "symbol") return "a symbol";
128
+ if (typeof value === "object" && value !== null) {
129
+ let stringified;
130
+ try {
131
+ stringified = `${value}`;
132
+ } catch {
133
+ stringified = "[object Object]";
134
+ }
135
+ if (/^\[object \w+\]$/.test(stringified)) return stringified === "[object Promise]" ? "a promise (use the `<await>` tag to render its resolved value)" : stringified === "[object Object]" ? "a plain object (it would render as `[object Object]`)" : `a value that renders as \`${stringified}\``;
136
+ }
137
+ }
138
+ function assertValidLoopKey(key, seenKeys) {
139
+ if (typeof key !== "string" && typeof key !== "number") throw new Error(`A \`<for>\` tag's \`by\` attribute must return a string or number for each item, but received ${key === null ? "null" : `type "${typeof key}"`}.`);
140
+ if (seenKeys) {
141
+ if (seenKeys.has(key)) throw new Error(`A \`<for>\` tag's \`by\` attribute must return a unique value for each item, but \`${key}\` was used more than once.`);
142
+ seenKeys.add(key);
143
+ }
144
+ }
145
+ function assertValidAttrName(name) {
146
+ if (htmlAttrNameReg.test(name)) throw new Error(`Invalid attribute name: ${JSON.stringify(name)}`);
147
+ const suggestion = getWrongAttrSuggestion(name);
148
+ if (suggestion) throw new Error(`\`${name}\` is not a valid attribute, did you mean \`${suggestion}\`?`);
149
+ }
26
150
  function _el_read_error() {
27
151
  throw new Error("Element references can only be read in scripts and event handlers.");
28
152
  }
@@ -47,9 +171,6 @@ function assertExclusiveAttrs(attrs, onError = throwErr) {
47
171
  if (exclusiveAttrs && exclusiveAttrs.length > 1) onError(`The attributes ${joinWithAnd(exclusiveAttrs)} are mutually exclusive.`);
48
172
  }
49
173
  }
50
- function assertValidEventHandlerAttr(name, value) {
51
- if (value && typeof value !== "string" && lowercaseEventHandlerReg.test(name)) throw new Error(`The \`${name}\` attribute must be a string or a falsey value (\`null\`, \`undefined\`, \`false\`, \`0\`, …), but received type "${typeof value}". To attach an event listener, use the \`on${name[2].toUpperCase()}${name.slice(3)}\` event handler instead.`);
52
- }
53
174
  function assertHandlerIsFunction(name, value) {
54
175
  if (value && typeof value !== "function") throw new Error(`The \`${name}\` handler must be a function or a falsey value (\`null\`, \`undefined\`, \`false\`, \`0\`, …), but received type "${typeof value}".`);
55
176
  }
@@ -73,27 +194,32 @@ const DYNAMIC_TAG_SCRIPT_REGISTER_ID = "_dynamicTagScript";
73
194
  //#endregion
74
195
  //#region src/html/content.ts
75
196
  function _unescaped(val) {
197
+ assertValidTextValue(val);
76
198
  return val ? val + "" : val === 0 ? "0" : "";
77
199
  }
78
200
  const unsafeXMLReg = /[<&]/g;
79
201
  const replaceUnsafeXML = (c) => c === "&" ? "&amp;" : "&lt;";
80
202
  const escapeXMLStr = (str) => unsafeXMLReg.test(str) ? str.replace(unsafeXMLReg, replaceUnsafeXML) : str;
81
203
  function _escape(val) {
204
+ assertValidTextValue(val);
82
205
  return val ? escapeXMLStr(val + "") : val === 0 ? "0" : "";
83
206
  }
84
207
  const unsafeScriptReg = /<\/script/gi;
85
208
  const escapeScriptStr = (str) => unsafeScriptReg.test(str) ? str.replace(unsafeScriptReg, "\\x3C/script") : str;
86
209
  function _escape_script(val) {
210
+ assertValidTextValue(val);
87
211
  return val ? escapeScriptStr(val + "") : val === 0 ? "0" : "";
88
212
  }
89
213
  const unsafeStyleReg = /<\/style/gi;
90
214
  const escapeStyleStr = (str) => unsafeStyleReg.test(str) ? str.replace(unsafeStyleReg, "\\3C/style") : str;
91
215
  function _escape_style(val) {
216
+ assertValidTextValue(val);
92
217
  return val ? escapeStyleStr(val + "") : val === 0 ? "0" : "";
93
218
  }
94
219
  const unsafeCommentReg = />/g;
95
220
  const escapeCommentStr = (str) => unsafeCommentReg.test(str) ? str.replace(unsafeCommentReg, "&gt;") : str;
96
221
  function _escape_comment(val) {
222
+ assertValidTextValue(val);
97
223
  return val ? escapeCommentStr(val + "") : val === 0 ? "0" : "";
98
224
  }
99
225
  //#endregion
@@ -1159,6 +1285,7 @@ function isCircular(parent, ref) {
1159
1285
  }
1160
1286
  function toObjectKey(name) {
1161
1287
  if (name === "") return "\"\"";
1288
+ if (name === "__proto__") return "[\"__proto__\"]";
1162
1289
  const startChar = name[0];
1163
1290
  if (isDigit(startChar)) {
1164
1291
  if (startChar === "0") {
@@ -1171,7 +1298,7 @@ function toObjectKey(name) {
1171
1298
  }
1172
1299
  function toAccess(accessor) {
1173
1300
  const start = accessor[0];
1174
- return start === "\"" || start >= "0" && start <= "9" ? "[" + accessor + "]" : "." + accessor;
1301
+ return start === "[" ? accessor : start === "\"" || start >= "0" && start <= "9" ? "[" + accessor + "]" : "." + accessor;
1175
1302
  }
1176
1303
  function quote(str, startPos) {
1177
1304
  let result = "";
@@ -1313,55 +1440,6 @@ function patchIteratorNext(proto) {
1313
1440
  proto.next[kTouchedIterator] = true;
1314
1441
  }
1315
1442
  //#endregion
1316
- //#region src/common/helpers.ts
1317
- const htmlAttrNameReg = /^[^a-z_]|[^a-z0-9._:-]/i;
1318
- function stringifyClassObject(name, value) {
1319
- return value ? name : "";
1320
- }
1321
- function stringifyStyleObject(name, value) {
1322
- return value || value === 0 ? name + ":" + value : "";
1323
- }
1324
- const toDelimitedString = function toDelimitedString(val, delimiter, stringify) {
1325
- let str = "";
1326
- let sep = "";
1327
- let part;
1328
- if (val) if (typeof val !== "object") str += val;
1329
- else if (Array.isArray(val)) for (const v of val) {
1330
- part = toDelimitedString(v, delimiter, stringify);
1331
- if (part) {
1332
- str += sep + part;
1333
- sep = delimiter;
1334
- }
1335
- }
1336
- else for (const name in val) {
1337
- part = stringify(name, val[name]);
1338
- if (part) {
1339
- str += sep + part;
1340
- sep = delimiter;
1341
- }
1342
- }
1343
- return str;
1344
- };
1345
- function isEventHandler(name) {
1346
- return /^on[A-Z-]/.test(name);
1347
- }
1348
- function getEventHandlerName(name) {
1349
- return name[2] === "-" ? name.slice(3) : name.slice(2).toLowerCase();
1350
- }
1351
- function isVoid(value) {
1352
- return value == null || value === false;
1353
- }
1354
- function isNotVoid(value) {
1355
- return value != null && value !== false;
1356
- }
1357
- function normalizeDynamicRenderer(value) {
1358
- if (value) {
1359
- if (typeof value === "string") return value;
1360
- const normalized = value.content || value.default || value;
1361
- if ("id" in normalized) return normalized;
1362
- }
1363
- }
1364
- //#endregion
1365
1443
  //#region src/common/for.ts
1366
1444
  function forIn(obj, cb) {
1367
1445
  for (const key in obj) cb(key, obj[key]);
@@ -1404,28 +1482,13 @@ function concat(opt, other) {
1404
1482
  //#endregion
1405
1483
  //#region src/html/for.ts
1406
1484
  function forOfBy(by, item, index) {
1407
- if (by) {
1408
- const key = typeof by === "string" ? item[by] : by(item, index);
1409
- if (typeof key !== "string" && typeof key !== "number") console.error(`A <for> tag's \`by\` attribute must return a string or number, but it returned:`, key);
1410
- return key;
1411
- }
1412
- return index;
1485
+ return by ? typeof by === "string" ? item[by] : by(item, index) : index;
1413
1486
  }
1414
1487
  function forInBy(by, name, value) {
1415
- if (by) {
1416
- const key = by(name, value);
1417
- if (typeof key !== "string" && typeof key !== "number") console.error(`A <for> tag's \`by\` attribute must return a string or number, but it returned:`, key);
1418
- return key;
1419
- }
1420
- return name;
1488
+ return by ? by(name, value) : name;
1421
1489
  }
1422
1490
  function forStepBy(by, index) {
1423
- if (by) {
1424
- const key = by(index);
1425
- if (typeof key !== "string" && typeof key !== "number") console.error(`A <for> tag's \`by\` attribute must return a string or number, but it returned:`, key);
1426
- return key;
1427
- }
1428
- return index;
1491
+ return by ? by(index) : index;
1429
1492
  }
1430
1493
  //#endregion
1431
1494
  //#region src/html/inlined-runtimes.debug.ts
@@ -1686,20 +1749,31 @@ function _for_in(obj, cb, by, scopeId, accessor, serializeBranch, serializeMarke
1686
1749
  }) : forIn(obj, cb), scopeId, accessor, serializeBranch, serializeMarker, serializeStateful, parentEndTag, singleNode);
1687
1750
  }
1688
1751
  function _for_to(to, from, step, cb, by, scopeId, accessor, serializeBranch, serializeMarker, serializeStateful, parentEndTag, singleNode) {
1689
- forBranches(by, (each) => each ? forTo(to, from, step, (i) => {
1690
- const itemKey = forStepBy(by, i);
1691
- each(itemKey, itemKey === i, () => cb(i));
1692
- }) : forTo(to, from, step, cb), scopeId, accessor, serializeBranch, serializeMarker, serializeStateful, parentEndTag, singleNode);
1752
+ forBranches(by, (each) => {
1753
+ let index = 0;
1754
+ return each ? forTo(to, from, step, (value) => {
1755
+ const itemKey = forStepBy(by, value);
1756
+ each(itemKey, itemKey === index++, () => cb(value));
1757
+ }) : forTo(to, from, step, cb);
1758
+ }, scopeId, accessor, serializeBranch, serializeMarker, serializeStateful, parentEndTag, singleNode);
1693
1759
  }
1694
1760
  function _for_until(to, from, step, cb, by, scopeId, accessor, serializeBranch, serializeMarker, serializeStateful, parentEndTag, singleNode) {
1695
- forBranches(by, (each) => each ? forUntil(to, from, step, (i) => {
1696
- const itemKey = forStepBy(by, i);
1697
- each(itemKey, itemKey === i, () => cb(i));
1698
- }) : forUntil(to, from, step, cb), scopeId, accessor, serializeBranch, serializeMarker, serializeStateful, parentEndTag, singleNode);
1761
+ forBranches(by, (each) => {
1762
+ let index = 0;
1763
+ return each ? forUntil(to, from, step, (value) => {
1764
+ const itemKey = forStepBy(by, value);
1765
+ each(itemKey, itemKey === index++, () => cb(value));
1766
+ }) : forUntil(to, from, step, cb);
1767
+ }, scopeId, accessor, serializeBranch, serializeMarker, serializeStateful, parentEndTag, singleNode);
1699
1768
  }
1700
1769
  function forBranches(by, iterate, scopeId, accessor, serializeBranch, serializeMarker, serializeStateful, parentEndTag, singleNode) {
1770
+ var seenKeys = /* @__PURE__ */ new Set();
1701
1771
  if (serializeBranch === 0) {
1702
- iterate(0);
1772
+ if (by) iterate((itemKey, _sameAsIndex, render) => {
1773
+ assertValidLoopKey(itemKey, seenKeys);
1774
+ render();
1775
+ });
1776
+ else iterate(0);
1703
1777
  writeBranchEnd(scopeId, accessor, serializeStateful, serializeMarker, parentEndTag, singleNode, "");
1704
1778
  return;
1705
1779
  }
@@ -1708,13 +1782,9 @@ function forBranches(by, iterate, scopeId, accessor, serializeBranch, serializeM
1708
1782
  const resumeMarker = serializeMarker !== 0 && (!parentEndTag || serializeStateful !== 0);
1709
1783
  let flushBranchIds = "";
1710
1784
  let loopScopes;
1711
- var seenKeys = /* @__PURE__ */ new Set();
1712
1785
  iterate((itemKey, sameAsIndex, render) => {
1713
1786
  const branchId = _peek_scope_id();
1714
- if (by) {
1715
- if (seenKeys.has(itemKey)) console.error(`A <for> tag's \`by\` attribute must return a unique value for each item, but a duplicate was found matching:`, itemKey);
1716
- seenKeys.add(itemKey);
1717
- }
1787
+ if (by) assertValidLoopKey(itemKey, seenKeys);
1718
1788
  if (resumeMarker) if (singleNode) flushBranchIds = " " + branchId + flushBranchIds;
1719
1789
  else {
1720
1790
  $chunk.writeHTML(state.mark("[", flushBranchIds));
@@ -2386,12 +2456,24 @@ function _attr_style(value) {
2386
2456
  }
2387
2457
  function _attr_option_value(value) {
2388
2458
  const valueAttr = _attr("value", value);
2389
- return normalizedValueMatches(getContext(kSelectedValue), value) ? valueAttr + " selected" : valueAttr;
2459
+ if (normalizedValueMatches(getContext(kSelectedValue), value)) {
2460
+ {
2461
+ const matched = getContext(kSelectedValueMatched);
2462
+ if (matched) matched.value = true;
2463
+ }
2464
+ return valueAttr + " selected";
2465
+ }
2466
+ return valueAttr;
2390
2467
  }
2391
2468
  const kSelectedValue = Symbol("selectedValue");
2469
+ const kSelectedValueMatched = Symbol("selectedValueMatched");
2392
2470
  function _attr_select_value(scopeId, nodeAccessor, value, valueChange, content) {
2393
2471
  if (valueChange) writeControlledScope(3, scopeId, nodeAccessor, void 0, valueChange);
2394
- if (content) withContext(kSelectedValue, value, content);
2472
+ if (content) if (valueChange) {
2473
+ const matched = { value: false };
2474
+ withContext(kSelectedValue, value, () => withContext(kSelectedValueMatched, matched, content));
2475
+ if (!matched.value && (Array.isArray(value) ? value.some((v) => normalizeStrAttrValue(v) !== "") : normalizeStrAttrValue(value) !== "")) console.error("A controlled `<select>`'s `value` has no matching `<option>`:", value);
2476
+ } else withContext(kSelectedValue, value, content);
2395
2477
  }
2396
2478
  function _attr_textarea_value(scopeId, nodeAccessor, value, valueChange) {
2397
2479
  if (valueChange) writeControlledScope(2, scopeId, nodeAccessor, void 0, valueChange);
@@ -2430,7 +2512,6 @@ function _attr_nonce() {
2430
2512
  return getChunk().boundary.state.nonceAttr;
2431
2513
  }
2432
2514
  function _attr(name, value) {
2433
- assertValidEventHandlerAttr(name, value);
2434
2515
  return isVoid(value) ? "" : nonVoidAttr(name, value);
2435
2516
  }
2436
2517
  function _attrs(data, nodeAccessor, scopeId, tagName) {
@@ -2475,7 +2556,7 @@ function _attrs(data, nodeAccessor, scopeId, tagName) {
2475
2556
  break;
2476
2557
  default:
2477
2558
  if (name && !(isVoid(value) || skip.test(name) || name === "content" && tagName !== "meta")) {
2478
- if (htmlAttrNameReg.test(name)) throw new Error(`Invalid attribute name: ${JSON.stringify(name)}`);
2559
+ assertValidAttrName(name);
2479
2560
  if (isEventHandler(name)) {
2480
2561
  if (!events) {
2481
2562
  events = {};
@@ -2517,6 +2598,7 @@ function stringAttr(name, value) {
2517
2598
  return value && " " + name + attrAssignment(value);
2518
2599
  }
2519
2600
  function nonVoidAttr(name, value) {
2601
+ assertValidAttrValue(name, value);
2520
2602
  switch (typeof value) {
2521
2603
  case "string": return " " + name + attrAssignment(value);
2522
2604
  case "boolean": return " " + name;