marko 6.1.12 → 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,7 +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
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
+ }
25
150
  function _el_read_error() {
26
151
  throw new Error("Element references can only be read in scripts and event handlers.");
27
152
  }
@@ -46,6 +171,9 @@ function assertExclusiveAttrs(attrs, onError = throwErr) {
46
171
  if (exclusiveAttrs && exclusiveAttrs.length > 1) onError(`The attributes ${joinWithAnd(exclusiveAttrs)} are mutually exclusive.`);
47
172
  }
48
173
  }
174
+ function assertHandlerIsFunction(name, value) {
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}".`);
176
+ }
49
177
  function assertValidTagName(tagName) {
50
178
  if (!/^[a-z][a-z0-9._-]*$/i.test(tagName)) throw new Error(`Invalid tag name: "${tagName}". Tag names must start with a letter and contain only letters, numbers, periods, hyphens, and underscores.`);
51
179
  }
@@ -66,27 +194,32 @@ const DYNAMIC_TAG_SCRIPT_REGISTER_ID = "_dynamicTagScript";
66
194
  //#endregion
67
195
  //#region src/html/content.ts
68
196
  function _unescaped(val) {
197
+ assertValidTextValue(val);
69
198
  return val ? val + "" : val === 0 ? "0" : "";
70
199
  }
71
200
  const unsafeXMLReg = /[<&]/g;
72
201
  const replaceUnsafeXML = (c) => c === "&" ? "&amp;" : "&lt;";
73
202
  const escapeXMLStr = (str) => unsafeXMLReg.test(str) ? str.replace(unsafeXMLReg, replaceUnsafeXML) : str;
74
203
  function _escape(val) {
204
+ assertValidTextValue(val);
75
205
  return val ? escapeXMLStr(val + "") : val === 0 ? "0" : "";
76
206
  }
77
207
  const unsafeScriptReg = /<\/script/gi;
78
208
  const escapeScriptStr = (str) => unsafeScriptReg.test(str) ? str.replace(unsafeScriptReg, "\\x3C/script") : str;
79
209
  function _escape_script(val) {
210
+ assertValidTextValue(val);
80
211
  return val ? escapeScriptStr(val + "") : val === 0 ? "0" : "";
81
212
  }
82
213
  const unsafeStyleReg = /<\/style/gi;
83
214
  const escapeStyleStr = (str) => unsafeStyleReg.test(str) ? str.replace(unsafeStyleReg, "\\3C/style") : str;
84
215
  function _escape_style(val) {
216
+ assertValidTextValue(val);
85
217
  return val ? escapeStyleStr(val + "") : val === 0 ? "0" : "";
86
218
  }
87
219
  const unsafeCommentReg = />/g;
88
220
  const escapeCommentStr = (str) => unsafeCommentReg.test(str) ? str.replace(unsafeCommentReg, "&gt;") : str;
89
221
  function _escape_comment(val) {
222
+ assertValidTextValue(val);
90
223
  return val ? escapeCommentStr(val + "") : val === 0 ? "0" : "";
91
224
  }
92
225
  //#endregion
@@ -1152,6 +1285,7 @@ function isCircular(parent, ref) {
1152
1285
  }
