Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions agent-feedback/bugs.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ Out-of-scope defects noticed while working on something else. Format and rules:
`docs/reference/core-tag.md` › `## <html-script> & <html-style>` | 2026-07-29 | impact:low | effort:low

`docs/reference/native-tag.md` has two headings that slug to the same base: the `style=` heading under Enhanced Attributes and the `<style>` heading under Enhanced Tags. `github-slugger` resolves collisions in document order, so the attribute section (line 56) takes `#style` while the tag section (line 533) becomes `#style-1`. Both `./native-tag.md#style` links in `core-tag.md` mean the `<style>` tag but land the reader on the unrelated `style=` attribute. `#script` is unaffected, since the `<script>` heading is the only one slugging to it. Prefer renaming one heading over hardcoding `#style-1`, which would rot silently if heading order ever changed. Re-verify from the repo root: `node --input-type=module -e "import S from './node_modules/github-slugger/index.js'; const s = new S(); for (const h of ['class=','style=','Event Handlers','<script>','<style>']) console.log(h, '->', s.slug(h))"` prints `style= -> style` and `<style> -> style-1`.

## Add `NaN` and `0n` to the values that drop a `style=` declaration

`docs/reference/native-tag.md` › `### style=` | 2026-07-30 | impact:low | effort:low

The `style=` section states "A declaration is dropped when its value is `false`, `null`, `undefined` or an empty string, but `0` is kept" (line 90), which reads as the complete set but omits `NaN` and bigint `0n`. Marko's runtime writes a declaration only when `value || value === 0` (`stringifyStyleObject` in the marko repo's `packages/runtime-tags/src/common/helpers.ts`, where a bigint never satisfies `0n === 0`), so `<div style={ "line-height": total / count }/>` with a `count` of `0` renders no `line-height` declaration at all rather than the ignored `line-height:NaN` the current wording promises, and a `0n` value disappears the same way while the equivalent attribute still writes `NaN` or `0`. `docs/reference/language.md` already lists all six values under [Skipped Values](./language.md#skipped-values) for dynamic text and contrasts them with skipped attributes, so the `style=` sentence should carry the same set and link there; the neighboring `class=` claim ("every falsy value drops the class") needs no change, since a class name is kept only when its value is truthy. Re-verify: `grep -n "A declaration is dropped" docs/reference/native-tag.md` lists four values against the six in `grep -n "renders nothing" docs/reference/language.md`, then run `pnpm run lint`.
6 changes: 6 additions & 0 deletions agent-feedback/unclear.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,9 @@ Things that were hard to understand, and what would have clarified them. Format
`docs/reference/template.md` › `Template.mount(input, node, position?)` | 2026-07-19 | impact:low | effort:low

The `Template.mount(input, node, position?)` parameter table lists a Default of `{}` for `input` and `"beforeend"` for `position` (both real defaults) but `undefined` for `node`, which reads as "node is optional and defaults to undefined". `node` is actually required: `packages/runtime-tags/index.d.ts` in the marko repo declares `mount(input, reference: Node, position?)` with `reference` non-optional, and `packages/runtime-tags/src/dom/template.ts` › `mount` defaults only `input = {}` while `reference` has no default and is dereferenced unconditionally (`parentNode = reference as ParentNode`), so `template.mount(input)` is a type error and throws at runtime. The doc's own examples always pass a node (`template.mount({}, document.body)`), confirming node is mandatory. Agents treat parameter tables as the machine-readable contract: an agent building a client mount or test harness reads "node: Default undefined", writes `template.mount(input)` expecting a detached mount, and burns a debug cycle on the type mismatch — or, working from the rendered doc without a type-check, ships code that crashes on the undefined reference. Replace the `undefined` cell with "required" (or split required params from defaulted ones) so the table agrees with the `reference: Node` signature. Re-verify: read the parameter table under the `Template.mount` heading.

## Document when a `<script>` that reads a tag variable first runs

`docs/reference/core-tag.md` › `## <script>` | 2026-07-30 | impact:med | effort:low

The `<script>` section says the body "is executed first when the template has finished rendering and is mounted in the browser" (line 370) and re-runs when a referenced tag variable changes, which leaves source order as the only ordering a reader can infer between two `<script>` tags. Marko compiles a `<script>` that reads a tag variable into that variable's own setup, so it first runs when the variable initializes, ahead of an earlier-in-source `<script>` that reads nothing: given `<let/board=DEFAULT/>`, a first script that only assigns `board` from `localStorage`, and a second that reads `board` and writes it back, the second runs first with `DEFAULT` and overwrites the saved value before the restore reads it (compiled dom output puts the persist effect inside `_let(...)` while the restore stays a separate `$setup__script`). The page's own `<script=remember/>` example already persists `input.collapsed` to `sessionStorage` without saying when it first fires, so the rule belongs there, stated positively: reading a tag variable ties the effect to that variable's initialization. The paired restore-and-persist idiom belongs under `## <lifecycle>`, whose `onMount`/`onUpdate` handlers already model "set up once, then follow the value" and give `<script>` somewhere to link. Re-verify: `grep -n "finished rendering" docs/reference/core-tag.md` is the page's only ordering statement and `grep -rn "localStorage" docs/` returns nothing, so neither the rule nor the idiom is documented today; the clobber itself reproduces in the local playground (`pnpm run dev`).
Loading