marko 6.3.33 → 6.3.35

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.
Files changed (69) hide show
  1. package/cheatsheet.md +37 -33
  2. package/dist/common/constants/accessor-prefix.d.ts +1 -0
  3. package/dist/common/constants/accessor-prefix.debug.d.ts +1 -0
  4. package/dist/common/errors.d.ts +2 -0
  5. package/dist/common/types.d.ts +10 -0
  6. package/dist/debug/dom/catch.feat.js +1 -1
  7. package/dist/debug/dom/catch.feat.mjs +1 -1
  8. package/dist/debug/dom/controllable-input.feat.js +1 -1
  9. package/dist/debug/dom/controllable-input.feat.mjs +1 -1
  10. package/dist/debug/dom/controllable-open.feat.js +1 -1
  11. package/dist/debug/dom/controllable-open.feat.mjs +1 -1
  12. package/dist/debug/dom/controllable-select.feat.js +1 -1
  13. package/dist/debug/dom/controllable-select.feat.mjs +1 -1
  14. package/dist/debug/dom/controllable-textarea.feat.js +1 -1
  15. package/dist/debug/dom/controllable-textarea.feat.mjs +1 -1
  16. package/dist/debug/dom/controllable.feat.js +1 -1
  17. package/dist/debug/dom/controllable.feat.mjs +1 -1
  18. package/dist/debug/{dom-BJ93mcSe.mjs → dom-B57LrRnX.mjs} +89 -46
  19. package/dist/debug/{dom-CiFITSPN.js → dom-Bt4OoZ-j.js} +89 -46
  20. package/dist/debug/dom.js +3 -1
  21. package/dist/debug/dom.mjs +3 -1
  22. package/dist/debug/html.js +205 -98
  23. package/dist/debug/html.mjs +205 -98
  24. package/dist/dom/catch.feat.js +1 -1
  25. package/dist/dom/catch.feat.mjs +1 -1
  26. package/dist/dom/control-flow.d.ts +4 -1
  27. package/dist/dom/controllable-input.feat.js +1 -1
  28. package/dist/dom/controllable-input.feat.mjs +1 -1
  29. package/dist/dom/controllable-open.feat.js +1 -1
  30. package/dist/dom/controllable-open.feat.mjs +1 -1
  31. package/dist/dom/controllable-select.feat.js +1 -1
  32. package/dist/dom/controllable-select.feat.mjs +1 -1
  33. package/dist/dom/controllable-textarea.feat.js +1 -1
  34. package/dist/dom/controllable-textarea.feat.mjs +1 -1
  35. package/dist/dom/controllable.feat.js +1 -1
  36. package/dist/dom/controllable.feat.mjs +1 -1
  37. package/dist/dom/signals.d.ts +3 -3
  38. package/dist/{dom-Cj4HQ7T_.mjs → dom-BP2XSglG.mjs} +46 -33
  39. package/dist/{dom-CI-06TZb.js → dom-BeF9xIzO.js} +46 -33
  40. package/dist/dom.js +3 -1
  41. package/dist/dom.mjs +3 -1
  42. package/dist/html/compat.d.ts +4 -2
  43. package/dist/html/dynamic-tag.d.ts +1 -1
  44. package/dist/html/serializer.d.ts +9 -1
  45. package/dist/html/template.d.ts +1 -0
  46. package/dist/html/writer.d.ts +1 -0
  47. package/dist/html.js +88 -63
  48. package/dist/html.mjs +88 -63
  49. package/dist/translator/core/client.d.ts +1 -2
  50. package/dist/translator/core/server.d.ts +1 -2
  51. package/dist/translator/core/static.d.ts +1 -2
  52. package/dist/translator/index.js +514 -314
  53. package/dist/translator/util/constants/binding-type.d.ts +1 -0
  54. package/dist/translator/util/references.d.ts +8 -1
  55. package/dist/translator/util/serialize-reasons.d.ts +4 -4
  56. package/dist/translator/util/signals.d.ts +5 -0
  57. package/dist/translator/util/statement-tag.d.ts +2 -0
  58. package/dist/translator/util/translate-var.d.ts +1 -1
  59. package/dist/translator/visitors/export-declaration.d.ts +8 -0
  60. package/dist/translator/visitors/program/index.d.ts +0 -1
  61. package/package.json +5 -4
  62. package/tags/html-comment.d.marko +2 -0
  63. package/tags/html-script.d.marko +2 -0
  64. package/tags/html-style.d.marko +2 -0
  65. package/tags/let.d.marko +4 -5
  66. package/tags/show.d.marko +6 -0
  67. package/tags/try.d.marko +1 -1
  68. package/tags-html.d.ts +6 -1
  69. /package/dist/translator/util/{get-accessor-char.d.ts → get-accessor-enums.d.ts} +0 -0