1153
1286
  function toObjectKey(name) {
1154
1287
  if (name === "") return "\"\"";
1288
+ if (name === "__proto__") return "[\"__proto__\"]";
1155
1289
  const startChar = name[0];
1156
1290
  if (isDigit(startChar)) {
1157
1291
  if (startChar === "0") {
@@ -1164,7 +1298,7 @@ function toObjectKey(name) {
1164
1298
  }
1165
1299
  function toAccess(accessor) {
1166
1300
  const start = accessor[0];
1167
- return start === "\"" || start >= "0" && start <= "9" ? "[" + accessor + "]" : "." + accessor;
1301
+ return start === "[" ? accessor : start === "\"" || start >= "0" && start <= "9" ? "[" + accessor + "]" : "." + accessor;
1168
1302
  }
1169
1303
  function quote(str, startPos) {
1170
1304
  let result = "";
@@ -1306,55 +1440,6 @@ function patchIteratorNext(proto) {
1306
1440
  proto.next[kTouchedIterator] = true;
1307
1441
  }
1308
1442
  //#endregion
1309
- //#region src/common/helpers.ts
1310
- const htmlAttrNameReg = /^[^a-z_]|[^a-z0-9._:-]/i;
1311
- function stringifyClassObject(name, value) {
1312
- return value ? name : "";
1313
- }
1314
- function stringifyStyleObject(name, value) {
1315
- return value || value === 0 ? name + ":" + value : "";
1316
- }
1317
- const toDelimitedString = function toDelimitedString(val, delimiter, stringify) {
1318
- let str = "";
1319
- let sep = "";
1320
- let part;
1321
- if (val) if (typeof val !== "object") str += val;
1322
- else if (Array.isArray(val)) for (const v of val) {
1323
- part = toDelimitedString(v, delimiter, stringify);
1324
- if (part) {
1325
- str += sep + part;
1326
- sep = delimiter;
1327
- }
1328
- }
1329
- else for (const name in val) {
1330
- part = stringify(name, val[name]);
1331
- if (part) {
1332
- str += sep + part;
1333
- sep = delimiter;
1334
- }
1335
- }
1336
- return str;
1337
- };
1338
- function isEventHandler(name) {
1339
- return /^on[A-Z-]/.test(name);
1340
- }
1341
- function getEventHandlerName(name) {
1342
- return name[2] === "-" ? name.slice(3) : name.slice(2).toLowerCase();
1343
- }
1344
- function isVoid(value) {
1345
- return value == null || value === false;
1346
- }
1347
- function isNotVoid(value) {
1348
- return value != null && value !== false;
1349
- }
1350
- function normalizeDynamicRenderer(value) {
1351
- if (value) {
1352
- if (typeof value === "string") return value;
1353
- const normalized = value.content || value.default || value;
1354
- if ("id" in normalized) return normalized;
1355
- }
1356
- }
1357
- //#endregion
1358
1443
  //#region src/common/for.ts
1359
1444
  function forIn(obj, cb) {
1360
1445
  for (const key in obj) cb(key, obj[key]);
@@ -1397,19 +1482,13 @@ function concat(opt, other) {
1397
1482
  //#endregion
1398
1483
  //#region src/html/for.ts
1399
1484
  function forOfBy(by, item, index) {
1400
- if (by) {
1401
- if (typeof by === "string") return item[by];
1402
- return by(item, index);
1403
- }
1404
- return index;
1485
+ return by ? typeof by === "string" ? item[by] : by(item, index) : index;
1405
1486
  }
1406
1487
  function forInBy(by, name, value) {
1407
- if (by) return by(name, value);
1408
- return name;
1488
+ return by ? by(name, value) : name;
1409
1489
  }
1410
1490
  function forStepBy(by, index) {
1411
- if (by) return by(index);
1412
- return index;
1491
+ return by ? by(index) : index;
1413
1492
  }
1414
1493
  //#endregion
1415
1494
  //#region src/html/inlined-runtimes.debug.ts
@@ -1670,20 +1749,31 @@ function _for_in(obj, cb, by, scopeId, accessor, serializeBranch, serializeMarke
1670
1749
  }) : forIn(obj, cb), scopeId, accessor, serializeBranch, serializeMarker, serializeStateful, parentEndTag, singleNode);
1671
1750
  }
1672
1751
  function _for_to(to, from, step, cb, by, scopeId, accessor, serializeBranch, serializeMarker, serializeStateful, parentEndTag, singleNode) {
1673
- forBranches(by, (each) => each ? forTo(to, from, step, (i) => {
1674
- const itemKey = forStepBy(by, i);
1675
- each(itemKey, itemKey === i, () => cb(i));
1676
- }) : 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);
1677
1759
  }
1678
1760
  function _for_until(to, from, step, cb, by, scopeId, accessor, serializeBranch, serializeMarker, serializeStateful, parentEndTag, singleNode) {
1679
- forBranches(by, (each) => each ? forUntil(to, from, step, (i) => {
1680
- const itemKey = forStepBy(by, i);
1681
- each(itemKey, itemKey === i, () => cb(i));
1682
- }) : 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);
1683
1768
  }
1684
1769
  function forBranches(by, iterate, scopeId, accessor, serializeBranch, serializeMarker, serializeStateful, parentEndTag, singleNode) {
1770
+ var seenKeys = /* @__PURE__ */ new Set();
1685
1771
  if (serializeBranch === 0) {
1686
- iterate(0);
1772
+ if (by) iterate((itemKey, _sameAsIndex, render) => {
1773
+ assertValidLoopKey(itemKey, seenKeys);
1774
+ render();
1775
+ });
1776
+ else iterate(0);
1687
1777
  writeBranchEnd(scopeId, accessor, serializeStateful, serializeMarker, parentEndTag, singleNode, "");
1688
1778
  return;
1689
1779
  }
@@ -1692,13 +1782,9 @@ function forBranches(by, iterate, scopeId, accessor, serializeBranch, serializeM
1692
1782
  const resumeMarker = serializeMarker !== 0 && (!parentEndTag || serializeStateful !== 0);
1693
1783
  let flushBranchIds = "";
1694
1784
  let loopScopes;
1695
- var seenKeys = /* @__PURE__ */ new Set();
1696
1785
  iterate((itemKey, sameAsIndex, render) => {
1697
1786
  const branchId = _peek_scope_id();
1698
- if (by) {
1699
- 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);
1700
- seenKeys.add(itemKey);
1701
- }
1787
+ if (by) assertValidLoopKey(itemKey, seenKeys);
1702
1788
  if (resumeMarker) if (singleNode) flushBranchIds = " " + branchId + flushBranchIds;
1703
1789
  else {
1704
1790
  $chunk.writeHTML(state.mark("[", flushBranchIds));
@@ -2370,12 +2456,24 @@ function _attr_style(value) {
2370
2456
  }
2371
2457
  function _attr_option_value(value) {
2372
2458
  const valueAttr = _attr("value", value);
2373
- 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;
2374
2467
  }
2375
2468
  const kSelectedValue = Symbol("selectedValue");
2469
+ const kSelectedValueMatched = Symbol("selectedValueMatched");
2376
2470
  function _attr_select_value(scopeId, nodeAccessor, value, valueChange, content) {
2377
2471
  if (valueChange) writeControlledScope(3, scopeId, nodeAccessor, void 0, valueChange);
2378
- 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);
2379
2477
  }
2380
2478
  function _attr_textarea_value(scopeId, nodeAccessor, value, valueChange) {
2381
2479
  if (valueChange) writeControlledScope(2, scopeId, nodeAccessor, void 0, valueChange);
@@ -2458,7 +2556,7 @@ function _attrs(data, nodeAccessor, scopeId, tagName) {
2458
2556
  break;
2459
2557
  default:
2460
2558
  if (name && !(isVoid(value) || skip.test(name) || name === "content" && tagName !== "meta")) {
2461
- if (htmlAttrNameReg.test(name)) throw new Error(`Invalid attribute name: ${JSON.stringify(name)}`);
2559
+ assertValidAttrName(name);
2462
2560
  if (isEventHandler(name)) {
2463
2561
  if (!events) {
2464
2562
  events = {};
@@ -2489,6 +2587,7 @@ function _attrs_partial_content(data, skip, nodeAccessor, scopeId, tagName, seri
2489
2587
  _attr_content(nodeAccessor, scopeId, data?.content, serializeReason);
2490
2588
  }
2491
2589
  function writeControlledScope(type, scopeId, nodeAccessor, value, valueChange) {
2590
+ assertHandlerIsFunction("valueChange", valueChange);
2492
2591
  writeScope(scopeId, {
2493
2592
  ["ControlledType:" + nodeAccessor]: type,
2494
2593
  ["ControlledValue:" + nodeAccessor]: value,
@@ -2499,6 +2598,7 @@ function stringAttr(name, value) {
2499
2598
  return value && " " + name + attrAssignment(value);
2500
2599
  }
2501
2600
  function nonVoidAttr(name, value) {
2601
+ assertValidAttrValue(name, value);
2502
2602
  switch (typeof value) {
2503
2603
  case "string": return " " + name + attrAssignment(value);
2504
2604
  case "boolean": return " " + name;