@marko/runtime-tags 6.3.1 → 6.3.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/cheatsheet.md ADDED
@@ -0,0 +1,146 @@
1
+ # Marko 6 cheat sheet
2
+
3
+ Marko 6 = HTML superset. NOT JSX, NOT old Marko 4/5. `.marko` files are components; the filename is the tag name.
4
+
5
+ ## Golden rules
6
+
7
+ 1. Text interpolation: `${expr}` inside tag bodies. A bare line like `Welcome aboard` at the root of the template parses as a TAG named `Welcome` (concise mode) and fails to compile. Wrap it in an element (`<p>Welcome aboard</p>`) or prefix the line with `-- ` to mark it as text (`-- Welcome ${name}` works at the top level). Attributes take raw JS after `=` with NO braces/quotes needed: `<div title=user.name data-n=1 + 1>` (parenthesize if the value contains `>`).
8
+ 2. State: `<let/name=initial>` (slash then var name!). Update by plain assignment in an event handler: `count++`, `text = "hi"`. No setState, no hooks.
9
+ 3. Derived values: `<const/total=items.length * price>` — auto-recomputes. Never use an effect to derive state.
10
+ 4. NEVER mutate state in place. `items.push(x)` will NOT update the UI. Always reassign:
11
+ - add: `items = items.concat(x)`
12
+ - remove: `items = items.toSpliced(i, 1)`
13
+ - update: `items = items.toSpliced(i, 1, { ...item, done: true })`
14
+ - object: `user = { ...user, name }`
15
+ 5. 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` listeners — that's what change handlers (next rule) are for, and they make the data's owner explicit.
16
+ 6. 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.)
17
+ 7. Write the change handler yourself when updates need transforming — number inputs give STRINGS: `<input type="number" value=n valueChange(v) { n = +v }>`.
18
+
19
+ ## Canonical component (copy this shape)
20
+
21
+ ```marko
22
+ <let/items=[]>
23
+ <let/draft="">
24
+ <const/remaining=items.filter(t => !t.done).length>
25
+
26
+ <input value:=draft placeholder="What next?">
27
+ <button onClick() {
28
+ const text = draft.trim();
29
+ if (text) {
30
+ items = items.concat({ id: items.length + 1, text, done: false });
31
+ draft = "";
32
+ }
33
+ }>Add</button>
34
+
35
+ <if=items.length>
36
+ <ul>
37
+ <for|item, i| of=items by="id">
38
+ <li class={ done: item.done }>
39
+ <input
40
+ type="checkbox"
41
+ checked=item.done
42
+ checkedChange(v) { items = items.toSpliced(i, 1, { ...item, done: v }) }
43
+ >
44
+ ${item.text}
45
+ </li>
46
+ </for>
47
+ </ul>
48
+ <p>${remaining} left</p>
49
+ </if>
50
+ <else>
51
+ <p>Nothing yet</p>
52
+ </else>
53
+ ```
54
+
55
+ ## Control flow
56
+
57
+ ```marko
58
+ <if=cond> A </if>
59
+ <else if=other> B </else>
60
+ <else> C </else>
61
+
62
+ <for|item, index| of=list by="id"> ${item.name} </for> // by keys the loop (no key= attr!)
63
+ <for|city| of=cities by=(city) => city> ${city} </for> // primitives: by takes a FUNCTION — by=city would be an undefined variable (the loop param is not in scope in by=)
64
+ <for|i| from=0 until=5> ${i} </for> // 0..4
65
+
66
+ <show=open> stays mounted, keeps state (form drafts) when hidden </show>
67
+ ```
68
+
69
+ `<if>` destroys/rebuilds its content; `<show>` just hides it (use for toggles that must keep state).
70
+
71
+ ## Async (`<await>`)
72
+
73
+ ```marko
74
+ import { getUser } from "../data.js";
75
+
76
+ <try>
77
+ <await|user|=getUser()>
78
+ <h2>${user.name}</h2>
79
+ </await>
80
+
81
+ <@placeholder>Loading...</@placeholder>
82
+ <@catch|err|>${err.message}</@catch>
83
+ </try>
84
+ ```
85
+
86
+ `@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.
87
+
88
+ 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>`.
89
+
90
+ ## Components
91
+
92
+ - File `src/tags/product-card.marko` is auto-discovered as `<product-card>` from any template (no import needed). Attributes arrive as `input`: `${input.title}`.
93
+ - Body content passed by the parent renders with `<${input.content}/>`.
94
+ - Named sections use attribute tags:
95
+
96
+ ```marko
97
+ /* parent */
98
+ <my-card>
99
+ <@header>Hello</@header>
100
+ body text
101
+ </my-card>
102
+
103
+ /* src/tags/my-card.marko */
104
+ <div class="card">
105
+ <header><${input.header.content}/></header>
106
+ <${input.content}/>
107
+ </div>
108
+ ```
109
+
110
+ - 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>`.
111
+ - Conditional attrs: `false`/`null` attrs are omitted from HTML. `aria-selected` etc. want strings: `aria-selected=(i === active && "true")`.
112
+ - `class=` / `style=` accept strings, objects, arrays: `class=["btn", { active }]`, `style={ color }` (single braces).
113
+
114
+ ## Client-side effects (rare — prefer state/const)
115
+
116
+ ```marko
117
+ <div/el/>
118
+ <script>
119
+ // Browser-only. Runs after mount and re-runs when referenced state changes.
120
+ el().focus(); // element refs are getter FUNCTIONS
121
+ const id = setInterval(tick, 1000);
122
+ $signal.onabort = () => clearInterval(id); // cleanup
123
+ </script>
124
+ ```
125
+
126
+ `<style>` = real CSS, extracted & global. `<script>` = reactive effect, NOT an HTML script tag.
127
+
128
+ ## DON'T (these are errors or silently wrong)
129
+
130
+ | Wrong (React/Vue/Marko5 habit) | Right |
131
+ | ----------------------------------------------------------- | ------------------------------------------------------------------------------------ |
132
+ | `{expr}` in markup, `className`, `key=`, `style={{...}}` | `${expr}`, `class`, `by=` on `<for>`, `style={...}` |
133
+ | `onClick={() => ...}` / `@click` / `on-click("name")` | `onClick() { ... }` |
134
+ | `const [x, setX] = useState()` / `state` / `class {}` block | `<let/x=0>` then `x = 1` |
135
+ | `$ const y = x * 2;` (scriptlets are removed) | `<const/y=x * 2>` |
136
+ | `<let x=0>` | `<let/x=0>` |
137
+ | `<if(cond)>` | `<if=cond>` |
138
+ | `items.push(x)` | `items = items.concat(x)` |
139
+ | `input.renderBody` | `input.content` |
140
+ | `<await>` with `@placeholder`/`@catch` | wrap in `<try>` |
141
+ | `el.focus()` on a ref | `el().focus()` inside `<script>`/handler |
142
+ | `input.tab[0]` / `input.tab.length` | `[...input.tab ?? []]` first (attr tags are iterables, not arrays) |
143
+ | bare text on its own line at template root | wrap in an element (`<p>...`), or prefix the line with `-- ` |
144
+ | `by=item` using the loop variable | `by="propName"` or `by=(item) => key` — `by=` is evaluated outside the loop |
145
+ | `onInput(e) { q = e.target.value }` to sync an input | `value:=q` — the change handler owns the value |
146
+ | fetching inside the component that renders the data | start the promise early (route handler / top of template), pass it down to `<await>` |
@@ -220,8 +220,8 @@ function _escape(val) {
220
220
  assertValidTextValue(val);
221
221
  return val ? escapeXMLStr(val + "") : val === 0 ? "0" : "";
222
222
  }