package/cheatsheet.md CHANGED
@@ -1,25 +1,25 @@
1
1
  # Marko 6 cheat sheet
2
2
 
3
- Marko 6 = HTML superset. NOT JSX, NOT old Marko 4/5. `.marko` files are components; the filename is the tag name.
3
+ Marko 6 = HTML superset, not JSX and not Marko 4/5 syntax. `.marko` files are components; the filename is the tag name.
4
4
 
5
5
  ## Golden rules
6
6
 
7
- 1. Text interpolation: `${expr}` inside tag bodies. A bare line at the template root parses as a TAG (concise mode): `Welcome aboard` fails to compile, but `p is a tag` compiles SILENTLY to `<p is a tag></p>` any line starting with a real tag name loses its words to attributes. Wrap text in an element (`<p>Welcome aboard</p>`) or prefix the line with `--` and a space (`-- Welcome ${name}`). Attributes take raw JS after `=` with NO braces/quotes: `<div title=user.name data-n=1 + 1>`.
8
- 2. A top-level `>` in an attribute value **ENDS THE TAG**: the value truncates there, the rest of the line becomes body text, and it usually still compiles clean. `<button disabled=count>=8 onClick() {…}>More</button>` is `disabled=count` plus the TEXT `=8 onClick() {…}>`, so the handler never binds; spaces don't help (`disabled=a > b` closes too). Parenthesize the value `disabled=(count >= 8)`, `hidden=(a > b)`, and for a TS type argument `<let/s=(new Set<string>())>`. Do NOT move the type onto the tag variable instead: `<let/s:Set<string>=new Set()>` compiles but fails type-check with TS2322 (the annotation does not flow into the initializer). A `>` nested inside `(…)`/`{…}`/`[…]` is safe (`class={ big: n > 1 }`, `of=list.filter(x => x > 1)`), but an arrow BODY is not nested: `<const/f=(a, b) => a > b>` truncates to `(a, b) => a`. `<` never closes a tag (`disabled=count<=1` is fine).
7
+ 1. Text interpolation: `${expr}` inside tag bodies. A bare line at the template root parses as a tag (concise mode): `Welcome aboard` fails to compile, but `p is a tag` compiles **silently** to `<p is a tag></p>`, since any line starting with a real tag name loses its words to attributes. Wrap text in an element (`<p>Welcome aboard</p>`) or prefix the line with `--` and a space (`-- Welcome ${name}`). Attributes take raw JS after `=` with no braces or quotes: `<div title=user.name data-n=1 + 1>`.
8
+ 2. A top-level `>` hugging its operand in an attribute value **ends the tag** silently: `<button disabled=count>=8 onClick() {…}>More</button>` is `disabled=count` plus the text `=8 onClick() {…}>`, so the handler never binds. Space a `>=` (`disabled=count >= 8`), and parenthesize a bare `>` comparison (`hidden=(a > b)`) and a TS type argument `<let/s=(new Set<string>())>`. Do not move the type onto the tag variable instead: `<let/s:Set<string>=new Set()>` compiles but fails type-check with TS2322 (the annotation does not flow into the initializer). A `>` nested inside `(…)`/`{…}`/`[…]` is safe (`class={ big: n > 1 }`). `<` never closes a tag (`disabled=count<=1` is fine).
9
9
  3. State: `<let/name=initial>` (slash then var name!). Update by plain assignment in an event handler: `count++`, `text = "hi"`. No setState, no hooks.
10
- 4. Derived values: `<const/total=items.length * price>` auto-recomputes. Never use an effect to derive state. `<let>` is deliberately different: its value is an INITIAL value, so `<let/draft=input.text>` seeds from a reactive value and then de-syncs that de-sync is the point of an editable copy. So pick by intent: recomputes → `<const>`, seeds then diverges → `<let>`. A `<let>` you never assign is just a frozen `<const>`. Updates batch: mid-handler a reassigned `<let>` reads current but its derived `<const>` reads stale recompute from the `<let>`.
11
- 5. NEVER mutate state in place. `items.push(x)` will NOT update the UI. Always reassign:
10
+ 4. Derived values: `<const/total=items.length * price>` auto-recomputes. Never use an effect to derive state. `<let>` is deliberately different: its value is an _initial_ value, so `<let/draft=input.text>` seeds from a reactive value and then de-syncs; that de-sync is the point of an editable copy. So pick by intent: recomputes → `<const>`, seeds then diverges → `<let>`. A `<let>` you never assign is just a frozen `<const>`. Updates batch: mid-handler a reassigned `<let>` reads current but its derived `<const>` reads stale, so recompute from the `<let>`.
11
+ 5. Never mutate state in place: `items.push(x)` does not update the UI. Always reassign:
12
12
  - add: `items = items.concat(x)`
