@marko/runtime-tags 0.2.1 → 0.2.3

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/debug/dom.js CHANGED
@@ -447,15 +447,16 @@ var DIRTY = true ? Symbol("dirty") : {};
447
447
  function state(valueAccessor, fn, getIntersection) {
448
448
  const valueSignal = value(valueAccessor, fn, getIntersection);
449
449
  const markAccessor = valueAccessor + "#" /* Mark */;
450
+ const valueChangeAccessor = valueAccessor + "@" /* TagVariableChange */;
450
451
  return (scope, valueOrOp, valueChange) => {
451
452
  if (rendering) {
452
453
  const valueIsOp = valueOrOp === MARK || valueOrOp === CLEAN || valueOrOp === DIRTY;
453
454
  valueSignal(
454
455
  scope,
455
- valueIsOp || valueChange || scope[markAccessor] === void 0 ? valueOrOp : CLEAN
456
+ valueIsOp || (scope[valueChangeAccessor] = valueChange) || scope[markAccessor] === void 0 ? valueOrOp : CLEAN
456
457
  );
457
- } else if (valueChange) {
458
- valueChange(valueOrOp);
458
+ } else if (scope[valueChangeAccessor]) {
459
+ scope[valueChangeAccessor](valueOrOp);
459
460
  } else {
460
461
  queueSource(scope, valueSignal, valueOrOp);
461
462
  }
@@ -358,15 +358,16 @@ var DIRTY = true ? Symbol("dirty") : {};
358
358
  function state(valueAccessor, fn, getIntersection) {
359
359
  const valueSignal = value(valueAccessor, fn, getIntersection);
360
360
  const markAccessor = valueAccessor + "#" /* Mark */;
361
+ const valueChangeAccessor = valueAccessor + "@" /* TagVariableChange */;
361
362
  return (scope, valueOrOp, valueChange) => {
362
363
  if (rendering) {
363
364
  const valueIsOp = valueOrOp === MARK || valueOrOp === CLEAN || valueOrOp === DIRTY;
364
365
  valueSignal(
365
366
  scope,
366
- valueIsOp || valueChange || scope[markAccessor] === void 0 ? valueOrOp : CLEAN
367
+ valueIsOp || (scope[valueChangeAccessor] = valueChange) || scope[markAccessor] === void 0 ? valueOrOp : CLEAN
367
368
  );
368
- } else if (valueChange) {
369
- valueChange(valueOrOp);
369
+ } else if (scope[valueChangeAccessor]) {
370
+ scope[valueChangeAccessor](valueOrOp);
370
371
  } else {
371
372
  queueSource(scope, valueSignal, valueOrOp);
372
373
  }
@@ -42,8 +42,11 @@ __export(html_exports, {
42
42
  escapeStyle: () => escapeStyle,
43
43
  escapeXML: () => escapeXML,
44
44
  forIn: () => forIn,
45
+ forInBy: () => forInBy,
45
46
  forOf: () => forOf,
47
+ forOfBy: () => forOfBy,
46
48
  forTo: () => forTo,
49
+ forToBy: () => forToBy,
47
50
  fork: () => fork,
48
51
  getScopeById: () => getScopeById,
49
52
  markResumeCleanup: () => markResumeCleanup,
@@ -66,7 +69,8 @@ __export(html_exports, {
66
69
  write: () => write,
67
70
  writeEffect: () => writeEffect,
68
71
  writeExistingScope: () => writeExistingScope,
69
- writeScope: () => writeScope
72
+ writeScope: () => writeScope,
73
+ writeTrailers: () => writeTrailers
70
74
  });
71
75
  module.exports = __toCommonJS(html_exports);
72
76
 
@@ -94,28 +98,6 @@ function* attrTagIterator() {
94
98
  yield* this[rest];
95
99
  }
96
100
 
97
- // src/common/for.ts
98
- function forIn(obj, cb) {
99
- for (const key in obj) {
100
- cb(key, obj[key]);
101
- }
102
- }
103
- function forOf(list, cb) {
104
- if (list) {
105
- let i = 0;
106
- for (const item of list) {
107
- cb(item, i++);
108
- }
109
- }
110
- }
111
- function forTo(to, from, step, cb) {
112
- const start = from || 0;
113
- const delta = step || 1;
114
- for (let steps = (to - start) / delta, i = 0; i <= steps; i++) {
115
- cb(start + i * delta);
116
- }
117
- }
118
-
119
101
  // src/common/helpers.ts
120
102
  function classValue(value) {
121
103
  return toDelimitedString(value, " ", stringifyClassObject);
@@ -1676,6 +1658,7 @@ var State2 = class {
1676
1658
  hasMainRuntime = false;
1677
1659
  hasReorderRuntime = false;
1678
1660
  hasWrittenResume = false;
1661
+ trailerHTML = "";
1679
1662
  serializer = new Serializer();
1680
1663
  writeReorders = null;
1681
1664
  scopes = /* @__PURE__ */ new Map();
@@ -1952,18 +1935,29 @@ function prepareChunk(chunk) {
1952
1935
  head.scripts = scripts;
1953
1936
  return head;
1954
1937
  }
1955
- function flushChunk(head) {
1938
+ function flushChunk(head, last) {
1939
+ const { boundary } = head;
1940
+ const { state } = boundary;
1956
1941
  const { html, scripts } = head;
1957
- const { $global: $global2 } = head.boundary.state;
1942
+ const { $global: $global2 } = state;
1958
1943
  const { __flush__ } = $global2;
1959
- const result = scripts ? html + "<script" + (head.boundary.state.$global.cspNonce ? " nonce=" + escapeAttrValue(head.boundary.state.$global.cspNonce + "") : "") + ">" + scripts + "</script>" : html;
1944
+ let result = html;
1960
1945
  head.html = head.scripts = "";
1946
+ if (scripts) {
1947
+ result += ($global2.cspNonce ? "<script nonce=" + escapeAttrValue($global2.cspNonce + "") + ">" : "<script>") + scripts + "</script>";
1948
+ }
1961
1949
  if (__flush__) {
1962
1950
  $global2.__flush__ = void 0;
1963
- return __flush__($global2, result);
1951
+ result = __flush__($global2, result);
1952
+ }
1953
+ if (last && state.trailerHTML) {
1954
+ result += state.trailerHTML;
1964
1955
  }
1965
1956
  return result;
1966
1957
  }
1958
+ function writeTrailers(html) {
1959
+ $chunk.boundary.state.trailerHTML += html;
1960
+ }
1967
1961
  function concatEffects(a, b) {
1968
1962
  return a ? b ? a + "," + b : a : b;
1969
1963
  }
@@ -2040,10 +2034,13 @@ function optionValueAttr(value) {
2040
2034
  var kSelectedValue = Symbol("selectedValue");
2041
2035
  function controllable_select_value(scopeId, nodeAccessor, value, valueChange, renderBody) {
2042
2036
  if (valueChange) {
2043
- const scope = ensureScopeWithId(scopeId);
2044
- scope[nodeAccessor + ":" /* ControlledValue */] = value;
2045
- scope[nodeAccessor + ";" /* ControlledHandler */] = valueChange;
2046
- scope[nodeAccessor + "=" /* ControlledType */] = 3 /* SelectValue */;
2037
+ writeControlledScope(
2038
+ 3 /* SelectValue */,
2039
+ scopeId,
2040
+ nodeAccessor,
2041
+ value,
2042
+ valueChange
2043
+ );
2047
2044
  }
2048
2045
  if (renderBody) {
2049
2046
  withContext(kSelectedValue, value, renderBody);
@@ -2051,25 +2048,37 @@ function controllable_select_value(scopeId, nodeAccessor, value, valueChange, re
2051
2048
  }
2052
2049
  function controllable_textarea_value(scopeId, nodeAccessor, value, valueChange) {
2053
2050
  if (valueChange) {
2054
- const scope = ensureScopeWithId(scopeId);
2055
- scope[nodeAccessor + ";" /* ControlledHandler */] = valueChange;
2056
- scope[nodeAccessor + "=" /* ControlledType */] = 2 /* InputValue */;
2051
+ writeControlledScope(
2052
+ 2 /* InputValue */,
2053
+ scopeId,
2054
+ nodeAccessor,
2055
+ void 0,
2056
+ valueChange
2057
+ );
2057
2058
  }
2058
2059
  return escapeTextAreaValue(value);
2059
2060
  }
2060
2061
  function controllable_input_value(scopeId, nodeAccessor, value, valueChange) {
2061
2062
  if (valueChange) {
2062
- const scope = ensureScopeWithId(scopeId);
2063
- scope[nodeAccessor + ";" /* ControlledHandler */] = valueChange;
2064
- scope[nodeAccessor + "=" /* ControlledType */] = 2 /* InputValue */;
2063
+ writeControlledScope(
2064
+ 2 /* InputValue */,
2065
+ scopeId,
2066
+ nodeAccessor,
2067
+ void 0,
2068
+ valueChange
2069
+ );
2065
2070
  }
2066
2071
  return attr("value", value);
2067
2072
  }
2068
2073
  function controllable_input_checked(scopeId, nodeAccessor, checked, checkedChange) {
2069
2074
  if (checkedChange) {
2070
- const scope = ensureScopeWithId(scopeId);
2071
- scope[nodeAccessor + ";" /* ControlledHandler */] = checkedChange;
2072
- scope[nodeAccessor + "=" /* ControlledType */] = 0 /* InputChecked */;
2075
+ writeControlledScope(
2076
+ 0 /* InputChecked */,
2077
+ scopeId,
2078
+ nodeAccessor,
2079
+ void 0,
2080
+ checkedChange
2081
+ );
2073
2082
  }
2074
2083
  return attr("checked", checked);
2075
2084
  }
@@ -2077,21 +2086,25 @@ function controllable_input_checkedValue(scopeId, nodeAccessor, checkedValue, ch
2077
2086
  const multiple = Array.isArray(checkedValue);
2078
2087
  const valueAttr = attr("value", value);
2079
2088
  if (checkedValueChange) {
2080
- const scope = ensureScopeWithId(scopeId);
2081
- scope[nodeAccessor + ";" /* ControlledHandler */] = checkedValueChange;
2082
- scope[nodeAccessor + "=" /* ControlledType */] = 1 /* InputCheckedValue */;
2083
- if (multiple) {
2084
- scope[nodeAccessor + ":" /* ControlledValue */] = checkedValue;
2085
- }
2089
+ writeControlledScope(
2090
+ 1 /* InputCheckedValue */,
2091
+ scopeId,
2092
+ nodeAccessor,
2093
+ multiple ? checkedValue : void 0,
2094
+ checkedValueChange
2095
+ );
2086
2096
  }
2087
2097
  return (multiple ? checkedValue.includes(value) : checkedValue === value) ? valueAttr + " checked" : valueAttr;
2088
2098
  }
2089
2099
  function controllable_detailsOrDialog_open(scopeId, nodeAccessor, open, openChange) {
2090
2100
  if (openChange) {
2091
- const scope = ensureScopeWithId(scopeId);
2092
- scope[nodeAccessor + ":" /* ControlledValue */] = open;
2093
- scope[nodeAccessor + ";" /* ControlledHandler */] = openChange;
2094
- scope[nodeAccessor + "=" /* ControlledType */] = 4 /* DetailsOrDialogOpen */;
2101
+ writeControlledScope(
2102
+ 4 /* DetailsOrDialogOpen */,
2103
+ scopeId,
2104
+ nodeAccessor,
2105
+ open,
2106
+ openChange
2107
+ );
2095
2108
  }
2096
2109
  return attr("open", open);
2097
2110
  }
@@ -2171,7 +2184,13 @@ function attrs(data, nodeAccessor, scopeId, tagName) {
2171
2184
  default:
2172
2185
  if (!isVoid(val)) {
2173
2186
  if (isEventHandler(name)) {
2174
- (events ||= ensureScopeWithId(scopeId)[nodeAccessor + "~" /* EventAttributes */] = {})[getEventHandlerName(name)] = val;
2187
+ if (!events) {
2188
+ events = {};
2189
+ writeScope(scopeId, {
2190
+ [nodeAccessor + "~" /* EventAttributes */]: events
2191
+ });
2192
+ }
2193
+ events[getEventHandlerName(name)] = val;
2175
2194
  } else if (!skip.test(name)) {
2176
2195
  result += nonVoidAttr(name, val);
2177
2196
  }
@@ -2188,6 +2207,13 @@ function partialAttrs(data, skip, nodeAccessor, scopeId, tagName) {
2188
2207
  }
2189
2208
  return attrs(partial, nodeAccessor, scopeId, tagName);
2190
2209
  }
2210
+ function writeControlledScope(type, scopeId, nodeAccessor, value, valueChange) {
2211
+ writeScope(scopeId, {
2212
+ [nodeAccessor + "=" /* ControlledType */]: type,
2213
+ [nodeAccessor + ":" /* ControlledValue */]: value,
2214
+ [nodeAccessor + ";" /* ControlledHandler */]: valueChange
2215
+ });
2216
+ }
2191
2217
  function stringAttr(name, val) {
2192
2218
  return val && ` ${name}=${escapeAttrValue(val)}`;
2193
2219
  }
@@ -2398,6 +2424,51 @@ var compat = {
2398
2424
  }
2399
2425
  };
2400
2426
 
2427
+ // src/common/for.ts
2428
+ function forIn(obj, cb) {
2429
+ for (const key in obj) {
2430
+ cb(key, obj[key]);
2431
+ }
2432
+ }
2433
+ function forOf(list, cb) {
2434
+ if (list) {
2435
+ let i = 0;
2436
+ for (const item of list) {
2437
+ cb(item, i++);
2438
+ }
2439
+ }
2440
+ }
2441
+ function forTo(to, from, step, cb) {
2442
+ const start = from || 0;
2443
+ const delta = step || 1;
2444
+ for (let steps = (to - start) / delta, i = 0; i <= steps; i++) {
2445
+ cb(start + i * delta);
2446
+ }
2447
+ }
2448
+
2449
+ // src/html/for.ts
2450
+ function forOfBy(by, item, index) {
2451
+ if (by) {
2452
+ if (typeof by === "string") {
2453
+ return item[by];
2454
+ }
2455
+ return by(item, index);
2456
+ }
2457
+ return index;
2458
+ }
2459
+ function forInBy(by, name, value) {
2460
+ if (by) {
2461
+ return by(name, value);
2462
+ }
2463
+ return name;
2464
+ }
2465
+ function forToBy(by, index) {
2466
+ if (by) {
2467
+ return by(index);
2468
+ }
2469
+ return index;
2470
+ }
2471
+
2401
2472
  // src/html/template.ts
2402
2473
  var createTemplate = (templateId, renderer) => {
2403
2474
  renderer.render = render;
@@ -2561,7 +2632,7 @@ var ServerRenderResult = class {
2561
2632
  reject(boundary.signal.reason);
2562
2633
  } else {
2563
2634
  head = prepareChunk(head);
2564
- if (boundary.done) resolve(flushChunk(head));
2635
+ if (boundary.done) resolve(flushChunk(head, true));
2565
2636
  }
2566
2637
  }
2567
2638
  })();
@@ -2586,7 +2657,7 @@ var ServerRenderResult = class {
2586
2657
  head = prepareChunk(head);
2587
2658
  }
2588
2659
  if (write2 || boundary.done) {
2589
- const html = flushChunk(head);
2660
+ const html = flushChunk(head, boundary.done);
2590
2661
  if (html) onWrite(html);
2591
2662
  if (boundary.done) {
2592
2663
  if (!tick2) offTick(onNext);
@@ -2607,7 +2678,7 @@ var ServerRenderResult = class {
2607
2678
  if (!head) throw new Error("Cannot read from a consumed render result");
2608
2679
  if (head.next) throw new Error("Cannot fork in sync mode");
2609
2680
  this.#head = null;
2610
- return flushChunk(prepareChunk(head));
2681
+ return flushChunk(prepareChunk(head), true);
2611
2682
  }
2612
2683
  };
2613
2684
  // Annotate the CommonJS export names for ESM import in node:
@@ -2634,8 +2705,11 @@ var ServerRenderResult = class {
2634
2705
  escapeStyle,
2635
2706
  escapeXML,
2636
2707
  forIn,
2708
+ forInBy,
2637
2709
  forOf,
2710
+ forOfBy,
2638
2711
  forTo,
2712
+ forToBy,
2639
2713
  fork,
2640
2714
  getScopeById,
2641
2715
  markResumeCleanup,
@@ -2658,5 +2732,6 @@ var ServerRenderResult = class {
2658
2732
  write,
2659
2733
  writeEffect,
2660
2734
  writeExistingScope,
2661
- writeScope
2735
+ writeScope,
2736
+ writeTrailers
2662
2737
  });
@@ -22,28 +22,6 @@ function* attrTagIterator() {
22
22
  yield* this[rest];
23
23
  }
24
24
 
25
- // src/common/for.ts
26
- function forIn(obj, cb) {
27
- for (const key in obj) {
28
- cb(key, obj[key]);
29
- }
30
- }
31
- function forOf(list, cb) {
32
- if (list) {
33
- let i = 0;
34
- for (const item of list) {
35
- cb(item, i++);
36
- }
37
- }
38
- }
39
- function forTo(to, from, step, cb) {
40
- const start = from || 0;
41
- const delta = step || 1;
42
- for (let steps = (to - start) / delta, i = 0; i <= steps; i++) {
43
- cb(start + i * delta);
44
- }
45
- }
46
-
47
25
  // src/common/helpers.ts
48
26
  function classValue(value) {
49
27
  return toDelimitedString(value, " ", stringifyClassObject);
@@ -1604,6 +1582,7 @@ var State2 = class {
1604
1582
  hasMainRuntime = false;
1605
1583
  hasReorderRuntime = false;
1606
1584
  hasWrittenResume = false;
1585
+ trailerHTML = "";
1607
1586
  serializer = new Serializer();
1608
1587
  writeReorders = null;
1609
1588
  scopes = /* @__PURE__ */ new Map();
@@ -1880,18 +1859,29 @@ function prepareChunk(chunk) {
1880
1859
  head.scripts = scripts;
1881
1860
  return head;
1882
1861
  }
1883
- function flushChunk(head) {
1862
+ function flushChunk(head, last) {
1863
+ const { boundary } = head;
1864
+ const { state } = boundary;
1884
1865
  const { html, scripts } = head;
1885
- const { $global: $global2 } = head.boundary.state;
1866
+ const { $global: $global2 } = state;
1886
1867
  const { __flush__ } = $global2;
1887
- const result = scripts ? html + "<script" + (head.boundary.state.$global.cspNonce ? " nonce=" + escapeAttrValue(head.boundary.state.$global.cspNonce + "") : "") + ">" + scripts + "</script>" : html;
1868
+ let result = html;
1888
1869
  head.html = head.scripts = "";
1870
+ if (scripts) {
1871
+ result += ($global2.cspNonce ? "<script nonce=" + escapeAttrValue($global2.cspNonce + "") + ">" : "<script>") + scripts + "</script>";
1872
+ }
1889
1873
  if (__flush__) {
1890
1874
  $global2.__flush__ = void 0;
1891
- return __flush__($global2, result);
1875
+ result = __flush__($global2, result);
1876
+ }
1877
+ if (last && state.trailerHTML) {
1878
+ result += state.trailerHTML;
1892
1879
  }
1893
1880
  return result;
1894
1881
  }
1882
+ function writeTrailers(html) {
1883
+ $chunk.boundary.state.trailerHTML += html;
1884
+ }
1895
1885
  function concatEffects(a, b) {
1896
1886
  return a ? b ? a + "," + b : a : b;
1897
1887
  }
@@ -1968,10 +1958,13 @@ function optionValueAttr(value) {
1968
1958
  var kSelectedValue = Symbol("selectedValue");
1969
1959
  function controllable_select_value(scopeId, nodeAccessor, value, valueChange, renderBody) {
1970
1960
  if (valueChange) {
1971
- const scope = ensureScopeWithId(scopeId);
1972
- scope[nodeAccessor + ":" /* ControlledValue */] = value;
1973
- scope[nodeAccessor + ";" /* ControlledHandler */] = valueChange;
1974
- scope[nodeAccessor + "=" /* ControlledType */] = 3 /* SelectValue */;
1961
+ writeControlledScope(
1962
+ 3 /* SelectValue */,
1963
+ scopeId,
1964
+ nodeAccessor,
1965
+ value,
1966
+ valueChange
1967
+ );
1975
1968
  }
1976
1969
  if (renderBody) {
1977
1970
  withContext(kSelectedValue, value, renderBody);
@@ -1979,25 +1972,37 @@ function controllable_select_value(scopeId, nodeAccessor, value, valueChange, re
1979
1972
  }
1980
1973
  function controllable_textarea_value(scopeId, nodeAccessor, value, valueChange) {
1981
1974
  if (valueChange) {
1982
- const scope = ensureScopeWithId(scopeId);
1983
- scope[nodeAccessor + ";" /* ControlledHandler */] = valueChange;
1984
- scope[nodeAccessor + "=" /* ControlledType */] = 2 /* InputValue */;
1975
+ writeControlledScope(
1976
+ 2 /* InputValue */,
1977
+ scopeId,
1978
+ nodeAccessor,
1979
+ void 0,
1980
+ valueChange
1981
+ );
1985
1982
  }
1986
1983
  return escapeTextAreaValue(value);
1987
1984
  }
1988
1985
  function controllable_input_value(scopeId, nodeAccessor, value, valueChange) {
1989
1986
  if (valueChange) {
1990
- const scope = ensureScopeWithId(scopeId);
1991
- scope[nodeAccessor + ";" /* ControlledHandler */] = valueChange;
1992
- scope[nodeAccessor + "=" /* ControlledType */] = 2 /* InputValue */;
1987
+ writeControlledScope(
1988
+ 2 /* InputValue */,
1989
+ scopeId,
1990
+ nodeAccessor,
1991
+ void 0,
1992
+ valueChange
1993
+ );
1993
1994
  }
1994
1995
  return attr("value", value);
1995
1996
  }
1996
1997
  function controllable_input_checked(scopeId, nodeAccessor, checked, checkedChange) {
1997
1998
  if (checkedChange) {
1998
- const scope = ensureScopeWithId(scopeId);
1999
- scope[nodeAccessor + ";" /* ControlledHandler */] = checkedChange;
2000
- scope[nodeAccessor + "=" /* ControlledType */] = 0 /* InputChecked */;
1999
+ writeControlledScope(
2000
+ 0 /* InputChecked */,
2001
+ scopeId,
2002
+ nodeAccessor,
2003
+ void 0,
2004
+ checkedChange
2005
+ );
2001
2006
  }
2002
2007
  return attr("checked", checked);
2003
2008
  }
@@ -2005,21 +2010,25 @@ function controllable_input_checkedValue(scopeId, nodeAccessor, checkedValue, ch
2005
2010
  const multiple = Array.isArray(checkedValue);
2006
2011
  const valueAttr = attr("value", value);
2007
2012
  if (checkedValueChange) {
2008
- const scope = ensureScopeWithId(scopeId);
2009
- scope[nodeAccessor + ";" /* ControlledHandler */] = checkedValueChange;
2010
- scope[nodeAccessor + "=" /* ControlledType */] = 1 /* InputCheckedValue */;
2011
- if (multiple) {
2012
- scope[nodeAccessor + ":" /* ControlledValue */] = checkedValue;
2013
- }
2013
+ writeControlledScope(
2014
+ 1 /* InputCheckedValue */,
2015
+ scopeId,
2016
+ nodeAccessor,
2017
+ multiple ? checkedValue : void 0,
2018
+ checkedValueChange
2019
+ );
2014
2020
  }
2015
2021
  return (multiple ? checkedValue.includes(value) : checkedValue === value) ? valueAttr + " checked" : valueAttr;
2016
2022
  }
2017
2023
  function controllable_detailsOrDialog_open(scopeId, nodeAccessor, open, openChange) {
2018
2024
  if (openChange) {
2019
- const scope = ensureScopeWithId(scopeId);
2020
- scope[nodeAccessor + ":" /* ControlledValue */] = open;
2021
- scope[nodeAccessor + ";" /* ControlledHandler */] = openChange;
2022
- scope[nodeAccessor + "=" /* ControlledType */] = 4 /* DetailsOrDialogOpen */;
2025
+ writeControlledScope(
2026
+ 4 /* DetailsOrDialogOpen */,
2027
+ scopeId,
2028
+ nodeAccessor,
2029
+ open,
2030
+ openChange
2031
+ );
2023
2032
  }
2024
2033
  return attr("open", open);
2025
2034
  }
@@ -2099,7 +2108,13 @@ function attrs(data, nodeAccessor, scopeId, tagName) {
2099
2108
  default:
2100
2109
  if (!isVoid(val)) {
2101
2110
  if (isEventHandler(name)) {
2102
- (events ||= ensureScopeWithId(scopeId)[nodeAccessor + "~" /* EventAttributes */] = {})[getEventHandlerName(name)] = val;
2111
+ if (!events) {
2112
+ events = {};
2113
+ writeScope(scopeId, {
2114
+ [nodeAccessor + "~" /* EventAttributes */]: events
2115
+ });
2116
+ }
2117
+ events[getEventHandlerName(name)] = val;
2103
2118
  } else if (!skip.test(name)) {
2104
2119
  result += nonVoidAttr(name, val);
2105
2120
  }
@@ -2116,6 +2131,13 @@ function partialAttrs(data, skip, nodeAccessor, scopeId, tagName) {
2116
2131
  }
2117
2132
  return attrs(partial, nodeAccessor, scopeId, tagName);
2118
2133
  }
2134
+ function writeControlledScope(type, scopeId, nodeAccessor, value, valueChange) {
2135
+ writeScope(scopeId, {
2136
+ [nodeAccessor + "=" /* ControlledType */]: type,
2137
+ [nodeAccessor + ":" /* ControlledValue */]: value,
2138
+ [nodeAccessor + ";" /* ControlledHandler */]: valueChange
2139
+ });
2140
+ }
2119
2141
  function stringAttr(name, val) {
2120
2142
  return val && ` ${name}=${escapeAttrValue(val)}`;
2121
2143
  }
@@ -2326,6 +2348,51 @@ var compat = {
2326
2348
  }
2327
2349
  };
2328
2350
 
2351
+ // src/common/for.ts
2352
+ function forIn(obj, cb) {
2353
+ for (const key in obj) {
2354
+ cb(key, obj[key]);
2355
+ }
2356
+ }
2357
+ function forOf(list, cb) {
2358
+ if (list) {
2359
+ let i = 0;
2360
+ for (const item of list) {
2361
+ cb(item, i++);
2362
+ }
2363
+ }
2364
+ }
2365
+ function forTo(to, from, step, cb) {
2366
+ const start = from || 0;
2367
+ const delta = step || 1;
2368
+ for (let steps = (to - start) / delta, i = 0; i <= steps; i++) {
2369
+ cb(start + i * delta);
2370
+ }
2371
+ }
2372
+
2373
+ // src/html/for.ts
2374
+ function forOfBy(by, item, index) {
2375
+ if (by) {
2376
+ if (typeof by === "string") {
2377
+ return item[by];
2378
+ }
2379
+ return by(item, index);
2380
+ }
2381
+ return index;
2382
+ }
2383
+ function forInBy(by, name, value) {
2384
+ if (by) {
2385
+ return by(name, value);
2386
+ }
2387
+ return name;
2388
+ }
2389
+ function forToBy(by, index) {
2390
+ if (by) {
2391
+ return by(index);
2392
+ }
2393
+ return index;
2394
+ }
2395
+
2329
2396
  // src/html/template.ts
2330
2397
  var createTemplate = (templateId, renderer) => {
2331
2398
  renderer.render = render;
@@ -2489,7 +2556,7 @@ var ServerRenderResult = class {
2489
2556
  reject(boundary.signal.reason);
2490
2557
  } else {
2491
2558
  head = prepareChunk(head);
2492
- if (boundary.done) resolve(flushChunk(head));
2559
+ if (boundary.done) resolve(flushChunk(head, true));
2493
2560
  }
2494
2561
  }
2495
2562
  })();
@@ -2514,7 +2581,7 @@ var ServerRenderResult = class {
2514
2581
  head = prepareChunk(head);
2515
2582
  }
2516
2583
  if (write2 || boundary.done) {
2517
- const html = flushChunk(head);
2584
+ const html = flushChunk(head, boundary.done);
2518
2585
  if (html) onWrite(html);
2519
2586
  if (boundary.done) {
2520
2587
  if (!tick2) offTick(onNext);
@@ -2535,7 +2602,7 @@ var ServerRenderResult = class {
2535
2602
  if (!head) throw new Error("Cannot read from a consumed render result");
2536
2603
  if (head.next) throw new Error("Cannot fork in sync mode");
2537
2604
  this.#head = null;
2538
- return flushChunk(prepareChunk(head));
2605
+ return flushChunk(prepareChunk(head), true);
2539
2606
  }
2540
2607
  };
2541
2608
  export {
@@ -2561,8 +2628,11 @@ export {
2561
2628
  escapeStyle,
2562
2629
  escapeXML,
2563
2630
  forIn,
2631
+ forInBy,
2564
2632
  forOf,
2633
+ forOfBy,
2565
2634
  forTo,
2635
+ forToBy,
2566
2636
  fork,
2567
2637
  getScopeById,
2568
2638
  markResumeCleanup,
@@ -2585,5 +2655,6 @@ export {
2585
2655
  write,
2586
2656
  writeEffect,
2587
2657
  writeExistingScope,
2588
- writeScope
2658
+ writeScope,
2659
+ writeTrailers
2589
2660
  };
package/dist/dom.js CHANGED
@@ -299,11 +299,11 @@ function nodeRef(id, key) {
299
299
  // src/dom/signals.ts
300
300
  var MARK = {}, CLEAN = {}, DIRTY = {};
301
301
  function state(valueAccessor, fn, getIntersection) {
302
- let valueSignal = value(valueAccessor, fn, getIntersection), markAccessor = valueAccessor + "#" /* Mark */;
302
+ let valueSignal = value(valueAccessor, fn, getIntersection), markAccessor = valueAccessor + "#" /* Mark */, valueChangeAccessor = valueAccessor + "@" /* TagVariableChange */;
303
303
  return (scope, valueOrOp, valueChange) => (rendering ? valueSignal(
304
304
  scope,
305
- valueOrOp === MARK || valueOrOp === CLEAN || valueOrOp === DIRTY || valueChange || scope[markAccessor] === void 0 ? valueOrOp : CLEAN
306
- ) : valueChange ? valueChange(valueOrOp) : queueSource(scope, valueSignal, valueOrOp), valueOrOp);
305
+ valueOrOp === MARK || valueOrOp === CLEAN || valueOrOp === DIRTY || (scope[valueChangeAccessor] = valueChange) || scope[markAccessor] === void 0 ? valueOrOp : CLEAN
306
+ ) : scope[valueChangeAccessor] ? scope[valueChangeAccessor](valueOrOp) : queueSource(scope, valueSignal, valueOrOp), valueOrOp);
307
307
  }
308
308
  function value(valueAccessor, fn, getIntersection) {
309
309
  let markAccessor = valueAccessor + "#" /* Mark */, intersection2 = getIntersection && ((scope, op) => (intersection2 = getIntersection())(scope, op));
package/dist/dom.mjs CHANGED
@@ -213,11 +213,11 @@ function nodeRef(id, key) {
213
213
  // src/dom/signals.ts
214
214
  var MARK = {}, CLEAN = {}, DIRTY = {};
215
215
  function state(valueAccessor, fn, getIntersection) {
216
- let valueSignal = value(valueAccessor, fn, getIntersection), markAccessor = valueAccessor + "#" /* Mark */;
216
+ let valueSignal = value(valueAccessor, fn, getIntersection), markAccessor = valueAccessor + "#" /* Mark */, valueChangeAccessor = valueAccessor + "@" /* TagVariableChange */;
217
217
  return (scope, valueOrOp, valueChange) => (rendering ? valueSignal(
218
218
  scope,
219
- valueOrOp === MARK || valueOrOp === CLEAN || valueOrOp === DIRTY || valueChange || scope[markAccessor] === void 0 ? valueOrOp : CLEAN
220
- ) : valueChange ? valueChange(valueOrOp) : queueSource(scope, valueSignal, valueOrOp), valueOrOp);
219
+ valueOrOp === MARK || valueOrOp === CLEAN || valueOrOp === DIRTY || (scope[valueChangeAccessor] = valueChange) || scope[markAccessor] === void 0 ? valueOrOp : CLEAN
220
+ ) : scope[valueChangeAccessor] ? scope[valueChangeAccessor](valueOrOp) : queueSource(scope, valueSignal, valueOrOp), valueOrOp);
221
221
  }
222
222
  function value(valueAccessor, fn, getIntersection) {
223
223
  let markAccessor = valueAccessor + "#" /* Mark */, intersection2 = getIntersection && ((scope, op) => (intersection2 = getIntersection())(scope, op));
@@ -0,0 +1,4 @@
1
+ export { forIn, forOf, forTo } from "../common/for";
2
+ export declare function forOfBy(by: unknown, item: any, index: unknown): any;
3
+ export declare function forInBy(by: unknown, name: string, value: unknown): any;
4
+ export declare function forToBy(by: unknown, index: number): any;
@@ -56,6 +56,7 @@ export declare class State {
56
56
  hasMainRuntime: boolean;
57
57
  hasReorderRuntime: boolean;
58
58
  hasWrittenResume: boolean;
59
+ trailerHTML: string;
59
60
  serializer: Serializer;
60
61
  writeReorders: Chunk[] | null;
61
62
  scopes: Map<number, PartialScope>;
@@ -104,7 +105,8 @@ export declare class Chunk {
104
105
  render<T>(renderBody: (val: T) => void, val: T): Chunk;
105
106
  }
106
107
  export declare function prepareChunk(chunk: Chunk): Chunk;
107
- export declare function flushChunk(head: Chunk): string;
108
+ export declare function flushChunk(head: Chunk, last: boolean): string;
109
+ export declare function writeTrailers(html: string): void;
108
110
  type QueueCallback = (ticked: true) => void;
109
111
  export declare function queueTick(cb: QueueCallback): void;
110
112
  export declare function offTick(cb: QueueCallback): void;
package/dist/html.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  export { attrTag, attrTags } from "./common/attr-tag";
2
- export { forIn, forOf, forTo } from "./common/for";
3
2
  export { normalizeDynamicRenderer } from "./common/helpers";
4
3
  export { attr, attrs, classAttr, controllable_detailsOrDialog_open, controllable_input_checked, controllable_input_checkedValue, controllable_input_value, controllable_select_value, controllable_textarea_value, optionValueAttr, partialAttrs, styleAttr, } from "./html/attrs";
5
4
  export { compat } from "./html/compat";
6
5
  export { escapeScript, escapeStyle, escapeXML, toString } from "./html/content";
7
6
  export { createRenderer, dynamicTagArgs, dynamicTagInput, } from "./html/dynamic-tag";
7
+ export { forIn, forInBy, forOf, forOfBy, forTo, forToBy } from "./html/for";
8
8
  export { createTemplate } from "./html/template";
9
- export { $global, ensureScopeWithId, fork, getScopeById, markResumeCleanup, markResumeControlEnd, markResumeControlSingleNodeEnd, markResumeNode, markResumeScopeStart, nextScopeId, nextTagId, nodeRef, peekNextScope, register, tryCatch, tryPlaceholder, write, writeEffect, writeExistingScope, writeScope, } from "./html/writer";
9
+ export { $global, ensureScopeWithId, fork, getScopeById, markResumeCleanup, markResumeControlEnd, markResumeControlSingleNodeEnd, markResumeNode, markResumeScopeStart, nextScopeId, nextTagId, nodeRef, peekNextScope, register, tryCatch, tryPlaceholder, write, writeEffect, writeExistingScope, writeScope, writeTrailers, } from "./html/writer";
package/dist/html.js CHANGED
@@ -39,8 +39,11 @@ __export(html_exports, {
39
39
  escapeStyle: () => escapeStyle,
40
40
  escapeXML: () => escapeXML,
41
41
  forIn: () => forIn,
42
+ forInBy: () => forInBy,
42
43
  forOf: () => forOf,
44
+ forOfBy: () => forOfBy,
43
45
  forTo: () => forTo,
46
+ forToBy: () => forToBy,
44
47
  fork: () => fork,
45
48
  getScopeById: () => getScopeById,
46
49
  markResumeCleanup: () => markResumeCleanup,
@@ -63,7 +66,8 @@ __export(html_exports, {
63
66
  write: () => write,
64
67
  writeEffect: () => writeEffect,
65
68
  writeExistingScope: () => writeExistingScope,
66
- writeScope: () => writeScope
69
+ writeScope: () => writeScope,
70
+ writeTrailers: () => writeTrailers
67
71
  });
68
72
  module.exports = __toCommonJS(html_exports);
69
73
 
@@ -79,24 +83,6 @@ function* attrTagIterator() {
79
83
  yield this, yield* this[rest];
80
84
  }
81
85
 
82
- // src/common/for.ts
83
- function forIn(obj, cb) {
84
- for (let key in obj)
85
- cb(key, obj[key]);
86
- }
87
- function forOf(list, cb) {
88
- if (list) {
89
- let i = 0;
90
- for (let item of list)
91
- cb(item, i++);
92
- }
93
- }
94
- function forTo(to, from, step, cb) {
95
- let start = from || 0, delta = step || 1;
96
- for (let steps = (to - start) / delta, i = 0; i <= steps; i++)
97
- cb(start + i * delta);
98
- }
99
-
100
86
  // src/common/helpers.ts
101
87
  function classValue(value) {
102
88
  return toDelimitedString(value, " ", stringifyClassObject);
@@ -1119,6 +1105,7 @@ var State2 = class {
1119
1105
  hasMainRuntime = !1;
1120
1106
  hasReorderRuntime = !1;
1121
1107
  hasWrittenResume = !1;
1108
+ trailerHTML = "";
1122
1109
  serializer = new Serializer();
1123
1110
  writeReorders = null;
1124
1111
  scopes = /* @__PURE__ */ new Map();
@@ -1272,9 +1259,12 @@ function prepareChunk(chunk) {
1272
1259
  }
1273
1260
  return hasWalk && (scripts = concatScripts(scripts, runtimePrefix + ".w()")), head.html = html, head.scripts = scripts, head;
1274
1261
  }
1275
- function flushChunk(head) {
1276
- let { html, scripts } = head, { $global: $global2 } = head.boundary.state, { __flush__ } = $global2, result = scripts ? html + "<script" + (head.boundary.state.$global.cspNonce ? " nonce=" + escapeAttrValue(head.boundary.state.$global.cspNonce + "") : "") + ">" + scripts + "</script>" : html;
1277
- return head.html = head.scripts = "", __flush__ ? ($global2.__flush__ = void 0, __flush__($global2, result)) : result;
1262
+ function flushChunk(head, last) {
1263
+ let { boundary } = head, { state } = boundary, { html, scripts } = head, { $global: $global2 } = state, { __flush__ } = $global2, result = html;
1264
+ return head.html = head.scripts = "", scripts && (result += ($global2.cspNonce ? "<script nonce=" + escapeAttrValue($global2.cspNonce + "") + ">" : "<script>") + scripts + "</script>"), __flush__ && ($global2.__flush__ = void 0, result = __flush__($global2, result)), last && state.trailerHTML && (result += state.trailerHTML), result;
1265
+ }
1266
+ function writeTrailers(html) {
1267
+ $chunk.boundary.state.trailerHTML += html;
1278
1268
  }
1279
1269
  function concatEffects(a, b) {
1280
1270
  return a ? b ? a + "," + b : a : b;
@@ -1330,47 +1320,59 @@ function optionValueAttr(value) {
1330
1320
  }
1331
1321
  var kSelectedValue = Symbol("selectedValue");
1332
1322
  function controllable_select_value(scopeId, nodeAccessor, value, valueChange, renderBody) {
1333
- if (valueChange) {
1334
- let scope = ensureScopeWithId(scopeId);
1335
- scope[nodeAccessor + ":" /* ControlledValue */] = value, scope[nodeAccessor + ";" /* ControlledHandler */] = valueChange, scope[nodeAccessor + "=" /* ControlledType */] = 3 /* SelectValue */;
1336
- }
1337
- renderBody && withContext(kSelectedValue, value, renderBody);
1323
+ valueChange && writeControlledScope(
1324
+ 3 /* SelectValue */,
1325
+ scopeId,
1326
+ nodeAccessor,
1327
+ value,
1328
+ valueChange
1329
+ ), renderBody && withContext(kSelectedValue, value, renderBody);
1338
1330
  }
1339
1331
  function controllable_textarea_value(scopeId, nodeAccessor, value, valueChange) {
1340
- if (valueChange) {
1341
- let scope = ensureScopeWithId(scopeId);
1342
- scope[nodeAccessor + ";" /* ControlledHandler */] = valueChange, scope[nodeAccessor + "=" /* ControlledType */] = 2 /* InputValue */;
1343
- }
1344
- return escapeTextAreaValue(value);
1332
+ return valueChange && writeControlledScope(
1333
+ 2 /* InputValue */,
1334
+ scopeId,
1335
+ nodeAccessor,
1336
+ void 0,
1337
+ valueChange
1338
+ ), escapeTextAreaValue(value);
1345
1339
  }
1346
1340
  function controllable_input_value(scopeId, nodeAccessor, value, valueChange) {
1347
- if (valueChange) {
1348
- let scope = ensureScopeWithId(scopeId);
1349
- scope[nodeAccessor + ";" /* ControlledHandler */] = valueChange, scope[nodeAccessor + "=" /* ControlledType */] = 2 /* InputValue */;
1350
- }
1351
- return attr("value", value);
1341
+ return valueChange && writeControlledScope(
1342
+ 2 /* InputValue */,
1343
+ scopeId,
1344
+ nodeAccessor,
1345
+ void 0,
1346
+ valueChange
1347
+ ), attr("value", value);
1352
1348
  }
1353
1349
  function controllable_input_checked(scopeId, nodeAccessor, checked, checkedChange) {
1354
- if (checkedChange) {
1355
- let scope = ensureScopeWithId(scopeId);
1356
- scope[nodeAccessor + ";" /* ControlledHandler */] = checkedChange, scope[nodeAccessor + "=" /* ControlledType */] = 0 /* InputChecked */;
1357
- }
1358
- return attr("checked", checked);
1350
+ return checkedChange && writeControlledScope(
1351
+ 0 /* InputChecked */,
1352
+ scopeId,
1353
+ nodeAccessor,
1354
+ void 0,
1355
+ checkedChange
1356
+ ), attr("checked", checked);
1359
1357
  }
1360
1358
  function controllable_input_checkedValue(scopeId, nodeAccessor, checkedValue, checkedValueChange, value) {
1361
1359
  let multiple = Array.isArray(checkedValue), valueAttr = attr("value", value);
1362
- if (checkedValueChange) {
1363
- let scope = ensureScopeWithId(scopeId);
1364
- scope[nodeAccessor + ";" /* ControlledHandler */] = checkedValueChange, scope[nodeAccessor + "=" /* ControlledType */] = 1 /* InputCheckedValue */, multiple && (scope[nodeAccessor + ":" /* ControlledValue */] = checkedValue);
1365
- }
1366
- return (multiple ? checkedValue.includes(value) : checkedValue === value) ? valueAttr + " checked" : valueAttr;
1360
+ return checkedValueChange && writeControlledScope(
1361
+ 1 /* InputCheckedValue */,
1362
+ scopeId,
1363
+ nodeAccessor,
1364
+ multiple ? checkedValue : void 0,
1365
+ checkedValueChange
1366
+ ), (multiple ? checkedValue.includes(value) : checkedValue === value) ? valueAttr + " checked" : valueAttr;
1367
1367
  }
1368
1368
  function controllable_detailsOrDialog_open(scopeId, nodeAccessor, open, openChange) {
1369
- if (openChange) {
1370
- let scope = ensureScopeWithId(scopeId);
1371
- scope[nodeAccessor + ":" /* ControlledValue */] = open, scope[nodeAccessor + ";" /* ControlledHandler */] = openChange, scope[nodeAccessor + "=" /* ControlledType */] = 4 /* DetailsOrDialogOpen */;
1372
- }
1373
- return attr("open", open);
1369
+ return openChange && writeControlledScope(
1370
+ 4 /* DetailsOrDialogOpen */,
1371
+ scopeId,
1372
+ nodeAccessor,
1373
+ open,
1374
+ openChange
1375
+ ), attr("open", open);
1374
1376
  }
1375
1377
  function attr(name, val) {
1376
1378
  return isVoid(val) ? "" : nonVoidAttr(name, val);
@@ -1435,7 +1437,9 @@ function attrs(data, nodeAccessor, scopeId, tagName) {
1435
1437
  case "renderBody":
1436
1438
  break;
1437
1439
  default:
1438
- isVoid(val) || (isEventHandler(name) ? (events ||= ensureScopeWithId(scopeId)[nodeAccessor + "~" /* EventAttributes */] = {})[getEventHandlerName(name)] = val : skip.test(name) || (result += nonVoidAttr(name, val)));
1440
+ isVoid(val) || (isEventHandler(name) ? (events || (events = {}, writeScope(scopeId, {
1441
+ [nodeAccessor + "~" /* EventAttributes */]: events
1442
+ })), events[getEventHandlerName(name)] = val) : skip.test(name) || (result += nonVoidAttr(name, val)));
1439
1443
  break;
1440
1444
  }
1441
1445
  }
@@ -1447,6 +1451,13 @@ function partialAttrs(data, skip, nodeAccessor, scopeId, tagName) {
1447
1451
  skip[key] || (partial[key] = data[key]);
1448
1452
  return attrs(partial, nodeAccessor, scopeId, tagName);
1449
1453
  }
1454
+ function writeControlledScope(type, scopeId, nodeAccessor, value, valueChange) {
1455
+ writeScope(scopeId, {
1456
+ [nodeAccessor + "=" /* ControlledType */]: type,
1457
+ [nodeAccessor + ":" /* ControlledValue */]: value,
1458
+ [nodeAccessor + ";" /* ControlledHandler */]: valueChange
1459
+ });
1460
+ }
1450
1461
  function stringAttr(name, val) {
1451
1462
  return val && ` ${name}=${escapeAttrValue(val)}`;
1452
1463
  }
@@ -1579,6 +1590,35 @@ var K_TAGS_API_STATE = Symbol(), COMPAT_REGISTRY = /* @__PURE__ */ new WeakMap()
1579
1590
  }
1580
1591
  };
1581
1592
 
1593
+ // src/common/for.ts
1594
+ function forIn(obj, cb) {
1595
+ for (let key in obj)
1596
+ cb(key, obj[key]);
1597
+ }
1598
+ function forOf(list, cb) {
1599
+ if (list) {
1600
+ let i = 0;
1601
+ for (let item of list)
1602
+ cb(item, i++);
1603
+ }
1604
+ }
1605
+ function forTo(to, from, step, cb) {
1606
+ let start = from || 0, delta = step || 1;
1607
+ for (let steps = (to - start) / delta, i = 0; i <= steps; i++)
1608
+ cb(start + i * delta);
1609
+ }
1610
+
1611
+ // src/html/for.ts
1612
+ function forOfBy(by, item, index) {
1613
+ return by ? typeof by == "string" ? item[by] : by(item, index) : index;
1614
+ }
1615
+ function forInBy(by, name, value) {
1616
+ return by ? by(name, value) : name;
1617
+ }
1618
+ function forToBy(by, index) {
1619
+ return by ? by(index) : index;
1620
+ }
1621
+
1582
1622
  // src/html/template.ts
1583
1623
  var createTemplate = (templateId, renderer) => (renderer.render = render, renderer._ = renderer, register2(renderer, templateId));
1584
1624
  function render(input = {}) {
@@ -1689,7 +1729,7 @@ var ServerRenderResult = class {
1689
1729
  return reject(new Error("Cannot read from a consumed render result"));
1690
1730
  let { boundary } = head;
1691
1731
  (boundary.onNext = () => {
1692
- boundary.done && (boundary.signal.aborted ? reject(boundary.signal.reason) : (head = prepareChunk(head), boundary.done && resolve(flushChunk(head))));
1732
+ boundary.done && (boundary.signal.aborted ? reject(boundary.signal.reason) : (head = prepareChunk(head), boundary.done && resolve(flushChunk(head, !0))));
1693
1733
  })();
1694
1734
  });
1695
1735
  }
@@ -1708,7 +1748,7 @@ var ServerRenderResult = class {
1708
1748
  head = prepareChunk(head);
1709
1749
  }
1710
1750
  if (write2 || boundary.done) {
1711
- let html = flushChunk(head);
1751
+ let html = flushChunk(head, boundary.done);
1712
1752
  html && onWrite(html), boundary.done ? (tick2 || offTick(onNext), onClose()) : tick2 = !0;
1713
1753
  } else tick2 && (tick2 = !1, queueTick(onNext));
1714
1754
  };
@@ -1718,7 +1758,7 @@ var ServerRenderResult = class {
1718
1758
  let head = this.#head;
1719
1759
  if (!head) throw new Error("Cannot read from a consumed render result");
1720
1760
  if (head.next) throw new Error("Cannot fork in sync mode");
1721
- return this.#head = null, flushChunk(prepareChunk(head));
1761
+ return this.#head = null, flushChunk(prepareChunk(head), !0);
1722
1762
  }
1723
1763
  };
1724
1764
  // Annotate the CommonJS export names for ESM import in node:
@@ -1745,8 +1785,11 @@ var ServerRenderResult = class {
1745
1785
  escapeStyle,
1746
1786
  escapeXML,
1747
1787
  forIn,
1788
+ forInBy,
1748
1789
  forOf,
1790
+ forOfBy,
1749
1791
  forTo,
1792
+ forToBy,
1750
1793
  fork,
1751
1794
  getScopeById,
1752
1795
  markResumeCleanup,
@@ -1769,5 +1812,6 @@ var ServerRenderResult = class {
1769
1812
  write,
1770
1813
  writeEffect,
1771
1814
  writeExistingScope,
1772
- writeScope
1815
+ writeScope,
1816
+ writeTrailers
1773
1817
  });
package/dist/html.mjs CHANGED
@@ -10,24 +10,6 @@ function* attrTagIterator() {
10
10
  yield this, yield* this[rest];
11
11
  }
12
12
 
13
- // src/common/for.ts
14
- function forIn(obj, cb) {
15
- for (let key in obj)
16
- cb(key, obj[key]);
17
- }
18
- function forOf(list, cb) {
19
- if (list) {
20
- let i = 0;
21
- for (let item of list)
22
- cb(item, i++);
23
- }
24
- }
25
- function forTo(to, from, step, cb) {
26
- let start = from || 0, delta = step || 1;
27
- for (let steps = (to - start) / delta, i = 0; i <= steps; i++)
28
- cb(start + i * delta);
29
- }
30
-
31
13
  // src/common/helpers.ts
32
14
  function classValue(value) {
33
15
  return toDelimitedString(value, " ", stringifyClassObject);
@@ -1050,6 +1032,7 @@ var State2 = class {
1050
1032
  hasMainRuntime = !1;
1051
1033
  hasReorderRuntime = !1;
1052
1034
  hasWrittenResume = !1;
1035
+ trailerHTML = "";
1053
1036
  serializer = new Serializer();
1054
1037
  writeReorders = null;
1055
1038
  scopes = /* @__PURE__ */ new Map();
@@ -1203,9 +1186,12 @@ function prepareChunk(chunk) {
1203
1186
  }
1204
1187
  return hasWalk && (scripts = concatScripts(scripts, runtimePrefix + ".w()")), head.html = html, head.scripts = scripts, head;
1205
1188
  }
1206
- function flushChunk(head) {
1207
- let { html, scripts } = head, { $global: $global2 } = head.boundary.state, { __flush__ } = $global2, result = scripts ? html + "<script" + (head.boundary.state.$global.cspNonce ? " nonce=" + escapeAttrValue(head.boundary.state.$global.cspNonce + "") : "") + ">" + scripts + "</script>" : html;
1208
- return head.html = head.scripts = "", __flush__ ? ($global2.__flush__ = void 0, __flush__($global2, result)) : result;
1189
+ function flushChunk(head, last) {
1190
+ let { boundary } = head, { state } = boundary, { html, scripts } = head, { $global: $global2 } = state, { __flush__ } = $global2, result = html;
1191
+ return head.html = head.scripts = "", scripts && (result += ($global2.cspNonce ? "<script nonce=" + escapeAttrValue($global2.cspNonce + "") + ">" : "<script>") + scripts + "</script>"), __flush__ && ($global2.__flush__ = void 0, result = __flush__($global2, result)), last && state.trailerHTML && (result += state.trailerHTML), result;
1192
+ }
1193
+ function writeTrailers(html) {
1194
+ $chunk.boundary.state.trailerHTML += html;
1209
1195
  }
1210
1196
  function concatEffects(a, b) {
1211
1197
  return a ? b ? a + "," + b : a : b;
@@ -1261,47 +1247,59 @@ function optionValueAttr(value) {
1261
1247
  }
1262
1248
  var kSelectedValue = Symbol("selectedValue");
1263
1249
  function controllable_select_value(scopeId, nodeAccessor, value, valueChange, renderBody) {
1264
- if (valueChange) {
1265
- let scope = ensureScopeWithId(scopeId);
1266
- scope[nodeAccessor + ":" /* ControlledValue */] = value, scope[nodeAccessor + ";" /* ControlledHandler */] = valueChange, scope[nodeAccessor + "=" /* ControlledType */] = 3 /* SelectValue */;
1267
- }
1268
- renderBody && withContext(kSelectedValue, value, renderBody);
1250
+ valueChange && writeControlledScope(
1251
+ 3 /* SelectValue */,
1252
+ scopeId,
1253
+ nodeAccessor,
1254
+ value,
1255
+ valueChange
1256
+ ), renderBody && withContext(kSelectedValue, value, renderBody);
1269
1257
  }
1270
1258
  function controllable_textarea_value(scopeId, nodeAccessor, value, valueChange) {
1271
- if (valueChange) {
1272
- let scope = ensureScopeWithId(scopeId);
1273
- scope[nodeAccessor + ";" /* ControlledHandler */] = valueChange, scope[nodeAccessor + "=" /* ControlledType */] = 2 /* InputValue */;
1274
- }
1275
- return escapeTextAreaValue(value);
1259
+ return valueChange && writeControlledScope(
1260
+ 2 /* InputValue */,
1261
+ scopeId,
1262
+ nodeAccessor,
1263
+ void 0,
1264
+ valueChange
1265
+ ), escapeTextAreaValue(value);
1276
1266
  }
1277
1267
  function controllable_input_value(scopeId, nodeAccessor, value, valueChange) {
1278
- if (valueChange) {
1279
- let scope = ensureScopeWithId(scopeId);
1280
- scope[nodeAccessor + ";" /* ControlledHandler */] = valueChange, scope[nodeAccessor + "=" /* ControlledType */] = 2 /* InputValue */;
1281
- }
1282
- return attr("value", value);
1268
+ return valueChange && writeControlledScope(
1269
+ 2 /* InputValue */,
1270
+ scopeId,
1271
+ nodeAccessor,
1272
+ void 0,
1273
+ valueChange
1274
+ ), attr("value", value);
1283
1275
  }
1284
1276
  function controllable_input_checked(scopeId, nodeAccessor, checked, checkedChange) {
1285
- if (checkedChange) {
1286
- let scope = ensureScopeWithId(scopeId);
1287
- scope[nodeAccessor + ";" /* ControlledHandler */] = checkedChange, scope[nodeAccessor + "=" /* ControlledType */] = 0 /* InputChecked */;
1288
- }
1289
- return attr("checked", checked);
1277
+ return checkedChange && writeControlledScope(
1278
+ 0 /* InputChecked */,
1279
+ scopeId,
1280
+ nodeAccessor,
1281
+ void 0,
1282
+ checkedChange
1283
+ ), attr("checked", checked);
1290
1284
  }
1291
1285
  function controllable_input_checkedValue(scopeId, nodeAccessor, checkedValue, checkedValueChange, value) {
1292
1286
  let multiple = Array.isArray(checkedValue), valueAttr = attr("value", value);
1293
- if (checkedValueChange) {
1294
- let scope = ensureScopeWithId(scopeId);
1295
- scope[nodeAccessor + ";" /* ControlledHandler */] = checkedValueChange, scope[nodeAccessor + "=" /* ControlledType */] = 1 /* InputCheckedValue */, multiple && (scope[nodeAccessor + ":" /* ControlledValue */] = checkedValue);
1296
- }
1297
- return (multiple ? checkedValue.includes(value) : checkedValue === value) ? valueAttr + " checked" : valueAttr;
1287
+ return checkedValueChange && writeControlledScope(
1288
+ 1 /* InputCheckedValue */,
1289
+ scopeId,
1290
+ nodeAccessor,
1291
+ multiple ? checkedValue : void 0,
1292
+ checkedValueChange
1293
+ ), (multiple ? checkedValue.includes(value) : checkedValue === value) ? valueAttr + " checked" : valueAttr;
1298
1294
  }
1299
1295
  function controllable_detailsOrDialog_open(scopeId, nodeAccessor, open, openChange) {
1300
- if (openChange) {
1301
- let scope = ensureScopeWithId(scopeId);
1302
- scope[nodeAccessor + ":" /* ControlledValue */] = open, scope[nodeAccessor + ";" /* ControlledHandler */] = openChange, scope[nodeAccessor + "=" /* ControlledType */] = 4 /* DetailsOrDialogOpen */;
1303
- }
1304
- return attr("open", open);
1296
+ return openChange && writeControlledScope(
1297
+ 4 /* DetailsOrDialogOpen */,
1298
+ scopeId,
1299
+ nodeAccessor,
1300
+ open,
1301
+ openChange
1302
+ ), attr("open", open);
1305
1303
  }
1306
1304
  function attr(name, val) {
1307
1305
  return isVoid(val) ? "" : nonVoidAttr(name, val);
@@ -1366,7 +1364,9 @@ function attrs(data, nodeAccessor, scopeId, tagName) {
1366
1364
  case "renderBody":
1367
1365
  break;
1368
1366
  default:
1369
- isVoid(val) || (isEventHandler(name) ? (events ||= ensureScopeWithId(scopeId)[nodeAccessor + "~" /* EventAttributes */] = {})[getEventHandlerName(name)] = val : skip.test(name) || (result += nonVoidAttr(name, val)));
1367
+ isVoid(val) || (isEventHandler(name) ? (events || (events = {}, writeScope(scopeId, {
1368
+ [nodeAccessor + "~" /* EventAttributes */]: events
1369
+ })), events[getEventHandlerName(name)] = val) : skip.test(name) || (result += nonVoidAttr(name, val)));
1370
1370
  break;
1371
1371
  }
1372
1372
  }
@@ -1378,6 +1378,13 @@ function partialAttrs(data, skip, nodeAccessor, scopeId, tagName) {
1378
1378
  skip[key] || (partial[key] = data[key]);
1379
1379
  return attrs(partial, nodeAccessor, scopeId, tagName);
1380
1380
  }
1381
+ function writeControlledScope(type, scopeId, nodeAccessor, value, valueChange) {
1382
+ writeScope(scopeId, {
1383
+ [nodeAccessor + "=" /* ControlledType */]: type,
1384
+ [nodeAccessor + ":" /* ControlledValue */]: value,
1385
+ [nodeAccessor + ";" /* ControlledHandler */]: valueChange
1386
+ });
1387
+ }
1381
1388
  function stringAttr(name, val) {
1382
1389
  return val && ` ${name}=${escapeAttrValue(val)}`;
1383
1390
  }
@@ -1510,6 +1517,35 @@ var K_TAGS_API_STATE = Symbol(), COMPAT_REGISTRY = /* @__PURE__ */ new WeakMap()
1510
1517
  }
1511
1518
  };
1512
1519
 
1520
+ // src/common/for.ts
1521
+ function forIn(obj, cb) {
1522
+ for (let key in obj)
1523
+ cb(key, obj[key]);
1524
+ }
1525
+ function forOf(list, cb) {
1526
+ if (list) {
1527
+ let i = 0;
1528
+ for (let item of list)
1529
+ cb(item, i++);
1530
+ }
1531
+ }
1532
+ function forTo(to, from, step, cb) {
1533
+ let start = from || 0, delta = step || 1;
1534
+ for (let steps = (to - start) / delta, i = 0; i <= steps; i++)
1535
+ cb(start + i * delta);
1536
+ }
1537
+
1538
+ // src/html/for.ts
1539
+ function forOfBy(by, item, index) {
1540
+ return by ? typeof by == "string" ? item[by] : by(item, index) : index;
1541
+ }
1542
+ function forInBy(by, name, value) {
1543
+ return by ? by(name, value) : name;
1544
+ }
1545
+ function forToBy(by, index) {
1546
+ return by ? by(index) : index;
1547
+ }
1548
+
1513
1549
  // src/html/template.ts
1514
1550
  var createTemplate = (templateId, renderer) => (renderer.render = render, renderer._ = renderer, register2(renderer, templateId));
1515
1551
  function render(input = {}) {
@@ -1620,7 +1656,7 @@ var ServerRenderResult = class {
1620
1656
  return reject(new Error("Cannot read from a consumed render result"));
1621
1657
  let { boundary } = head;
1622
1658
  (boundary.onNext = () => {
1623
- boundary.done && (boundary.signal.aborted ? reject(boundary.signal.reason) : (head = prepareChunk(head), boundary.done && resolve(flushChunk(head))));
1659
+ boundary.done && (boundary.signal.aborted ? reject(boundary.signal.reason) : (head = prepareChunk(head), boundary.done && resolve(flushChunk(head, !0))));
1624
1660
  })();
1625
1661
  });
1626
1662
  }
@@ -1639,7 +1675,7 @@ var ServerRenderResult = class {
1639
1675
  head = prepareChunk(head);
1640
1676
  }
1641
1677
  if (write2 || boundary.done) {
1642
- let html = flushChunk(head);
1678
+ let html = flushChunk(head, boundary.done);
1643
1679
  html && onWrite(html), boundary.done ? (tick2 || offTick(onNext), onClose()) : tick2 = !0;
1644
1680
  } else tick2 && (tick2 = !1, queueTick(onNext));
1645
1681
  };
@@ -1649,7 +1685,7 @@ var ServerRenderResult = class {
1649
1685
  let head = this.#head;
1650
1686
  if (!head) throw new Error("Cannot read from a consumed render result");
1651
1687
  if (head.next) throw new Error("Cannot fork in sync mode");
1652
- return this.#head = null, flushChunk(prepareChunk(head));
1688
+ return this.#head = null, flushChunk(prepareChunk(head), !0);
1653
1689
  }
1654
1690
  };
1655
1691
  export {
@@ -1675,8 +1711,11 @@ export {
1675
1711
  escapeStyle,
1676
1712
  escapeXML,
1677
1713
  forIn,
1714
+ forInBy,
1678
1715
  forOf,
1716
+ forOfBy,
1679
1717
  forTo,
1718
+ forToBy,
1680
1719
  fork,
1681
1720
  getScopeById,
1682
1721
  markResumeCleanup,
@@ -1699,5 +1738,6 @@ export {
1699
1738
  write,
1700
1739
  writeEffect,
1701
1740
  writeExistingScope,
1702
- writeScope
1741
+ writeScope,
1742
+ writeTrailers
1703
1743
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marko/runtime-tags",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "Optimized runtime for Marko templates.",
5
5
  "keywords": [
6
6
  "api",