223
- const unsafeScriptReg = /<\/script/gi;
224
- const escapeScriptStr = (str) => unsafeScriptReg.test(str) ? str.replace(unsafeScriptReg, "\\x3C/script") : str;
223
+ const unsafeScriptReg = /<(\/?script|!--)/gi;
224
+ const escapeScriptStr = (str) => unsafeScriptReg.test(str) ? str.replace(unsafeScriptReg, "\\x3C$1") : str;
225
225
  function _escape_script(val) {
226
226
  assertValidTextValue(val);
227
227
  return val ? escapeScriptStr(val + "") : val === 0 ? "0" : "";
@@ -648,7 +648,7 @@ function writeAssigned(state) {
648
648
  } else state.buf.push("void 0");
649
649
  const valueStartIndex = state.buf.push(toAccess(toObjectKey(mutation.property)) + "(");
650
650
  if (mutation.value === void 0) {} else if (writeProp(state, mutation.value, null, "")) {
651
- const valueRef = state.refs.get(mutation.value);
651
+ const valueRef = typeof mutation.value === "string" ? state.strs.get(mutation.value) : state.refs.get(mutation.value);
652
652
  if (valueRef && !valueRef.id && valueRef.scopeId === void 0) {
653
653
  valueRef.id = mutation.valueId || nextRefAccess(state);
654
654
  state.buf[valueStartIndex] = valueRef.id + "=" + state.buf[valueStartIndex];
@@ -1161,7 +1161,7 @@ function writeReadableStream(state, val, ref) {
1161
1161
  }
1162
1162
  function writeGenerator(state, iter, ref) {
1163
1163
  if (iter[kTouchedIterator]) {
1164
- state.buf.push("(async function*(){}())");
1164
+ state.buf.push("(function*(){}())");
1165
1165
  return true;
1166
1166
  }
1167
1167
  let sep = "";
@@ -218,8 +218,8 @@ function _escape(val) {
218
218
  assertValidTextValue(val);
219
219
  return val ? escapeXMLStr(val + "") : val === 0 ? "0" : "";
220
220
  }
221
- const unsafeScriptReg = /<\/script/gi;
222
- const escapeScriptStr = (str) => unsafeScriptReg.test(str) ? str.replace(unsafeScriptReg, "\\x3C/script") : str;
221
+ const unsafeScriptReg = /<(\/?script|!--)/gi;
222
+ const escapeScriptStr = (str) => unsafeScriptReg.test(str) ? str.replace(unsafeScriptReg, "\\x3C$1") : str;
223
223
  function _escape_script(val) {
224
224
  assertValidTextValue(val);
225
225
  return val ? escapeScriptStr(val + "") : val === 0 ? "0" : "";
@@ -646,7 +646,7 @@ function writeAssigned(state) {
646
646
  } else state.buf.push("void 0");
647
647
  const valueStartIndex = state.buf.push(toAccess(toObjectKey(mutation.property)) + "(");
648
648
  if (mutation.value === void 0) {} else if (writeProp(state, mutation.value, null, "")) {
649
- const valueRef = state.refs.get(mutation.value);
649
+ const valueRef = typeof mutation.value === "string" ? state.strs.get(mutation.value) : state.refs.get(mutation.value);
650
650
  if (valueRef && !valueRef.id && valueRef.scopeId === void 0) {
651
651
  valueRef.id = mutation.valueId || nextRefAccess(state);
652
652
  state.buf[valueStartIndex] = valueRef.id + "=" + state.buf[valueStartIndex];
@@ -1159,7 +1159,7 @@ function writeReadableStream(state, val, ref) {
1159
1159
  }
1160
1160
  function writeGenerator(state, iter, ref) {
1161
1161
  if (iter[kTouchedIterator]) {
1162
- state.buf.push("(async function*(){}())");
1162
+ state.buf.push("(function*(){}())");
1163
1163
  return true;
1164
1164
  }
1165
1165
  let sep = "";
package/dist/html.js CHANGED
@@ -4,7 +4,7 @@ let empty = [], rest = Symbol(), toDelimitedString = function toDelimitedString(
4
4
  else if (Array.isArray(val)) for (let v of val) part = toDelimitedString(v, delimiter, stringify), part && (str += sep + part, sep = delimiter);
5
5
  else for (let name in val) part = stringify(name, val[name]), part && (str += sep + part, sep = delimiter);
6
6
  return str;
7
- }, unsafeXMLReg = /[<&]/g, replaceUnsafeXML = (c) => c === "&" ? "&amp;" : "&lt;", escapeXMLStr = (str) => unsafeXMLReg.test(str) ? str.replace(unsafeXMLReg, replaceUnsafeXML) : str, unsafeScriptReg = /<\/script/gi, escapeScriptStr = (str) => unsafeScriptReg.test(str) ? str.replace(unsafeScriptReg, "\\x3C/script") : str, unsafeStyleReg = /<\/style/gi, escapeStyleStr = (str) => unsafeStyleReg.test(str) ? str.replace(unsafeStyleReg, "\\3C/style") : str, unsafeCommentReg = />/g, escapeCommentStr = (str) => unsafeCommentReg.test(str) ? str.replace(unsafeCommentReg, "&gt;") : str, K_SCOPE_ID = Symbol("Scope ID"), kTouchedIterator = Symbol.for("marko.touchedIterator"), { hasOwnProperty: hasOwnProperty$1 } = {}, Generator = (function* () {})().constructor, AsyncGenerator = (async function* () {})().constructor, REGISTRY = /* @__PURE__ */ new WeakMap(), KNOWN_SYMBOLS = (() => {
7
+ }, unsafeXMLReg = /[<&]/g, replaceUnsafeXML = (c) => c === "&" ? "&amp;" : "&lt;", escapeXMLStr = (str) => unsafeXMLReg.test(str) ? str.replace(unsafeXMLReg, replaceUnsafeXML) : str, unsafeScriptReg = /<(\/?script|!--)/gi, escapeScriptStr = (str) => unsafeScriptReg.test(str) ? str.replace(unsafeScriptReg, "\\x3C$1") : str, unsafeStyleReg = /<\/style/gi, escapeStyleStr = (str) => unsafeStyleReg.test(str) ? str.replace(unsafeStyleReg, "\\3C/style") : str, unsafeCommentReg = />/g, escapeCommentStr = (str) => unsafeCommentReg.test(str) ? str.replace(unsafeCommentReg, "&gt;") : str, K_SCOPE_ID = Symbol("Scope ID"), kTouchedIterator = Symbol.for("marko.touchedIterator"), { hasOwnProperty: hasOwnProperty$1 } = {}, Generator = (function* () {})().constructor, AsyncGenerator = (async function* () {})().constructor, REGISTRY = /* @__PURE__ */ new WeakMap(), KNOWN_SYMBOLS = (() => {
8
8
  let KNOWN_SYMBOLS = /* @__PURE__ */ new Map();
9
9
  for (let name of Object.getOwnPropertyNames(Symbol)) {
10
10
  let symbol = Symbol[name];
@@ -534,7 +534,7 @@ function writeAssigned(state) {
534
534
  } else state.buf.push("void 0");
535
535
  let valueStartIndex = state.buf.push(toAccess(toObjectKey(mutation.property)) + "(");
536
536
  if (mutation.value !== void 0) if (writeProp(state, mutation.value, null, "")) {
537
- let valueRef = state.refs.get(mutation.value);
537
+ let valueRef = typeof mutation.value == "string" ? state.strs.get(mutation.value) : state.refs.get(mutation.value);
538
538
  valueRef && !valueRef.id && valueRef.scopeId === void 0 && (valueRef.id = mutation.valueId || nextRefAccess(state), state.buf[valueStartIndex] = valueRef.id + "=" + state.buf[valueStartIndex]);
539
539
  } else state.buf.push("void 0");
540
540
  state.buf.push(")");
@@ -819,7 +819,7 @@ function writeReadableStream(state, val, ref) {
819
819
  return state.buf.push("new ReadableStream({start(c){(async(_,f,v,l,i,p=a=>l=new Promise((r,j)=>{f=_.r=r;_.j=j}),a=((_.f=v=>{f(v);a.push(p())}),[p()]))=>{for(i of a)v=await i,i==l?c.close():c.enqueue(v)})(" + iterId + "={}).catch(e=>c.error(e))}})"), reader.read().then(onFulfilled, onRejected), boundary.startAsync(), !0;
820
820
  }
821
821
  function writeGenerator(state, iter, ref) {
822
- if (iter[kTouchedIterator]) return state.buf.push("(async function*(){}())"), !0;
822
+ if (iter[kTouchedIterator]) return state.buf.push("(function*(){}())"), !0;
823
823
  let sep = "";
824
824
  for (state.buf.push("(function*(){");;) {
825
825
  let { value, done } = iter.next();
package/dist/html.mjs CHANGED
@@ -4,7 +4,7 @@ let empty = [], rest = Symbol(), toDelimitedString = function toDelimitedString(
4
4
  else if (Array.isArray(val)) for (let v of val) part = toDelimitedString(v, delimiter, stringify), part && (str += sep + part, sep = delimiter);
5
5
  else for (let name in val) part = stringify(name, val[name]), part && (str += sep + part, sep = delimiter);
6
6
  return str;
7
- }, unsafeXMLReg = /[<&]/g, replaceUnsafeXML = (c) => c === "&" ? "&amp;" : "&lt;", escapeXMLStr = (str) => unsafeXMLReg.test(str) ? str.replace(unsafeXMLReg, replaceUnsafeXML) : str, unsafeScriptReg = /<\/script/gi, escapeScriptStr = (str) => unsafeScriptReg.test(str) ? str.replace(unsafeScriptReg, "\\x3C/script") : str, unsafeStyleReg = /<\/style/gi, escapeStyleStr = (str) => unsafeStyleReg.test(str) ? str.replace(unsafeStyleReg, "\\3C/style") : str, unsafeCommentReg = />/g, escapeCommentStr = (str) => unsafeCommentReg.test(str) ? str.replace(unsafeCommentReg, "&gt;") : str, K_SCOPE_ID = Symbol("Scope ID"), kTouchedIterator = Symbol.for("marko.touchedIterator"), { hasOwnProperty: hasOwnProperty$1 } = {}, Generator = (function* () {})().constructor, AsyncGenerator = (async function* () {})().constructor, REGISTRY = /* @__PURE__ */ new WeakMap(), KNOWN_SYMBOLS = (() => {
7
+ }, unsafeXMLReg = /[<&]/g, replaceUnsafeXML = (c) => c === "&" ? "&amp;" : "&lt;", escapeXMLStr = (str) => unsafeXMLReg.test(str) ? str.replace(unsafeXMLReg, replaceUnsafeXML) : str, unsafeScriptReg = /<(\/?script|!--)/gi, escapeScriptStr = (str) => unsafeScriptReg.test(str) ? str.replace(unsafeScriptReg, "\\x3C$1") : str, unsafeStyleReg = /<\/style/gi, escapeStyleStr = (str) => unsafeStyleReg.test(str) ? str.replace(unsafeStyleReg, "\\3C/style") : str, unsafeCommentReg = />/g, escapeCommentStr = (str) => unsafeCommentReg.test(str) ? str.replace(unsafeCommentReg, "&gt;") : str, K_SCOPE_ID = Symbol("Scope ID"), kTouchedIterator = Symbol.for("marko.touchedIterator"), { hasOwnProperty: hasOwnProperty$1 } = {}, Generator = (function* () {})().constructor, AsyncGenerator = (async function* () {})().constructor, REGISTRY = /* @__PURE__ */ new WeakMap(), KNOWN_SYMBOLS = (() => {
8
8
  let KNOWN_SYMBOLS = /* @__PURE__ */ new Map();
9
9
  for (let name of Object.getOwnPropertyNames(Symbol)) {
10
10
  let symbol = Symbol[name];
@@ -533,7 +533,7 @@ function writeAssigned(state) {
533
533
  } else state.buf.push("void 0");
534
534
  let valueStartIndex = state.buf.push(toAccess(toObjectKey(mutation.property)) + "(");
535
535
  if (mutation.value !== void 0) if (writeProp(state, mutation.value, null, "")) {
536
- let valueRef = state.refs.get(mutation.value);
536
+ let valueRef = typeof mutation.value == "string" ? state.strs.get(mutation.value) : state.refs.get(mutation.value);
537
537
  valueRef && !valueRef.id && valueRef.scopeId === void 0 && (valueRef.id = mutation.valueId || nextRefAccess(state), state.buf[valueStartIndex] = valueRef.id + "=" + state.buf[valueStartIndex]);
538
538
  } else state.buf.push("void 0");
539
539
  state.buf.push(")");
@@ -818,7 +818,7 @@ function writeReadableStream(state, val, ref) {
818
818
  return state.buf.push("new ReadableStream({start(c){(async(_,f,v,l,i,p=a=>l=new Promise((r,j)=>{f=_.r=r;_.j=j}),a=((_.f=v=>{f(v);a.push(p())}),[p()]))=>{for(i of a)v=await i,i==l?c.close():c.enqueue(v)})(" + iterId + "={}).catch(e=>c.error(e))}})"), reader.read().then(onFulfilled, onRejected), boundary.startAsync(), !0;
819
819
  }
820
820
  function writeGenerator(state, iter, ref) {
821
- if (iter[kTouchedIterator]) return state.buf.push("(async function*(){}())"), !0;
821
+ if (iter[kTouchedIterator]) return state.buf.push("(function*(){}())"), !0;
822
822
  let sep = "";
823
823
  for (state.buf.push("(function*(){");;) {
824
824
  let { value, done } = iter.next();
@@ -1249,6 +1249,7 @@ function startSection(path) {
1249
1249
  upstreamExpression: void 0,
1250
1250
  downstreamBinding: void 0,
1251
1251
  hasAbortSignal: false,
1252
+ abortSignalExprs: 0,
1252
1253
  readsOwner: false,
1253
1254
  isBranch: false
1254
1255
  };
@@ -1539,6 +1540,21 @@ function isStaticRoot(path) {
1539
1540
  }
1540
1541
  }
1541
1542
  //#endregion
1543
+ //#region src/translator/util/analyze-errors.ts
1544
+ const [getHasAnalyzeErrors, setHasAnalyzeErrors] = createProgramState(() => false);
1545
+ function reportAnalyzeError(path, error) {
1546
+ if (!(error instanceof Error)) throw error;
1547
+ const { label = error.message, loc } = error;
1548
+ setHasAnalyzeErrors(true);
1549
+ (0, _marko_compiler_babel_utils.diagnosticError)(path, {
1550
+ label,
1551
+ loc: loc ?? path.node.loc ?? void 0
1552
+ });
1553
+ }
1554
+ function hasAnalyzeErrors() {
1555
+ return getHasAnalyzeErrors();
1556
+ }
1557
+ //#endregion
1542
1558
  //#region src/translator/util/asset-imports.ts
1543
1559
  function addAssetImport(file, request) {
1544
1560
  (file.metadata.marko.assetImports ??= /* @__PURE__ */ new Set()).add(request);
@@ -1713,8 +1729,8 @@ const escapeXMLStr = (str) => unsafeXMLReg.test(str) ? str.replace(unsafeXMLReg,
1713
1729
  function _escape(val) {
1714
1730
  return val ? escapeXMLStr(val + "") : val === 0 ? "0" : "";
1715
1731
  }
1716
- const unsafeScriptReg = /<\/script/gi;
1717
- const escapeScriptStr = (str) => unsafeScriptReg.test(str) ? str.replace(unsafeScriptReg, "\\x3C/script") : str;
1732
+ const unsafeScriptReg = /<(\/?script|!--)/gi;
1733
+ const escapeScriptStr = (str) => unsafeScriptReg.test(str) ? str.replace(unsafeScriptReg, "\\x3C$1") : str;
1718
1734
  function _escape_script(val) {
1719
1735
  return val ? escapeScriptStr(val + "") : val === 0 ? "0" : "";
1720
1736
  }
@@ -3766,9 +3782,9 @@ var for_default = {
3766
3782
  if (!isAttrTag) allowAttrs.push("by");
3767
3783
  (0, _marko_compiler_babel_utils.assertAllowedAttributes)(tag, allowAttrs);
3768
3784
  if (isAttrTag) return;
3769
- if (forType !== "of") {
3770
- if (getKnownAttrValues(tag.node).by?.type === "StringLiteral") throw (tag.get("attributes").find((attr) => attr.isMarkoAttribute() && attr.node.name === "by") || tag).buildCodeFrameError(`The [\`<for>\` tag](https://markojs.com/docs/reference/core-tag#for) only supports a string \`by\` key with \`of\`; use a \`by=(${forType === "in" ? "key, value" : "index"}) => ...\` function for \`<for ${forType}>\`.`);
3771
- }
3785
+ const byAttr = getKnownAttrValues(tag.node).by;
3786
+ if (forType !== "of" && byAttr?.type === "StringLiteral") throw tag.hub.buildError(byAttr, `The [\`<for>\` tag](https://markojs.com/docs/reference/core-tag#for) only supports a string \`by\` key with \`of\`; use a \`by=(${forType === "in" ? "key, value" : "index"}) => ...\` function for \`<for ${forType}>\`.`);
3787
+ if (byAttr?.type === "Identifier" && !tag.scope.getBinding(byAttr.name) && tag.node.body.params.some((param) => Object.hasOwn(_marko_compiler.types.getBindingIdentifiers(param), byAttr.name))) throw tag.hub.buildError(byAttr, `The \`by=\` attribute is evaluated before the loop runs, so \`${byAttr.name}\` is not in scope. Key with a property name string (\`by="id"\`) or a function (\`by=(${byAttr.name}) => key\`).`);
3772
3788
  const bodySection = startSection(tagBody);
3773
3789
  if (!bodySection) {
3774
3790
  dropNodes(getAllTagReferenceNodes(tag.node));
@@ -4300,6 +4316,7 @@ var native_tag_default = {
4300
4316
  (0, _marko_compiler_babel_utils.getProgram)().node.extra.page ??= true;
4301
4317
  break;
4302
4318
  }
4319
+ if (tagName === "option") assertOptionInSelectWithValue(tag);
4303
4320
  const isTextOnly = isTextOnlyNativeTag(tag);
4304
4321
  const seen = {};
4305
4322
  const { attributes } = tag.node;
@@ -4772,6 +4789,7 @@ function assertNativeAttrValueType(tag, attr) {
4772
4789
  if (_marko_compiler.types.isObjectExpression(attr.value)) throw tag.hub.buildError(attr, `The \`${name}\` attribute cannot be a plain object (it would render as \`[object Object]\`).`, Error);
4773
4790
  }
4774
4791
  function assertNativeHandlerAttr(tag, attr) {
4792
+ if (_marko_compiler.types.isObjectExpression(attr.value)) throw tag.hub.buildError(attr.value, `The \`${attr.name}\` ${isEventHandler(attr.name) ? "event handler" : "change handler"} on a [native tag](https://markojs.com/docs/reference/native-tag) must be a function. Attribute values in Marko are plain JavaScript expressions, not JSX; remove the wrapping \`{ }\` (e.g. \`${attr.name}=myHandler\` or \`${attr.name}() { ... }\`).`, Error);
4775
4793
  if ((0, _marko_compiler_babel_utils.computeNode)(attr.value)?.value) throw tag.hub.buildError(attr.value, `The \`${attr.name}\` ${isEventHandler(attr.name) ? "event handler" : "change handler"} on a [native tag](https://markojs.com/docs/reference/native-tag) must be a function or a falsey value (\`null\`, \`undefined\`, \`false\`, \`0\`, …).`, Error);
4776
4794
  }
4777
4795
  const lowercaseEventHandlerReg = /^on[a-z]/;
@@ -4796,6 +4814,31 @@ function getCanonicalTagName(tag) {
4796
4814
  default: return tagName;
4797
4815
  }
4798
4816
  }
4817
+ function assertOptionInSelectWithValue(tag) {
4818
+ let parent = tag.parentPath;
4819
+ while (parent) {
4820
+ if (parent.isMarkoTag()) {
4821
+ if (analyzeTagNameType(parent) === 0) {
4822
+ const parentName = getCanonicalTagName(parent);
4823
+ if (parentName === "select") {
4824
+ if (parent.node.attributes.some((attr) => _marko_compiler.types.isMarkoAttribute(attr) && (attr.name === "value" || attr.name === "valueChange"))) {
4825
+ let hasValue = false;
4826
+ const attributes = tag.get("attributes");
4827
+ for (let i = 0; i < attributes.length; i++) {
4828
+ const attr = attributes[i].node;
4829
+ if (!_marko_compiler.types.isMarkoAttribute(attr) || attr.name === "value") hasValue = true;
4830
+ else if (attr.name === "selected") throw attributes[i].buildCodeFrameError("The `selected` attribute is not supported on an `<option>` within a `<select>` that has a `value` attribute; include the option's `value` in the select's `value` instead.");
4831
+ }
4832
+ if (!hasValue) throw tag.buildCodeFrameError("An `<option>` within a `<select>` that has a `value` attribute must also have a `value` attribute.");
4833
+ }
4834
+ return;
4835
+ }
4836
+ if (parentName !== "optgroup") return;
4837
+ } else if (!isControlFlowTag(parent)) return;
4838
+ } else if (parent.isProgram()) return;
4839
+ parent = parent.parentPath;
4840
+ }
4841
+ }
4799
4842
  function getTextOnlyEscapeHelper(tagName) {
4800
4843
  switch (tagName) {
4801
4844
  case "script": return "_escape_script";
@@ -5171,8 +5214,9 @@ function flattenTextOnlyConditional(rootTag) {
5171
5214
  rootTag.replaceWith(_marko_compiler.types.markoPlaceholder(expr, true));
5172
5215
  }
5173
5216
  function assertValidCondition(tag) {
5217
+ const conditionTagName = getTagName(tag);
5174
5218
  (0, _marko_compiler_babel_utils.assertNoVar)(tag);
5175
- (0, _marko_compiler_babel_utils.assertNoArgs)(tag);
5219
+ (0, _marko_compiler_babel_utils.assertNoArgs)(tag, conditionTagName === "else" ? "Write the condition as an attribute instead: `<else if=condition>`." : `Write the condition as a value attribute instead: \`<${conditionTagName}=condition>\`.`);
5176
5220
  (0, _marko_compiler_babel_utils.assertNoParams)(tag);
5177
5221
  assertHasBody$1(tag);
5178
5222
  assertNoSpreadAttrs(tag);
@@ -5524,6 +5568,7 @@ var program_default = {
5524
5568
  }
5525
5569
  },
5526
5570
  exit(program) {
5571
+ if (hasAnalyzeErrors()) return;
5527
5572
  finalizeReferences();
5528
5573
  const programExtra = program.node.extra;
5529
5574
  const paramsBinding = programExtra.binding;
@@ -6985,7 +7030,7 @@ function addReadToExpression(root, binding, getter) {
6985
7030
  const fnRoot = getFnRoot(root);
6986
7031
  const exprRoot = getExprRoot(fnRoot || root);
6987
7032
  const section = getOrCreateSection(exprRoot);
6988
- const exprExtra = exprRoot.node.extra ??= { section };
7033
+ const exprExtra = getCanonicalExtra(exprRoot.node.extra ??= { section });
6989
7034
  const read = addRead(exprExtra, node.extra ??= {}, binding, section, getter);
6990
7035
  const { parent } = root;
6991
7036
  if (parent.type === "BinaryExpression" && (parent.operator === "===" || parent.operator === "!==")) read.comparedTo = parent.left === node ? parent.right : parent.left;
@@ -7462,9 +7507,9 @@ const kDOMBinding$2 = Symbol("await tag dom binding");
7462
7507
  var await_default = {
7463
7508
  analyze(tag) {
7464
7509
  (0, _marko_compiler_babel_utils.assertNoVar)(tag);
7465
- (0, _marko_compiler_babel_utils.assertNoArgs)(tag);
7510
+ (0, _marko_compiler_babel_utils.assertNoArgs)(tag, "Write the promise as a value attribute and receive the result as a tag parameter instead: `<await|result|=promise>`.");
7466
7511
  assertNoSpreadAttrs(tag);
7467
- (0, _marko_compiler_babel_utils.assertNoAttributeTags)(tag);
7512
+ (0, _marko_compiler_babel_utils.assertNoAttributeTags)(tag, "For pending and error UI, wrap the `<await>` in a [`<try>` tag](https://markojs.com/docs/reference/core-tag#try) with `<@placeholder>` and `<@catch|err|>` attribute tags.");
7468
7513
  const { node } = tag;
7469
7514
  const tagBody = tag.get("body");
7470
7515
  const section = getOrCreateSection(tag);
@@ -7573,7 +7618,10 @@ var const_default = {
7573
7618
  assertNoBodyContent(tag);
7574
7619
  const { node } = tag;
7575
7620
  const [valueAttr] = node.attributes;
7576
- if (!node.var) throw tag.get("name").buildCodeFrameError("The [`<const>` tag](https://markojs.com/docs/reference/core-tag#const) requires a [tag variable](https://markojs.com/docs/reference/language#tag-variables).");
7621
+ if (!node.var) {
7622
+ const looksLikeDeclaration = !node.attributes.some((attr) => _marko_compiler.types.isMarkoAttribute(attr) && (attr.default || attr.name === "value")) && node.attributes.length === 1 && _marko_compiler.types.isMarkoAttribute(node.attributes[0]) && /^[A-Za-z_$][\w$]*$/.test(node.attributes[0].name);
7623
+ throw tag.get("name").buildCodeFrameError(`The [\`<const>\` tag](https://markojs.com/docs/reference/core-tag#const) requires a [tag variable](https://markojs.com/docs/reference/language#tag-variables)${looksLikeDeclaration ? `; the variable goes after a slash: \`<const/${node.attributes[0].name}=...>\`. For a one time module level value, prefix a plain JavaScript statement with \`static\`.` : ", e.g. `<const/doubled=count * 2>`."}`);
7624
+ }
7577
7625
  if (!valueAttr) throw tag.get("name").buildCodeFrameError("The [`<const>` tag](https://markojs.com/docs/reference/core-tag#const) requires a [`value=` attribute](https://markojs.com/docs/reference/language#shorthand-value).");
7578
7626
  if (node.attributes.length > 1 || !_marko_compiler.types.isMarkoAttribute(valueAttr) || !valueAttr.default && valueAttr.name !== "value") throw tag.get("name").buildCodeFrameError("The [`<const>` tag](https://markojs.com/docs/reference/core-tag#const) only supports the [`value=` attribute](https://markojs.com/docs/reference/language#shorthand-value).");
7579
7627
  const valueExtra = evaluate(valueAttr.value);
@@ -7772,6 +7820,7 @@ var export_default = {
7772
7820
  //#endregion
7773
7821
  //#region src/translator/core/html-comment.ts
7774
7822
  const kNodeBinding$1 = Symbol("comment tag binding");
7823
+ const escapeCommentText = (text) => text.replace(/>/g, "&gt;");
7775
7824
  var html_comment_default = {
7776
7825
  analyze(tag) {
7777
7826
  (0, _marko_compiler_babel_utils.assertNoArgs)(tag);
@@ -7809,11 +7858,11 @@ var html_comment_default = {
7809
7858
  const nodeBinding = tagExtra[kNodeBinding$1];
7810
7859
  const write = writeTo(tag);
7811
7860
  if (isOutputHTML()) {
7812
- for (const child of tag.node.body.body) if (_marko_compiler.types.isMarkoText(child)) write`${child.value}`;
7861
+ for (const child of tag.node.body.body) if (_marko_compiler.types.isMarkoText(child)) write`${escapeCommentText(child.value)}`;
7813
7862
  else if (_marko_compiler.types.isMarkoPlaceholder(child)) write`${callRuntime(child.escape ? "_escape_comment" : "_unescaped", child.value)}`;
7814
7863
  } else {
7815
7864
  const textLiteral = bodyToTextLiteral(tag.node.body);
7816
- if (_marko_compiler.types.isStringLiteral(textLiteral)) write`${textLiteral}`;
7865
+ if (_marko_compiler.types.isStringLiteral(textLiteral)) write`${escapeCommentText(textLiteral.value)}`;
7817
7866
  else addStatement("render", tagSection, tagExtra.referencedBindings, _marko_compiler.types.expressionStatement(callRuntime("_text", createScopeReadExpression(nodeBinding), textLiteral)));
7818
7867
  }
7819
7868
  exit(tag);
@@ -7937,7 +7986,8 @@ var let_default = {
7937
7986
  } else {
7938
7987
  const start = attr.loc?.start;
7939
7988
  const end = attr.loc?.end;
7940
- const msg = "The [`<let>` tag](https://markojs.com/docs/reference/core-tag#let) only supports the [`value=` attribute](https://markojs.com/docs/reference/language#shorthand-value) and its change handler.";
7989
+ let msg = "The [`<let>` tag](https://markojs.com/docs/reference/core-tag#let) only supports the [`value=` attribute](https://markojs.com/docs/reference/language#shorthand-value) and its change handler.";
7990
+ if (!tagVar && /^[A-Za-z_$][\w$]*$/.test(attr.name)) msg += ` To declare reactive state, the variable goes after a slash: \`<let/${attr.name}=...>\`. For a one time module level value, prefix a plain JavaScript statement with \`static\`.`;
7941
7991
  if (start == null || end == null) throw tag.get("name").buildCodeFrameError(msg);
7942
7992
  else throw tag.hub.buildError({ loc: {
7943
7993
  start,
@@ -7948,7 +7998,7 @@ var let_default = {
7948
7998
  (0, _marko_compiler_babel_utils.assertNoParams)(tag);
7949
7999
  assertNoBodyContent(tag);
7950
8000
  assertNoSpreadAttrs(tag);
7951
- if (!tagVar) throw tag.get("name").buildCodeFrameError("The [`<let>` tag](https://markojs.com/docs/reference/core-tag#let) requires a [tag variable](https://markojs.com/docs/reference/language#tag-variables).");
8001
+ if (!tagVar) throw tag.get("name").buildCodeFrameError("The [`<let>` tag](https://markojs.com/docs/reference/core-tag#let) requires a [tag variable](https://markojs.com/docs/reference/language#tag-variables), e.g. `<let/count=0>`.");
7952
8002
  if (!_marko_compiler.types.isIdentifier(tagVar)) throw tag.get("var").buildCodeFrameError("The [`<let>` tag](https://markojs.com/docs/reference/core-tag#let) variable cannot be destructured.");
7953
8003
  if (valueChangeAttr && (0, _marko_compiler_babel_utils.computeNode)(valueChangeAttr.value)?.value) throw tag.get("attributes").find((attr) => attr.node === valueChangeAttr).get("value").buildCodeFrameError("The [`<let>` tag](https://markojs.com/docs/reference/core-tag#let) [`valueChange=` attribute](https://markojs.com/docs/reference/core-tag#controllable-let) must be a function.");
7954
8004
  const tagSection = getOrCreateSection(tag);
@@ -8312,7 +8362,7 @@ function isLiteral(expr) {
8312
8362
  }
8313
8363
  function assertValidShow(tag) {
8314
8364
  (0, _marko_compiler_babel_utils.assertNoVar)(tag);
8315
- (0, _marko_compiler_babel_utils.assertNoArgs)(tag);
8365
+ (0, _marko_compiler_babel_utils.assertNoArgs)(tag, "Write the condition as a value attribute instead: `<show=condition>`.");
8316
8366
  (0, _marko_compiler_babel_utils.assertNoParams)(tag);
8317
8367
  assertNoSpreadAttrs(tag);
8318
8368
  assertHasBody(tag);
@@ -9053,7 +9103,7 @@ function getInlinedBodyTag(parent) {
9053
9103
  }
9054
9104
  //#endregion
9055
9105
  //#region src/translator/visitors/referenced-identifier.ts
9056
- const abortIdsByExpressionForSection = /* @__PURE__ */ new WeakMap();
9106
+ const [getAbortResetEmitted] = createSectionState("abortResetEmitted", () => /* @__PURE__ */ new Set());
9057
9107
  var referenced_identifier_default = {
9058
9108
  migrate(identifier) {
9059
9109
  const { name } = identifier.node;
@@ -9073,6 +9123,9 @@ var referenced_identifier_default = {
9073
9123
  const section = getOrCreateSection(identifier);
9074
9124
  section.hasAbortSignal = true;
9075
9125
  setReferencesScope(identifier);
9126
+ const exprRoot = getExprRoot(identifier);
9127
+ const rootExtra = exprRoot.node.extra ??= { section };
9128
+ if (rootExtra.abortId === void 0) rootExtra.abortId = section.abortSignalExprs++;
9076
9129
  }
9077
9130
  },
9078
9131
  translate(identifier) {
@@ -9087,16 +9140,10 @@ var referenced_identifier_default = {
9087
9140
  else {
9088
9141
  const section = getSection(identifier);
9089
9142
  const exprRoot = getExprRoot(identifier);
9090
- let abortIdsByExpression = abortIdsByExpressionForSection.get(section);
9091
- let exprId;
9092
- if (abortIdsByExpression) exprId = abortIdsByExpression.get(exprRoot);
9093
- else {
9094
- abortIdsByExpression = /* @__PURE__ */ new Map();
9095
- abortIdsByExpressionForSection.set(section, abortIdsByExpression);
9096
- }
9097
- if (exprId === void 0) {
9098
- exprId = abortIdsByExpression.size;
9099
- abortIdsByExpression.set(exprRoot, exprId);
9143
+ const exprId = exprRoot.node.extra.abortId;
9144
+ const resetEmitted = getAbortResetEmitted(section);
9145
+ if (!resetEmitted.has(exprRoot)) {
9146
+ resetEmitted.add(exprRoot);
9100
9147
  addStatement("render", section, exprRoot.node.extra?.referencedBindings, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(importRuntime("$signalReset"), [scopeIdentifier, _marko_compiler.types.numericLiteral(exprId)])), false);
9101
9148
  }
9102
9149
  identifier.replaceWith(_marko_compiler.types.callExpression(importRuntime("$signal"), [scopeIdentifier, _marko_compiler.types.numericLiteral(exprId)]));
@@ -9108,7 +9155,11 @@ var referenced_identifier_default = {
9108
9155
  //#region src/translator/visitors/scriptlet.ts
9109
9156
  var scriptlet_default = {
9110
9157
  analyze(scriptlet) {
9111
- if (!scriptlet.node.static) throw scriptlet.buildCodeFrameError("Scriptlets are not supported when using the tags api.");
9158
+ if (!scriptlet.node.static) {
9159
+ reportAnalyzeError(scriptlet, scriptlet.buildCodeFrameError("Scriptlets are not supported when using the tags api."));
9160
+ scriptlet.skip();
9161
+ return;
9162
+ }
9112
9163
  mergeReferences(getOrCreateSection(scriptlet), scriptlet.node, scriptlet.node.body);
9113
9164
  if (scriptlet.node.target === "client") (0, _marko_compiler_babel_utils.getProgram)().node.extra.isInteractive = true;
9114
9165
  },
@@ -9267,11 +9318,18 @@ function getTagRelativePath(tag) {
9267
9318
  if (!relativePath) throw tagNotFoundError(tag);
9268
9319
  return relativePath;
9269
9320
  }
9321
+ const knownWrongTags = /* @__PURE__ */ new Map([
9322
+ ["slot", "To render content passed to this tag, use a [dynamic tag](https://markojs.com/docs/reference/language#dynamic-tags): `<${input.content}/>`."],
9323
+ ["state", "Reactive state is declared with the [`<let>` tag](https://markojs.com/docs/reference/core-tag#let): `<let/name=initialValue>`."],
9324
+ ["fragment", "Marko templates and tag bodies may have multiple root nodes; no fragment wrapper is needed."]
9325
+ ]);
9270
9326
  function tagNotFoundError(tag) {
9271
9327
  const tagName = getTagName(tag);
9272
9328
  if (tagName && tag.scope.hasBinding(tagName)) return tag.get("name").buildCodeFrameError(`Local variables must be in a [dynamic tag](https://markojs.com/docs/reference/language#dynamic-tags) unless they are PascalCase. Use \`<\${${tagName}}/>\` or rename to \`${tagName.charAt(0).toUpperCase() + tagName.slice(1)}\`.`);
9273
9329
  let didYouMean = "";
9274
- if (tagName) {
9330
+ const knownWrongTagHint = tagName && knownWrongTags.get(tagName);
9331
+ if (knownWrongTagHint) didYouMean = ` ${knownWrongTagHint}`;
9332
+ else if (tagName) {
9275
9333
  const closestTag = (0, fastest_levenshtein.closest)(tagName, Object.keys((0, _marko_compiler_babel_utils.getTaglibLookup)(tag.hub.file).merged.tags));
9276
9334
  if ((0, fastest_levenshtein.distance)(tagName, closestTag) < 4) didYouMean = ` Did you mean \`<${closestTag}>\`?`;
9277
9335
  }
@@ -9478,33 +9536,46 @@ function enableDynamicTagResume(tag) {
9478
9536
  var tag_default = {
9479
9537
  analyze: {
9480
9538
  enter(tag) {
9481
- const tagDef = (0, _marko_compiler_babel_utils.getTagDef)(tag);
9482
- const type = analyzeTagNameType(tag);
9483
- const hook = tagDef?.analyzer?.hook;
9484
- if (hook) {
9485
- enter$1(hook, tag);
9486
- return;
9487
- }
9488
- if (type === 0) {
9489
- native_tag_default.analyze.enter(tag);
9490
- return;
9491
- }
9492
- switch (type) {
9493
- case 1:
9494
- custom_tag_default.analyze.enter(tag);
9495
- break;
9496
- case 3:
9497
- attribute_tag_default.analyze.enter(tag);
9498
- break;
9499
- case 2:
9500
- dynamic_tag_default.analyze.enter(tag);
9501
- break;
9539
+ try {
9540
+ const tagDef = (0, _marko_compiler_babel_utils.getTagDef)(tag);
9541
+ const type = analyzeTagNameType(tag);
9542
+ const hook = tagDef?.analyzer?.hook;
9543
+ if (hook) {
9544
+ enter$1(hook, tag);
9545
+ return;
9546
+ }
9547
+ if (type === 0) {
9548
+ native_tag_default.analyze.enter(tag);
9549
+ return;
9550
+ }
9551
+ switch (type) {
9552
+ case 1:
9553
+ custom_tag_default.analyze.enter(tag);
9554
+ break;
9555
+ case 3:
9556
+ attribute_tag_default.analyze.enter(tag);
9557
+ break;
9558
+ case 2:
9559
+ dynamic_tag_default.analyze.enter(tag);
9560
+ break;
9561
+ }
9562
+ } catch (err) {
9563
+ (tag.node.extra ??= {}).analyzeFailed = true;
9564
+ reportAnalyzeError(tag, err);
9565
+ tag.skip();
9502
9566
  }
9503
9567
  },
9504
9568
  exit(tag) {
9505
- const hook = (0, _marko_compiler_babel_utils.getTagDef)(tag)?.analyzer?.hook;
9506
- if (hook) {
9507
- exit$1(hook, tag);
9569
+ if (tag.node.extra?.analyzeFailed) return;
9570
+ try {
9571
+ const hook = (0, _marko_compiler_babel_utils.getTagDef)(tag)?.analyzer?.hook;
9572
+ if (hook) {
9573
+ exit$1(hook, tag);
9574
+ return;
9575
+ }
9576
+ } catch (err) {
9577
+ (tag.node.extra ??= {}).analyzeFailed = true;
9578
+ reportAnalyzeError(tag, err);
9508
9579
  return;
9509
9580
  }
9510
9581
  }
@@ -0,0 +1,3 @@
1
+ import type { types as t } from "@marko/compiler";
2
+ export declare function reportAnalyzeError(path: t.NodePath<t.Node>, error: unknown): void;
3
+ export declare function hasAnalyzeErrors(): boolean;
@@ -47,6 +47,9 @@ export interface Section {
47
47
  properties: Opt<string>;
48
48
  } | false | undefined;
49
49
  hasAbortSignal: boolean;
50
+ /** Count of distinct `$signal` expression roots; analyze allocates each
51
+ * root's `abortId` from this so translates read, never re-derive. */
52
+ abortSignalExprs: number;
50
53
  readsOwner: boolean;
51
54
  isBranch: boolean;
52
55
  content: null | {
@@ -1,4 +1,11 @@
1
1
  import { types as t } from "@marko/compiler";
2
+ declare module "@marko/compiler/dist/types" {
3
+ interface NodeExtra {
4
+ /** `$signal` abort id for this expression root, allocated in analyze
5
+ * (see below) so every translate reads the same id. */
6
+ abortId?: number;
7
+ }
8
+ }
2
9
  declare const _default: {
3
10
  migrate(this: unknown, identifier: t.NodePath<t.Identifier>): void;
4
11
  analyze(this: unknown, identifier: t.NodePath<t.Identifier>): void;
@@ -1,4 +1,9 @@
1
1
  import { types as t } from "@marko/compiler";
2
+ declare module "@marko/compiler/dist/types" {
3
+ interface MarkoTagExtra {
4
+ analyzeFailed?: boolean;
5
+ }
6
+ }
2
7
  declare const _default: {
3
8
  analyze: {
4
9
  enter(this: unknown, tag: t.NodePath<t.MarkoTag>): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marko/runtime-tags",
3
- "version": "6.3.1",
3
+ "version": "6.3.3",
4
4
  "description": "Optimized runtime for Marko templates.",
5
5
  "keywords": [
6
6
  "api",
@@ -20,6 +20,7 @@
20
20
  ".": {
21
21
  "types": "./index.d.ts"
22
22
  },
23
+ "./cheatsheet.md": "./cheatsheet.md",
23
24
  "./package.json": "./package.json",
24
25
  "./translator": "./dist/translator/index.js",
25
26
  "./tags/*": "./tags/*",
@@ -43,13 +44,14 @@
43
44
  "tags-html.d.ts",
44
45
  "!**/meta.*.json",
45
46
  "!**/__tests__",
46
- "!**/*.tsbuildinfo"
47
+ "!**/*.tsbuildinfo",
48
+ "cheatsheet.md"
47
49
  ],
48
50
  "scripts": {
49
51
  "build": "node -r ~ts ./scripts/bundle.mts"
50
52
  },
51
53
  "dependencies": {
52
- "@marko/compiler": "^5.39.66",
54
+ "@marko/compiler": "^5.40.2",
53
55
  "csstype": "^3.2.3",
54
56
  "fastest-levenshtein": "^1.0.16",
55
57
  "magic-string": "^0.30.21"
@@ -61,6 +63,7 @@
61
63
  ".": {
62
64
  "types": "./index.d.ts"
63
65
  },
66
+ "./cheatsheet.md": "./cheatsheet.md",
64
67
  "./translator": "./src/translator/index.ts",
65
68
  "./tags/*": "./tags/*",
66
69
  "./debug/*": "./src/*.ts",