13
13
  - remove: `items = items.toSpliced(i, 1)`
14
14
  - update: `items = items.toSpliced(i, 1, { ...item, done: true })`
15
15
  - object: `user = { ...user, name }`
16
- 6. Events: method shorthand `onClick() { ... }` or `onClick=fn`. Handler gets the DOM event: `onSubmit(e) { e.preventDefault(); save() }`. Don't sync input values through `onInput`/`onChange` that's what the change handlers below are for.
17
- 7. Native inputs are UNCONTROLLED by default: `value=` only sets the initial value. Adding the matching `*Change` handler is what makes them controlled `valueChange` on `<input>`/`<textarea>`/`<select>`, `checkedChange` on checkboxes/radios, `openChange` on `<details>`/`<dialog>`. `value:=text` is the shorthand for `value=text valueChange(v) { text = v }`. (`<textarea value:=text/>` value attribute, not body.)
18
- 8. Transform in the handler when needed number inputs give STRINGS: `<input type="number" value=n valueChange(v) { n = +v }>`, or `value:parseFloat:=n`.
19
- 9. Radio/checkbox groups: `checkedValue:=picked` on each input (shared var, distinct `value=`) the match is checked; array var for multi-checkbox. Dropdown: `<select value:=picked>`.
20
- 10. Module-level values and helpers need `static`: `static const LIMIT = 10`, `static function fmt(n) {…}`. Without it `function fmt(n) {` parses as a TAG ``Unable to find entry point for custom tag `<function>` ``, an error that never says `static`. Prefer it to `<const>` for anything that never changes: `<const/LIMIT=10>` emits a per-instance signal plus a `$setup` call.
16
+ 6. Events: method shorthand `onClick() { ... }` or `onClick=fn`. Handlers receive `(event, element)`; delegation means the element is the second parameter, not `event.currentTarget`: `onSubmit(e) { e.preventDefault(); save() }`, `onClick(e, el) { el.focus() }`. Don't sync input values through `onInput`/`onChange`; that's what the change handlers below are for. Prefix with `async` to `await` in the body: `async onClick() { await save() }`.
17
+ 7. Native inputs are uncontrolled by default: `value=` sets the default value — later writes update what `form.reset()` restores, never a dirty field's display. Adding the matching `*Change` handler is what makes them controlled: `valueChange` on `<input>`/`<textarea>`/`<select>`, `checkedChange` on checkboxes/radios, `openChange` on `<details>`/`<dialog>`. `value:=text` is the shorthand for `value=text valueChange(v) { text = v }`. (`<textarea value:=text/>`: value attribute, not body.)
18
+ 8. Transform in the handler when needed; number inputs give strings: `<input type="number" value=n valueChange(v) { n = +v }>`, or `value:parseFloat:=n`.
19
+ 9. Radio/checkbox groups: `checkedValue:=picked` on each input (shared var, distinct `value=`); the match is checked; array var for multi-checkbox. Dropdown: `<select value:=picked>`.
20
+ 10. Module-level values and helpers need `static`: `static const LIMIT = 10`, `static function fmt(n) {…}`. Without it `function fmt(n) {` parses as a tag: ``Unable to find entry point for custom tag `<function>` ``, an error that never says `static`. Prefer it to `<const>` for anything that never changes: `<const/LIMIT=10>` emits a per-instance signal plus a `$setup` call.
21
21
 
22
- ## Canonical component (copy this shape)
22
+ ## Canonical component
23
23
 
24
24
  ```marko
25
25
  <let/items=[]>
@@ -58,12 +58,12 @@ Marko 6 = HTML superset. NOT JSX, NOT old Marko 4/5. `.marko` files are componen
58
58
  ## Control flow
59
59
 
60
60
  ```marko
61
- <if=cond> A </if>
61
+ <if=(count > 10)> A </if> // parenthesize comparisons; a bare `>` ends the tag (rule 2)
62
62
  <else if=other> B </else>
63
63
  <else> C </else>
64
64
 
65
65
  <for|item, index| of=list by="id"> ${item.name} </for> // by keys the loop (no key= attr!)
66
- <for|city| of=cities by=(city) => city> ${city} </for> // primitives: by takes a FUNCTION the loop param is not in scope in by=, so by=city is an undefined variable
66
+ <for|city| of=cities by=(city) => city> ${city} </for> // primitives: by takes a function; the loop param is not in scope in by=, so by=city is an undefined variable
67
67
  <for|i| from=0 until=5> ${i} </for> // 0..4
68
68
 
69
69
  <show=open> stays mounted, keeps state (form drafts) when hidden </show>
@@ -88,13 +88,13 @@ import { getUser } from "../data.js";
88
88
 
89
89
  `@placeholder`/`@catch` go on `<try>`, never on `<await>`. On the server this streams (placeholder flushes first, content follows). It works in the browser too: hand `<await>` a new promise (e.g. a `<const>` derived from state) and it shows the placeholder again, then the new result. `@catch` can't recover in place: redirect (a `<script>` setting `location`), or re-render the `<try>` by bumping a key on a wrapping `<for>`.
90
90
 
91
- Don't fetch while rendering: start data loads early, pass the PROMISE through the template, and `<await>` it where the data is rendered. Fetching inside each component that renders the data serializes the requests (waterfalls). Under @marko/run, load in the route handler `return next({ user: getUser() })`, no await and render with `<await|user|=$global.data.user>`.
91
+ Don't fetch while rendering: start data loads early, pass the promise through the template, and `<await>` it where the data is rendered. Fetching inside each component that renders the data serializes the requests (waterfalls). Under @marko/run, load in the route handler (`return next({ user: getUser() })`, no await) and render with `<await|user|=$global.data.user>`.
92
92
 
93
93
  ## Components
94
94
 
95
95
  - File `src/tags/product-card.marko` is auto-discovered as `<product-card>` from any template (no import needed). Attributes arrive as `input`: `${input.title}`.
96
- - Body content renders where the child places `<${input.content}/>`, and the child can hand it values `<${input.content}(x, y)/>` in the child, `<my-tag|count, total|>${count}</my-tag>` in the parent. Placement is the child's: put it inside a `<for>` and the body appears once per item, each with its own values (`<for|...args| to=input.to><${input.content}(...args)/></>`). Those values exist ONLY inside that body.
97
- - `<return=value>` publishes ONE value into the PARENT's scope, named by a tag variable; from there it is an ordinary value in that template. A native tag variable's value is itself a function returning the element, so `<div/el>` is read as `el()`. So: body parameters when the value belongs to the nested markup, including one set per item where the child loops; a tag variable when the parent needs one value outside the body. A tag var on a child that never returns is `undefined`.
96
+ - Body content renders where the child places `<${input.content}/>`, and the child can hand it values: `<${input.content}(x, y)/>` in the child, `<my-tag|count, total|>${count}</my-tag>` in the parent. Placement is the child's: put it inside a `<for>` and the body appears once per item, each with its own values (`<for|...args| to=input.to><${input.content}(...args)/></>`). Those values exist only inside that body.
97
+ - `<return=value>` publishes one value into the parent's scope, named by a tag variable; from there it is an ordinary value in that template. A native tag variable's value is itself a function returning the element, so `<div/el>` is read as `el()`. So: body parameters when the value belongs to the nested markup, including one set per item where the child loops; a tag variable when the parent needs one value outside the body. A tag var on a child that never returns is `undefined`.
98
98
 
99
99
  ```marko
100
100
  /* src/tags/toggle-section.marko */
@@ -125,30 +125,32 @@ Don't fetch while rendering: start data loads early, pass the PROMISE through th
125
125
  </div>
126
126
  ```
127
127
 
128
- - Repeated attr tags (many `<@tab ...>`) arrive as the SINGULAR prop `input.tab`, which is iterable but NOT an array: `input.tab[i]` and `input.tab.length` are undefined. To index or count, spread first: `<const/tabs=[...input.tab ?? []]>` then `tabs[active]`/`tabs.length`. Looping directly is fine: `<for|tab| of=input.tab>`.
128
+ - Repeated attr tags (many `<@tab ...>`) arrive as the singular prop `input.tab`, which is iterable but not an array: `input.tab[i]` and `input.tab.length` are undefined. To index or count, spread first: `<const/tabs=[...input.tab ?? []]>` then `tabs[active]`/`tabs.length`. Looping directly is fine: `<for|tab| of=input.tab>`.
129
129
  - Conditional attrs: `false`/`null` attrs are omitted from HTML. `aria-selected` etc. want strings: `aria-selected=(i === active && "true")`.
130
130
  - `class=` / `style=` accept strings, objects, arrays: `class=["btn", { active }]`, `style={ color }` (single braces). `style=` keys are kebab-case CSS names (`{ "background-color": c }`), not camelCase.
131
- - `<id/x>` mints a collision-free id for label/input wiring (`<label for=x>`/`<input id=x>`) don't hardcode ids in reusable tags; `<id/x=input.id>` reuses a caller's.
131
+ - `<id/x>` mints a collision-free id for label/input wiring (`<label for=x>`/`<input id=x>`); don't hardcode ids in reusable tags; `<id/x=input.id>` reuses a caller's.
132
132
 
133
133
  ## Sharing data (`$global`)
134
134
 
135
- - Read request-scoped `$global` from any template, no threading: `${$global.messages.title}`. Otherwise prop-drill through `input` there is no provider/consumer context API.
135
+ - Read request-scoped `$global` from any template, no threading: `${$global.messages.title}`. Otherwise prop-drill through `input`; there is no provider/consumer context API.
136
136
  - Populate at the render call: `template.render({ $global: { messages } })`. Under @marko/run a middleware's `return next({ messages })` merges into `$global.data`.
137
- - `$global` is NOT serialized to the client by default. Mark any key the BROWSER itself evaluates an event handler, a `<script>`, markup the browser (re)creates, a `<const>` that recomputes from state: `$global.serializedGlobals = { messages: true }` at the render call (under @marko/run, `context.serializedGlobals.data = true`; it ships `params`/`url` already). What the server already rendered needs no opt-in.
137
+ - `$global` is not serialized to the client by default. Mark any key the browser itself evaluates, e.g. an event handler, a `<script>`, markup the browser (re)creates, or a `<const>` that recomputes from state: `$global.serializedGlobals = { messages: true }` at the render call (under @marko/run, `context.serializedGlobals.data = true`; it ships `params`/`url` already). What the server already rendered needs no opt-in.
138
138
 
139
- ## Client-side effects (rare — prefer state/const)
139
+ ## Client-side effects
140
+
141
+ Rare; prefer state and `<const>`.
140
142
 
141
143
  ```marko
142
144
  <div/el/>
143
145
  <script>
144
146
  // Browser-only. Runs after mount and re-runs when referenced state changes.
145
- el().focus(); // NATIVE element refs are getter FUNCTIONS
147
+ el().focus(); // native element refs are getter functions
146
148
  const id = setInterval(tick, 1000);
147
149
  $signal.onabort = () => clearInterval(id); // cleanup
148
150
  </script>
149
151
  ```
150
152
 
151
- `<style>` = real CSS, extracted & global; `<style/styles>` scopes it (CSS modules) `.card {...}` then `class=styles.card`, or `<style/{card}>` then `class=card`. Don't hand-namespace globals. `<script>` = reactive effect, NOT an HTML script tag.
153
+ `<style>` = real CSS, extracted & global; `<style/styles>` scopes it (CSS modules): `.card {...}` then `class=styles.card`, or `<style/{card}>` then `class=card`. Don't hand-namespace globals. `<script>` = reactive effect, not an HTML script tag.
152
154
 
153
155
  Imperative libs (charts, maps) needing mount/update/destroy: use `<lifecycle>`, not a hand-wired `<script>`. `this` persists across all three; return an object from `onMount` to stash the instance:
154
156
 
@@ -172,7 +174,7 @@ import PriceChart from "<price-chart>" with { load: "visible#chart" }
172
174
 
173
175
  ## TypeScript
174
176
 
175
- `export interface Input` types `input` generic as `Input<T>`, body content as `Marko.Body<[params]>`, repeated attr tags as `Marko.AttrTag<T>`.
177
+ `export interface Input` types `input`; generic as `Input<T>`, body content as `Marko.Body<[params]>`, repeated attr tags as `Marko.AttrTag<T>`.
176
178
 
177
179
  ```marko
178
180
  export interface Input<T> {
@@ -184,19 +186,21 @@ export interface Input<T> {
184
186
  <${input.then}(input.value)/>
185
187
  ```
186
188
 
187
- `tsc` silently SKIPS `.marko` a type-broken template still exits 0. Check with `mtc` (`@marko/type-check`).
189
+ `tsc` silently skips `.marko`, so a type-broken template still exits 0. Check with `mtc` (`@marko/type-check`); in TS mode an undeclared `Input` is `{}` by design, so declare one before reading `input`.
190
+
191
+ ## DON'T
188
192
 
189
- ## DON'T (these are errors or silently wrong)
193
+ Each left-hand habit is an error or silently wrong.
190
194
 
191
195
  | Wrong (React/Vue/Marko5 habit) | Right |
192
196
  | ----------------------------------------------------------- | ------------------------------------------------------------------------------------ |
193
- | `disabled=n>=8` / `hidden=a > b` (top-level `>` in a value) | `disabled=(n >= 8)` a bare `>` closes the tag; the rest of the line becomes text |
194
- | `<let/s=new Set<string>()>` (type argument in a value) | `<let/s=(new Set<string>())>` a tag-var annotation fails type-check |
197
+ | `disabled=n>=8` (hugging `>` in a value) | `disabled=n >= 8` or `disabled=(n >= 8)`; a hugging `>` silently closes the tag |
198
+ | `<let/s=new Set<string>()>` (type argument in a value) | `<let/s=(new Set<string>())>`; a tag-var annotation fails type-check |
195
199
  | `{expr}` in markup, `className`, `key=`, `style={{...}}` | `${expr}`, `class`, `by=` on `<for>`, `style={...}` |
196
200
  | `onClick={() => ...}` / `@click` / `on-click("name")` | `onClick() { ... }` |
197
201
  | `const [x, setX] = useState()` / `state` / `class {}` block | `<let/x=0>` then `x = 1` |
198
202
  | `$ const y = x * 2;` (scriptlets are removed) | `<const/y=x * 2>` |
199
- | `<let/n=a + b>` when you want it to recompute | `<const/n=a + b>` `<let>` seeds an initial value, then de-syncs by design |
203
+ | `<let/n=a + b>` for a value that should recompute | `<const/n=a + b>`; `<let>` seeds an initial value, then de-syncs by design |
200
204
  | `function fmt(n) {…}` / `const LIMIT = 10` at module level | `static function fmt(n) {…}` / `static const LIMIT = 10` |
201
205
  | `<let x=0>` | `<let/x=0>` |
202
206
  | `<if(cond)>` | `<if=cond>` |
@@ -206,8 +210,8 @@ export interface Input<T> {
206
210
  | `el.focus()` on a ref | `el().focus()` inside `<script>`/handler |
207
211
  | `input.tab[0]` / `input.tab.length` | `[...input.tab ?? []]` first (attr tags are iterables, not arrays) |
208
212
  | bare text on its own line at template root | wrap in an element (`<p>...`), or prefix the line with `--` and a space |
209
- | `by=item` using the loop variable | `by="propName"` or `by=(item) => key` `by=` is evaluated outside the loop |
210
- | `onInput(e) { q = e.target.value }` to sync an input | `value:=q` the change handler owns the value |
213
+ | `by=item` using the loop variable | `by="propName"` or `by=(item) => key`; `by=` is evaluated outside the loop |
214
+ | `onInput(e) { q = e.target.value }` to sync an input | `value:=q`; the change handler owns the value |
211
215
  | fetching inside the component that renders the data | start the promise early (route handler / top of template), pass it down to `<await>` |
212
216
  | `style={ backgroundColor: c }` (camelCase keys) | `style={ "background-color": c }` (kebab-case) |
213
217
  | `this.querySelector` / `this.getRootNode()` in `<script>` | element ref getter: `<div/el>` then `el()` (there is no `this`) |
@@ -216,6 +220,6 @@ export interface Input<T> {
216
220
  | hand-rolled `IntersectionObserver` to defer a widget's JS | `import W from "<w>" with { load: "visible#sel" }` |
217
221
  | imperative lib wired through `<script>` mount + cleanup | `<lifecycle onMount/onUpdate/onDestroy>` (keeps `this` across all three) |
218
222
  | `createContext`/provider to share data | `input` (prop drilling) or request-scoped `$global` |
219
- | `$global.x` in client-reactive code, not allow-listed | `$global.serializedGlobals = { x: true }` first otherwise the read is `undefined` |
223
+ | `$global.x` in client-reactive code, not allow-listed | `$global.serializedGlobals = { x: true }` first; otherwise the read is `undefined` |
220
224
  | hand-namespaced global classes (`.my-card-title`) | `<style/styles>` + `class=styles.card` (scoped CSS modules) |
221
- | `tsc --noEmit` to type check templates | `mtc` `tsc` skips `.marko` files and exits 0 |
225
+ | `tsc --noEmit` to type check templates | `mtc`; `tsc` skips `.marko` files and exits 0 |
@@ -8,6 +8,7 @@ export declare const ControlledType = "F";
8
8
  export declare const ControlledValue = "G";
9
9
  export declare const DynamicHTMLLastChild = "H";
10
10
  export declare const EventAttributes = "I";
11
+ export declare const IdFallback = "J";
11
12
  export declare const KeyedScopes = "O";
12
13
  export declare const Lifecycle = "K";
13
14
  export declare const Promise = "L";
@@ -8,6 +8,7 @@ export declare const ControlledType = "ControlledType:";
8
8
  export declare const ControlledValue = "ControlledValue:";
9
9
  export declare const DynamicHTMLLastChild = "DynamicHTMLLastChild:";
10
10
  export declare const EventAttributes = "EventAttributes:";
11
+ export declare const IdFallback = "IdFallback:";
11
12
  export declare const KeyedScopes = "KeyedScopes:";
12
13
  export declare const Lifecycle = "Lifecycle:";
13
14
  export declare const Promise = "Promise:";
@@ -2,12 +2,14 @@ export declare function assertValidAttrValue(name: string, value: unknown): void
2
2
  export declare function assertValidTextValue(value: unknown): void;
3
3
  export declare function assertValidLoopKey(key: unknown, seenKeys?: Set<unknown>): void;
4
4
  export declare function assertValidList(value: unknown): void;
5
+ export declare function assertValidRangeStart(name: string, value: unknown): void;
5
6
  export declare function assertValidRangeBound(name: string, value: unknown): void;
6
7
  export declare function assertValidAttrName(name: string): void;
7
8
  export declare function _el_read_error(): void;
8
9
  export declare function _hoist_read_error(): void;
9
10
  export declare function _assert_hoist(value: unknown): void;
10
11
  export declare function assertExclusiveAttrs(attrs: Record<string, unknown> | undefined, onError?: typeof throwErr): void;
12
+ export declare function assertNoValueBindingOnCheckable(type: unknown, valueChange: unknown): void;
11
13
  export declare function assertHandlerIsFunction(name: string, value: unknown): void;
12
14
  export declare function assertValidTagName(tagName: string): void;
13
15
  declare function throwErr(msg: string): void;
@@ -73,6 +73,16 @@ export interface MountedTemplate {
73
73
  }
74
74
  export type RenderedTemplate = PromiseLike<string> & AsyncIterable<string> & {
75
75
  toReadable(): ReadableStream<Uint8Array<ArrayBufferLike>>;
76
+ pipe(stream: {
77
+ write(chunk: string): unknown;
78
+ end(): unknown;
79
+ flush?(): void;
80
+ destroy?(): void;
81
+ emit?(name: PropertyKey, ...args: unknown[]): unknown;
82
+ }): void;
83
+ toString(): string;
84
+ catch<T = never>(onrejected?: ((reason: unknown) => T | PromiseLike<T>) | undefined | null): Promise<string | T>;
85
+ finally(onfinally?: (() => void) | undefined | null): Promise<string>;
76
86
  };
77
87
  type ControlledType = ControlledType.Value;
78
88
  export { ControlledType };
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- const require_control_flow = require("../dom-CiFITSPN.js");
2
+ const require_control_flow = require("../dom-Bt4OoZ-j.js");
3
3
  //#region src/dom/catch.feat.ts
4
4
  const handlePendingTry = (fn, scope, branch) => {
5
5
  while (branch) {
@@ -1,4 +1,4 @@
1
- import { Cn as PendingRenders, Jt as caughtError, Sn as PendingEffects, Xt as placeholderShown, Yt as installCatch, gn as ClosestBranch, h as renderCatch, mn as Scope, pn as Pending, xn as ParentBranch } from "../dom-BJ93mcSe.mjs";
1
+ import { Cn as PendingRenders, Jt as caughtError, Sn as PendingEffects, Xt as placeholderShown, Yt as installCatch, gn as ClosestBranch, h as renderCatch, mn as Scope, pn as Pending, xn as ParentBranch } from "../dom-B57LrRnX.mjs";
2
2
  //#region src/dom/catch.feat.ts
3
3
  const handlePendingTry = (fn, scope, branch) => {
4
4
  while (branch) {
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- const require_control_flow = require("../dom-CiFITSPN.js");
2
+ const require_control_flow = require("../dom-Bt4OoZ-j.js");
3
3
  //#region src/dom/controllable-input.feat.ts
4
4
  require_control_flow.controllableScripts[0] = require_control_flow._attr_input_checked_script;
5
5
  require_control_flow.controllableScripts[1] = require_control_flow._attr_input_checkedValue_script;
@@ -1,4 +1,4 @@
1
- import { R as controllableScripts, S as _attr_input_checkedValue_script, k as _attr_input_value_script, w as _attr_input_checked_script } from "../dom-BJ93mcSe.mjs";
1
+ import { R as controllableScripts, S as _attr_input_checkedValue_script, k as _attr_input_value_script, w as _attr_input_checked_script } from "../dom-B57LrRnX.mjs";
2
2
  //#region src/dom/controllable-input.feat.ts
3
3
  controllableScripts[0] = _attr_input_checked_script;
4
4
  controllableScripts[1] = _attr_input_checkedValue_script;
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- const require_control_flow = require("../dom-CiFITSPN.js");
2
+ const require_control_flow = require("../dom-Bt4OoZ-j.js");
3
3
  //#region src/dom/controllable-open.feat.ts
4
4
  require_control_flow.controllableScripts[4] = require_control_flow._attr_details_or_dialog_open_script;
5
5
  //#endregion
@@ -1,4 +1,4 @@
1
- import { R as controllableScripts, v as _attr_details_or_dialog_open_script } from "../dom-BJ93mcSe.mjs";
1
+ import { R as controllableScripts, v as _attr_details_or_dialog_open_script } from "../dom-B57LrRnX.mjs";
2
2
  //#region src/dom/controllable-open.feat.ts
3
3
  controllableScripts[4] = _attr_details_or_dialog_open_script;
4
4
  //#endregion
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- const require_control_flow = require("../dom-CiFITSPN.js");
2
+ const require_control_flow = require("../dom-Bt4OoZ-j.js");
3
3
  //#region src/dom/controllable-select.feat.ts
4
4
  require_control_flow.controllableScripts[3] = require_control_flow._attr_select_value_script;
5
5
  //#endregion
@@ -1,4 +1,4 @@
1
- import { M as _attr_select_value_script, R as controllableScripts } from "../dom-BJ93mcSe.mjs";
1
+ import { M as _attr_select_value_script, R as controllableScripts } from "../dom-B57LrRnX.mjs";
2
2
  //#region src/dom/controllable-select.feat.ts
3
3
  controllableScripts[3] = _attr_select_value_script;
4
4
  //#endregion
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- const require_control_flow = require("../dom-CiFITSPN.js");
2
+ const require_control_flow = require("../dom-Bt4OoZ-j.js");
3
3
  //#region src/dom/controllable-textarea.feat.ts
4
4
  require_control_flow.controllableScripts[2] = require_control_flow._attr_input_value_script;
5
5
  //#endregion
@@ -1,4 +1,4 @@
1
- import { R as controllableScripts, k as _attr_input_value_script } from "../dom-BJ93mcSe.mjs";
1
+ import { R as controllableScripts, k as _attr_input_value_script } from "../dom-B57LrRnX.mjs";
2
2
  //#region src/dom/controllable-textarea.feat.ts
3
3
  controllableScripts[2] = _attr_input_value_script;
4
4
  //#endregion
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- const require_control_flow = require("../dom-CiFITSPN.js");
2
+ const require_control_flow = require("../dom-Bt4OoZ-j.js");
3
3
  require("./controllable-input.feat.js");
4
4
  require("./controllable-open.feat.js");
5
5
  require("./controllable-select.feat.js");
@@ -1,4 +1,4 @@
1
- import { F as _controllable_select, I as _controllable_textarea, L as controllableRenders, N as _controllable_input, P as _controllable_open } from "../dom-BJ93mcSe.mjs";
1
+ import { F as _controllable_select, I as _controllable_textarea, L as controllableRenders, N as _controllable_input, P as _controllable_open } from "../dom-B57LrRnX.mjs";
2
2
  import "./controllable-input.feat.mjs";
3
3
  import "./controllable-open.feat.mjs";
4
4
  import "./controllable-select.feat.mjs";