{"owner":"marko-js","repo":"marko","hasSkills":true,"totalSkillsCount":48,"totalTokensCount":87874,"categories":["root-instruction","claude-rule","anthropic-skill","plugin-manifest"],"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md","CLAUDE.md","packages/compiler/AGENTS.md","packages/compiler/README.md","packages/runtime-class/AGENTS.md","packages/runtime-class/README.md","packages/runtime-class/docs/10-awesome-marko-features.md","packages/runtime-class/docs/body-content.md","packages/runtime-class/docs/class-components.md","packages/runtime-class/docs/cloudflare-workers.md","packages/runtime-class/docs/compiler.md","packages/runtime-class/docs/concise.md","packages/runtime-class/docs/conditionals-and-lists.md","packages/runtime-class/docs/core-tags.md","packages/runtime-class/docs/custom-tags.md","packages/runtime-class/docs/editor-plugins.md","packages/runtime-class/docs/events.md","packages/runtime-class/docs/express.md","packages/runtime-class/docs/fastify.md","packages/runtime-class/docs/getting-started.md","packages/runtime-class/docs/http.md","packages/runtime-class/docs/installing.md","packages/runtime-class/docs/koa.md","packages/runtime-class/docs/lasso.md","packages/runtime-class/docs/marko-5-upgrade.md","packages/runtime-class/docs/marko-json.md","packages/runtime-class/docs/marko-vs-react.md","packages/runtime-class/docs/redux.md","packages/runtime-class/docs/rendering.md","packages/runtime-class/docs/rollup.md","packages/runtime-class/docs/state.md","packages/runtime-class/docs/structure.json","packages/runtime-class/docs/styles.md","packages/runtime-class/docs/syntax.md","packages/runtime-class/docs/troubleshooting-streaming.md","packages/runtime-class/docs/typescript.md","packages/runtime-class/docs/vite.md","packages/runtime-class/docs/webpack.md","packages/runtime-class/docs/why-is-marko-fast.md","packages/runtime-class/helpers/README.md","packages/runtime-tags/AGENTS.md","packages/runtime-tags/README.md","skills/README.md","skills/marko-5-to-6-migration/SKILL.md","skills/marko-5-to-6-migration/api-mapping.md","skills/marko-5-to-6-migration/interop.md","skills/marko-5-to-6-migration/patterns.md","skills/marko-best-practices/SKILL.md"],"skills":{"AGENTS.md":"# Marko Monorepo\n\nMarko compiles `.marko` templates into optimized server (streaming HTML) and client (fine-grained DOM) JavaScript. pnpm workspaces; Node >= 22.18 (native TS type stripping + module.registerHooks). Primary development happens in `packages/runtime-tags`.\n\n## Packages\n\n- [`packages/compiler`](packages/compiler/AGENTS.md) — `@marko/compiler`. Translator-agnostic: parses `.marko` into a (patched) Babel AST, then hands off to a translator for codegen.\n- [`packages/runtime-tags`](packages/runtime-tags/AGENTS.md) — `marko@6` / `@marko/runtime-tags`. The Marko 6 runtime **and** its translator. **Primary development.**\n- [`packages/runtime-class`](packages/runtime-class/AGENTS.md) — `marko@5` (private package, published only as `marko`). Marko 5, in maintenance; its translator wraps the class-API translator with runtime-tags' interop layer.\n\nA \"translator\" is the Babel-plugin half of a runtime package; the compiler loads it as `<pkg>/translator`. \"Marko 6\" is the runtime-tags version — the compiler stays 5.x.\n\n## Commands\n\nAll from repo root. Tests and tooling run directly from TS source (native Node type stripping plus the `~ts` resolve hook for extensionless imports; package `exports` point at `src/` until publish), so no build step is needed to iterate.\n\n```sh\npnpm test                                                 # whole suite fanned across CPU cores (~3x faster than serial)\npnpm test -- --grep \"runtime-tags/translator <fixture> \"  # scoped test run\npnpm run test:serial -- --grep \"...\"                      # same run in one process: bail at first failure, live output, --inspect-brk\npnpm test -- <file.test.ts>                               # only the given spec files (dirs and globs work too)\npnpm run test:update -- --grep \"...\"                      # regenerate snapshots (review the diff!)\npnpm run compile -- -o dom -d foo.marko                   # print compiled output (-o html for SSR; omit -d for optimized)\npnpm run build                                            # all packages -> dist/ + .d.ts\npnpm run build:sizes                                      # bundle-size table; diffs vs .sizes.json\npnpm run lint                                             # oxlint + oxfmt check\npnpm run format                                           # oxlint --fix + oxfmt write\npnpm run change                                           # add a changeset (required for user-facing changes)\n```\n\n`pnpm run compile` is the fastest way to inspect what the translator generates. It writes nothing: each compiled module, and then any module the translator generates for it, prints to stdout under a `// <resolved path>` header. (Pass `-t class` for the Marko 5 translator; `-t` also accepts a full translator module id.)\n\n`pnpm run change` prompts, so write `.changeset/<name>.md` directly, naming the package that owns the changed code: `packages/compiler` is `@marko/compiler`, `packages/runtime-tags` is `@marko/runtime-tags`, `packages/runtime-class` is `marko`. `pnpm exec changeset status` fails on a name that is no workspace package (which would break the release on `main`), but not on the wrong one: `marko` for a runtime-tags fix passes and publishes the wrong package. Restricting behavior that was already broken is a fix (`patch`), never described as a breaking change.\n\n## Repo invariants\n\n- **Dependencies are patched.** `patches/` (applied by pnpm patchedDependencies on install) adds Marko AST node types to `@babel/types`/`traverse`/`generator`, and makes mocha print the `require()` error it otherwise drops when its `import()` fallback rescues a spec. The Babel patches only add Marko AST support; never patch Babel's own behavior. Import Babel only via `@marko/compiler/internal/babel` and helpers via `@marko/compiler/babel-utils`, never `@babel/*` directly. Bumping any patched dependency requires regenerating its patch.\n- **Bundle size is a feature.** The pre-commit hook runs lint-staged, a full build, and `build:sizes`, staging `.sizes.json`/`.sizes/` — that diff is the size impact of the change. Commits are slow by design. The floor is `.sizes/counter.ssr` and `.sizes/comments.ssr` (a resumed page with no async, reorder, lazy, or dynamic html): code for an optional feature, even one `?.`, must fold out of them. Lint rules whose fix rewrites runtime code into larger output stay off in `.oxlintrc.json` (`unicorn/prefer-string-starts-ends-with`, `unicorn/no-new-array`); enabling one means checking `build:sizes` first.\n- **Snapshots and sizes are generated.** Never hand-edit _or delete_ `__snapshots__/**`, fixture `sizes.json`, or `.sizes*`; regenerate with `pnpm run test:update` (which also prunes stale snapshots after a green run) and the commit hook.\n- **CI** (`.github/workflows/ci.yml`): build + lint on Node 26; tests on Node 22/24/26 (zcov coverage). Releases go out via changesets on push to `main`.\n\n## Conventions\n\nOrganize files top-down (progressive disclosure): public API/exports first, then orchestration, helpers, and low-level detail last — use function-declaration hoisting.\n\nComments are a last resort and never exceed two lines: prefer self-describing code, and when one is needed it captures intent — never what the code was or what was removed. Wording is plain and direct, with no invented shorthand.\n\nDerive before adding. Before a new field, flag, helper, state container, parameter, test config, or module, find the existing analysis, helper, or runtime structure that already answers it and extend that. A parallel mechanism for one feature (one the rest of the code never needed) is a smell: say in the summary why nothing existing fits.\n\nEvery line needs a reason you can name. No guards, `?.`, fallbacks, casts (`as never`, `as any`, or one the type already satisfies), or parameters for states the design rules out; lean on the invariant (`!`, or a `MARKO_DEBUG` assert). Name checks, dependency method overrides, and machine heuristics are hacks: find the structural fix. A perf or config knob ships only with a measured win, and never restates a default. Measure performance on the bundled build that ships (`pnpm run build`), not the TS source that tests and tooling run: V8 inlines the bundle's module-level function declarations but not those of an ES module, so source timings can mislead.\n\nDon't bend the code around an edge case. Input the design has no reason to support (a `NaN` loop key, say) gets a compile error or a `MARKO_DEBUG` error that rules it out, not runtime handling that every caller pays for in size or speed. Harden the invariant, then rely on it.\n\nWrite the direct form. No rest or spread to copy, extend, or strip an object: share one record, or key a collection by the field it lacks. Client runtime code, where bundle size comes first, may keep a spread that `build:sizes` shows is smallest, but it is still a red flag to justify. No function that only forwards, and no type named for a single use. A helper every caller guards takes the `undefined` itself, and a flag is set as `flag ||= condition`.\n\nDon't add Babel `NodePath` helper calls (`findParent`, `find`, `getFunctionParent`, …): walk `parentPath` and compare node types directly; existing uses are migrated later.\n\nNames come from the code. Reuse the vocabulary of neighboring code, [`CONTEXT.md`](packages/runtime-tags/CONTEXT.md), and the markojs.com docs; never coin a term the codebase does not already use.\n\nTest through existing fixture families; add a test file only when no fixture can reach the behavior. A fix adds a fixture that fails without it, and so does every branch or statement a change adds: revert each one and confirm a fixture fails. Code no fixture needs is deleted, never kept behind a fixture that passes either way.\n\nMarko language reference: <https://markojs.com/llms.txt> lists every docs page; append `.md` to any docs URL for markdown.\n\n## Agent feedback\n\nAnything actionable but out of scope for the current task (suspected bug, cleanup, perf or size win, tooling friction, confusing code) must be filed in [`agent-feedback/`](agent-feedback/README.md) before finishing. Never drop it silently. Never fix it inside an unrelated diff. In scope, so fixed rather than filed: a defect in code the diff touches or exposes, and anything in the unreleased feature a branch builds (which also takes no changesets). A deliberate limitation gets a site comment, not an item.\n","CLAUDE.md":"AGENTS.md","packages/compiler/AGENTS.md":"# `@marko/compiler`\n\nTranslator-agnostic compiler: parses `.marko` into a Babel AST (custom node types like `MarkoTag`, `MarkoAttribute` — added to Babel by the root `patches/`), runs migrate/transform passes, then hands the AST to a **translator** (`@marko/runtime-tags/translator` or `marko/translator`) for codegen. Stays at v5.x; language changes belong in the translators, not here.\n\n## Map\n\n- `src/index.js` — public API: `compile[File][Sync](src, filename, config)` → `{ code, map, meta, ast }`, `configure`, `taglib`, `types`.\n- `src/config.js` — config defaults, and the `globalConfig` that `configure()` sets (both re-exported by `index.js`); an omitted translator in `getRuntimeEntryFiles`, `getRuntimeVersion` and `taglib.buildLookup` reads it. Key options: `output` (`\"html\"` | `\"dom\"` | `\"source\"` | `\"migrate\"`), `optimize`, `translator`, `modules` (`\"esm\"`/`\"cjs\"`), `optimizeKnownTemplates`, `errorRecovery`, `cache`, `fileSystem`.\n- `src/babel-plugin/` — pipeline core. Stages: `parse → migrate → transform → analyze` (cached per template) then `translate` on a clone. Taglib visitors run in `migrate`, `transform` and `translate` — including those from the taglibs a translator registers via `taglibs`/`optionalTaglibs`, which is how a translator contributes migrators. The translator's own hooks are `transform` (optional), `analyze` and `translate`; there is no `translator.migrate` hook, and `analyze` is translator-only — a taglib-level `analyze` prop is a hard load error. Taglib `translate` is skipped for `output: \"hydrate\"`.\n- `src/taglib/` — tag registry/discovery: built-in HTML/SVG/MathML JSON taglibs, `marko.json` / `marko-tag.json` discovery walking up from the template, `buildLookup`.\n- `src/babel-utils/` — the helper API for translator authors (`assert*`, `diagnostic*`, `import*`, `parse*`, `getTagDef`, `isNativeTag`, `resolveTagImport`, ...). Exported as `@marko/compiler/babel-utils`.\n- `internal/babel/index.ts` — the single controlled Babel entry, re-exported as `@marko/compiler/internal/babel`. All Babel access (here and in translators) goes through it, never `@babel/*` directly.\n\n## Translator contract\n\nA translator module exports: `translate` (required visitor), `taglibs` (required, `[[id, props]]`), optional `transform` / `analyze` visitors, `tagDiscoveryDirs`, `optionalTaglibs`, `preferAPI` (`\"tags\"` | `\"class\"`), `getRuntimeEntryFiles(output, optimize)`, and optionally `cheatsheet` (a module-relative path to an LLM syntax reference; `tryLoadTranslator` resolves it to a cwd-relative path and `util/agent-fix-guide.js` points coding agents at it on compile errors). Loading is resolved from `config.translator` or auto-detected from the app's dependencies (`util/try-load-translator.js`, default logic in `config.js`).\n\n## Notes\n\n- `output: \"source\"` / `\"migrate\"` re-print `.marko` source (tooling/codemods) — no translator codegen.\n- Bumping any `@babel/*` version requires regenerating the corresponding patch in root `patches/` (pnpm patchedDependencies); the custom AST types and generated `dist/types.d.ts` (`pnpm --filter @marko/compiler run build-babel-types`) depend on them.\n- Adding a core tag in a translator shows up in taglib-lookup expectations here and in `packages/runtime-class/test/taglib-lookup/`.\n- `util/agent-fix-guide.js` — when a terminal coding agent is detected (env markers; `AI_AGENT=1` is the generic opt-in for harnesses not on the list) and the loaded translator declares a `cheatsheet`, thrown compile errors get a one-line pointer to it (relative to `cwd`) appended at the `compile[Sync]` boundary (to `message`, and to a `CompileError`'s `label`, which bundler plugins like `@marko/vite` print in place of the framed message), and under `errorRecovery` — where nothing throws — the same pointer is appended to the first error in `meta.diagnostics` instead. `MARKO_AGENT_FIX_GUIDE` overrides the sniff in either direction: `0` suppresses the guide, any other value forces it on (e.g. when compiling in a subprocess that drops the inherited marker). No-op for humans, for runtimes without a cheat sheet, and for inline translator objects (so error snapshots, which compile with an inline translator object, are unaffected).\n","packages/compiler/README.md":"# @marko/compiler\n\nCompiles [Marko](https://markojs.com/) templates into JavaScript modules.\n\nThe [bundler integrations](https://markojs.com/docs/introduction/integrations#bundlers) call the compiler for every template, so applications rarely use it directly. It is the API for building a bundler integration, a test transform, or other tooling around Marko templates.\n\n```sh\nnpm install @marko/compiler\n```\n\n```js\nimport * as compiler from \"@marko/compiler\";\n\nconst { code, map } = await compiler.compileFile(\"./src/card.marko\", {\n  output: \"dom\",\n  sourceMaps: true,\n});\n```\n\nSee the [Compiler API reference](https://markojs.com/docs/reference/compiler) for the compile functions, their options and the compile result.\n","packages/runtime-class/AGENTS.md":"# Marko 5 (runtime & translator)\n\n## Architecture\n\nThe package is organized into four layers:\n\n| Directory              | Purpose                                                                |\n| ---------------------- | ---------------------------------------------------------------------- |\n| `src/runtime/helpers/` | Shared runtime helpers (class/style values, dynamic tags, attr-tags)   |\n| `src/runtime/html/`    | SSR runtime: streaming HTML output, helpers, hot reload                |\n| `src/runtime/vdom/`    | CSR runtime: virtual DOM, morphdom reconciliation, component lifecycle |\n| `src/translator/`      | Babel-based compiler that transforms `.marko` into SSR/CSR JavaScript  |\n\nThe compiler/translator entry is `src/translator/index.js`, but the package's exported translator (`src/translator.js`) wraps it with `createInteropTranslator` from `@marko/runtime-tags/translator`, so Marko 5 projects can mix in Marko 6 (Tags API) components. Interop behavior changes are usually made in `packages/runtime-tags/src/translator/interop/`, not here.\n\nNote: the package is private (named `marko`); `scripts/publish-alias.mts` publishes it as `marko` under the `m5` dist-tag.\n\nCompiled templates import runtime helpers by string path (`marko/src/runtime/helpers/...`, see `translator/util/load-import.js`), so a source search for importers misses those uses.\n\n`src` mixes ESM and CommonJS `.js` with no `\"type\"`, so Node warns `MODULE_TYPELESS_PACKAGE_JSON` under `-t class`. Accepted: Marko 5 is in maintenance and `src` ships in `files`, so a `{\"type\":\"module\"}` marker would force converting every CJS file.\n\n## Naming Conventions\n\n### Triple-underscore prefix (`___name`)\n\nAll internal properties and methods on runtime objects use a triple-underscore prefix:\n\n```js\nthis.___state;\ncomponent.___queueUpdate();\nexports.___batchUpdate = batchUpdate;\n```\n\nThe build step mangles these names into short single-character identifiers.\n\n### `MARKO_DEBUG` pattern\n\nDebug-only code is wrapped in string-compared conditionals that tree-shake in prod:\n\n```js\n// eslint-disable-next-line no-constant-binary-expression\nvar complain = \"MARKO_DEBUG\" && require(\"complain\");\nif (\"MARKO_DEBUG\") {\n  complain(\"Deprecated: ...\");\n}\n```\n\nThe build step replaces `\"MARKO_DEBUG\"` with `false` and dead-code-eliminates the branches.\n\n## Output Modes\n\n- **HTML (SSR)** — `src/runtime/html/index.js` creates a `Template` produces `AsyncStream`. Output is HTML strings piped to a Node.js stream.\n- **VDOM (browser)** — `src/runtime/vdom/index.js` creates a `Template` produces `AsyncVDOMBuilder`. Output is a virtual DOM tree reconciled via local morphdom .\n\nBoth stacks share `src/runtime/renderable.js`, which mixes `render()`, `renderSync()`, `renderToString()`, and `mount()` into `Template.prototype`.\n\n## Error Handling\n\n- Compile-time errors use Babel's `path.buildCodeFrameError(message)` to include source locations\n- Most validation happens at compile time; runtime errors in production are minimal\n\n## Testing\n\n### Test structure\n\n```\ntest/\n  translator/              # Snapshot tests for compiler output\n  components-pages/        # Full page hydration (ssr + csr) tests\n  components-browser/      # jsdom-based browser component tests\n  components-server/       # SSR rendering tests\n  morphdom/                # morphdom unit tests\n  vdom-create/             # VNode construction unit tests\n  async-stream/            # AsyncStream unit tests\n```\n\n### Translator tests\n\nEach fixture has a `template.marko` input and a `snapshots/` directory:\n\n```\nfixtures/<name>/\n  template.marko\n  snapshots/\n    vdom-expected.js\n    html-expected.js\n    htmlProduction-expected.js\n    hydrate-expected.js\n    cjs-expected.js\n    generated-expected.marko\n```\n\n### Running tests\n\nFrom the repo root:\n\n```sh\npnpm test # all tests\npnpm test -- --grep \"<fixture> \" # specific fixture\npnpm run test:update # update snapshots\n```\n","packages/runtime-class/README.md":"<div align=\"center\">\n\n# [<img alt=\"Marko\" src=\"https://raw.githubusercontent.com/marko-js/branding/master/marko-logo-medium-cropped.png\" width=\"250\">](https://markojs.com/)\n\n**A declarative, HTML-based language that makes building web apps fun 🔥**\n\n[![NPM](https://img.shields.io/npm/v/marko.svg)](https://www.npmjs.com/package/marko)\n[![Discord Chat](https://img.shields.io/badge/discord-chat-7188da.svg)](https://discord.gg/RFGxYGs)\n[![Continuous Integration status](https://github.com/marko-js/marko/actions/workflows/ci.yml/badge.svg)](https://github.com/marko-js/marko/actions/workflows/ci.yml)\n[![Code coverage %](https://codecov.io/gh/marko-js/marko/branch/master/graph/badge.svg)](https://codecov.io/gh/marko-js/marko)\n[![# of monthly downloads](https://img.shields.io/npm/dm/marko.svg)](https://npm-stat.com/charts.html?package=marko)\n[![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/7029/badge)](https://bestpractices.coreinfrastructure.org/projects/7029)\n\n[Docs](https://markojs.com/docs/getting-started/) ∙ [Try Online](https://markojs.com/try-online/) ∙ [Contribute](#contributors) ∙ [Get Support](#community--support)\n\n</div>\n\n## Intro\n\nMarko is HTML _reimagined_ as a language for building dynamic and reactive user interfaces. Almost any valid HTML is valid Marko, and Marko extends HTML for building modern applications more declaratively. Among these extensions are [conditionals and lists](https://markojs.com/docs/conditionals-and-lists/), [state](https://markojs.com/docs/state/), and [components](https://markojs.com/docs/class-components/).\n\nMarko supports both single-file components and components across separate files.\n\n### Single-file component\n\nThe following renders a button and a counter of how many times the button has been pressed:\n\n**click-count.marko**\n\n```marko\nclass {\n  onCreate() {\n    this.state = { count: 0 };\n  }\n  increment() {\n    this.state.count++;\n  }\n}\n\nstyle {\n  .count {\n    color: #09c;\n    font-size: 3em;\n  }\n  .press-me {\n    padding: 0.5em;\n  }\n}\n\n<output.count>\n  ${state.count}\n</output>\n<button.press-me on-click('increment')>\n  Press me!\n</button>\n```\n\n### Multi-file component\n\nThe same component as above, but split into:\n\n- `index.marko` template file\n- `component.js` component JS logic file\n- `style.css` component styles file\n\n**index.marko**\n\n```marko\n<output.count>\n  ${state.count}\n</output>\n<button.press-me on-click('increment')>\n  Press me!\n</button>\n```\n\n**component.js**\n\n```js\nexport default {\n  onCreate() {\n    this.state = { count: 0 };\n  },\n  increment() {\n    this.state.count++;\n  },\n};\n```\n\n**style.css**\n\n```css\n.count {\n  color: #09c;\n  font-size: 3em;\n}\n.press-me {\n  padding: 0.5em;\n}\n```\n\n## Concise Syntax\n\nMarko also supports [a beautifully concise syntax as an alternative](https://markojs.com/docs/concise/) to its HTML syntax:\n\n<table><thead><tr><th>Concise syntax<th>HTML syntax\n<tbody><tr>\n<td>\n\n```marko\nul.example-list\n  for|color| of=[a, b, c]\n    li -- ${color}\n```\n\n<td>\n\n```marko\n<ul class=\"example-list\">\n  <for|color| of=[a, b, c]>\n    <li>${color}</li>\n  </for>\n</ul>\n```\n\n</table>\n\n## Getting Started\n\n1. `npm install marko`\n2. Read the [docs](https://markojs.com/docs/getting-started/)\n\n## Community & Support\n\n<table>\n<thead><tr>\n  <th><img alt=\"Stack Overflow\" src=\"https://user-images.githubusercontent.com/1958812/56055468-619b3e00-5d0e-11e9-92ae-200c212cafb8.png\" width=\"205\"> \n  <th><img alt=\"Discord\" src=\"https://user-images.githubusercontent.com/4985201/89313514-6edbea80-d62d-11ea-8447-ca2fd8983661.png\" width=\"162\">\n  <th><img alt=\"Twitter\" src=\"https://user-images.githubusercontent.com/1958812/56055707-07e74380-5d0f-11e9-8a59-d529fbb5a81e.png\" width=\"53\">\n<tbody><tr><td>\n\nAsk and answer [StackOverflow questions with the `#marko` tag](https://stackoverflow.com/questions/tagged/marko)<td>\n\nCome [hang out in our Discord chat](https://discord.gg/RFGxYGs), ask questions, and discuss project direction<td>\n\n[Tweet to `@MarkoDevTeam`](https://twitter.com/MarkoDevTeam), or with the [`#markojs` hashtag](https://twitter.com/search?q=%23markojs&f=live)\n\n</table>\n\n### Contributors\n\nMarko would not be what it is without all those who have contributed ✨\n\n[![All marko-js/marko GitHub contributors](https://opencollective.com/marko-js/contributors.svg?width=890&button=false)](https://github.com/marko-js/marko/graphs/contributors)\n\n### Get Involved!\n\n- Pull requests are welcome!\n- Submit [GitHub issues](https://github.com/marko-js/marko/issues) for any feature enhancements, bugs, or documentation problems\n- [Read the Contribution Tips and Guidelines](.github/CONTRIBUTING.md)\n- Participants in this project agree to abide by [its Code of Conduct](https://github.com/eBay/.github/blob/main/CODE_OF_CONDUCT.md)\n","packages/runtime-class/docs/10-awesome-marko-features.md":"<a href=\"#\">\n  <img src=\"https://cdn-images-1.medium.com/max/1000/1*Cmy6UutD5-ogL8dr1DySMQ.png\" alt=\"Marko logo\" width=\"100%\" />\n</a><br />\n\n> This article was published in August 2017. You can find the original [\"10 Awesome Marko Features\" article here](https://medium.com/@austinkelleher/10-awesome-marko-features-afba9d094d42)!\n\n# 10 Awesome Marko Features\n\n[Marko](https://markojs.com/) is a friendly and super fast UI library that makes\nbuilding web apps<br> fun! In celebration of rapidly approaching [5,000 stars on\nGitHub](https://github.com/marko-js/marko) (the ultimate open source vanity\nmetric), here are 10 features that will make you more productive in no\nparticular order...\n\n#### 1. Shorthand Attributes\n\nTired of constantly typing out `class` and `id` attributes? No need with Marko.\nSimply utilize the shorthand based on CSS selectors:\n\n```marko\nstyle {\n  .count {\n    color:#09c;\n  }\n}\n\n// Equivalent to <div class=\"count\"/>\n<div.count/>\n\n// Equivalent to <span id=\"my-id\"/>\n<span#my-id/>\n\n// Combined\n<button#submit.primary/>\n```\n\n#### 2. All attribute values are Just JavaScript™\n\nUnlike with HTML, you are not limited to string attribute values when using\nMarko. Attributes can have types, which makes it really easy to pass data to\ncustom tags and it works for standard HTML tags too:\n\n```marko\n<div class=input.myClassName/>\n<input type=\"checkbox\" checked=input.isChecked/>\n<awesome-component myString=\"Hello\"/>\n<awesome-component myNumber=1/>\n<awesome-component myTemplateString=`Hello ${name}`/>\n<awesome-component myBoolean=true/>\n<awesome-component myArray=[1, 2, 3]/>\n<awesome-component myObject={hello: 'world'}/>\n<awesome-component myVariable=name/>\n<awesome-component myFunctionCall=input.foo()/>\n```\n\n#### 3. Isomorphic UI components made easy\n\nTired of boilerplate code and trouble managing component input and state? Marko\nmakes it a breeze to develop self-contained and individually testable\ncomponents. Changing state is completely synchronous, so there won’t be any\nheadaches. You can also use inline styles making it very easy to develop small\ncomponents quickly.\n\n```marko\nclass {\n  onInput(input) {\n    this.state = {\n      count: input.count || 0\n    };\n  }\n  increment() {\n    this.state.count++;\n  }\n}\n\nstyle {\n  .count {\n    color:#09c;\n  }\n}\n\n<div.count>${state.count}</div>\n<button on-click('increment')>\n  Click me!\n</button>\n```\n\nDo you see references to “Marko” in the snippet above? Yeah, me neither.\n\nIs your component becoming too large? Do you prefer separating your CSS,\nJavaScript, and markup code? No problem. You can easily [rip out your code into\nmultiple files](https://markojs.com/docs/class-components/#multi-file-components):\n\n```\ncomponents/\n  click-counter/\n    component.js\n    index.marko\n    style.css\n```\n\n#### 4. Concise syntax\n\nThe DOM is just a tree structure. Indentation is a great way to describe a DOM\ntree without having to worry about matching up beginning and ending tags. Marko\nlets you choose between a concise, indentation-based syntax, and a familiar HTML\nsyntax:\n\n```marko\n<!-- Count our clicks! -->\n<div.count>\n  <p>Count: ${state.count}</p>\n</div>\n<button.example-button on-click('increment')>\n  Click me!\n</button>\n```\n\nHere’s the same thing with the concise syntax:\n\n```marko\n// Count our clicks!\ndiv.count\n  p -- Count: ${state.count}\nbutton.example-button on-click('increment') -- Click me!\n```\n\nCan’t make up your mind or just want to paste in that code snippet from\nStackOverflow? HTML syntax can be used within in the concise syntax. You’ll come\nback and make it consistent…_one day_.\n\n#### 5. Import JavaScript modules\n\nDo you have some helper JavaScript functions that you need to use in your views?\nMarko lets you import any JavaScript module into your template using the same\nsyntax as the JavaScript `import` statement without using Babel or any other\nbuild tool. No need for problematic globals (you could do that too, but please\ndon’t or your coworkers will hate you).\n\n```marko\nimport sum from './utils/sum';\n\n<div>The sum of 2 + 3 is ${sum(2, 3)}</div>\n```\n\n#### 6. No need to import custom tags (it’s a good thing, trust me)\n\nMarko uses your directory structure as a method for automatically registering\ncustom tags. This means that Marko can implicitly import tags based on where the\ntemplate is located on disk. Marko will search up the directory looking for\ncustom tags in `components/`directories similar to how Node.js discovers modules\nin `node_modules/` directories.\n\nGiven the following directory structure:\n\n```\ncomponents/\n  fancy-button/\n    index.marko\n  fancy-container/\n    index.marko\n```\n\nIf `fancy-button` is used inside of `fancy-container`, it will be implicitly<br>\nimported:\n\n```marko\n<!-- No need to use `require` or `import` because it will implicitly import custom tags -->\n<div>\n  <fancy-button color=input.buttonColor/>\n</div>\n```\n\n#### 7. Use JavaScript to set CSS classes and styles\n\nSetting CSS classes and styles is made easy using JavaScript! Marko will happily\naccept simple strings, JavaScript objects and arrays (_falsy values will be\nignored)._\n\n```marko\n$ const fontColor = input.color || 'blue';\n$ const isActive = input.active === true;\n\n<div class=['person', isActive && 'active']\n  style={color: fontColor} />\n```\n\n#### 8. Inline JavaScript Statements\n\nMarko takes HTML and makes it more like JavaScript. You can exit out of HTML\nmode to embed a JavaScript statement by starting the line with a `$`. You can\nuse this feature to embed JavaScript variables, functions, etc. where they are\nneeded (take that, “separation of concerns”).\n\n```marko\n$ const randomNumber = Math.random();\n$ const person = {\n  name: 'Frank',\n  age: 32\n};\n\n<div>Random number: ${randomNumber}</div>\n<div>${person.name} is ${person.age} years old</div>\n```\n\nIf you want to combine multiple JavaScript statements you can do that too:\n\n```marko\n$ {\n  const randomNumber = Math.random();\n  const person = {\n    name: 'Frank',\n    age: 32\n  };\n}\n\n<div>Random number: ${randomNumber}</div>\n<div>${person.name} is ${person.age} years old</div>\n```\n\n#### 9. Async rendering with the `<await>` tag\n\nNode.js is asynchronous. Browsers are asynchronous. Why should rendering be\nsynchronous? Pass your promise along to your template and Marko will\nasynchronously render parts of your view. Turns out, [this is good for\nperformance](https://tech.ebayinc.com/engineering/async-fragments-rediscovering-progressive-html-rendering-with-marko/).\n\n```marko\n$ const searchResultsPromise = searchService.performSearch(keywords);\n\n<await(searchResultsPromise)>\n  <@then|person|>\n    Hello ${person.name}!\n  </@then>\n  <@catch|err|>\n    The error was: ${err.message}.\n  </@catch>\n</await>\n```\n\n#### 10. Server side rendering is easy\n\nCan’t decide if you want to do server-side rendering or client-side rendering?\nWhy are we even talking about this in 2017? It doesn’t matter. Seriously, just\ndo both. Marko makes this a no-brainer since you can render a Marko template\ndirectly to a stream (oh, and Marko will automatically mount UI\ncomponents rendered on the server when the page loads in the browser):\n\n```js\nrequire(\"@marko/compiler/register\"); // require .marko files!\n\nconst http = require(\"http\");\nconst template = require(\"./template\");\n\nhttp\n  .createServer()\n  .on(\"request\", (req, res) => {\n    template.render(\n      {\n        name: \"Frank\",\n        count: 30,\n        colors: [\"red\", \"green\", \"blue\"],\n      },\n      res,\n    );\n  })\n  .listen(8080);\n```\n\n#### Bonus: Friendly compile-time errors\n\nWe all make mistakes _every now and then_. Typo in your custom tag? Forgot an\nending tag? No worries! Marko will give you a friendly error message and point\nyou right to the problematic code.\n\n```marko\n<!-- Ahhhh typo! This should be <fancy-button/> -->\n<fancy-buttn/>\n```\n\nYou may have missed it, but it was obvious to Marko:\n\n```\nUnrecognized tag: fancy-buttn — More details: https://github.com/marko-js/marko/wiki/Error:-Unrecognized-Tag at line 2 col 1\n```\n\nComing soon: auto correction and autonomous coding\n\n---\n\n[_Cover image from Wikipedia_](https://commons.wikimedia.org/wiki/File:Amanhecer_no_Hercules_--.jpg)\n","packages/runtime-class/docs/body-content.md":"# Body content\n\nWe're used to passing body content to HTML tags. When you do this, the tag has control over where and when this content is rendered. A good example of this is the [HTML `<details>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details):\n\n```html\n<details>\n  <summary>Hello <strong>World</strong></summary>\n  This is some <em>content</em> that can be toggled.\n</details>\n```\n\nThis is what it renders (try clicking it):\n\n---\n\n<details>\n    <summary>Hello <strong>World</strong></summary>\n    This is some <em>content</em> that can be toggled.\n</details>\n\n---\n\nCustom tags can also receive content in the same way. This allows a component to give its user full control over _how_ some section of the content is rendered, but control _where_, _when_, and with _what_ data it is rendered. This feature is necessary to build composable components like overlays, layouts, dropdowns, etc. Imagine a `<table>` that didn't give you control over how its cells were rendered. That would be pretty limited!\n\n## Rendering body content\n\nWhen a custom tag is passed body content, it is received as a special `renderBody` property on the component's `input`. You can include this content anywhere in your component by using the [`<${dynamic}>` syntax](./syntax.md#dynamic-tagname).\n\n_components/fancy-container.marko:_\n\n```marko\n<div class=\"container fancy\">\n    <${input.renderBody}/>\n</div>\n```\n\nIf we were to use this tag like this:\n\n_Marko Source:_\n\n```marko\n<fancy-container>\n    <p>Content goes here...</p>\n</fancy-container>\n```\n\nThe rendered output would be:\n\n_HTML Output:_\n\n```html\n<div class=\"container fancy\"><p>Content goes here...</p></div>\n```\n\nThis is a pretty basic example, but you can imagine how this could be incorporated into a more advanced component to render passed content where/when needed.\n\n> **ProTip:**\n> Body content can be rendered multiple times. Or not at all.\n\n## Passing attributes to body content\n\nWhen rendering body content with `<${dynamic}>`, attributes may also be passed:\n\n_components/random-value.marko:_\n\n```marko\n<!-- heh, it's not actually random -->\n<${input.renderBody} number=1337 />\n```\n\nThese attribute values can be received as a [tag parameter](./syntax.md#parameters):\n\n```marko\n<random-value|{ number }|>\n    The number is ${number}\n</random-value>\n```\n\n> **ProTip:**\n> Some tags (like the above tag) may not render anything except their body content with some data. This can be quite useful, just look at the `<for>` and `<await>` tags!\n\n## Named body content\n\nYou can also pass named content sections to a tag using [attribute tags](./syntax.md#attribute-tag) which are denoted by the `@` prefix.\n\n```marko\n<layout>\n    <@heading>\n        <h1>Hello Marko</h1>\n    </@heading>\n    <@content>\n        <p>...</p>\n    </@content>\n</layout>\n```\n\nLike attributes, these attribute tags are received as `input.heading` and `input.content`, but they each have a `renderBody` property which we can now use:\n\n_components/layout.marko_\n\n```marko\n<!doctype html>\n<html>\n    <body>\n        <${input.heading.renderBody}/>\n        <hr/>\n        <${input.content.renderBody}/>\n    </body>\n</html>\n```\n\n> **ProTip:** The `renderBody` property can be omitted. You could use `<${input.heading}/>`, for example.\n\n### Repeated body content\n\nWhen an attribute tag is repeated, the child component can consume all instances using the [iterable protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol).\n\nThis allows us to, for example, build a custom table component which allows its user to specify any number of columns, while still giving the user control over how each column is rendered.\n\n_Marko Source:_\n\n```marko\n<fancy-table data=people>\n    <@column|person|>\n        Name: ${person.name}\n    </@column>\n    <@column|person|>\n        Age: ${person.age}\n    </@column>\n</fancy-table>\n```\n\n> _Note_\n> For TypeScript the [`Marko.AttrTag` helper](./typescript.md#built-in-marko-types) should be used here.\n\n> _Protip_\n> Since attribute tags are iterable you could pass `input.column` to a `for of` loop, or `[...spread]` it into an array.\n> To `.map`, `.filter` or otherwise work with attribute tags as an array you can use the following pattern:\n>\n> ```marko\n> $ const columns = [...input.column || []];\n> ```\n\nWe can then use the `<for>` tag to render the body content into table, passing the row data to each column's body.\n\n_components/fancy-table/index.marko:_\n\n```marko {4-8}\n<table class=\"fancy\">\n    <for|row| of=input.data>\n        <tr>\n            <for|column| of=input.column>\n                <td>\n                    <${column.renderBody} ...row/>\n                </td>\n            </for>\n        </tr>\n    </for>\n</table>\n```\n\nWe now have a working `<fancy-table>`. Let's see what it renders:\n\n_Example Data:_\n\n```js\n[\n  {\n    name: \"Patrick\",\n    age: 63,\n  },\n  {\n    name: \"Austin\",\n    age: 12,\n  },\n];\n```\n\n_HTML Output:_\n\n```html\n<table class=\"fancy\">\n  <tr>\n    <td>Name: Patrick</td>\n    <td>Age: 63</td>\n  </tr>\n  <tr>\n    <td>Name: Austin</td>\n    <td>Age: 12</td>\n  </tr>\n</table>\n```\n\n### Attributes on attribute tags\n\nIf you look at our previous example, we had to prefix each cell with the column label. It would be better if we could give a name to each column instead and only render that once.\n\n_Marko Source:_\n\n```marko\n<fancy-table>\n    <@column|person| heading=\"Name\">\n        ${person.name}\n    </@column>\n    <@column|person| heading=\"Age\">\n        ${person.age}\n    </@column>\n</fancy-table>\n```\n\nNow, each attribute tag in `input.column` will contain a `heading` property in addition to its `renderBody`. We can use another `<for>` and render the headings in `<th>` tags:\n\n_components/fancy-table/index.marko:_\n\n```marko {3-5}\n<table class=\"fancy\">\n    <tr>\n        <for|column| of=input.column>\n            <th>${column.heading}</th>\n        </for>\n    </tr>\n    <for|row| of=input.data>\n        <tr>\n            <for|column| of=input.column>\n                <td>\n                    <${column.renderBody} ...row/>\n                </td>\n            </for>\n        </tr>\n    </for>\n</table>\n```\n\nWe'll now get a row of headings when we render our `<fancy-table>`\n\n_HTML Output:_\n\n```html\n<table class=\"fancy\">\n  <tr>\n    <th>Name</th>\n    <th>Age</th>\n  </tr>\n  <tr>\n    <td>Patrick</td>\n    <td>63</td>\n  </tr>\n  <tr>\n    <td>Austin</td>\n    <td>12</td>\n  </tr>\n</table>\n```\n\n### Nested attribute tags\n\nContinuing to build on our example, what if we want to add some custom content or even components into the column headings? In this case, we can extend our `<fancy-table>` to use nested attribute tags. We'll now have `<@heading>` and `<@cell>` tags nested under `<@column>`. This gives users of our tag full control over how to render both column headings and the cells within the column!\n\n_Marko Source:_\n\n```marko {3-8}\n<fancy-table>\n    <@column>\n        <@heading>\n            <app-icon type=\"profile\"/> Name\n        </@heading>\n        <@cell|person|>\n            ${person.name}\n        </@cell>\n    </@column>\n    <@column>\n        <@heading>\n            <app-icon type=\"calendar\"/> Age\n        </@heading>\n        <@cell|person|>\n            ${person.age}\n        </@cell>\n    </@column>\n</fancy-table>\n```\n\nNow instead of rendering the heading as text, we'll render the heading's body content.\n\n_components/fancy-table/index.marko:_\n\n```marko {5}\n<table class=\"fancy\">\n    <tr>\n        <for|column| of=input.column>\n            <th>\n                <${column.heading.renderBody}/>\n            </th>\n        </for>\n    </tr>\n    <for|row| of=input.data>\n        <tr>\n            <for|column| of=input.column>\n                <td>\n                    <${column.cell.renderBody} ...row/>\n                </td>\n            </for>\n        </tr>\n    </for>\n</table>\n```\n\nOur headings can now include icons (and anything else)!\n\n_HTML Output:_\n\n```html\n<table class=\"fancy\">\n  <tr>\n    <th><img class=\"icon\" src=\"profile.svg\" /> Name</th>\n    <th><img class=\"icon\" src=\"calendar.svg\" /> Age</th>\n  </tr>\n  <tr>\n    <td>Patrick</td>\n    <td>63</td>\n  </tr>\n  <tr>\n    <td>Austin</td>\n    <td>12</td>\n  </tr>\n</table>\n```\n\n### Dynamic attribute tags\n\nThe flexibility of the `<fancy-table>` is great if you want to render columns differently or have columns that display the data in a special way (such as displaying an age derived from a date of birth). However, if all columns are basically the same, the user might feel they're repeating themselves. As you might expect, you can use `<for>` (and `<if>`) to dynamically render attribute tags.\n\n```marko\n$ const columns = [{\n    property: \"name\",\n    title: \"Name\",\n    icon: \"profile\"\n}, {\n    property: \"age\",\n    title: \"Age\",\n    icon: \"calendar\"\n}]\n\n<fancy-table>\n    <for|{ property, title, icon }|>\n        <@column>\n            <@heading>\n                <app-icon type=icon/> ${title}\n            </@heading>\n            <@cell|person|>\n                ${person[property]}\n            </@cell>\n        </@column>\n    </for>\n</fancy-table>\n```\n","packages/runtime-class/docs/class-components.md":"# Class Components\n\nMarko makes it easy to create user interface components to use as building blocks for web pages and applications of any complexity.\n\nMarko promotes self-contained components that:\n\n- Are independently testable\n- Encapsulate the view, client-side behavior (like event handling) and styling\n- Can easily be combined to create composite UI components.\n\nMarko components compile into small, efficient JavaScript modules that hide implementation details from consumers. Components can be published to [npm](https://www.npmjs.com) for reuse across applications.\n\n## UI component diagram\n\n![Component diagram](./component-diagram.svg)\n\nIn Marko, the DOM output of a UI component is based on _input properties_ and optional _internal state_ used to control the view.\n\nIf Marko detects changes to `input` or the internal `state`, then the view (that is, the DOM) will automatically update to reflect the new input and state. Internally, Marko uses virtual DOM diffing/patching to update the view, but that’s an implementation detail that could change at any time.\n\n## Component structure\n\nMarko makes it easy to keep your component’s class and styles next to the HTML view that they correspond to. The following are the key parts of any UI component:\n\n- **View** - The HTML template for your UI component. Receives input properties and states, and renders to either server-side HTML or browser-side virtual DOM nodes.\n- **Client-side behavior** - A JavaScript `class` with methods and properties for initialization, event handling (including DOM events, custom events and lifecycle events), and state management.\n- **Styles** - Cascading StyleSheets, including support for CSS preprocessors like [Less](https://lesscss.org/) or [Sass](https://sass-lang.com/).\n\n## Server-side rendering\n\nA UI component can be rendered on the server or in the browser, but stateful component instances will be automatically mounted to the DOM in the browser for both. If a UI component tree is rendered on the server, then Marko will recreate the UI component tree in the browser with no extra code required. For more details, please see [Rendering](/docs/rendering/).\n\n## Single-file components\n\nMarko lets you define a `class` for a component right in the `.marko` file, and call that class’s methods with `on-*` attributes:\n\n```marko\nclass {\n    onCreate() {\n        this.state = {\n            count: 0\n        };\n    }\n    increment() {\n        this.state.count++;\n    }\n}\n\n<label>The current count is <output>${state.count}</output></label>\n<p><button on-click('increment')>+1</button></p>\n```\n\n### Styles\n\nAdding styles in your view is also made easy:\n\n```marko\nstyle {\n    .primary {\n        background: #09c;\n    }\n}\n\n<label>The current count is <output>${state.count}</output></label>\n<p><button.primary on-click('increment')>+1</button></p>\n```\n\nThese styles aren’t output in a `<style>` tag as inline styles usually are, but are externalized to deduplicate them across multiple component instances on a page.\n\nIf you use a CSS preprocessor, you can add its file extension on `style`:\n\n```marko\nstyle.less {\n    .primary {\n        background: @primaryColor;\n    }\n}\n```\n\n> **Note:** The code in the `style` section is processed in a context separate from the rest of the template, so you can’t use JavaScript variables inside it. If you need variables in your CSS, use a CSS preprocessor that supports them.\n\n## Multi-file components\n\nYou might prefer to keep your component’s class and styles in separate files from the view — the classical separation of HTML, CSS, and JavaScript. Marko makes this possible with a filename-based convention.\n\n> **ProTip:** If your’re moving the component’s class and styles to separate files is because the code is getting too large, consider splitting the component into smaller, more manageable components.\n\n### Supporting files\n\nMarko discovers supporting files in the same directory as a Marko view. For example, if you have a view named `counter.marko`, Marko will automatically look for `counter.component.js` and `counter.style.css`.\n\n```\ncounter.marko\ncounter.component.js\ncounter.style.css\n```\n\nMarko also handles views named `index.marko` specially. It will look for `component.js` and `style.css` in addition to `index.component.js` and `index.style.css`. This allows easily grouping component files into a directory:\n\n```\ncounter/\n    index.marko\n    component.js\n    style.css\n```\n\nIn your `component.js` file, export the component’s class:\n\n```js\nexport default class {\n  onCreate() {\n    this.state = {\n      count: 0,\n    };\n  }\n  increment() {\n    this.state.count++;\n  }\n}\n```\n\nIn your `index.marko` file, you can reference methods from that class with `on-*` attributes:\n\n```marko\n<label>The current count is <output>${state.count}</output></label>\n<p><button.primary on-click('increment')>+1</button></p>\n```\n\nAnd in your `style.css`, define the styles:\n\n```css\n.primary {\n  background: #09c;\n}\n```\n\n> **ProTip:** Marko actually looks any filenames with the pattern `[name].style.*`, so it will pick up any CSS preprocessor file extensions you use: `.less`, `.stylus`, `.scss`, etc.\n\n### Components with plain objects\n\nIf you target browsers that does not support classes, a plain object of methods can be exported:\n\n```js\nexport default {\n  onCreate: function () {\n    this.state = {\n      count: 0,\n    };\n  },\n  increment: function () {\n    this.state.count++;\n  },\n};\n```\n\n## Split components\n\nSplit components optimize for when a component renders on the server, and doesn’t need to dynamically rerender in the browser. As a result, its template and logic aren’t sent to the browser, reducing load time and download size.\n\n> **Note:** If a split component is the child of a stateful component, its full rendering logic will still be sent because the parent may pass new input to the split component and rerender it.\n\nAdditionally, if _all_ components rendered on a page are split components, Marko’s VDOM and rendering runtime is unnecessary, and therefore not sent to the browser.\n\n> **ProTip:** Don’t over-optimize. If your component really doesn’t need rerendering, go ahead and split, but don’t forgo stateful rerendering when it would make your code more maintainable.\n\n### Usage\n\nMarko discovers split components similarly to how it discovers an external component class. For example, if you have a view named `button.marko`, it will automatically look for `button.component-browser.js`. If your view is named `index.marko`, it will look for `component-browser.js` in addition to `index.component-browser.js`.\n\n```\ncounter/\n    index.marko\n    component-browser.js\n```\n\nA split component might need to do some setup as part of its initial render. In this case, the component may define a second component class to use the `onCreate`, `onInput`, and `onRender` [lifecycle methods](#lifecycle-events).\n\nThis class can be exported from `component.js`, or defined right in the template as a single-file components. In this case, your component folder may contain a `component.js` file, and must contain a `component-browser.js`. The following [lifecycle methods](#lifecycle-events) can go inside the `component.js` file:\n\n```\nclass {\n  onCreate(input, out) { }\n  onInput(input, out) { }\n  onRender(out) { }\n  onDestroy() { }\n}\n```\n\nAnd the following [lifecycle methods](#lifecycle-events) can go inside the `component-browser.js` file:\n\n```\nclass {\n  onMount() { }\n  onUpdate() { }\n}\n```\n\nAny JavaScript code related to the DOM or browser should also be inside `component-browser.js`.\n\n### Example\n\n`index.marko`\n\n```marko\nclass {\n    onCreate() {\n        this.number = 123;\n    }\n}\n\n<button on-click('shout')>What’s my favorite number?</button>\n```\n\n`component-browser.js`\n\n```js\nexport default {\n  shout() {\n    alert(`My favorite number is ${this.number}!`);\n  },\n};\n```\n\n## Event handling\n\nThe `on-[event](methodName|function, ...args)` attributes allow event listeners to be attached for either:\n\n- A native DOM event, when used on a native DOM element such as a `<button>`\n- Or a UI component event, when used on a custom tag for a UI component such as `<my-component>`\n\nThe `on-*` attributes are used to associate event handler methods with an event name. Event handlers may be specified by `'methodName'` — a string that matches a method on the component instance, or they may be a `function`. Attaching listeners for native DOM events and UI component custom events is explained in more detail in the sections below.\n\nYou may also use the `once-[event](methodName|function, ...args)` syntax, which will listen for only the first event, and then remove the listener.\n\n### Attaching DOM event listeners\n\nThe code below illustrates how to attach an event listener for native DOM events:\n\n```marko\nclass {\n  onButtonClick(name, event, el) {\n    alert(`Hello ${name}!`);\n  }\n}\n\nstatic function fadeIn(event, el) {\n  el.hidden = false;\n  el.style.opacity = 0;\n  el.style.transition = 'opacity 1s';\n  setTimeout(() => el.style.opacity = 1);\n}\n\n<button on-click('onButtonClick', 'Frank')>\n  Say Hello to Frank\n</button>\n\n<button on-click('onButtonClick', 'John')>\n  Say Hello to John\n</button>\n\n<img src='foo.jpg' once-load(fadeIn) hidden />\n```\n\nThe following arguments are passed to the event handler when the event occurs:\n\n1.  `...args` - Any extra bound arguments are _prepended_ to the arguments passed to the component’s handler method.\n    For example: `on-click('onButtonClick', arg1, arg2)` → `onButtonClick(arg1, arg2, event, el)`\n2.  `event` - The native DOM event object.\n3.  `el` - The DOM element that the event listener was attached to.\n\nWhen using the `on-*` or `once-*` attributes to attach event listeners, Marko uses event delegation that is more efficient than direct attachment of `el.addEventListener()`. Please see [Why is Marko Fast? § Event delegation](/docs/why-is-marko-fast/#event-delegation) for more details.\n\n<a id=\"declarative-custom-events\"></a>\n\n### Attaching custom event listeners\n\nThe code below illustrates how to attach an event listener for a UI component’s custom event:\n\n```marko\nclass {\n  onCounterChange(newValue, el) {\n    alert(`New value: ${newValue}!`);\n  }\n  onCounterMax(max) {\n    alert(`It reached the max: ${max}!`);\n  }\n}\n\n<counter on-change('onCounterChange') once-max('onCounterMax') />\n```\n\nThe following arguments are passed to the event handler when the event occurs:\n\n1.  `...args` - Any extra bound arguments are _prepended_ to the arguments passed to the component’s handler method.\n2.  `...eventArgs` - The arguments passed to `this.emit()` by the target UI component.\n3.  `component` - The component instance that the event listener was attached to.\n\nThe following code illustrates how the UI component for `<counter>` might emit its `change` event:\n\n`counter/index.marko`\n\n```marko\nclass {\n  onCreate() {\n    this.max = 50;\n    this.state = { count: 0 };\n  }\n  increment() {\n    if (this.state.count < this.max) {\n        this.emit('change', ++this.state.count);\n    }\n    if (this.state.count === this.max) {\n        this.emit('max', this.state.count);\n    }\n  }\n}\n\n\n<button.example-button on-click('increment')>\n  Increment\n</button>\n```\n\n> **ProTip:** Unlike native DOM events, UI component custom events may be emitted with multiple arguments. For example:\n>\n> ```js\n> this.emit(\"foo\", \"bar\", \"baz\");\n> ```\n\n## Attributes\n\n### `on-[event](methodName|function, ...args)`\n\nThe `on-*` attribute syntax attaches an event listener to either a native DOM event or a UI component event. The `on-*` attribute associates an event handler method with an event name. Please see the [Event handling](#event-handling) section above for details.\n\n### `once-[event](methodName|function, ...args)`\n\nThe same as the `on-*` attribute, except that its listener is only invoked for the first event, and then removed from memory. Please see the [Event handling](#event-handling) section above for more details.\n\n### `key`\n\nThe `key` property does 2 things in Marko:\n\n- Obtains references to nested HTML elements and nested UI components.\n- Matches corresponding elements together when DOM diffing/patching after a rerender. When updating the DOM, keyed elements/components are matched up and reused rather than discarded and recreated.\n\nInternally, Marko assigns a unique key to all HTML elements and UI components in a `.marko` file, based on the order they appear in the file. If you have repeated elements or elements that move between locations in the DOM, then you likely want to assign a custom `key` by adding a `key` attribute. The `key` attribute can be applied to both HTML elements and custom tags.\n\n#### Referencing nested HTML elements and components\n\n```marko\nclass {\n  onMount() {\n    const headerElement = this.getEl('header');\n    const colorListItems = this.getEls('colors');\n    const myFancyButton = this.getComponent('myFancyButton');\n  }\n}\n\n<h1 key=\"header\">Hello</h1>\n\n<ul>\n  <for|color| of=['red', 'green', 'blue']>\n      <li key=\"colors[]\">${color}</li>\n  </for>\n</ul>\n\n<fancy-button key=\"myFancyButton\"/>\n```\n\n> **Note:** The `[]` suffix (e.g. `key=\"colors[]\"`) lets Marko know that the element will be repeated multiple times with the same key.\n\n#### Keyed matching\n\nThe `key` attribute can pair an HTML element or UI component that moves to a new location in the DOM. For example:\n\n```marko\nclass {\n  onCreate() {\n    this.state = {\n      swapped: false\n    }\n  }\n}\n\n<if(state.swapped)>\n  <p key=\"b\">B</p>\n  <p key=\"a\">A</p>\n</if>\n<else>\n  <p key=\"a\">A</p>\n  <p key=\"b\">B</p>\n</else>\n```\n\nThe `key` attribute can be used to pair HTML elements or UI components that are repeated:\n\n```marko\n<ul>\n  <for|user| of=input.users>\n      <li key=user.id>${user.name}</li>\n  </for>\n</ul>\n```\n\nThis way, if the order of `input.users` changes, the DOM will be rerendered more efficiently.\n\n#### `*:scoped`\n\nThe `:scoped` attribute modifier results in the attribute value getting prefixed with a unique ID associated with the current UI component. `:scoped` attribute modifiers can be used to assign a globally unique attribute value from a value that only needs to be unique to the current UI component.\n\nHere’s a use-case: certain HTML attributes reference the `id` of other elements on the page. For example, the [HTML `<label>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label) `for` attribute takes an `id` as its value. Many `ARIA` attributes like [`aria-describedby`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-describedby_attribute) also take an `id` as their value.\n\nThe `:scoped` modifier on an attribute allows you to reference another element without fear of duplicate `id`s, as shown in the following examples:\n\n**`for:scoped`**\n\n```marko\n<label for:scoped=\"name\">Name</label>\n<input id:scoped=\"name\" value=\"Frank\"/>\n```\n\nThe above code will output HTML similar to the following:\n\n```html\n<label for=\"c0-name\">Name</label> <input id=\"c0-name\" value=\"Frank\" />\n```\n\n**`aria-describedby:scoped`**\n\n```marko\n<button\n   aria-describedby:scoped=\"closeDisclaimer\"\n   on-click('closeDialog')>Close</button>\n\n<p id:scoped=\"closeDisclaimer\">\n   Closing this window will discard any entered information and return you to the main page.\n</p>\n```\n\n```html\n<button aria-describedby=\"c0-closeDisclaimer\">Close</button>\n\n<p id=\"c0-closeDisclaimer\">\n  Closing this window will discard any entered information and return you to the\n  main page.\n</p>\n```\n\n**`href:scoped`**\n\n```marko\n<a href:scoped=\"#anchor\">Jump to section</a>\n<section id:scoped=\"anchor\"></section>\n```\n\n```html\n<a href=\"#c0-anchor\">Jump to section</a>\n<section id=\"c0-anchor\"></section>\n```\n\n### `no-update`\n\nPreserves the DOM subtree associated with the element or component, so it won’t be modified when rerendering.\n\n```marko\n<!-- Never rerender this table -->\n<table no-update>\n  …\n</table>\n```\n\n```marko\n<!-- N ever rerender this UI component -->\n<app-map no-update/>\n```\n\nThis is most useful when other JavaScript modifies the DOM tree of an element, like for embeds.\n\n### `no-update-if`\n\nSimilar to [no-update](#no-update), except that the DOM subtree is _conditionally_ preserved:\n\n```marko\n<!-- Don’t re-render this table without table data -->\n<table no-update-if(input.tableData == null)>\n  …\n</table>\n```\n\n### `no-update-body`\n\nSimilar to [no-update](#no-update), except that only the descendant DOM nodes are preserved:\n\n```marko\n<!-- Never rerender any nested DOM elements -->\n<div no-update-body>\n  …\n</div>\n```\n\n### `no-update-body-if`\n\nSimilar to [no-update-body](#no-update-body), except that its descendant DOM nodes are _conditionally_ preserved:\n\n```marko\n<!-- Never rerender any nested DOM elements without table data -->\n<table no-update-body-if(input.tableData == null)>\n  …\n</table>\n```\n\n### `:no-update`\n\nPrevents certain attributes from being modified during a rerender. The attribute(s) that should not be modified should have a `:no-update` modifier:\n\n```marko\n<!-- Never modify the `class` attribute -->\n<div class:no-update=input.className>\n  …\n</div>\n```\n\n## Properties\n\n### `this.id`\n\nA string identifier for the root HTML element that the component is bound to. (Not the `id` attribute.)\n\n### `this.state`\n\nThe current state for the component. Changing `this.state` or its direct properties will cause the component to rerender.\n\nOnly properties that exist when `this.state` is first defined will be watched for changes. If you don’t need a property initially, you can set its value to `null`:\n\n```marko\nclass {\n    onCreate() {\n        this.state = {\n            data: null,\n            error: null\n        }\n    }\n    getData() {\n        fetch('/endpoint')\n            .then(data => this.state.data = data)\n            .catch(error => this.state.error = error);\n    }\n}\n```\n\nBeware: setting a `state` property only _nominates_ the component for a possible rerender, and properties are only watched one level deep. Thus, the component is only rerendered if at least one of the component state properties changed (`oldValue !== newValue`).\n\nIf none of the properties changed (because the new value is identical, or no difference is detected by a shallow comparison), the assignment is considered a no-operation (great for performance).\n\nWe recommend using [immutable data structures](https://wecodetheweb.com/2016/02/12/immutable-javascript-using-es6-and-beyond/), but if you want to mutate a state property (perhaps push a new item into an array), you can mark it as dirty with `setStateDirty`:\n\n```js\nthis.state.numbers.push(num);\n\n// Mark numbers as dirty, because a `push`\n// won’t be automatically detected by Marko\nthis.setStateDirty(\"numbers\");\n```\n\n### `this.input`\n\nThe current input for the component. Setting `this.input` will rerender the component which can be useful for testing, but generally avoided (prefer `state` instead).\n\n## Variables\n\nWhen a Marko component is compiled, some additional variables are available to the rendering function. These variables are described below.\n\n### `component`\n\nThe `component` variable refers to the instance of the currently rendering UI component. This variable can be used to call methods on the UI component instance:\n\n```marko\nclass {\n    getFullName() {\n        const { person } = this.input;\n        return `${person.firstName} ${person.lastName}`;\n    }\n}\n\n<h1>Hello, ${component.getFullName()}</h1>\n```\n\n### `input`\n\nThe `input` variable refers to the `input` object, and is equivalent to `component.input`|`this.input`.\n\n```marko\n<h1>Hello, ${input.name}</h1>\n```\n\n### `state`\n\nThe `state` variable refers to the UI component’s `state` object, and is the _unwatched_ equivalent of `component.state`|`this.state`.\n\n```marko\n<h1>Hello ${state.name}</h1>\n```\n\n## Methods\n\n### `destroy([options])`\n\n| Option       | Type      | Default | Description                                                                       |\n| ------------ | --------- | ------- | --------------------------------------------------------------------------------- |\n| `removeNode` | `Boolean` | `true`  | `false` will keep the component in the DOM while unsubscribing all events from it |\n| `recursive`  | `Boolean` | `true`  | `false` will prevent child components from being destroyed                        |\n\nDestroys the component by unsubscribing from all listeners made using the `subscribeTo` method, and then detaching the component’s root element from the DOM. All nested components (discovered by querying the DOM) are also destroyed.\n\n```js\ncomponent.destroy({\n  removeNode: false, // true by default\n  recursive: false, // true by default\n});\n```\n\n### `forceUpdate()`\n\nQueue the component to re-render and skip all checks to see if it actually needs it.\n\n> When using `forceUpdate()` the updating of the DOM will be queued up. If you want to immediately update the DOM\n> then call `this.update()` after calling `this.forceUpdate()`.\n\n### `getEl([key, index])`\n\n| Signature    | Type          | Description                                                                       |\n| ------------ | ------------- | --------------------------------------------------------------------------------- |\n| `key`        | `String`      | _optional_ — the scoped identifier for the element                                |\n| `index`      | `Number`      | _optional_ — the index of the component, if `key` references a repeated component |\n| return value | `HTMLElement` | The element matching the key, or `this.el` if no key is provided                  |\n\nReturns a nested DOM element by prefixing the provided `key` with the component’s ID. For Marko, nested DOM elements should be assigned an ID with the `key` attribute.\n\n### `getEls(key)`\n\n| Signature    | Type                 | Description                                           |\n| ------------ | -------------------- | ----------------------------------------------------- |\n| `key`        | `String`             | The scoped identifier for the element                 |\n| return value | `Array<HTMLElement>` | An array of _repeated_ DOM elements for the given key |\n\nRepeated DOM elements must have a value for the `key` attribute that ends with `[]`. For example, `key=\"items[]\"`.\n\n### `getElId([key, index])`\n\n| Signature    | Type     | Description                                                                       |\n| ------------ | -------- | --------------------------------------------------------------------------------- |\n| `key`        | `String` | _optional_ — The scoped identifier for the element                                |\n| `index`      | `Number` | _optional_ — The index of the component, if `key` references a repeated component |\n| return value | `String` | The element ID matching the key, or `this.el.id` if `key` is undefined            |\n\nSimilar to `getEl`, but only returns the String ID of the nested DOM element instead of the actual DOM element.\n\n### `getComponent(key[, index])`\n\n| Signature    | Type        | Description                                                                                                                                                                                                       |\n| ------------ | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `key`        | `String`    | The scoped identifier for the element                                                                                                                                                                             |\n| `index`      | `Number`    | _optional_ — The index of the component, if `key` references a repeated component                                                                                                                                 |\n| return value | `Component` | A reference to a nested `Component` for the given key. If an `index` is provided and the target component is a repeated component (i.e. `key=\"items[]\"`), then the component at the given index will be returned. |\n\nFor example, given the following component,\n\n```marko\n<app-main>\n  <app-child key=\"child\"/>\n</app-main>\n```\n\nThe following code can be used to get the `<app-child/>` component:\n\n```js\nconst childComponent = this.getComponent(\"child\");\n```\n\n### `getComponents(key, [, index])`\n\n| Signature    | Type               | Description                                                                       |\n| ------------ | ------------------ | --------------------------------------------------------------------------------- |\n| `key`        | `String`           | The scoped identifier for the element                                             |\n| `index`      | `Number`           | _optional_ — The index of the component, if `key` references a repeated component |\n| return value | `Array<Component>` | An array of _repeated_ `Component` instances for the given key                    |\n\nRepeated components must have a value for the `key` attribute that ends with `[]`, like `key=\"items[]\"`.\n\n### `isDestroyed()`\n\nReturns `true` if a component has been destroyed using [`component.destroy()`](#ondestroy), otherwise `false`.\n\n### `isDirty()`\n\nReturns `true` if the component needs a bath.\n\n### `replaceState(newState)`\n\n| Signature  | Type     | Description                                      |\n| ---------- | -------- | ------------------------------------------------ |\n| `newState` | `Object` | A new state object to replace the previous state |\n\nReplaces the state with an entirely new state. Equivalent to `this.state = newState`.\n\n> **Note:** While `setState()` is additive and will not remove properties that are in the old state but not in the new state, `replaceState()` _will_ add the new state and remove the old state properties that are not found in the new state. Thus, if `replaceState()` is used, consider possible side effects if the new state contains less or other properties than the replaced state.\n\n### `rerender([input])`\n\n| Signature | Type     | Description                                         |\n| --------- | -------- | --------------------------------------------------- |\n| `input`   | `Object` | _optional_ — New input data to use when rerendering |\n\nRerenders the component using its `renderer`, and either supplied `input` or internal `input` and `state`.\n\n### `setState(name, value)`\n\n| Signature | Type     | Description                                |\n| --------- | -------- | ------------------------------------------ |\n| `name`    | `String` | The name of the `state` property to update |\n| `value`   | `Any`    | The new value for the `state` property     |\n\nChanges the value of a single `state` property. Equivalent to `this.state[name] = value`, except it will also work for adding new properties to the component state.\n\n```js\nthis.setState(\"disabled\", true);\n```\n\n### `setState(newState)`\n\n| Signature  | Type     | Description                                         |\n| ---------- | -------- | --------------------------------------------------- |\n| `newState` | `Object` | A new state object to merge into the previous state |\n\nChanges the value of multiple state properties:\n\n```js\nthis.setState({\n  disabled: true,\n  size: \"large\",\n});\n```\n\n### `setStateDirty(name[, value])`\n\n| Signature | Type     | Description                                       |\n| --------- | -------- | ------------------------------------------------- |\n| `name`    | `String` | The name of the `state` property to mark as dirty |\n| `value`   | `Any`    | _optional_ — A new value for the `state` property |\n\nForces a state property change, even if the value is equal to the old value. This is helpful in cases where a change occurs to a complex object that would not be detected by a shallow compare. Invoking this function completely circumvents all property equality checks (shallow compares) and always rerenders the component.\n\n#### More details\n\nThe first parameter, `name`, is used to allow update handlers (e.g. `update_foo(newValue)`) to handle the state transition for the specific state property that was marked dirty.\n\nThe second parameter, `value`, is used as the new value that is given to update handlers. Because `setStateDirty()` always bypasses all property equality checks, this parameter is optional. If not given or equal to the old value, the old value will be used for the update handler.\n\nImportant: the given parameters do not affect how or if `setStateDirty()` rerenders a component; they are only considered as additional information to update handlers.\n\n```js\n// Because this does not create a new array, the change\n// would not be detected by a shallow property comparison\nthis.state.colors.push(\"red\");\n\n// Force that particular state property to be considered dirty so\n// that it will trigger the component's view to be updated\nthis.setStateDirty(\"colors\");\n```\n\n### `subscribeTo(emitter)`\n\n| Signature    | Description                                                                                                                                           |\n| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `emitter`    | A [Node.js `EventEmitter`](https://nodejs.org/api/events.html#events_class_eventemitter) or DOM object that emits events (`window`, `document`, etc.) |\n| return value | A tracked subscription                                                                                                                                |\n\nWhen a component is destroyed, it is necessary to remove any listeners that were attached by the component to prevent memory leaks. By using `subscribeTo`, Marko will automatically track and remove any listeners you attach when the component is destroyed.\n\nMarko uses [`listener-tracker`](https://github.com/patrick-steele-idem/listener-tracker) to provide this feature.\n\n```js\nthis.subscribeTo(window).on(\"scroll\", () =>\n  console.log(\"The user scrolled the window!\"),\n);\n```\n\n### `update()`\n\nImmediately executes any pending updates to the DOM, rather than following the normal queued update mechanism for rendering.\n\n```js\nthis.setState(\"foo\", \"bar\");\nthis.update(); // Force the DOM to update\nthis.setState(\"hello\", \"world\");\nthis.update(); // Force the DOM to update\n```\n\n## Event methods\n\nMarko components inherit from [`EventEmitter`](https://nodejs.org/api/events.html#events_class_eventemitter). Below are a few commonly used methods — view the Node.js docs for the full list.\n\n### `emit(eventName, ...args)`\n\n| Signature   | Type     | Description                                           |\n| ----------- | -------- | ----------------------------------------------------- |\n| `eventName` | `String` | Name of the event                                     |\n| `...args`   | `Any`    | All subsequent parameters are passed to the listeners |\n\nEmits a UI component custom event. If a UI component attached a listener with the matching `eventName`, then the corresponding event listener method will be invoked. Event listeners can be attached using either the [`on-[event](methodName|function, ...args)`](#declarative-custom-events) attribute syntax, or `targetComponent.on()`.\n\n### `on(eventName, handler)`\n\n| Signature   | Type       | Description                               |\n| ----------- | ---------- | ----------------------------------------- |\n| `eventName` | `String`   | Name of the event to listen for           |\n| `handler`   | `Function` | The function to call when the event fires |\n\nAdds the listener function to the end of the listeners array for the `eventName` event. Does not check to see if the listener has already been added. Multiple calls passing the same combination of `eventName` and `handler` will result in the listener being added and called multiple times.\n\n### `once(eventName, handler)`\n\n| Signature   | Type       | Description                               |\n| ----------- | ---------- | ----------------------------------------- |\n| `eventName` | `String`   | Name of the event to listen for           |\n| `handler`   | `Function` | The function to call when the event fires |\n\nAdds a one-time listener function for the `eventName` event. The next time `eventName` triggers, this listener is removed and then invoked.\n\n## Lifecycle events\n\nMarko defines six lifecycle events:\n\n- `create`\n- `input`\n- `render`\n- `mount`\n- `update`\n- `destroy`\n\nThese events are emitted at specific points over the lifecycle of a component, as shown below:\n\n**First render**\n\n```js\nemit('create') → emit('input') → emit('render') → emit('mount')\n```\n\n**New input**\n\n```js\nemit('input') → emit('render') → emit('update')\n```\n\n**Internal state change**\n\n```js\nemit('render') → emit('update')\n```\n\n**Destroy**\n\n```js\nemit(\"destroy\");\n```\n\n### Lifecycle event methods\n\nEach lifecycle event has a corresponding component lifecycle method that can listen for the event:\n\n```js\nclass {\n  onCreate(input, out) { }\n  onInput(input, out) { }\n  onRender(out) { }\n  onMount() { }\n  onUpdate() { }\n  onDestroy() { }\n}\n```\n\n> **ProTip:** When a lifecycle event occurs in the browser, the corresponding event is emitted on the component instance. A parent component, or other code that has access to the component instance, can listen for these events. For example:\n>\n> ```js\n> component.on(\"input\", function (input, out) {\n>   // The component received an input\n> });\n> ```\n\n### `onCreate(input, out)`\n\n| Signature | Description                                                     |\n| --------- | --------------------------------------------------------------- |\n| `input`   | The input data used to render the component for the first time  |\n| `out`     | The async `out` used to render the component for the first time |\n\nThe `create` event is emitted (and `onCreate` is called) when the component is first created.\n\n`onCreate` is typically used to set the initial state for stateful components:\n\n```marko\nclass {\n    onCreate(input) {\n        this.state = { count: input.initialCount };\n    }\n}\n```\n\n### `onInput(input, out)`\n\n| Signature | Description        |\n| --------- | ------------------ |\n| `input`   | The new input data |\n\nThe `input` event is emitted (and `onInput` is called) when the component receives input: both the initial input, and for any subsequent updates to its input.\n\n### `onRender(out)`\n\n| Signature | Description                            |\n| --------- | -------------------------------------- |\n| `out`     | The async `out` for the current render |\n\nThe `render` event is emitted (and `onRender` is called) when the component is about to render or rerender.\n\n### `onMount()`\n\nThe `mount` event is emitted (and `onMount` is called) when the component is first mounted to the DOM. For server-rendered components, this is the first event that is emitted only in the browser.\n\nThis is the first point at which `this.el` and `this.els` are defined. `onMount` is commonly used to attach third-party JavaScript to the newly-mounted DOM.\n\nFor example, attaching a library that monitors if the component is in the viewport:\n\n```marko\nimport scrollmonitor from 'scrollmonitor';\n\nclass {\n    onMount() {\n        this.watcher = scrollmonitor.create(this.el);\n        this.watcher.enterViewport(() => console.log('I have entered the viewport'));\n        this.watcher.exitViewport(() => console.log('I have left the viewport'));\n    }\n}\n```\n\n### `onUpdate()`\n\nThe `update` event is emitted (and `onUpdate` is called) when the component is called after a component rerenders and the DOM has been updated. If a rerender does not update the DOM (nothing changed), this event will not fire.\n\n### `onDestroy()`\n\nThe `destroy` event is emitted (and `onDestroy` is called) when the component is about to unmount from the DOM and cleaned up. `onDestroy` should be used to do any additional cleanup beyond what Marko handles itself.\n\nFor example, cleaning up from our `scrollmonitor` example in [`onMount`](#onmount):\n\n```marko\nimport scrollmonitor from 'scrollmonitor';\n\nclass {\n    onMount() {\n        this.watcher = scrollmonitor.create(this.el);\n        this.watcher.enterViewport(() => console.log('Entered the viewport'));\n        this.watcher.exitViewport(() => console.log('Left the viewport'));\n    }\n    onDestroy() {\n        this.watcher.destroy();\n    }\n}\n```\n\n## DOM manipulation methods\n\nThe following methods move the component’s root DOM node(s) from the current parent element to a new parent element (or out of the DOM in the case of `detach`).\n\n### `appendTo(targetEl)`\n\nMoves the UI component’s DOM elements into the position after the target element’s last child.\n\n```js\nthis.appendTo(document.body);\n```\n\n### `insertAfter(targetEl)`\n\nMoves the UI component’s DOM elements into the position after the target DOM element.\n\n### `insertBefore(targetEl)`\n\nMoves the UI component’s DOM elements into the position before the target DOM element.\n\n### `prependTo(targetEl)`\n\nMoves the UI component’s DOM elements into the position before the target element’s first child.\n\n### `replace(targetEl)`\n\nReplaces the target element with the UI component’s DOM elements.\n\n### `replaceChildrenOf(targetEl)`\n\nReplaces the target element’s children with the UI component’s DOM elements.\n","packages/runtime-class/docs/cloudflare-workers.md":"# Marko + Cloudflare Workers\n\nSee the [the cloudflare sample](https://github.com/marko-js/examples/tree/master/examples/vite-cloudflare)\nproject for a working example.\n\n## Usage\n\nWhen using Marko with [Cloudflare Workers](https://workers.cloudflare.com/), make sure that Marko is loaded with a `worker` [export condition](https://nodejs.org/api/packages.html#conditional-exports). Most bundlers support defining export conditions.\n\nAfter that point, imported `.marko` files will export a `.stream` method that returns a worker compatible [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream). You can then respond with that returned stream:\n\n```js\nimport Template from \"./index.marko\";\n\naddEventListener(\"fetch\", (event) => {\n  event.respondWith(handleRequest(event.request));\n});\n\nasync function handleRequest(request) {\n  return new Response(Template.stream(), {\n    headers: {\n      status: 200,\n      headers: { \"content-type\": \"text/html;charset=UTF-8\" },\n    },\n  });\n}\n```\n\n### BYOB (Bring your own bundler)\n\nFor the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.\nMarko supports a number of bundlers, [take a look through our supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) and pick what works best for you.\n","packages/runtime-class/docs/compiler.md":"# Compiler\n\n> **Note**:\n> This page documents the compiler for Marko 5. The [Compiler API reference](https://markojs.com/docs/reference/compiler) covers the current compiler, including the options Marko 6 adds.\n\n> **Warning**:\n> The compiler API and hooks are not terribly stable. They’re intended for advanced integrations or userland experimentation with new language features.\n>\n> Prefer existing official plugins and the standard tag library when possible.\n\n## Compile API\n\n> **Warning**:\n> The Compile API is intended for advanced integration with build tools, like Webpack and Rollup. Unless you’re doing that, you probably instead want [`build`/`serve` in the Marko CLI](https://github.com/marko-js/cli#readme), or one of [Marko’s bundler integrations](https://markojs.com/docs/bundler-integrations-overview/).\n\n### Compile Functions\n\nCompile functions take two arguments:\n\n1. A source Marko template\n2. [`CompileOptions`](#options)\n\nThen, they return a `CompileResult`:\n\n```ts\ntype CompileResult = {\n  code: string;\n  map?: SourceMap;\n  meta: Record<string, unknown>;\n};\n```\n\n- `code`: The compiled output of executable JavaScript code.\n- `map`: [A source map, used for debugging.](https://firefox-source-docs.mozilla.org/devtools-user/debugger/how_to/use_a_source_map/index.html)\n- `meta`: Metadata gathered while compiling — nothing terribly useful, probably going to get deprecated.\n  - Data about child dependencies. Was useful back when it was primarily the bundlers that handled tree-shaking out server components. Now that happens in the compiler, so we don’t use this anymore and therefore might become inaccurate in the future.\n  - A list of `watchFiles`: files that were used to compile the template (e.g. `marko.json`). Used to tell bundlers which files should be watched in dev mode.\n\n#### `compileFile()` and `compileFileSync`\n\n```ts\ncompiler.compileFile(filename: string, options?: CompileOptions): Promise<CompileResult>\ncompiler.compileFileSync(filename: string, options?: CompileOptions): CompileResult\n```\n\n`compileFile` and `compileFileSync` load `filename` from disk to use as a source template, then translate it into JavaScript.\n\n```js\nimport * as compiler from \"@marko/compiler\";\n\nconst asyncResult = await compiler.compileFile(\"./src/index.marko\", {\n  modules: \"cjs\",\n});\nconst syncResult = compiler.compileFileSync(\"./src/index.marko\", {\n  modules: \"cjs\",\n});\n```\n\n#### `compile()` and `compileSync()`\n\n```ts\ncompiler.compile(src: string, filename: string, options?: CompileOptions): Promise<CompileResult>\ncompiler.compileSync(src: string, filename: string, options?: CompileOptions): CompileResult\n```\n\n`compile` and `compileSync` accept source templates as a string, rather than loading from disk.\n\nThe `filename` location is used for resolving taglibs and imports, but does not have to be an actually existing file. <!-- TODO: should it be renamed to baseFile or importBase or something? -->\n\n```js\nimport * as compiler from \"@marko/compiler\";\n\nconst asyncResult = await compiler.compile(\n  \"<h1>Hello!</>\",\n  \"./src/index.marko\",\n  { modules: \"cjs\" },\n);\nconst syncResult = compiler.compileSync(\"<h1>Hello!</>\", \"./src/index.marko\", {\n  modules: \"cjs\",\n});\n```\n\n### Options\n\nThe compiler may be configured globally to change its default options:\n\n```js\nimport * as compiler from \"@marko/compiler\";\ncompiler.configure({ output: \"dom\" });\n```\n\nOr you can pass options objects when calling compile functions. Each property will override individual properties set by `configure()`:\n\n```js\nimport * as compiler from \"@marko/compiler\";\ncompiler.configure({\n  output: \"dom\",\n  sourceMaps: true,\n});\nconst result = compiler.compileFileSync(\"./example.marko\", {\n  output: \"html\",\n});\n```\n\nIn the above example, `result` would be compiled with the options of `{ output: \"html\", sourceMaps: true }`.\n\n#### `output`\n\nType: `string`<br>\nDefault: `\"html\"`\n\n- `\"html\"`: compiles templates to JavaScript that generates HTML strings for server HTTP responses, writing `.html` files, or maybe even constructing `Response`s in Web Workers.\n- `\"dom\"`: compiles templates to JavaScript that generates DOM nodes for client-side rendering in browsers.\n- `\"hydrate\"`: like `\"dom\"`, but only includes assets & components needed in-browser, assuming the page was rendered on the server.\n- `\"migrate\"`: only runs migrations (no transforms or translation) and returns the migrated template code.\n- `\"source\"`: parses templates without running any migrations or transforms. (Useful with `ast: true`)\n\n> **Note**:\n> For `dom` or `hydrate` outputs, you should also specify a [`resolveVirtualDependency`](#resolvevirtualdependency) function.\n\n#### `code`\n\nType: `boolean`<br>\nDefault: `true`\n\nIf `false`, will not generate or return the compiled `code` string.\n\n#### `ast`\n\nType: `boolean`<br>\nDefault: `false`\n\nIf `true`, the compiler will provide the `ast` in its output.\n\n#### `stripTypes`\n\nType: `boolean|undefined`<br>\nDefault: `undefined`\n\nIf `true`, removes all TypeScript types from the output.\nIf the value is `undefined` (the default), the compiler will remove types if the `output` option is not `source` or `migrate`.\n\nFor example, to run migrations _and_ strip types, you can set both `output: \"migrate\"` and `stripTypes: true`.\n\n#### `runtimeId`\n\nType: `string`<br>\nDefault: `undefined`\n\nOptionally use to override the runtime ID used to differentiate multiple copies of Marko on the same page, which is passed to `marko/components.init(runtimeId)` when compiling in the `hydrate` output.\n\n#### `writeVersionComment`\n\nType: `boolean`<br>\nDefault: `true`\n\nWhether the Marko version should be written to the template in a comment, like so:\n\n```js\n// Compiled using marko@x.x.x - DO NOT EDIT\n```\n\n#### `ignoreUnrecognizedTags`\n\nType: `boolean`<br>\nDefault: `false`\n\nWhether unrecognized tags should be silently ignored or throw a compile error. Ignored tags will be output as native elements.\n\n> **ProTip**:\n> Some test setups use this alongside `taglib.excludeDir` and `taglib.excludePackage` from `@marko/compiler` to simulate \"shallow\" rendering.\n\n#### `sourceMaps`\n\nType: `boolean` or `string`<br>\nDefault: `false`\n\nWhether source maps should be output with the compiled templates.\n\n- When `true` a `map` property will be available on the compile result.\n- When `\"inline\"` the sourcemap will be inlined as a comment in the output code.\n- When `\"both\"` both of the above will be used.\n\n#### `meta`\n\nType: `boolean`<br>\nDefault: `false`\n\n_Deprecated_. This option inlines the metadata in the output Javascript code. Metadata should be accessed instead from the `CompileResult`.\n\n#### `fileSystem`\n\nType: typeof [`fs`](https://nodejs.org/api/fs.html) (specifically read APIs)<br>\nDefault: Cached `fs`\n\nUse a different file system object (eg. webpack's [CachedInputFileSystem](https://github.com/webpack/enhanced-resolve/blob/f08fe3f1a22c90c722eca14b38a9300ad00c62e8/lib/CachedInputFileSystem.js) or [`arc-fs`](https://github.com/eBay/arc/tree/master/packages/arc-fs))\n\n#### `modules`\n\nType: `string` (`\"esm\"` or `\"cjs\"`)<br>\nDefault: `\"esm\"`\n\nBy default Marko outputs ES Modules. You can optionally specify `\"cjs\"` for CommonJS/`require()`.\n\n#### `optimize`\n\nType: `boolean`<br>\nDefault: [environment based](https://github.com/marko-js/marko/blob/0f212897d2d3ec30b12c2f18ba950818bccb83b4/packages/compiler/src/babel-plugin/index.js#L277-L284) (`false` in development, `true` in production)\n\nEnables production mode optimizations.\n\n#### `optimizeKnownTemplates`\n\nType: `string[]`<br>\nDefault: `undefined`\n\nIf `optimize` is enabled you can provide an array of template paths which the compiler will use to generate shorter registry/template ids using incrementing ids. This can only be used if the same `optimizeKnownTemplates` are used for both server and client compilations.\n\n#### `resolveVirtualDependency`\n\nType:\n\n```ts\n(\n  filename: string,\n  dep: {\n    code: string;\n    virtualPath: string;\n    map?: SourceMap;\n  },\n) => string;\n```\n\nDefault: `undefined`\n\nThis option should be set for `dom` or `hydrate` outputs. Since Marko templates can represent multiple output files (eg. JS renderer and CSS styles), a single source `.marko` file must be treated as potentially multiple virtual files.\n\nDifferent build tools have different mechanisms for handling virtual files. You should pass a function that returns a virtual path that can be handled by your build tool.\n\n##### Example based on `@marko/webpack/loader`:\n\n```js\n// lookup is shared between resolveVirtualDependency and markoLoader\nconst virtualSources = new Map();\n\nfunction resolveVirtualDependency(filename, { virtualPath, code, map }) {\n  const virtualFilename = `${filename}?virtual=${virtualPath}`;\n\n  // Add virtual source to the lookup to be later accessed by the loader\n  virtualSources.set(virtualFilename, { code, map });\n\n  // Generate the webpack path, from right to left...\n  // 1. Pass the virtualFilename so webpack can find the real file\n  //    located at sourceFilename, but the virtualPath is also present\n  //    (eg. \"./index.marko?virtual=./index.marko.css\")\n  // 2. Use an inline loader to run this file through @marko/webpack/loader\n  //    https://webpack.js.org/concepts/loaders/#inline\n  // 3. Use an inline matchResource to redefine this as the virtualPath\n  //    which allows the appropriate loaders to match the virtual dependency\n  //    https://webpack.js.org/api/loaders/#inline-matchresource\n  return `${virtualPath}!=!@marko/webpack/loader!${virtualFilename}`;\n}\n\nexport default function markoLoader(source) {\n  let code, map;\n\n  if (virtualSources.has(this.resource)) {\n    // If the resource has a ?virtual query param, we should\n    // find it in the lookup and then return the virtual code\n    // rather than performing the normal compilation\n    ({ code, map } = virtualSources.get(this.resource));\n    virtualSources.delete(this.resource);\n  } else {\n    // The default behavior is to compile the template in dom output mode\n    ({ code, map } = markoCompiler.compileSync(source, this.resourcePath, {\n      output: \"dom\",\n      resolveVirtualDependency,\n    }));\n  }\n\n  return this.callback(null, code, map);\n}\n```\n\n#### `hydrateIncludeImports`\n\nThis option is only used for `output: \"hydrate\"`. By default, `import`s in server-only files are not included in the hydrate output. However, for some assets, like stylesheets, it is useful to have them included in hydrate mode.\n\nThe `hydrateIncludeImports` option allows you to provide a function which receives an import path, or a regexp to match against that path which tells Marko to include that import in the hydrate mode output.\n\nThe default regexp includes a list of common known asset file extensions, and is as follows:\n\n```js\n/\\.(css(\\.[cm]?[jt]s)?|less|s[ac]ss|styl(us)?|p(ost)?css|sss|png|jpe?g|gif|svg|ico|webp|avif|mp4|webm|ogg|mp3|wav|flac|aac|woff2?|eot|ttf|otf)$/;\n```\n\nLooking at a partial Marko file such as:\n\n```marko\nimport \"./bar\"\nimport \"./foo.css\";\nimport \"./baz.wasm\";\n\n<div/>\n```\n\nFor `hydrate` output, with the default `hydrateIncludeImports`, would only cause `./foo.css` to be loaded in the browser.\n\n#### `hydrateInit`\n\nThis option is only used for `output: \"hydrate\"`. It defaults to `true` and causes the hydrate output to include code which tells the Marko runtime to begin hydrating any registered components.\n\nSetting to false will disable that `init` call and allow you to generate code which _just_ imports any hydrate dependencies for a template.\n\n#### `cache`\n\nType: typeof [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) (specifically, `.get()` is required)<br>\nDefault: `new Map()`\n\nCompiling a Marko template may require other (used) Marko templates to compile. To prevent compiling templates more than once, most of the compilation is cached.\n\nThe default cache strategy is to clear the cache each macrotask. If the default cache is overwritten, it is up to the user to determine when the cache is cleared.\n\n#### `babelConfig`\n\nType: see [babel options](https://babeljs.io/docs/en/options)<br>\nDefault: babel defaults, plus\n\n```js\n{\n  filename,\n  sourceType: \"module\",\n  sourceMaps: config.sourceMaps\n}\n```\n\n#### `translator`\n\nType: `{ analyze: Visitor, transform:Visitor }`<br>\nDefault: [autodiscovers](https://github.com/marko-js/marko/blob/0f212897d2d3ec30b12c2f18ba950818bccb83b4/packages/compiler/src/config.js#L46-L89) a translator package starting with `@marko/translator-` or `marko-translator-`\n\nThe translator is a collection of transforms that translates the Marko AST into a valid JavaScript AST based on the `output` option. There is a default translator in Marko, but this option may be used to switch to experimental translators for alternate runtimes.\n\nThe translator is an object with `analyze` and `transform` [Babel Visitors](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#visitors):\n\n- The result of the `analyze` visitor is cached and may be requested by other templates.\n- The `transform` visitor transforms the AST to its final JavaScript AST.\n\nSee [`@marko/translator-default`](https://github.com/marko-js/marko/blob/11a10f82cdb5389880e6deca5f77d17727acb831/packages/translator-default/src/index.js) for a reference implementation.\n\n## Hooks\n\n> **Note**:\n> These compiler hooks aren’t terribly stable either. Using hooks for one-time migrations, like a codemod, is the best-supported way to use the compiler hooks, since you won’t have to worry about the code changing underneath you in the future.\n\n![1. Parse (angle bracket source code) 2. Migrate (old Marko to new Marko) 3. Transform (objects to different objects) 4. Translate (Marko to JavaScript.)](./compiler-hooks.png)\n\nThe Marko compiler runs a series of stages to produce its final JavaScript output. These stages handle different steps of template processing, and can be tweaked, extended, and hooked into with [`marko.json` configuration files](./marko-json.md).\n\n- All compiler hooks must have a default export of a [Babel-style visitor function](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#toc-visitors), which will receive a [babel `NodePath`](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#paths) with a `MarkoTag` node.\n\n- Hooks will also receive a `types` object that matches the [`@babel/types`](https://babeljs.io/docs/en/babel-types) API extended with the [Marko AST types](#marko-ast). (You may also reference the types by importing `{ types } from \"@marko/compiler\"`.)\n\n- Hooks may alternatively export an `enter` function (alias of `default`), and optionally an `exit` function. These map to [`@babel/traverse`’s `enter` and `exit` methods](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#babel-traverse).\n\nHere is an example hook:\n\n```js\nexport default (tag, types) => {\n  if (types.isStringLiteral(tag.node.name)) {\n    console.log(`Found a tag called ${tag.node.name.value}`);\n    tag.remove();\n  }\n};\n```\n\n### Parse\n\nMarko compilation starts by converting the raw text of your Marko template into an [AST (Abstract Syntax Tree)](https://en.wikipedia.org/wiki/Abstract_syntax_tree) — an object representation of your code.\n\n```marko\n<h1>Hello!</h1>\n```\n\n…will roughly become:\n\n```json\n{\n  \"type\": \"MarkoTag\",\n  \"name\": {\n    \"type\": \"StringLiteral\",\n    \"value\": \"h1\"\n  },\n  \"body\": {\n    \"type\": \"MarkoTagBody\",\n    \"body\": [\n      {\n        \"type\": \"MarkoText\",\n        \"value\": \"Hello!\"\n      }\n    ]\n  }\n}\n```\n\nThis might look a bit verbose, but ASTs aim for completeness, not terseness.\n\nMarko parses in two steps to stay flexible with the ever-changing syntax of JavaScript:\n\n1. The first parsing pass happens in our [`htmljs-parser`](https://github.com/marko-js/htmljs-parser), which understands the HTML and HTML-like parts of your template.\n\n2. For JavaScript expressions, Marko defers to [`@babel/parser`](https://babeljs.io/docs/en/babel-parser). The resulting [Marko AST](#marko-ast) is a superset of what `@babel/parser` would return.\n\nTo hook into the `parse` stage, use [the `parse` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n> **Note**: The `parse` hook deviates from the other compiler hooks:\n>\n> - It does not support the `enter` & `exit` API.\n> - You _must return_ a replacement AST node.\n\n### Migrate\n\nThat’s right, Marko has _first-class_ support for migrations. The **migration stage** can translate outdated APIs into modern counterparts, leaving the rest of the compilation none the wiser.\n\nMigrations run automatically in the background, and can be written to disk when users are ready by running the [`@marko/migrate` CLI command](https://github.com/marko-js/cli/blob/master/packages/migrate/README.md).\n\nTo hook into the `migrate` stage, [use the `migrate` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n> **Note:**\n> To make the compiler stop at this point and output the migrated template, rather than continuing to produce the JavaScript output, [set `output: \"migrate\"`](#output) in the [compilation options](#options).\n\n### Transform\n\nThe **transform stage** is meant for userland transformations of Marko code into different Marko code. Think of it like [`babel.transform`](https://babeljs.io/docs/en/babel-core#transform) for Marko templates.\nAt this stage, you are given a fully parsed and migrated AST to do what you will with.\n\nTo hook into the `transform` stage, [use the `transform` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n### Analyze\n\nNext is the **analyze stage**, intended for non-mutative analysis of the entire AST in a way that can be cached in RAM.\n\n> **Note**:\n> “Non-mutative analysis” means that if you modify the AST during this stage, _you’ll probably regret it_ someday.\n\nMetadata should be stored on nodes’ `.extra` property. These `.extra` properties are typically read in [the translate stage](#translate), or when using the child template analysis helpers.\n\nTo hook into the `analyze` stage, [use the `analyze` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n### Translate\n\nFinally, we have the **translation stage**. This stage is Marko’s “Rosetta Stone”, and is responsible for turning your beautiful `.marko` code into different versions of optimized JavaScript you’d rather not write yourself.\n\nTo hook into the `translate` stage, [use the `translate` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n## Utilities\n\n[The `@marko/babel-utils` package](https://github.com/marko-js/marko/tree/master/packages/babel-utils/index.d.ts) exposes a handful of utilities for various tasks on [Marko ASTs](#marko-ast).\n\n### Marko AST\n\nMarko extends Babel’s AST types to add nodes for `MarkoTag`, `MarkoAttribute`, etc.\n\nFor AST creation and assertion utilities, you can import Marko’s `@babel/types` superset from the compiler package:\n\n```js\nimport { types } from \"@marko/compiler\";\n```\n\nThe [`@babel/types` documentation](https://babeljs.io/docs/en/babel-types) shows all utility methods available for Babel AST nodes. When importing `types` from `@marko/compiler`, you also get the same types of utilities for Marko nodes: `types.markoTag`, `types.isMarkoTag`, `types.assertMarkoTag`, and so on.\n\nFor full definitions, view the source code for Babel and Marko:\n\n- [Babel’s Core Definitions](https://github.com/babel/babel/blob/master/packages/babel-types/src/definitions/core.js)\n- [Babel’s Extended Definitions](https://github.com/babel/babel/tree/master/packages/babel-types/src/definitions)\n- [Marko’s Definitions](https://github.com/marko-js/marko/blob/main/packages/compiler/src/babel-types/types/definitions.js)\n","packages/runtime-class/docs/concise.md":"# Concise syntax\n\nMarko's concise syntax is very similar to the HTML syntax, except it's more... concise. Essentially, you take an HTML tag, remove the angle brackets (`<>`) and use indentation rather than a closing tag:\n\n_input.marko_\n\n```marko\ndiv class=\"thumbnail\"\n    img src=\"https://example.com/thumb.png\"\n```\n\n_output.html_\n\n```html\n<div class=\"thumbnail\"><img src=\"https://example.com/thumb.png\" /></div>\n```\n\n## Shorthand attributes\n\nMarko provides a shorthand for declaring classes and ids on an element:\n\n_input.marko_\n\n```marko\ndiv.my-class\nspan#my-id\nbutton#submit.primary.large\n```\n\nYields this HTML:\n\n_output.html_\n\n```html\n<div class=\"my-class\"></div>\n<span id=\"my-id\"></span> <button id=\"submit\" class=\"primary large\"></button>\n```\n\n> **ProTip:** These shorthand attributes are available within the HTML syntax as well\n\n## Attributes on multiple lines\n\nIf a component has lots of attributes, you can spread them across multiple lines by surrounding them with square brackets\n\n_input.marko_\n\n```marko\ndiv [\n    id=\"hello\"\n    class=[\"class1\", \"class2\", \"class3\"]\n    style={ border: \"1px solid red\" }\n] -- hello\n```\n\n_output.html_\n\n```html\n<div id=\"hello\" class=\"class1 class2 class3\" style=\"border:1px solid red\">\n  hello\n</div>\n```\n\n## Text\n\nText in concise mode is denoted by two or more dashes (`--`).\n\nIf there is text on the same line following `--`, it is single-line text:\n\n_single-line-text.marko_\n\n```marko\n-- Hello world\n```\n\nThe dashes can also follow an element to give it a single text node as a child\n\n_single-line-text.marko_\n\n```marko\ndiv -- Hello world\n```\n\nIf there is a line break immediately following `--`, everything following the `--` at the current indentation is parsed as multi-line line text.\n\n_multi-line-text.marko_\n\n```marko\ndiv\n    --\n    Hello world\n    this text\n    is multi-line\n\ndiv\n    --\n    this is more\n    text\n```\n\nA multi-line text block can be ended by the same number of dashes that opened it. This allows it to have siblings:\n\n_multi-line-text.marko_\n\n```marko\ndiv\n    img src=\"https://example.com/photo.png\"\n    --\n    Hello world\n    this text\n    is multi-line\n    --\n    span -- text after\n```\n\n### Root level text\n\nThere is one \"gotcha\" that you need to be aware of. The Marko parser starts out in the concise mode. Therefore, given the following template:\n\n_input.marko_\n\n```marko\nHello World\nWelcome to Marko\n```\n\nThe output would be the following:\n\n_output.html_\n\n```html\n<Hello World></Hello> <Welcome to Marko></Welcome>\n```\n\nInstead, prefix the lines with `--` so they are parsed as text:\n\n_input.marko_\n\n```marko\n-- Hello World\n-- Welcome to Marko\n```\n","packages/runtime-class/docs/conditionals-and-lists.md":"# Conditionals and Lists\n\nWhile HTML itself does not support conditionally displaying elements or repeating elements, it is a critical part of building any web application. In Marko, this functionality is provided by the `<if>` and `<for>` tags.\n\n## Conditionals\n\nThe `<if>` tag receives an [argument](./syntax.md#arguments) which is used to determine if its body content should be present.\n\n```marko\n<if(user.loggedOut)>\n    <a href=\"/login\">Log in</a>\n</if>\n```\n\nAs you might expect, there are also `<else>` and `<else-if>` tags as well:\n\n```marko\n<if(user.loggedOut)>\n    <a href=\"/login\">Log in</a>\n</if>\n<else-if(!user.trappedForever)>\n    <a href=\"/logout\">Log out</a>\n</else-if>\n<else>\n    Hey ${user.name}!\n</else>\n```\n\n## Lists\n\nIf you have a list of data and need to represent it in the UI, the `<for>` tag is probably what you're looking for. The `<for>` tag passes each item and its index to its body as [parameters](./syntax.md#parameters).\n\n```marko\n<ul>\n    <for|color, index| of=colors>\n        <li>${index}: ${color}</li>\n    </for>\n</ul>\n```\n\nThe `<for>` tag actually support 3 different flavors:\n\n- [`<for|item, index, array| of=array>`](./core-tags.md#iterating-over-a-list) renders its body for each item of an array. It's similar to the JavaScript [`for...of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) loop.\n- [`<for|key, value| in=object>`](./core-tags.md#iterating-over-an-objects-properties) renders its body for each property in an object. It's similar to the JavaScript [`for...in`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in) loop.\n- [`<for|value| from=first to=last step=increment>`](./core-tags.md#iterating-between-a-range-of-numbers) renders its body for each value in between and including `from` and `to`.\n\n### Always set a `key`\n\nMarko automatically keeps your UI in sync with the state behind it, but one place where it needs a little extra help is repeated content. Specifying keys gives Marko a way to identify items in a list and keep track of which items have been changed, added, or removed.\n\nA key should be a string or number that uniquely identifies an item in the list and differentiates it from its siblings. The same key value should never be used twice! Often, you will use something like an `id` property.\n\n```marko\n<for|user| of=users>\n    <user-card key=user.id data=user/>\n</for>\n```\n\n> **ProTip:** If you have multiple tags underneath `<for>`, you can key only the first tag and that is enough to properly identify its siblings as well\n>\n> ```marko\n> <dl>\n>     <for|entry| of=entries>\n>         <!-- only the first tag needs a key -->\n>         <dt key=entry.id>${entry.word}</dt>\n>         <!-- This key can be omitted -->\n>         <dd>${entry.definition}</dd>\n>     </for>\n> </dl>\n> ```\n\n> **Note:** If a key is not set, Marko will use the index of an item as its key. However this only works perfectly if items are only ever added or removed at the end of a list. Here's an example where things break down: if we have a list of `[\"A\", \"B\", \"C\"]` and reverse the order, index keys would cause \"A\" to be transformed into \"C\" (and \"C\" into \"A\"), rather than just swapping them. Additionally if these components contained state, the new \"C\" would contain the state from the old \"A\" (and vice-versa). Be aware, stateful components include tags like the native `<input>` element. For this reason **it is always recommended to set a `key` on tags in a `<for>`.**\n","packages/runtime-class/docs/core-tags.md":"# Core tags and attributes\n\nMuch like [HTML has its own native tags](https://developer.mozilla.org/en-US/docs/Web/HTML/Element), Marko includes **core tags** and **global attributes** for declaratively building modern applications.\n\n## `<if>`, `<else-if>`, `<else>`\n\nLike the [equivalent JavaScript statements](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else), these tags render [conditional content](./conditionals-and-lists.md#conditionals):\n\n```marko\n<if(arriving)>\n  Hey there\n</if>\n<else-if(leaving)>\n  Bye now\n</else-if>\n<else>\n  What’s up?\n</else>\n```\n\nThey support any JavaScript expression in their [tag arguments](./syntax.md#arguments):\n\n```marko\n<if(Math.random() > 0.5)>\n  <p>50% chance to see this</p>\n</if>\n```\n\n## `<for>`\n\nThe `<for>` tag iterates over [arrays/array-likes](#iterating-over-a-list), [object properties](#iterating-over-an-objects-properties), and [ranges of numbers](#iterating-between-a-range-of-numbers).\n\n### Iterating over a list\n\nLike the [JavaScript `for...of` loop statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of), giving `<for>`’s `of` attribute a value will loop over that value as an array or iterable.\n\nThe current **item**, **index**, and the **iterating list** are provided as [tag parameters](./syntax.md#parameters):\n\n```marko\n$ const colors = [\"red\", \"green\", \"blue\"];\n<ol>\n  <for|color, index, colorList| of=colors>\n    <li value=index>${color}</li>\n  </for>\n</ol>\n```\n\nThe output HTML would be:\n\n```html\n<ol>\n  <li value=\"0\">red</li>\n  <li value=\"1\">green</li>\n  <li value=\"2\">blue</li>\n</ol>\n```\n\n> **Pro Tip**: `<for>`’s `of` attribute can loop over any iterable, just like JavaScript’s [`for...of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of). This includes strings, `NodeList`s, `Set`s… any object with zero-indexed numeric properties and a `.length`, basically.\n\n### Iterating over an object’s properties\n\nLike [JavaScript’s `for...in` loop statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in), giving `<for>` an object as its `in` attribute will loop over that object’s properties.\n\nThe current **property name** and **property value** are provided as [tag parameters](./syntax.md#parameters):\n\n```marko\n$ const settings = {\n  \"Dark Mode\": false,\n  \"Fullscreen\": true\n};\n\n<dl>\n  <for|name, enabled| in=settings>\n    <dt>${name}:</dt>\n    <dd>${enabled ? \"on\" : \"off\"}</dd>\n  </for>\n</dl>\n```\n\nThe output HTML would be:\n\n```html\n<dl>\n  <dt>Dark Mode:</dt>\n  <dd>off</dd>\n  <dt>Fullscreen:</dt>\n  <dd>on</dd>\n</dl>\n```\n\n### Iterating between a range of numbers\n\nThe final `<for>` variant loops between two numbers, by providing `from` and `to` attributes. The current number in the range will be provided as a [tag parameter](./syntax.md#parameters):\n\n```marko\n<ol type=\"I\">\n  <for|i| from=0 to=10>\n    <li value=i>${i}</li>\n  </for>\n</ol>\n```\n\nYou can also pass an optional `step` attribute, which defaults to 1 otherwise. `step` lets you increment by a specific amount:\n\n```marko\n<ol type=\"I\">\n  <for|i| from=0 to=10 step=2>\n    <li value=i>${i}</li>\n  </for>\n</ol>\n```\n\n…becomes:\n\n```marko\n<ol type=\"I\">\n  <li value=\"0\">0</li>\n  <li value=\"2\">2</li>\n  <li value=\"4\">4</li>\n  <li value=\"6\">6</li>\n  <li value=\"8\">8</li>\n  <li value=\"10\">10</li>\n</ol>\n```\n\n> **ProTip:** This syntax is for generating numbers from nothing. Don’t use it to iterate over an object, like so:\n>\n> ```marko\n> <!-- Inefficient code, do not copy -->\n> <ul>\n>   <for|i| from=0 to=(myArray.length - 1)>\n>     <li>${myArray[i]}</li>\n>   </for>\n> </ul>\n> ```\n>\n> Use [`<for of>`](#iterating-over-a-list) instead.\n\n## `<while>`\n\n> **Warning:** Using `<while>` is not recommended. Instead, replicate it with [an iterable and `<for>`](#iterating-over-a-list).\n>\n> In the future, Marko may restrict value mutation during rendering, for runtime optimizations.\n\nYou can repeat a chunk of markup _until a condition is met_ with the `while` tag:\n\n```marko\n$ let n = 0;\n\n<while(n < 4)>\n  <p>${n++}</p>\n</while>\n```\n\n…becomes:\n\n```html\n<p>0</p>\n<p>1</p>\n<p>2</p>\n<p>3</p>\n```\n\n## `<macro>`\n\nMacros create reusable markup fragments for later use in the same template they were defined in.\n\nThe `<macro>` tag defines a macro as a tag via the `name` attribute. For example, the following macro is registered as the `<greeting>` tag:\n\n```marko\n<macro name=\"greeting\">\n  <p>Welcome!</p>\n</macro>\n\n<greeting/>\n<greeting/>\n```\n\n…the output HTML would be:\n\n```html\n<p>Welcome!</p>\n<p>Welcome!</p>\n```\n\nMacros become more useful with [tag parameters](./syntax.md#parameters), allowing complex templates. In this next example, `<greeting>` can now receive `firstName` and `count` parameters from its parent:\n\n```marko\n<macro|{ firstName, count }| name=\"greeting\">\n  <p>Hello ${firstName}!\n    <output>You have ${count} new messages.</output>\n  </p>\n</macro>\n\n<greeting firstName=\"Frank\" count=20/>\n```\n\n…the output HTML would be:\n\n```html\n<p>\n  Hello Frank!\n  <output>You have 20 new messages.</output>\n</p>\n```\n\nMacros receive input like components do, including [a `renderBody` for provided body content](./body-content.md):\n\n```marko\n<macro|{ renderBody }| name=\"special-heading\">\n  <h1>\n    <${renderBody}/>!\n  </h1>\n</macro>\n\n<special-heading>\n  Hello\n</special-heading>\n```\n\n…the output HTML would be:\n\n```html\n<h1>Hello!</h1>\n```\n\n> **ProTip:** You can use a macro inside itself for recursive layouts, like displaying directory contents.\n\n## `<await>`\n\nThe `<await>` tag **renders markup asynchronously using a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)**.\n\n- Its `<@then>` [attribute tag](./syntax.md#attribute-tag) displays when the Promise _resolves_, optionally receiving the resolved value as a [tag parameter](./syntax.md#parameters).\n- Its `<@catch>` attribute tag displays when the Promise _rejects_, optionally receiving the rejected value as a tag parameter.\n- Its optional `<@placeholder>` attribute tag displays while the Promise is pending.\n\n```marko\n$ const personPromise = new Promise((resolve, reject) => {\n  setTimeout(() => resolve({ name: 'Frank' }), 1000);\n});\n\n<await(personPromise) client-reorder=true>\n  <@placeholder>\n    <!-- Displays while promise is pending -->\n    <label>Loading…\n      <progress></progress>\n    </label>\n  </@placeholder>\n\n  <@then|person|>\n    <!-- Displays if promise resolves -->\n    <p>Hello ${person.name}!</p>\n  </@then>\n\n  <@catch|err|>\n    <!-- Displays if promise rejects -->\n    ${err.name} error: ${err.message}\n  </@catch>\n</await>\n```\n\nOptional attributes for `<await>`:\n\n|        Attribute | Type    | Description                                                                                                                                                                   |\n| ---------------: | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n|        `timeout` | integer | An optional timeout. If reached, rejects the promise with a `TimeoutError`.                                                                                                   |\n|           `name` | string  | Improves debugging and ensures ordering with the `show-after` attribute.                                                                                                      |\n|     `show-after` | string  | Another `<await>` tag’s `name`. Use with `client-reorder` to ensure that the current `<await>` will always render alongside or after the named `<await>`.                     |\n| `client-reorder` | boolean | If true, anything after this `<await>` will be server-rendered before the Promise completes, then the fulfilled Promise’s result will be updated with client-side JavaScript. |\n\nRegardless of these attributes, the promise is executed as eagerly as possible. The attributes control how to coordinate rendering with the rest of the page:\n\n- `client-reorder` prevents `<await>` blocks from delaying the HTTP stream, at the expense of making their rendering rely on client-side JS. Useful for making non-critical page sections not block HTML streaming of important content.\n\n- Using `show-after` with `client-reorder` ensures that the current `<await>` block will always render simultaneously with or after the named `<await>`. Useful for cutting down on [layout shift](https://web.dev/debug-layout-shifts/). `<@placeholder>`s can help fine-tune the user experience while loading.\n\n- `timeout` is useful for limiting non-critical content from slowing down the rest of the page too much.\n\n> **Pro Tip**: When using `timeout`, you can distinguish between `TimeoutError`s and promise rejections by checking the error’s `name`:\n>\n> ```marko\n> <await(slowPromise) timeout=5000>\n>   <@then>Done</@then>\n>   <@catch|err|>\n>     <if(err.name === \"TimeoutError\")>\n>       Took too long to fetch the data!\n>     </if>\n>     <else>\n>       Promise failed with ${err.message}.\n>     </else>\n>   </@catch>\n> </await>\n> ```\n\n## `<include-text>`\n\n`<include-text>` inlines text files into a template, escaping HTML syntax characters (`<`, `\"`, etc.).\n\n```marko\n<include-text('./foo.txt')/>\n```\n\nIf you do not want escaping, use [`<include-html>`](#include-html) instead.\n\n## `<include-html>`\n\nLike `<include-text>`, `<include-html>` inlines the contents of a file. However, this tag **does _not_ escape** special HTML characters.\n\n```marko\n<include-html('./foo.html')/>\n```\n\n## `<html-comment>`\n\nMarko removes HTML comment tags from its output. But if you need comments in the output, that’s what `<html-comment>` is for:\n\n```marko\n<html-comment>[if IE]><script src=\"html-shiv.js\"></script><![endif]</html-comment>\n```\n\n…becomes:\n\n```html\n<!--[if IE]><script src=\"html-shiv.js\"></script><![endif]-->\n```\n","packages/runtime-class/docs/custom-tags.md":"# Custom tags\n\nCustom tags allow you to break up your application UI into encapsulated, reusable components.\n\n## Your first custom tag\n\nLet's say we have a page with the following content:\n\n_page.marko_\n\n```marko\n<!doctype html>\n<html>\n<body>\n    <h1>Hello World!</h1>\n</body>\n</html>\n```\n\nHowever, this page is getting pretty complex and unmaintainable. Let's split out the content into a separate component. To do this, we'll create a `components/` folder and inside it a `hello.marko` file:\n\n_components/hello.marko_\n\n```marko\n<h1>Hello World!</h1>\n```\n\nMarko [automatically discovers](#how-tags-are-discovered) `.marko` files under a `components/` directory, so we can now use the `<hello>` tag in our page:\n\n_page.marko_\n\n```marko\n<!doctype html>\n<html>\n<body>\n    <hello/>\n</body>\n</html>\n```\n\nNow this `<hello>` tag can be used multiple times, and even on multiple pages. But what if we don't only want to say hello to the world? Let's pass some attributes.\n\n_page.marko_\n\n```marko\n<!doctype html>\n<html>\n<body>\n    <hello name=\"World\"/>\n</body>\n</html>\n```\n\nThe component will receive these attributes as `input`:\n\n_components/hello.marko_\n\n```marko\n<h1>Hello ${input.name}!</h1>\n```\n\nNice.\n\n## How tags are discovered\n\nMarko discovers components relative to the `.marko` file where a custom tag is used. From this file, Marko walks up directories until it finds a `components/` folder which contains a component matching the name of the custom tag. If it reaches the project root without finding anything, it will then check installed packages for the component.\n\nLet's take a look at an example directory structure to better understand this:\n\n```dir\ncomponents/\n    app-header.marko\n    app-footer.marko\npages/\n    about/\n        components/\n            team-members.marko\n        page.marko\n    home/\n        components/\n            home-banner.marko\n        page.marko\n```\n\nThe file `pages/home/page.marko` can use the following tags:\n\n- `<app-header>`\n- `<app-footer>`\n- `<home-banner>`\n\nAnd the file `pages/about/page.marko` can use the following tags:\n\n- `<app-header>`\n- `<app-footer>`\n- `<team-members>`\n\nThe home page can't see `<team-members>` and the about page can't see `<home-banner>`. By using nested `component/` directories, we've scoped our page-specific components to their respective pages.\n\n## Tag directories\n\nIn addition to a Marko template, the children of `components/` can be a directory with an `index.marko` template:\n\n```dir\ncomponents/\n    app-header/\n        index.marko\n        logo.png\n        style.css\n    app-footer/\n        index.marko\n```\n\nOr a directory with a template whose name matches its parent directory:\n\n```dir\ncomponents/\n    app-header/\n        app-header.marko\n        app-header.style.css\n        logo.png\n    app-footer/\n        app-footer.marko\n```\n\nThis allows you to create components that have other files associated with them and keep those files together in the directory structure.\n\n> **ProTip:**\n> You can take advantage of nested `components/` directories to create \"subcomponents\" that are only available to the component that contains them.\n>\n> ```dir\n> components/\n>     app-header/\n>         components/\n>             navigation.marko\n>             user-info.marko\n>         app-header.marko\n>     app-footer/\n>         app-footer.marko\n> ```\n\n## Using tags from npm\n\nTo use [tags from npm](https://www.npmjs.com/search?q=keywords%3Amarko%20components), ensure that the package is installed and listed in your `package.json` dependencies:\n\n```\nnpm install --save @marko-tags/match-media\n```\n\nMarko discovers tags from packages defined in your `package.json`, so you can start using them right away:\n\n```marko\n<div>\n    <match-media|{ mobile }| mobile=\"max-width:30em\">\n        <!-- nice -->\n    </match-media>\n</div>\n```\n\n## Publishing tags to npm\n\nWe saw above that tags from npm are automatically discovered. In order to make this work, your package must include a [`marko.json`](./marko-json.md) at the root.\n\n_marko.json_\n\n```json\n{\n  \"tags-dir\": \"./dist/components\"\n}\n```\n\nThis example file tells Marko to expose all components directly under the `dist/components/` directory to the application using your package.\n\nIf your components are written in TypeScript, publish the output of [`mtc`](https://github.com/marko-js/language-server/tree/main/packages/type-check). Editors and type checkers read components under `node_modules` as JavaScript, so consumers get their types from the `.d.marko` files it emits. See [TypeScript in Marko](./typescript.md).\n\nWe recommend adding the `marko` and `components` keywords to your `package.json` so others can find your components. Then `npm publish`!\n\n# Macros\n\nThe [`<macro>`](./core-tags.md#macro) tag allows you to create custom tags in the same file that they are used in.\n\n```marko\n<macro|{ name }| name=\"welcome-message\">\n    <h1>Hello ${name}!</h1>\n</macro>\n\n<welcome-message name=\"Patrick\"/>\n<welcome-message name=\"Austin\"/>\n```\n\n# From Variables\n\nIf no other tag would be discovered Marko will check for an in scope variable that matches the tag name.\n\n```marko\nimport SomeTag from \"./somewhere.marko\"\n\n$ const { renderBody } = input;\n$ const MyTag = input.href ? \"a\" : \"button\";\n\n<SomeTag/>\n<MyTag/>\n<renderBody/>\n```\n","packages/runtime-class/docs/editor-plugins.md":"# Editor Plugins\n\n## Visual Studio Code\n\n[Documentation](https://marketplace.visualstudio.com/items?itemName=Marko-JS.marko-vscode)\n\n- Syntax highlighting\n- Tag matching\n- Tag, attribute and css autocompletion\n- Hyperclick (clickable tags and attributes)\n- Surfaces errors within the templates.\n- Prettyprinting ([marko-prettyprint](https://github.com/marko-js/marko-prettyprint) is used internally)\n\n## Atom\n\n[Documentation](https://atom.io/packages/language-marko)\n\n- Syntax highlighting\n- Tag matching\n- Tag and attribute autocompletion\n- Code snippets\n- Hyperclick (clickable tags and attributes)\n- Prettyprinting ([marko-prettyprint](https://github.com/marko-js/marko-prettyprint) is used internally)\n\n## Sublime\n\n[Documentation](https://github.com/merwan7/sublime-marko)\n\n- Syntax highlighting\n\n## WebStorm\n\n[Documentation](https://github.com/marko-js/marko-tmbundle)\n\n- Syntax highlighting\n\n## TextMate\n\n[Documentation](https://github.com/marko-js/marko-tmbundle)\n\n- Syntax highlighting\n\n## CodeMirror\n\n[codemirror-atom-modes](https://github.com/patrick-steele-idem/codemirror-atom-modes) + [atom-language-marko](https://github.com/marko-js/atom-language-marko)\n","packages/runtime-class/docs/events.md":"# Events\n\nMarko’s event API supports:\n\n- [Browser events](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Events) on native tags\n- Custom events from [custom tags](./custom-tags.md)\n\nNote that **you can’t mix event targets and event types**: custom tags can only listen for custom events, and native tags can only listen for native events.\n\n## Listening to events\n\nBoth kinds of events are received with an `on-*` attribute and the [attribute arguments syntax](./syntax.md#arguments):\n\n```marko\n<input type=\"checkbox\"\n  on-change(event => console.info(`Checked? ${event.target.checked}`))\n/>\n```\n\nThe [first argument for the attribute can be a function](#function-handler), or [a string matching a method name](#method-handler) on the [component’s `class` declaration](./class-components.md).\n\n### Function handler\n\nIf you provide a function as the first argument of the `on-*` attribute, the function is called whenever the event fires, like standard event listeners.\n\nBelow we use the [`static` prefix](./syntax.md#static-javascript) to define a function, then use it as a `click` handler:\n\n```marko\nstatic function handleClick(event) {\n  event.preventDefault();\n  console.log(\"Clicked!\");\n}\n\n<button on-click(handleClick)>\n  Log click\n</button>\n```\n\nIn the above example, any time the `<button>` is clicked the `handleClick` function is called.\n\nYou can also use an inline arrow function:\n\n```marko\n<button on-click(() => alert(\"Clicked! 🎉\"))>\n  Celebrate click\n</button>\n```\n\n…or anything that evaluates to a function:\n\n```marko\n$ const handler = (\n  input.dontBreakMyApp ?\n    () => console.error(\"Clicked!\") :\n    () => { throw Error(\"Clicked!\") }\n);\n\n<button on-click(handler)>\n  Do not click\n</button>\n```\n\n### Method handler\n\nWhen a string is the first argument, Marko calls a matching method on the component's `class`.\n\n```marko\nclass {\n  logChange(newTab) {\n    console.log(`changed to: ${newTab}`);\n  }\n}\n\n<my-tabs on-switch-tab(\"logChange\")>\n  …\n</my-tabs>\n```\n\nWhen `<my-tabs>` emits the `switch-tab` event, it will call its `logChange` method.\n\nWithin the handler you can access the current component instance, read data, emit events, update state, etc.\n\n### Binding additional arguments\n\nArguments after the handler are prepended when the handler is called:\n\n```marko\nstatic function removeFriend(friendId, event) {\n  event.preventDefault();\n  window.myAPI.unfriend(friendId);\n}\n\n<for|friend| of=input.friends>\n  <button on-click(removeFriend, friend.id)>\n    Unfriend ${friend.name}\n  </button>\n</for>\n```\n\nHere we share the logic for `removeFriend()` with each `friend` in the `friends` array. When the `<button>` is clicked, the `id` of the removed `friend` is passed to the `removeFriend()`, handler followed by the DOM `click` event.\n\n## Emitting custom events\n\nThe recommended way for a [custom tag](./custom-tags.md) to communicate with its parent is through **custom events**.\n\nAll components implement a [Node.js-style event emitter](https://nodejs.org/api/events.html#events_class_eventemitter) to send events to parent components.\n\n_email-input.marko_\n\n```marko\nclass {\n  handleChange(event) {\n    if (event.target.validity.valid) {\n      // Only emit email-changes if they are valid.\n      this.emit(\"email-change\", { email: event.target.value });\n    }\n  }\n}\n\n<input type=\"email\" name=input.name on-change(\"handleChange\")/>\n```\n\nThe above code listens to native `change` events from the `<input>` element, and then emits its own `email-change` event if the change was valid.\n\n```marko\n<form>\n  <email-input name=\"email\" on-email-change(\"...\")/>\n</form>\n```\n\n> **Note:** Events are not received as `input`; you cannot access `input.onEmailChange`. Instead, they set up subscriptions.\n","packages/runtime-class/docs/express.md":"# Marko + Express\n\n## Quick Start\n\n```sh\nnpm init marko -- --template vite-express\n# Or `npx create-marko --template vite-express`\n```\n\nSee [Marko’s example projects](https://github.com/marko-js/examples) for working [Express](https://expressjs.com/) integration code, such as:\n\n- [`examples/vite-express`](https://github.com/marko-js/examples/tree/master/examples/vite-express)\n- [`examples/rollup-express`](https://github.com/marko-js/examples/tree/master/examples/rollup-express)\n- [`examples/webpack-express`](https://github.com/marko-js/examples/tree/master/examples/webpack-express)\n\nBut if you want to do things the hard way…\n\n## Doing things the hard way\n\nFirst, install Marko, Express, and the glue to hold them together:\n\n```sh\nnpm install marko express @marko/express --save\n```\n\n### Skip the view engine\n\nExpress’s builtin view engine may be asynchronous, but it doesn’t support streaming — see [Rediscovering Progressive HTML Rendering](https://tech.ebayinc.com/engineering/async-fragments-rediscovering-progressive-html-rendering-with-marko/) for why that’s important. So instead, we [bypass Express’s view engine](https://strongloop.com/strongblog/bypassing-express-view-rendering-for-speed-and-modularity/) to use `@marko/express` instead.\n\n[The `@marko/express` package](https://www.npmjs.com/package/@marko/express) adds a `res.marko()` method to [Express’s response object](https://expressjs.com/en/api.html#res). This method works like [`res.render()`](https://expressjs.com/en/api.html#res.render), but without the restrictions of Express’s view engine, letting you take full advantage of Marko’s streaming and modular template organization.\n\n> **ProTip**: By using `res.marko()`, properties from [`app.locals`](https://expressjs.com/en/api.html#app.locals) and [`res.locals`](https://expressjs.com/en/api.html#res.locals) are automatically [available on `$global`](https://markojs.com/docs/rendering/#global-data).\n\n```js\nimport express from \"express\";\nimport markoPlugin from \"@marko/express\";\nimport template from \"./template.marko\";\n\nconst app = express();\napp.use(markoPlugin()); // Enables `res.marko(template, input)`\n\napp.get(\"/\", function (req, res) {\n  res.marko(template, {\n    name: \"Frank\",\n    count: 30,\n    colors: [\"red\", \"green\", \"blue\"],\n  });\n});\n\napp.listen(8080);\n```\n\n> **Note**: Older versions of `@marko/express` used to also attach Express’s `app`, `req`, and `res` objects onto `$global`. This meant uncontrolled network data could cause new and exciting surprises in your app code. Nowadays we recommend explicitly accessing the specific pieces of the HTTP exchange you’re interested in, like this:\n>\n> ```js\n> app.get(\"/\", function (req, res) {\n>   res.marko(template, {\n>     params: req.params,\n>     submitted: req.method === \"POST\" && req.body,\n>   });\n> });\n> ```\n\n### BYOB (Bring Your Own Bundler)\n\nMost of Marko’s API requires a bundler: the example code above assumes that `.marko` files can be `import`ed in your environment. [Check out Marko’s supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) to see what works best for you.\n","packages/runtime-class/docs/fastify.md":"# Marko + Fastify\n\n## Quick Start\n\n```terminal\nnpm init marko -- --template vite-fastify\n```\n\nSee the [the fastify sample](https://github.com/marko-js/examples/tree/master/examples/vite-fastify)\nproject for a working example.\n\n## From Scratch\n\nFirst install Marko and the fastify related dependencies:\n\n```terminal\nnpm install marko @marko/fastify fastify --save\n```\n\n### Usage\n\nThe [`@marko/fastify`](https://github.com/marko-js/fastify/) adds a `reply.marko` decorator to the `reply` object. This function allows us to pass in a Marko template and supports Marko's streaming and modular approach to templates.\n\nBy using `reply.marko` you'll automatically have access to `app.locals`, and `reply.locals` from within your Marko template and custom tags. These values are added to `$global`.\n\n```javascript\nimport fastify from \"fastify\";\nimport markoPlugin from \"@marko/fastify\";\nimport Template from \"./template.marko\";\n\nconst app = fastify();\n\napp.register(markoPlugin);\n\napp.get(\"/\", (request, reply) => {\n  // Streams Marko template into the response.\n  // Forwards errors into fa error handler.\n  reply.marko(Template, { hello: \"world\" });\n});\n\nawait fastify.listen(3000);\n```\n\n### Global Outputs\n\nWe can add global outputs from the server side using the reply object or fastify instance.\n\n```javascript\nreply.locals.newProperty = \"Your value\";\n```\n\nTo use this in marko components we just need to refer out.global\n\n```marko\n$ const { newProperty } = $global;\n```\n\nTo know more about sending the data to the browser checkout:\n\n### [Sending global data to browsers](https://markojs.com/docs/rendering/#sending-global-data-to-browsers)\n\n### BYOB (Bring your own bundler)\n\nFor the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.\nMarko supports a number of bundlers, [take a look through our supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) and pick what works best for you.\n","packages/runtime-class/docs/getting-started.md":"# Getting started\n\n## Setup\n\n### Marko Run (Recommended)\n\n[Marko Run](https://github.com/marko-js/run) makes it easy to get started with little to no config and is the recommended starting point for a new Marko project.\n\nTo set up your project:\n\n1. `npm init marko -- -t basic`\n2. `cd ./<PROJECT_NAME>`\n3. `npm run dev`\n\nOpen `src/routes/_index/+page.marko` in your editor to change the index page. See the [routing documentation](https://github.com/marko-js/run#file-based-routing) to learn how to add additional pages to your project.\n\n### Other setups\n\nIf you just want to test out Marko in your browser, use the [Try Online](https://markojs.com/try-online) feature. You can open it in another tab and follow along. For other setups, check out the [Installation](./installing.md) page.\n\n## Hello world\n\nMarko makes it easy to represent your UI using a [syntax](./syntax.md) that is like HTML:\n\n_hello.marko_\n\n```marko\n<h1>Hello World</h1>\n```\n\nIn fact, Marko is so much like HTML, that you can use it as a replacement for a templating language like handlebars, mustache, or pug:\n\n_template.marko_\n\n```marko\n<!doctype html>\n<html>\n<head>\n    <title>Hello World</title>\n</head>\n<body>\n    <h1>Hello World</h1>\n</body>\n</html>\n```\n\nHowever, Marko is much more than a templating language. It's a language that allows you to declaratively build an application by describing how the application view changes over time and in response to user actions.\n\nIn the browser, when the data representing your UI changes, Marko will automatically and efficiently update the DOM to reflect the changes.\n\n## A simple component\n\nLet's say we want to perform an action once a `<button>` is clicked:\n\n_button.marko_\n\n```marko\n<button>Click me!</button>\n```\n\nMarko makes this really easy, allowing you to define a `class` for a component right in the `.marko` view and call methods of that class with `on-` attributes:\n\n_button.marko_\n\n```marko\nclass {\n    sayHi() {\n        alert(\"Hi!\");\n    }\n}\n\n<button on-click(\"sayHi\")>Click me!</button>\n```\n\n### Adding state\n\nAlerting when a button is clicked is great, but what about updating your UI in response to an action? Marko's stateful components make this easy. All you need to do is set `this.state` from inside your component's class. This makes a new `state` variable available to your view. When a value in `this.state` is changed, the view will automatically re-render and only update the part of the DOM that changed.\n\n_counter.marko_\n\n```marko\nclass {\n    onCreate() {\n        this.state = {\n            count: 0\n        };\n    }\n    increment() {\n        this.state.count++;\n    }\n}\n\n<div>The current count is ${state.count}</div>\n<button on-click(\"increment\")>Click me!</button>\n```\n","packages/runtime-class/docs/http.md":"# Marko + HTTP Server\n\nSee the [the http sample](https://github.com/marko-js/examples/tree/master/examples/vite-http)\nproject for a working example.\n\n## Usage\n\n```js\nimport http from \"http\";\nimport Template from \"./index.marko\";\n\nconst port = 8080;\nconst server = http.createServer();\n\nserver.on(\"request\", (req, res) => {\n  Template.render(\n    {\n      name: \"Frank\",\n      count: 30,\n      colors: [\"red\", \"green\", \"blue\"],\n    },\n    res,\n  ).on(\"error\", (err) => {\n    // Without a listener, a render error crashes the process.\n    console.error(err);\n  });\n});\n\nserver.listen(port, () => {\n  console.log(`Successfully started server on port ${port}`);\n});\n```\n\n### BYOB (Bring your own bundler)\n\nFor the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.\nMarko supports a number of bundlers, [take a look through our supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) and pick what works best for you.\n","packages/runtime-class/docs/installing.md":"# Installation\n\n## Trying out Marko\n\nIf you just want to play around with Marko in the browser, head on over to our [Try Online](https://markojs.com/try-online) feature. You'll be able to develop a Marko application right in your browser.\n\n## Creating new apps (Recommended)\n\nIf you're starting from scratch, you can use Marko's [CLI](https://github.com/marko-js/cli) commands to quickly create a starter app:\n\n```bash\nnpm init marko\n```\n\nThis will use an interactive [CLI](https://github.com/marko-js/cli) to automatically create a project for you using the pre-made starter template of your choosing. The `basic` template is the most minimal and the easiest way to get started. It uses our recommended app framework [Marko Run](https://github.com/marko-js/run) that handles building, bundling, and serving your web application. These projects are config-free with built-in file based routing and automatic code reloading.\n\n## Custom Bundling\n\nMarko relies on JavaScript bundlers to package your code on both the client and the server. This is because Marko's client and server bundling works closely together to optimize the smallest client bundles and handle shared assets properly.\n\nUsing the CLI is still the easiest way to get started even when you want to get your hands dirty tweaking every last part of your config files. Marko currently supports Webpack, Lasso, and Rollup.\n\n### Webpack\n\n[Webpack Integration Docs](https://markojs.com/docs/webpack/)\n\n[Marko Webpack Plugin](https://github.com/marko-js/webpack)\n\n[Webpack Example](https://github.com/marko-js/examples/tree/master/examples/webpack-express)\n\nCLI Command: `npx @marko/create --template webpack-express`\n\n### Lasso\n\n[Lasso Integration Docs](https://markojs.com/docs/lasso/)\n\n[Marko Lasso Plugin](https://github.com/lasso-js/lasso-marko)\n\n[Lasso Example](https://github.com/marko-js/examples/tree/master/examples/lasso-express)\n\nCLI Command: `npx @marko/create --template lasso-express`\n\n### Rollup\n\n[Rollup Integration Docs](https://markojs.com/docs/rollup/)\n\n[Marko Rollup Plugin](https://github.com/marko-js/rollup)\n\n<!-- [Rollup Example](https://github.com/marko-js/examples/tree/master/examples/rollup)\n\nCLI Command: `npx @marko/create --template rollup` -->\n","packages/runtime-class/docs/koa.md":"# Marko + Koa\n\nSee the [the koa sample](https://github.com/marko-js/examples/tree/master/examples/vite-koa)\nproject for a working example.\n\n## Installation\n\n```terminal\nnpm install koa marko --save\n```\n\n## Usage\n\n```javascript\nimport Koa from \"koa\";\nimport Template from \"./index.marko\";\n\nconst app = new Koa();\n\napp.use((ctx, next) => {\n  ctx.type = \"html\";\n  ctx.body = Template.stream({\n    name: \"Frank\",\n    count: 30,\n    colors: [\"red\", \"green\", \"blue\"],\n  });\n});\n\napp.listen(8080);\n```\n\n### BYOB (Bring your own bundler)\n\nFor the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.\nMarko supports a number of bundlers, [take a look through our supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) and pick what works best for you.\n","packages/runtime-class/docs/lasso.md":"# Marko + Lasso\n\nThe [lasso-marko](https://github.com/lasso-js/lasso-marko) plugin for [Lasso.js](https://github.com/lasso-js/lasso) will automatically compile all imported Marko templates during bundling. In addition, the `lasso-marko` plugin will automatically bundle any template dependencies (including required CSS).\n\nLasso.js provides Marko custom tags for injecting JavaScript and CSS bundles, images and other resources.\n\nThe sample [lasso-express](https://github.com/marko-js/examples/tree/master/examples/lasso-express) app demonstrates how to build a production-ready web application using Marko and Lasso. Run `npx @marko/create --template lasso-express` to use this sample as a starting point for a new app.\n\n## Installation\n\n```\nnpm install lasso-marko --save\n```\n\n## Registering the plugin\n\n```js\nrequire('lasso').configure({\n    \"plugins\": [\n        ...\n        \"lasso-marko\"\n    ]\n    ...\n});\n```\n\n## Lasso custom tags\n\nTo inject the required JavaScript and CSS into the page you will want to use the `<lasso-page>`, `<lasso-head>` and `<lasso-body>` tags.\n\nIf you are using lasso@^3 (latest), make sure to install the [lasso-marko-taglib](https://github.com/lasso-js/lasso-marko-taglib), so that you can use the lasso custom tags.\n\n```\nnpm install lasso-marko\nnpm install @lasso/marko-taglib\n```\n\nAfter installing, the lasso custom tags can be used in your templates:\n\n```html\n<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>Marko + Lasso</title>\n    <lasso-head />\n  </head>\n  <body>\n    <lasso-body />\n  </body>\n</html>\n```\n\nLasso.js will automatically bundle up transitive dependencies by building and walking a dependency graph.\n\n## Client-side rendering\n\nMarko templates can be imported and rendered by any JavaScript module. The code below shows how to render a top-level UI component and have it be mounted to the DOM as a child `document.body`:\n\n_client.js_\n\n<!-- prettier-ignore -->\n```js\nrequire(\"./components/app/index.marko\")\n  .renderSync({})\n  .appendTo(document.body);\n```\n\nWhen Lasso.js bundles up the code above it will automatically bundle up the required `./components/app/index.marko` file.\n\n## Server-side rendering\n\nIf you are rendering the initial UI on the server then it is necessary to make sure that all UI components are bundled and sent to the browser so that UI components can be mounted in the browser. For example:\n\n_about-me/index.marko_\n\n```marko\n<!DOCTYPE html>\n<html lang=\"en\">\n    <head>\n        <meta charset=\"UTF-8\">\n        <title>Marko + Lasso</title>\n\n        <!-- CSS will be inserted here -->\n        <lasso-head/>\n    </head>\n    <body>\n        <!-- Top-level UI component: -->\n        <app/>\n\n        <!-- JS will be inserted here -->\n        <lasso-body/>\n    </body>\n</html>\n```\n\n## Browser refresh\n\n[browser-refresh](https://github.com/patrick-steele-idem/browser-refresh) is recommended in development for instant page refreshes and hot reloading of Marko templates, styles and other resources. `browser-refresh` works well with Lasso and Marko and is very easy to use as a drop-in replacement for `node`:\n\n```bash\nbrowser-refresh server.js\n```\n\n## Lasso package types commonly used with Marko\n\nFor many use cases, the combination of `lasso-marko` and `@lasso/marko-taglib` is sufficient to render and bundle components without the need for explicit `browser.json` files. For more advanced use cases, the following bundle types may be defined in a `browser.json` for Lasso.\n\n#### `marko-dependencies` _(provided by `lasso-marko`)_\n\nIncludes all the dependencies needed by template and the code to register all components that would be rendered by the template. It does not automatically initialize the component, so is most useful if you need to initialize components manually.\n\n```json\n{\n  \"type\": \"marko-dependencies\",\n  \"path\": \"src/ui-modules/outdated-browser-banner/index.marko\"\n}\n```\n\n**Note:** To initialize the server rendered components, there are 2 steps:\n\n**Step 1:** Manually _retrieve_ server rendered components, shipped via `marko-dependencies`.\n\nTo retrieve the list of server rendered components, do:\n\n```javascript\ntemplate.render(data, (err, output) => {\n  const renderedComponentsList =\n    require(\"marko/components\").getRenderedComponents(output.out);\n  const html = output.getOutput();\n});\nres.json({\n  renderedComponentsList,\n  html,\n});\n```\n\n**Step 2:** Manually _initialize_ server rendered components, shipped via `marko-dependencies`.\n\nTo initialize the list of server rendered components, do:\n\n```javascript\n// from the response received, retrieve as\nrequire(\"marko/components\").init(response.renderedComponentsList);\n```\n\n**Note:** Ensure Step 2 is inside a DOM-ready wrapper, for the legacy widgets layer to load (if there are widgets built out of Marko 3, that is being used inside a Marko 4 component.)\n\n#### `marko-hydrate` _(provided by `lasso-marko`)_\n\nIncludes all the dependencies needed by template and the code to register all components that would be rendered by the template. This also includes the code to initialize the rendered components. Including this bundle on the page will automatically hydrate server rendered components.\n\n```json\n{\n  \"type\": \"marko-hydrate\",\n  \"path\": \"src/ui-modules/outdated-browser-banner/index.marko\"\n}\n```\n\n**Note:** `marko-hydrate` will initialize the component if its defined on the global `window.$components` which is inserted by `Marko` when it sees a `<body>` tag. Else, if you are just rendering out and lasso-ing the a portion of a page with a set of components, include `<init-components/>` at the end of the associated `template.marko` file that builds out the page fragment.\n\n#### `package`\n\nA collection of dependencies. `browser.json` is the most common package type.\nIt could be used to point to another `browser.json` from within one component's `browser.json`.\nTypically also used when the dependencies of the referred `browser.json` have to be packaged inline.\n\n```json\n{\n  \"type\": \"package\",\n  \"path\": \"src/ui-modules/show-diag/browser.json\"\n}\n```\n\n#### `require`\n\nIf a javascript file has to be wrapped over for its common JS syntax, to a browser understandable format.\n\n```json\n{\n  \"type\": \"require\",\n  \"path\": \"src/ui-modules/dynamic-module-loader/dynamic-init-client.js\"\n}\n```\n\n#### `require` and `run`\n\nIf a javascript file has to be wrapped over for its common JS syntax, to a browser understandable format and be executed immediately.\n\n```json\n{\n  \"run\": true,\n  \"type\": \"require\",\n  \"path\": \"src/ui-modules/my-module/init.js\"\n}\n```\n","packages/runtime-class/docs/marko-5-upgrade.md":"# Upgrading to Marko 5\n\n## Step 0 - Ensure you're in a working state on the latest version of Marko 4\n\nBefore we start, you'll want to make sure that you are already on the latest `4.x` release of `marko`.\n\n```bash\n# Upgrade using yarn\nyarn upgrade marko@^4\n```\n\n```bash\n# Upgrade using npm\nnpm install marko@^4\n```\n\n> [!Warning]\n> Do _not_ run `npm install marko` (without the `@^4`). This will put you on Marko 5 and we're not quite there yet.\n\n> [!Tip]\n> If upgrading from Marko 3 you may want to reference [this guide](https://marko-v4.github.io/docs/marko-4-upgrade/).\n\nRun your application and tests to ensure your project is in a working state. There's little worse than finding an issue after you've started the upgrade process only to figure out the issue existed beforehand.\n\n## Step 1 - Upgrade Marko & Dependencies\n\n**TL;DR**: Paste & run this random shell script. It's safe. Trust us.\n\n```bash\n# Update Marko, and related ecosystem dependencies\nnpx -y npm-check-updates -u \\\n  marko \\\n  `# for webpack projects` \\\n  @marko/webpack \\\n  `# for lasso projects` \\\n  lasso lasso-marko @lasso/marko-taglib \\\n  `# for jest test runner` \\\n  @marko/jest \\\n  `# for projects with v3 widgets` \\\n  marko-widgets\n\n# Install @marko/compat-v4 unless `marko-widgets` is already installed\ngrep -q \"marko-widgets\" package.json || { [[ -f yarn.lock ]] && yarn add @marko/compat-v4 || npm install @marko/compat-v4; }\n[[ -f yarn.lock ]] && npx -y yarn-deduplicate && yarn\n[[ -f yarn.lock ]] || npm i\n```\n\nThis script automates the following steps for you:\n\n- Install the compat package\n  - `marko-widgets` if using Marko 3's Widgets\n  - `@marko/compat-v4` if not using Widgets\n- Update `marko` to 5.x\n- Update any ecosystem packages used by your app (lasso, webpack, jest, etc)\n\n> [!Note]\n> Check your `package.json`. If you have other third-party Marko packages not covered by the script, you may need to update them as well.\n\nYour application should continue to work. Run your tests to ensure everything is working. Congratulations! You've upgraded to Marko 5.\n","packages/runtime-class/docs/marko-json.md":"# `marko.json` & `marko-tag.json`\n\nMarko supports configuration files for validation, enabling experimental features, and custom paths for component files.\n\nThese configuration files are automatically found with [the same discovery mechanism as custom tags](./custom-tags.md#how-tags-are-discovered).\n\nThere are 2 types of configuration files:\n\n1. `marko.json` describes an entire suite of components.\n2. `marko-tag.json` describes a single component.\n\n## Single component definition\n\n`marko-tag.json` configures a single component. It’s automatically discovered if placed inside a [tag directory](./custom-tags.md#tag-directories).\n\n### Options\n\n```js\n{\n  \"html\": true, // Treat as a native HTML tag, not a custom tag.\n  \"htmlType\": \"svg\", // Optimizes for specific types of native tags (currently only `svg` and `html`).\n  \"open-tag-only\": true, // Forbids passing body content to this tag.\n  \"featureFlags\": [ \"feature-a\" ], // Enable beta features by passing feature flags.\n  \"nested-tags\": { // This section configures attribute tags.\n    \"tab\": {\n      \"target-property\": \"tabs\", // Puts `<@tab>` tags into `input.tabs`.\n      \"is-repeated\": true,  // Allow more than one nested `<@tab>`.\n      \"attributes\": {\n        // Same as the “Attributes” section below.\n      }\n    }\n  }\n}\n```\n\n### Attributes\n\nOne commonly-used feature of this config file is compile-time checks for attributes.\n\n```js\n{\n  \"attributes\": {\n    \"heading\": \"string\"\n  }\n}\n```\n\nThe above code ensures that the `heading` attribute is the _only_ attribute supplied to this tag.\n\nThe `string` value is used as documentation for the custom tag. It may be picked up by tooling, like Marko’s editor plugins, to provide hints to the user.\n\nThe recommended list of attribute types are as follows:\n\n- `expression` (any JavaScript expression)\n- `string`\n- `number`\n- `boolean`\n- `regexp`\n- `date`\n- `object`\n- `array`\n- `function`\n\nYou can also provide an object for an attribute definition’s value for additional options:\n\n```js\n{\n  \"attributes\": {\n    \"heading\": {\n      \"type\": \"string\", // Same as setting \"string\" above.\n      \"default-value\": 0, // The attribute will default to this value.\n      \"required\": true, // Error during compilation if this attribute is undefined. (Mutually exclusive with \"default-value\"\n      \"preserve-name\": true, // By default component attributes are camelCased; this disables that feature.\n      \"remove-dashes\": true, // By default native tag attributes are dash-cased; this disables that feature.\n\n      // The following attributes do nothing, but are picked up by tooling.\n      \"deprecated\": true,\n      \"description\": \"The component’s heading text\" // Describes the attribute’s purpose.\n    }\n  }\n}\n```\n\nWe can also describe a _pattern_ of attributes to match a definition:\n\n```js\n{\n    \"attributes\": {\n        \"data-*\": {\n          \"type\": \"string\",\n          \"pattern\": true\n        }\n    }\n}\n```\n\nIn the above, all attributes prefixed with `data-` are configured to be a `string`.\n\n> **Note:** Future Marko versions will describe these definitions/types in the component itself, reducing the need for this configuration file.\n\n### Paths\n\nThere are several options that override the default discovery of component files, such as the template.\n\nTypically, you should let Marko find these files automatically, but here is a reference in case you encounter these settings in the wild.\n\n```javascript\n{\n  \"template\": \"./template.marko\", // Custom path to the `.marko` template.\n  \"renderer\": \"./renderer.js\", // Custom path to the `renderer.js` file.\n\n  // Compiler file hooks\n  \"parse\": \"./parse.js\", // Used to augment parsing.\n  \"migrate\": \"./migrate.js\", // Used for migrating deprecated features.\n  \"transform\": \"./transform.js\", // Used to modify the AST before generating it.\n  \"analyze\": \"./analyze.js\" // Used to analyze metadata the entire ast before beginning to translate it.\n  \"translate\": \"./translate.js\" // Used to generate custom JS.\n}\n```\n\nFor more information about the compiler hooks [jump over here](./compiler.md#hooks).\n\n## Tag library definition\n\nAlong with configuring a single component, you can use a `marko.json` file to configure an _entire library of components_.\n\nSimilar to [`marko-tag.json`](#single-component-definition), this file is discovered if placed within a [tag directory](./custom-tags.md#tag-directories). It will also be discovered at the root directory of a project, or [in a `node_module` package](./custom-tags.md#publishing-tags-to-npm).\n\n### Options\n\n```js\n{\n  \"taglib-id\": \"my-custom-tag-library\", // Names the component library, for better errors.\n  \"exports\": \"./dist\", // Where to export the compiled components.\n  \"tags-dir\": \"./ui-modules\", // What directory to crawl to autodiscover components. Default:`./components/`\n  \"taglib-imports\": [\"./some-folder/marko.json\", \"./other-folder/marko.json\"], // Creates a _combined_ tag library by referencing others.\n  \"script-lang\": \"ts\", // Overrides the default script language, \"js\" or \"ts\", for mixed code such as an incremental TypeScript migration.\n\n  \"tags\": { // Definitions for individual tags.\n    \"my-tag\": {\n      // Same options as “marko-tag.json”.\n    }\n  },\n\n  \"attributes\": {\n    // Defines attributes on all tags.\n    // Options are the same as the “attributes” section in “marko-tag.json”.\n  },\n\n  // Compiler file hooks (run on all templates)\n  \"migrator\": \"./migrator.js\", // Hooks into the migration stage for migrating deprecated features.\n  \"transformer\": \"./transformer.js\", // Used to modify the AST before generating it.\n  \"text-transformer\": \"./text-transformer.js\", // Used to transform all static text in the template.\n}\n```\n\n> **⚠️ Note:** Compiler hooks are currently undocumented: avoid using them. The compiler API is overhauled in Marko 5, and will be documented once that transition is complete.\n\n## Shorthands\n\nBoth configuration files support _shorthands_ for defining `tags` and `attributes`. For example, take this `marko.json` file:\n\n_marko.json_\n\n```js\n{\n  \"taglib-id\": \"my-custom-tag-library\",\n  \"tags\": {\n    \"my-layout\": {\n      \"attributes\": {\n        \"name\": \"string\",\n        \"age\": \"number\"\n      },\n      \"nested-tags\": {\n        \"heading\": {\n          \"attributes\": {\n            \"color\": \"string\"\n          }\n        },\n        \"body\": {\n          \"attributes\": {\n            \"color\": \"string\"\n          }\n        }\n      }\n    }\n  }\n}\n```\n\nAs a shorthand, anywhere `tags` or `nested-tags` is used, you can remove the outer object and wrap the individual tags in `<angle-brackets>`.\n\nFor `attributes`, you can remove the outer object and prefix the attributes with an `@`.\n\nThe above example using the shorthand syntax would become:\n\n_marko.json_\n\n```js\n{\n  \"taglib-id\": \"my-custom-tag-library\",\n  \"<my-layout>\": {\n    \"@name\": \"string\",\n    \"@age\": \"number\",\n    \"<heading>\": {\n      \"@color\": \"string\"\n    },\n    \"<body>\": {\n      \"@color\": \"string\"\n    }\n  }\n}\n```\n\nFor `nested-tags`, there is also a shorthand for `is-repeated` (a postfix of `[]`) and `target-property` (a prefix of `@newName`):\n\n_marko.json_\n\n```javascript\n{\n  \"<my-layout>\": {\n    \"@sections <section>[]\": {\n      \"@color\": \"string\"\n    }\n  }\n}\n```\n\nIs equivalent to:\n\n_marko.json_\n\n```javascript\n{\n  \"tags\": {\n    \"my-layout\": {\n      \"nested-tags\": {\n        \"section\": {\n          \"target-property\": \"sections\",\n          \"is-repeated\": true,\n          \"attributes\": {\n            \"color\": \"string\"\n          }\n        }\n      }\n    }\n  }\n}\n```\n","packages/runtime-class/docs/marko-vs-react.md":"# Marko vs React: An In-depth Look\n\n<a href=\"https://hackernoon.com/marko-vs-react-an-in-depth-look-767de0a5f9a6\">\n  <img src=\"https://cdn-images-1.medium.com/max/2000/1*4BP6tPQtwImj6_QseeybwQ.png\" alt=\"Marko logo\" width=\"100%\" />\n</a><br />\n\n> This article was published March 2017. Both frameworks have gone through several updates since. You can find the original [\"Marko vs React: An In-depth Look\" article here](https://hackernoon.com/marko-vs-react-an-in-depth-look-767de0a5f9a6)!\n\nIn this article we will take an in-depth look at the differences and\nsimilarities between [Marko](https://markojs.com/) and React from the perspective\nof the maintainers of Marko.\n\nOn the surface, Marko and React have a lot in common and both are trying to\nsolve very similar problems. Specifically, both Marko and React allow developers\nto build web applications based on UI components and both free developers from\nhaving to write code to manually update the DOM. While many of the features in\nMarko were inspired by React, Marko and React offer very different usability and\nperformance characteristics. Marko was designed to avoid almost all boilerplate\nand is more closely aligned with HTML. In almost all cases, a Marko UI component\nwill require less lines of code than its React JSX equivalent while maintaining\nreadability and allowing the same expressiveness as JSX. In addition, Marko is\nhighly optimized for use on the server and in the browser and has a much smaller\nweight:\n\n<img src=\"https://cdn-images-1.medium.com/max/1600/1*a9hL_pfNrRq1UU3Mxkf3Jg.png\" alt=\"Marko logo\" width=\"100%\" /><br />\n\nBecause the Marko JavaScript library is much smaller than React, it will require\nless time to load and parse and this will drastically improve page load times on\nslow connections or on older devices. Based on [our\nbenchmarks](https://markojs.com/#benchmarks), Marko consistently outperforms\nReact by a significant margin on both the server and in the browser.\n\n### Example\n\nThe following code highlights some of the differences between Marko and React\nJSX using a somewhat contrived UI component as an example:\n\n#### React JSX\n\n```jsx\nclass Counter extends React.Component {\n  constructor(props) {\n    super(props);\n\n    this.state = { count: 0 };\n  }\n\n  increment(delta) {\n    this.setState({ count: this.state.count + delta });\n  }\n\n  render() {\n    const count = this.state.count;\n    let countClassName = \"count\";\n\n    if (count > 0) {\n      countClassName += \" positive\";\n    } else if (count < 0) {\n      countClassName += \" negative\";\n    }\n\n    return (\n      <div className=\"click-count\">\n        <div className={countClassName}>{count}</div>\n        <button\n          onClick={() => {\n            this.increment(-1);\n          }}\n        >\n          -1\n        </button>\n        <button\n          onClick={() => {\n            this.increment(1);\n          }}\n        >\n          +1\n        </button>\n      </div>\n    );\n  }\n}\n```\n\n<span class=\"figcaption_hack\">[▶ Try Online](https://codepen.io/mlrawlings/pen/wJXOWR?editors=0010)</span>\n\n#### Marko\n\n```marko\nclass {\n  onCreate() {\n    this.state = { count: 0 };\n  }\n  increment(delta) {\n    this.state.count += delta;\n  }\n}\n\n$ var count = state.count;\n\n<div.click-count>\n  <div.count class={\n      positive: count > 0,\n      negative: count < 0\n    }>\n    ${count}\n  </div>\n  <button on-click('increment', -1)>\n    -1\n  </button>\n  <button on-click('increment', 1)>\n    +1\n  </button>\n</div>\n```\n\n<span class=\"figcaption_hack\">[▶ Try\nOnline](https://markojs.com/try-online/?gist=8fe46bc5866605aca0dfeec202604011)</span>\n\n### Similarities\n\nMarko and React have the following in common:\n\n- UI component-based\n- JavaScript and HTML markup can be intertwined\n- No restrictions on JavaScript (use ES5 or ES2015+, your choice)\n- Virtual DOM rendering in the browser\n- DOM diffing/patching is used to reconcile views\n- Both support keyed element matching\n- UI components can have input properties\n- UI components can have internal state\n- Changes to state trigger an asynchronous update to the DOM\n- Updates to the DOM are batched\n- Compatible with central application state stores such as Redux and MobX\n- UI components can be embedded using custom tags\n- Declarative event binding (no `domEl.addEventListener()` needed)\n- Support for all DOM events\n- Event delegation utilized internally for DOM events that bubble\n- IE9+ support\n- Similar lifecycle events for UI components\n- JSX and Marko both compile to JavaScript\n\n### Differences\n\nAt a high level here are some differences:\n\n#### Differences in rendering\n\n- **Improved performance:** Marko renders to a virtual DOM in the browser and\n  directly to an HTML stream on the server (Marko supports multiple compilation\n  targets).\n- **Improved performance:** Marko supports asynchronous rendering with [early\n  flushing of\n  HTML](https://tech.ebayinc.com/engineering/async-fragments-rediscovering-progressive-html-rendering-with-marko/)\n  for improvements in actual and perceived page load times.\n- **Improved performance:** React requires an additional client-side re-render if\n  a page is initially rendered on the server while Marko does not.\n- **Improved ease of use:** Marko automatically serializes UI component state and\n  input down to the browser so that the browser can pick up right where the server\n  left off.\n- **Improved ease of use:** Marko is suitable for rendering an entire HTML page on\n  the server with support for tags such as `<doctype>` and `<html>`\n\n#### Differences in syntax\n\n- **Improved ease of use:** Marko uses the\n  [HTML-JS](https://markojs.com/docs/syntax/) syntax and the\n  [JSX](https://facebook.github.io/react/docs/jsx-in-depth.html) syntax is offered\n  for React.\n- **Improved ease of use:** Marko supports both a concise syntax and a familiar\n  HTML syntax.\n- **Improved ease of use:** JSX requires strict XML while Marko aligns with less\n  strict HTML that web developers are used to.\n- **Improved ease of use:** With Marko, _all_ HTML attribute values are parsed as\n  JavaScript expressions.\n- **Improved ease of use:** Marko supports simple directives for conditionals,\n  looping, etc.\n- **JSX limitation:** JSX is “just JavaScript” but requires expressions that\n  preclude the usage of JavaScript statements such as in certain places.\n\n#### Differences in compilation\n\n- **Improved performance:** Marko supports multiple compilation outputs (Marko\n  VDOM and HTML streaming are currently supported).\n- **Improved ease of use:** Marko compiles UI components to JavaScript modules\n  that export a rendering API.\n- **Expanded capabilities:** Marko supports a robust API for controlling how\n  custom tags and custom attributes get compiled and it supports compile-time\n  transforms based on a friendly Abstract Syntax Tree (AST).\n- **Improved performance:** JSX is just syntactic sugar that translates elements\n  to `createElement()` function calls while the Marko compiler has full control over how things are\n  compiled and optimized.\n- **Improved ease of use:** React requires all UI components to be explicitly\n  imported before they can be used as custom tags while Marko supports both\n  explicit importing and implicit importing.\n- **Improved performance:** Marko has a modular runtime and the compiler generates\n  code that only imports the parts of the Marko runtime that are needed for much\n  smaller builds.\n- **Improved ease of use:** Marko supports optional compile-time checks to ensure\n  that only allowed attributes are passed to custom tags. (React `PropTypes` only provide\n  validation at render-time)\n- **Improved ease of use:** Marko validates _all_ tag names at compile-time.\n- **Improved ease of use:** Marko provides its own compiler that integrates with\n  Node.js and JavaScript module bundlers while React JSX requires babel and custom\n  babel transforms.\n\n#### Differences in UI components\n\n- **Reduced boilerplate:** No explicit extending of JavaScript classes in Marko\n  (in contrast to `class Counter extends React.Component` in React).\n- **Improved ease of use:** Modifications to UI component state are synchronous\n  with Marko while [the rules for React are more\n  complicated](https://facebook.github.io/react/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous).\n- **Improved ease of use:** Marko watches UI component state objects to allow\n  state to be modified directly (e.g., `this.state.count++`).\n- **Improved ease of use:** Marko supports single-file UI components combining\n  JavaScript behavior, CSS styling (with support for CSS preprocessors) and HTML\n  markup. (React requires using one of the many [CSS in JS\n  solutions](https://github.com/MicheleBertoli/css-in-js) if you want styles in\n  the same file as your component and there is no standard in the community)\n- **Improved maintainability:** Marko supports a seamless transition from a\n  single-file UI component to a multi-file UI component.\n- **Improved performance:** Marko assumes UI components are pure by default and\n  skips re-rendering when input properties and state are unchanged (React requires\n  extending\n  [React.PureComponent](https://facebook.github.io/react/docs/react-api.html#react.purecomponent)).\n\n#### Differences in event systems\n\n- **Reduced complexity:** React utilizes [synthetic\n  events](https://facebook.github.io/react/docs/events.html) while Marko utilizes\n  real DOM events.\n- **Improved ease of use:** Custom events are emitted using the [EventEmitter\n  API](https://nodejs.org/api/events.html) in Marko (e.g., `this.emit('myCustomEvent', arg1, arg2)`).\n- **Improved ease of use:** Marko has a consistent approach for listening to both\n  native DOM events and custom events.\n- **Improved ease of use:** React requires passing around `Function` references for custom\n  events while Marko automatically delegates emitted custom events to event\n  handler methods on components.\n- **Improved ease of use:** Marko provides a simple mechanism for binding\n  additional arguments to event handler methods and `this` will be the component\n  instance.\n\n#### Differences in compatibility\n\n- **Marko limitation:** Marko has no support for native mobile similar to React\n  Native (although with Marko VDOM rendering, this is possible).\n- **Marko limitation:** Marko requires a JavaScript module bundler (such as\n  [Lasso](https://markojs.com/docs/lasso/),\n  [Webpack](https://markojs.com/docs/webpack/),\n  [Rollup](https://markojs.com/docs/rollup/)\n  since Marko UI components compile down to JavaScript modules. (we consider using\n  a JavaScript module bundler a best practice)\n\n---\n\nIn the sections below we will take a closer look at some of the differences\nbetween Marko and React.\n\n### Syntax\n\nBoth Marko and React JSX allow HTML markup and JavaScript to be combined into a\nsingle file and both support building web applications based on UI components.\nMarko utilizes an [HTML-JS syntax](https://markojs.com/docs/syntax/) while most\nReact apps use the JSX syntax.\n\n> React JSX makes JavaScript more like HTML and Marko makes HTML more like\n> JavaScript.\n\nIn the end, both Marko and React allow JavaScript and HTML to be intertwined.\n\n### Syntax: attributes\n\n#### React JSX\n\nIn React JSX, all attribute values are parsed as string values unless `{}` is used.\n\n```jsx\n<MyComponent\n  name=\"Frank\"\n  messageCount={30}\n  visible={true}\n  person={{ firstName: 'John', lastName: 'Doe' }}\n  colors={['red', 'green', 'blue']} />\n\n<div id=\"content\" className=\"foo\">Hello</div>\n```\n\n#### Marko\n\nWith Marko, _all_ attribute values are parsed as JavaScript expressions. The\nfollowing Marko code is equivalent to the React JSX code above:\n\n```marko\n<my-component\n  name=\"Frank\"\n  message-count=30\n  visible=true\n  person={ firstName: 'John', lastName: 'Doe' }\n  colors=['red', 'green', 'blue'] />\n\n<div id=\"content\" class=\"foo\">Hello</div>\n```\n\n### Syntax: inline JavaScript\n\n#### React JSX\n\nReact JSX starts with JavaScript and allows XML elements to be inlined as shown\nbelow:\n\n```jsx\nimport { formatDate } from \"./util\";\n\nfunction formatName(person) {\n  return person.firstName + \" \" + person.lastName.charAt(0) + \".\";\n}\n\nexport default function HelloMessage(props) {\n  var person = props.person;\n\n  return (\n    <div>\n      Hello {formatName(person)}!\n      <span>You were born on {formatDate(person.birthday)}.</span>\n    </div>\n  );\n}\n```\n\n#### Marko\n\nMarko starts out in HTML, but it allows JavaScript to be inlined in a clean and\nmaintainable way. Unlike other template languages, Marko aims to allow the full\npower of JavaScript. The following Marko code is equivalent to the React JSX\ncode above:\n\n```marko\nimport { formatDate } from './util';\n\nstatic function formatName(person) {\n    return person.firstName + ' ' + person.lastName.charAt(0) + '.';\n}\n\n$ var person = input.person;\n\n<div>\n    Hello ${formatName(person)}!\n    <span>\n      You were born on ${formatDate(person.birthday)}.\n    </span>\n</div>\n```\n\nLines prefixed with `$` are directly added to the compiled JavaScript output inside\nthe compiled `render()` function (for JavaScript code that should run for every render).\nLines prefixed with `static` are directly added to the compiled JavaScript output\noutside the `render()` function (for code that should only run _once_ when the template is\nloaded).\n\n### Syntax: HTML support\n\nWith Marko any valid HTML markup can be used inside a Marko template. This is\nnot the case with React. The following quote is from the [React\ndocumentation](https://facebook.github.io/react/docs/introducing-jsx.html#specifying-children-with-jsx):\n\n> **Caveat:**\n\n> Since JSX is closer to JavaScript than HTML, React DOM uses `camelCase` property naming\n> convention instead of HTML attribute names.\n\n> For example, `class` becomes `className` in JSX, and `tabindex` becomes `tabIndex`.\n\nAs a result of this caveat for React, [tools for converting HTML to JSX\nexist](https://magic.reactjs.net/htmltojsx.htm).\n\n#### React JSX\n\n```jsx\n<div id=\"content\" className=\"my-component\">Hello</div>\n\n<input type=\"text\" name=\"firstName\" value=\"John\" />\n```\n\n#### Marko\n\n```marko\n<div id=\"content\" class=\"my-component\">Hello</div>\n\n<input type=\"text\" name=\"firstName\" value=\"John\">\n```\n\n### Syntax: conditionals\n\nJSX is syntactic sugar on top of JavaScript, but it requires expressions, so\nsimple things like an `if/else/for` statement don’t work on their own within a JSX element. As\na result, you must either use a ternary expression, an immediately invoked\nfunction expression, function call expression, or the experimental `do {}` expression\n(stage 0 at the time of writing). This is not an issue for Marko, and tags\nsuch as `if()` and `for` can be used anywhere as shown below:\n\n#### React JSX\n\n```jsx\nfunction counterMessage(count) {\n  return (\n    <div className=\"counter-message\">\n      (function() {\n        if (count < 0) {\n          return <div>Count is negative</div>\n        } else if (count === 0) {\n          return <div>Count is zero</div>\n        } else {\n          return <div>Count is positive</div>\n        }\n      }())\n    </div>\n  )\n}\n```\n\n#### Marko\n\n```marko\n<div.counter-message>\n  <if(count < 0)>\n    <div>Count is negative</div>\n  </if>\n  <else if(count === 0)>\n    <div>Count is zero</div>\n  </else>\n  <else>\n    <div>Count is positive</div>\n  </else>\n</div>\n```\n\nMarko also allows directives to be used as attributes for a more condensed\ntemplate:\n\n```marko\n<div.counter-message>\n  <div if(count < 0)>Count is negative</div>\n  <div if(count === 0)>Count is zero</div>\n  <div else>Count is positive</div>\n</div>\n```\n\n### Syntax: looping\n\n#### React JSX\n\n```jsx\nfunction renderColors(colors) {\n  return (\n    <ul>\n      {colors.map((color) => (\n        <li\n          className=\"color\"\n          style={{\n            backgroundColor: color,\n          }}\n        >\n          {color}\n        </li>\n      ))}\n    </ul>\n  );\n}\n```\n\n#### Marko\n\n```marko\n<ul>\n  <for|color| of=colors>\n    <li.color style={ backgroundColor: color }>\n        ${color}\n    </li>\n  </for>\n</ul>\n```\n\n### Syntax: HTML shorthand\n\n```marko\n<div id=\"content\"/>\n<h1 class=\"subheader\"/>\n<h1 id=\"pageTitle\" class=\"foo bar\"/>\n\n<!-- Shorthand equivalent: -->\n<div#content/>\n<h1.subheader/>\n<h1#pageTitle.foo.bar/>\n```\n\nMarko supports a shorthand based on CSS selectors for less code.\n\nReact does not support these helpful shorthands.\n\n### Syntax: concise\n\nMarko supports a concise syntax that drops angled brackets and ending tags in\nfavor of indentation. Here’s how the Marko syntax options compare:\n\n#### Marko HTML syntax\n\n```marko\n<ul>\n  <for|color| of=colors>\n    <li>${color}</li>\n  </for>\n</ul>\n```\n\n#### Marko concise syntax\n\n```marko\nul\n  for|color| of=colors\n    li -- ${color}\n```\n\n#### Marko mixed syntax\n\n```marko\nul\n  for|color| of=colors\n    <li>${color}</li>\n```\n\nThe HTML syntax and the concise syntax can be used together:\n\n#### React JSX\n\nReact does not offer a concise syntax.\n\n### Components\n\nMarko starts with simple HTML and allows UI component logic to easily be layered\non top.\n\n#### React JSX\n\nA React UI component is typically implemented as a class that extends `ReactComponent`:\n\n```jsx\nclass HelloMessage extends React.Component {\n  render() {\n    return <div>Hello {this.props.name.toUpperCase()}</div>;\n  }\n}\n```\n\nReact also supports a more concise functional component:\n\n```jsx\nfunction HelloMessage(props) {\n  return <div>Hello {props.name.toUpperCase()}</div>;\n}\n```\n\nHowever, if state or lifecycle events are needed then a functional UI component\nmust be converted to a class component:\n\n```jsx\nclass HelloMessage extends React.Component {\n  componentDidMount() {\n    // ...\n  }\n  render() {\n    return <div>Hello {this.props.name.toUpperCase()}</div>;\n  }\n}\n```\n\n#### Marko\n\nHere is the same component in Marko:\n\n```marko\n<div>Hello ${input.name.toUpperCase()}</div>\n```\n\nBehavior can easily be added to any Marko UI component:\n\n```marko\nclass {\n  onMount() {\n    // ...\n  }\n}\n\n<div>Hello ${input.name.toUpperCase()}</div>\n```\n\nMarko also allows JavaScript behavior, CSS styling and HTML markup to be\nembedded in the Marko template as a single file UI component:\n\n```marko\nclass {\n  onMount() {\n    // ...\n  }\n}\n\nstyle.less {\n  .hello {\n    color: red;\n  }\n}\n\n<div.hello>\n  Hello ${input.name.toUpperCase()}\n</div>\n```\n\n### API\n\nMarko compiles components to JavaScript modules that export their rendering APIs,\nas shown below:\n\n```js\nimport Greeting from \"./components/greeting.marko\";\nGreeting.renderSync({ name: \"Frank\" }).appendTo(document.body);\n```\n\nThe same UI component can render to streams, such as a writable HTTP\nresponse stream:\n\n```js\nimport Greeting from \"./components/greeting.marko\";\nGreeting.render({ name: \"John\" }, res);\n```\n\n> The users of a Marko UI component do not need to know that the component was\n> implemented using Marko.\n\nContrast this with React as an example:\n\n```jsx\nimport ReactDOM from \"react-dom\";\n\nReactDOM.render(\n  <HelloMessage name=\"John\" />,\n  document.getElementById(\"container\"),\n);\n```\n\nOn top of that, React requires that a different module be imported to render the\nexact same UI component on the server:\n\n```jsx\nimport ReactDOMServer from \"react-dom/server\";\n\nvar html = ReactDOMServer.renderToString(<HelloMessage name=\"John\" />);\n```\n\n### Custom tags\n\n#### React JSX\n\nWith React, all custom tags for UI components must be explicitly imported:\n\n```jsx\nimport Hello from \"./components/Hello\";\nimport GoodBye from \"./components/GoodBye\";\n\nexport default function HelloGoodBye(props) {\n  return (\n    <div>\n      <Hello name={props.name} />\n      <GoodBye name={props.name} />\n    </div>\n  );\n}\n```\n\n#### Marko\n\nMarko supports a mechanism for [automatically discovering custom\ntags](https://markojs.com/docs/custom-tags/#discovering-tags) for UI components\nbased on the project directory structure. Marko walks up the directory tree to\ndiscover all directories and it will also automatically discover custom tags\nexported by installed packages. This approach negates the need for explicitly\nimporting a custom tag to reduce the amount of code needed in a Marko template.\nFor example given the following directory structure:\n\n```\n    .\n    ├── components/\n    │   ├── hello.marko\n    │   └── good-bye.marko\n    └── index.marko\n```\n\nThe `<hello>` tag and the `<good-bye>` tag nested below the `components/`\ndirectory will automatically be made available to the `index.marko` at the root:\n\n```marko\n<div>\n  <hello name=input.name />\n  <good-bye name=input.name />\n</div>\n```\n\nThis approach also allows editors and IDEs to offer autocompletion for custom\ntags.\n\n### Async\n\nEven after rendering has started, Marko allows parts of the view to be rendered\nasynchronously using the [`<await>`](https://markojs.com/docs/core-tags#await)\ntag as shown in the following Marko template:\n\n```marko\nimport fsp from 'fs-promise';\n\n$ var filePath = __dirname + '/hello.txt';\n$ var readPromise = fsp.readFile(filePath, {encoding: 'utf8'});\n\n<await(readPromise)>\n  <@then|helloText|>\n    <p>${helloText}</p>\n  </@then>\n</await>\n```\n\n### Compiler\n\nMarko compiles a template differently based on whether or not it will be used on\nthe server or in the browser. For example, given the following template:\n\n```marko\n<div>Hello ${input.name}!</div>\n```\n\n#### Compiled for the server:\n\n```js\nvar marko_template = require(\"marko/html\").t(__filename),\n  marko_helpers = require(\"marko/runtime/html/helpers\"),\n  marko_escapeXml = marko_helpers.x;\n\nfunction render(input, out) {\n  out.w(\"<div>Hello \" + marko_escapeXml(input.name) + \"!</div>\");\n}\n```\n\n#### Compiled for the browser:\n\n```js\nvar marko_template = require(\"marko/vdom\").t(__filename);\n\nfunction render(input, out) {\n  out.e(\"DIV\", null, 3).t(\"Hello \").t(input.name).t(\"!\");\n}\n```\n\n### Compile-time code transforms\n\nThe Marko compiler was built to support compile-time code generators for custom\ntags and it also provides support for compile-time transforms. While Babel\nallows code transformations of JavaScript, the Marko compiler provides support\nfor resolving custom tags declaratively and the Marko AST provides for very\npowerful and simple transformations as shown in the following code for rendering\nMarkdown to HTML at _compile-time_:\n\n**components/markdown/code-generator.js:**\n\n```js\nimport marked from \"marked\";\nimport { removeIndentation } from \"./util\";\n\nexport default function generateCode(el, codegen) {\n  var bodyText = removeIndentation(el.bodyText);\n  var html = marked(bodyText);\n  var builder = codegen.builder;\n  return builder.html(builder.literal(html));\n}\n```\n\nThe `<markdown>` tag can then be used as shown below:\n\n```marko\n<markdown>\n\n> This section demonstrates Markdown in Marko\n\n# Marko is awesome!\n\n- High performance\n- Small\n- Intuitive\n\n</markdown>\n```\n\nIn this example, after the template is compiled, the\n[marked](https://github.com/chjj/marked) library is no longer needed at\nrender-time.\n\n### Tools\n\nMarko and React offer a variety of developer tools. The [Marko developer\ntools](https://github.com/marko-js/marko-devtools) are constantly evolving, but\nMarko currently provides tools for unit testing UI components, precompiling `.marko`\nfiles and generating configuration-less apps (similar to\n[create-react-app](https://github.com/facebookincubator/create-react-app)).\nCurrently, there are no Marko developer tools that integrate with the browser,\nbut this is something we would like to see in the future. We will go into more\ndetail on the Marko developer tools in a future post.\n\n#### IDE and editor support\n\nMarko offers syntax highlighting across all major IDEs and editors, as well as\non GitHub. Marko provides first-class support for the Atom editor with syntax\nhighlighting,\n[Autocomplete](https://github.com/marko-js/atom-language-marko#autocomplete) for\nboth HTML and custom tags,\n[Hyperclick](https://github.com/marko-js/atom-language-marko#hyperclick) to\nquickly jump to referenced files and methods, and [Pretty\nprinting](https://github.com/marko-js/atom-language-marko#prettyprint) to keep\nyour code readable.\n\n---\n\n### Why Marko?\n\nHere are just a few reasons you should consider using\n[Marko](https://markojs.com/) over React:\n\n- Marko requires much less boilerplate.\n- Marko has much better performance based on our benchmarks.\n- Marko offers a clean and powerful syntax that aligns with HTML while also\n  allowing the full power of JavaScript.\n- Marko has much less complexity and a very small runtime.\n- Marko has a much lower page weight for faster page loads.\n- Marko has strong integrations with Node.js.\n- Marko allows for extremely powerful IDE and editor plugins (see the [Marko\n  plugin for Atom](https://github.com/marko-js/atom-language-marko) as an\n  example).\n- Marko has a powerful compiler that allows new features to be added without\n  introducing bloat.\n- eBay relies heavily on Marko and it is being used to build ebay.com (including\n  the mobile web).\n- Marko has a strong and growing community on\n  [GitHub](https://github.com/marko-js/marko) and in\n  [Discord](https://discord.gg/RFGxYGs).\n\nInterested in learning more about Marko? If so, you can get additional\ninformation on the [Marko website](https://markojs.com/). Join the conversation\nand contribute on [GitHub](https://github.com/marko-js/marko) and follow us on\n[Twitter](https://twitter.com/MarkoDevTeam).\n","packages/runtime-class/docs/redux.md":"# Redux + Marko\n\nSee the [`marko-redux` sample project](https://github.com/marko-js/examples/tree/master/examples/redux) for a fully-working example.\n\n## Installation\n\nFirst, save the [`marko`](https://www.npmjs.com/package/marko) and [`redux`](https://www.npmjs.com/package/redux) packages to your project’s dependencies:\n\n```bash\nnpm i marko redux\n```\n\n## Usage\n\nThe partial code below shows how a Marko UI component can connect to a Redux store, using Redux’s `store.subscribe()` method and Marko’s `forceUpdate()` method:\n\n### `counter.marko`\n\n```marko\nimport store from './store.js';\n\nclass {\n  onMount () {\n    store.subscribe(() => {\n      // Force this UI component to rerender\n      this.forceUpdate();\n\n      // The UI component will rerender with the new\n      // state returned by `store.getState()`\n      //\n      // You could also force an update like this:\n      // this.input = store.getState();\n    });\n  }\n}\n\n<counter(store.getState()) />\n```\n\n### `reducer.js`\n\n```js\nexport default function (state, action) {\n  state = state || { value: 0 };\n\n  // Additional reducer logic here…\n\n  return state;\n}\n```\n\n### `store.js`\n\nIn `counter.marko`, the imported store module exports a Redux store created with the following code:\n\n```js\nimport redux from \"redux\";\nimport counter from \"./reducer.js\";\n\nexport default redux.createStore(counter);\n```\n","packages/runtime-class/docs/rendering.md":"# Rendering\n\nTo render a Marko view, you need to `import` it.\n\n_example.js_\n\n```js\nimport FancyButton from \"./components/fancy-button.marko\";\n```\n\n> **Note:** If you are targeting node.js, you will need to enable the [require extension](./installing.md#require-marko-views) in order to require `.marko` files or you will need to precompile all of your templates using [Marko CLI](https://github.com/marko-js/cli). If you are targeting the browser, you will need to use a bundler like [`lasso`](./lasso.md), [`webpack`](./webpack.md) or [`rollup`](./rollup.md).\n\nOnce you have a view, you can pass input data and render it:\n\n_example.js_\n\n```js\nimport FancyButton from \"./components/fancy-button.marko\";\nconst html = FancyButton.renderToString({ label: \"Click me!\" });\n\nconsole.log(html);\n```\n\nThe data passed to `renderToString` becomes available as `input` in the component, so if `fancy-button.marko` looked like this:\n\n_./components/fancy-button.marko_\n\n```marko\n<button>${input.label}</button>\n```\n\nThe output HTML would be:\n\n```html\n<button>Click me!</button>\n```\n\n## Rendering methods\n\nWe used the `renderToString` method above to render the view, but there are a number of different method signatures that can be used to render.\n\nMany of these methods return a [`RenderResult`](#renderresult) which is an object with helper methods for working with the rendered output.\n\n### `renderSync(input)`\n\n| params       | type                            | description                            |\n| ------------ | ------------------------------- | -------------------------------------- |\n| `input`      | `Object`                        | the input data used to render the view |\n| return value | [`RenderResult`](#renderresult) | The result of the render               |\n\nUsing `renderSync` forces the render to complete synchronously. If a tag attempts to run asynchronously, an error will be thrown.\n\n```js\nimport View from \"./view.marko\";\nvar result = View.renderSync({});\n\nresult.appendTo(document.body);\n```\n\n### `render(input)`\n\n| params       | type                             | description                            |\n| ------------ | -------------------------------- | -------------------------------------- |\n| `input`      | `Object`                         | the input data used to render the view |\n| return value | `AsyncStream`/`AsyncVDOMBuilder` | the async `out` render target          |\n\nThe `render` method returns an async `out` which is used to generate HTML on the server or a virtual DOM in the browser. In either case, the async `out` has a `then` method that follows the Promises/A+ spec, so it can be used as if it were a Promise. This promise resolves to a [`RenderResult`](#renderresult).\n\n```js\nimport View from \"./view.marko\";\nvar resultPromise = View.render({});\n\nresultPromise.then((result) => {\n  result.appendTo(document.body);\n});\n```\n\n### `render(input, callback)`\n\n| params         | type                             | description                                    |\n| -------------- | -------------------------------- | ---------------------------------------------- |\n| `input`        | `Object`                         | the input data used to render the view         |\n| `callback`     | `Function`                       | a function to call when the render is complete |\n| callback value | [`RenderResult`](#renderresult)  | The result of the render                       |\n| return value   | `AsyncStream`/`AsyncVDOMBuilder` | the async `out` render target                  |\n\n```js\nimport View from \"./view.marko\";\n\nView.render({}, (err, result) => {\n  result.appendTo(document.body);\n});\n```\n\n### `render(input, stream)`\n\n| params       | type                             | description                            |\n| ------------ | -------------------------------- | -------------------------------------- |\n| `input`      | `Object`                         | the input data used to render the view |\n| `stream`     | `WritableStream`                 | a writeable stream                     |\n| return value | `AsyncStream`/`AsyncVDOMBuilder` | the async `out` render target          |\n\nThe HTML output is written to the passed `stream`. Render errors are emitted as `\"error\"` events on the stream, and like any unhandled stream `\"error\"` event, one without a listener crashes the process, so always attach one:\n\n```js\nimport http from \"http\";\nimport View from \"./view.marko\";\n\nhttp.createServer((req, res) => {\n  res.setHeader(\"content-type\", \"text/html\");\n  View.render({}, res).on(\"error\", (err) => {\n    console.error(err);\n  });\n});\n```\n\n### `render(input, out)`\n\n| params       | type                             | description                            |\n| ------------ | -------------------------------- | -------------------------------------- |\n| `input`      | `Object`                         | the input data used to render the view |\n| `out`        | `AsyncStream`/`AsyncVDOMBuilder` | The async `out` to render to           |\n| return value | `AsyncStream`/`AsyncVDOMBuilder` | The `out` that was passed              |\n\nThe `render` method also allows passing an existing async `out`. If you do this, `render` will not automatically end the async `out` (this allows rendering a view in the middle of another view). If the async `out` won't be ended by other means, you are responsible for ending it.\n\n```js\nimport View from \"./view.marko\";\nvar out = View.createOut();\n\nView.render({}, out);\n\nout.on(\"finish\", () => {\n  console.log(out.getOutput());\n});\n\nout.end();\n```\n\n### `renderToString(input)`\n\n| params       | type     | description                            |\n| ------------ | -------- | -------------------------------------- |\n| `input`      | `Object` | the input data used to render the view |\n| return value | `String` | The HTML string produced by the render |\n\nReturns an HTML string and forces the render to complete synchronously. If a tag attempts to run asynchronously, an error will be thrown.\n\n```js\nimport View from \"./view.marko\";\nvar html = View.renderToString({});\n\ndocument.body.innerHTML = html;\n```\n\n### `renderToString(input, callback)`\n\n| params         | type        | description                            |\n| -------------- | ----------- | -------------------------------------- |\n| `input`        | `Object`    | the input data used to render the view |\n| callback value | `String`    | The HTML string produced by the render |\n| return value   | `undefined` | N/A                                    |\n\nAn HTML string is passed to the callback.\n\n```js\nimport View from \"./view.marko\";\n\nView.renderToString({}, (err, html) => {\n  document.body.innerHTML = html;\n});\n```\n\n### `stream(input)`\n\nThe `stream` method returns a Node.js-style stream of the output HTML.\n\n```js\nimport fs from \"fs\";\nimport View from \"./view.marko\";\nconst writeStream = fs.createWriteStream(\"output.html\");\n\nView.stream({}).pipe(writeStream);\n```\n\nThis method is available on the server, but not available by default in the browser. If you need to use streams in the browser, you may `import 'marko/stream'` as part of your client-side bundle.\n\n## RenderResult\n\n### `getComponent()`\n\n### `getComponents(selector)`\n\n### `afterInsert(doc)`\n\n### `getNode(doc)`\n\n### `getOutput()`\n\n### `appendTo(targetEl)`\n\n### `insertAfter(targetEl)`\n\n### `insertBefore(targetEl)`\n\n### `prependTo(targetEl)`\n\n### `replace(targetEl)`\n\n### `replaceChildrenOf(targetEl)`\n\n## Global data\n\nIf you need to make data available to all rendered views, use the `$global` property on the input data object. This property will be removed from `input` and provided to the template through a variable called `$global`. It is also made available on the `out.global` property.\n\nGlobal values persist across renders.\n\n```js\nView.render({\n  $global: {\n    flags: [\"mobile\"],\n  },\n});\n```\n\nWithin the template you can access `$global` similar to accessing `input`.\n\n```marko\n<div>\n  You are on ${$global.flags.includes(\"mobile\") ? \"mobile\" : \"desktop\"}\n</div>\n```\n\n> **Note:** `$global` is not available within [`static`](./syntax.md#static-javascript) parts of the template. In order to reference `$global` within the component class you must use `out.global` from one of the lifecycle methods that provide it.\n\n> **Warning:** Use `$global` with caution; it is visible in any component.\n\n### Sending global data to browsers\n\n⚠️ To prevent accidentally exposing sensitive data, by default **no keys** in `$global` are sent to browsers. To serialize data to the frontend, name the desired properties in `$global.serializedGlobals`.\n\nValues must be serializable by [the `warp10` module](https://www.npmjs.com/package/warp10).\n\n```js\nimport Page from \"./index.marko\";\n\napp.get(\"/\", (req, res) => {\n  const ua = req.get(\"User-Agent\");\n\n  Page.render(\n    {\n      $global: {\n        isIos: /iPad|iPhone/.test(ua), // Serialized and available on the server and browser as `$global.isIos`\n        isAndroid: /Android/.test(ua), // Serialized and available on the server and browser as `$global.isAndroid`\n        req, // Only available server-side and not serialized, because it’s not in `serializedGlobals`\n\n        serializedGlobals: {\n          isIos: true, // Tell Marko to serialize `isIos`\n          isAndroid: true, // Tell Marko to serialize `isAndroid`\n        },\n      },\n    },\n    res,\n  );\n});\n```\n\n> **Warning:** Ensure that you serialize only data which is necessary for the browser. Serialization is expensive for both server rendering performance and HTML output size.\n\nFor details, check [#672: “Serialize only input and state on top-level server-rendered UI components”](https://github.com/marko-js/marko/pull/672).\n","packages/runtime-class/docs/rollup.md":"# Marko + Rollup\n\nThis is Marko’s official integration plugin for [the Rollup bundler](https://rollupjs.org/).\n\n## Installation\n\n```sh\nnpm install --save-dev \\\n  @marko/rollup \\\n  rollup \\\n  @rollup/plugin-node-resolve \\\n  @rollup/plugin-commonjs\n```\n\n> **Note**: The Marko runtime is CommonJS, so don’t forget the `@rollup/plugin-commonjs` package!\n\n## Configuration\n\n`@marko/rollup` exports two methods for use in [Rollup configuration files](https://rollupjs.org/guide/en/#configuration-files): `.browser()` and `.server()`.\n\nYou _probably_ want to use both, since that’ll get you…\n\n- Automatic [`input` entrypoint configuration](https://rollupjs.org/guide/en/#input) for route-based bundle splitting\n- Complete control over asset loading with [the `<rollup>` tag](#rollup-tag)\n- The strengths behind why Marko exists in the first place: cooperation between servers and browsers for high performance in both\n\n> **ProTip**: You _could_ use only `.browser()` or only `.server()` to build a completely client-side-rendered or server-side-rendered app. That would be a little odd, but you could.\n\n### Config example\n\n```js\nimport nodeResolve from \"@rollup/plugin-node-resolve\";\nimport commonjs from \"@rollup/plugin-commonjs\";\nimport marko from \"@marko/rollup\";\n\nconst sharedPlugins = [\n  commonjs({\n    extensions: [\".js\", \".marko\"]\n  }),\n  // If using Marko’s `style {}` blocks, you’ll need an appropriate plugin, like npmjs.com/rollup-plugin-postcss\n  postcss({ external: true })\n]\n\nconst serverAssetsConfig = {\n  input: \"src/start-server.js\",\n  plugins: [\n    marko.server(),\n    nodeResolve({ preferBuiltins: true })\n    ...sharedPlugins\n  ]\n};\nconst browsersAssetsConfig = {\n  plugins: [\n    marko.browser(),\n    nodeResolve({ browser: true })\n    ...sharedPlugins\n  ]\n};\n\nexport default [serverAssetsConfig, browsersAssetsConfig];\n```\n\n### Advanced config example\n\nThe following configuration file is long and hairy, which may be upsetting to some viewers. However, it does show how to accomplish the following:\n\n- Support for Rollup’s watch mode\n- A bundle analyzer\n- The ability to `import` JSON files to use their data\n- The ability to `import` image files to use their asset URLs for `img[src]` and such\n- Dead-code elimination for development-only code\n- Static compression of assets for something like [NGiNX’s `gzip_static`](https://nginx.org/en/docs/http/ngx_http_gzip_static_module.html)\n- A CSS preprocessor (Sass, in this case)\n- Browserslist to automatically configure:\n  - Babel for JS transpilation\n  - Autoprefixer for CSS transpilation\n\n<details><summary>Big ugly production-esque Rollup config</summary>\n\n```js\nimport { builtinModules } from \"module\";\nimport path from \"path\";\nimport autoprefixer from \"autoprefixer\";\nimport babelPlugin from \"@rollup/plugin-babel\";\nimport commonjsPlugin from \"@rollup/plugin-commonjs\";\nimport jsonPlugin from \"@rollup/plugin-json\";\nimport markoPlugin from \"@marko/rollup\";\nimport nodeResolvePlugin from \"@rollup/plugin-node-resolve\";\nimport replacePlugin from \"@rollup/plugin-replace\";\nimport runPlugin from \"@rollup/plugin-run\";\nimport stylesPlugin from \"rollup-plugin-styles\";\nimport urlPlugin from \"@rollup/plugin-url\";\nimport pkg from \"./package.json\";\n\nconst __DEV__ = process.env.NODE_ENV === \"development\";\nconst __PROD__ = !__DEV__;\n\nconst isWatch = Boolean(process.env.ROLLUP_WATCH);\n\nconst publicPath = \"/s/\"; // Guess what character is only 5 bits under HPACK\nconst assetFileNames = \"[name]-[hash][extname]\";\n\nconst externalDependencies = [\n  ...Object.keys(pkg.dependencies),\n  ...builtinModules,\n];\n\nprocess.env.SASS_PATH = \"./:./node_modules\";\n\nexport default (async () => [\n  compiler(\"server\", {\n    input: \"index.js\",\n    output: {\n      dir: \"built/server/\",\n      assetFileNames: `../browser/${assetFileNames}`,\n      format: \"cjs\",\n      sourcemap: true,\n    },\n    external: (id) =>\n      externalDependencies.some(\n        (dependency) => id === dependency || id.startsWith(dependency + \"/\"),\n      ),\n    plugins: [isWatch && runPlugin({ execArgv: [\"--enable-source-maps\"] })],\n  }),\n\n  compiler(\"browser\", {\n    output: {\n      dir: \"built/browser/\",\n      chunkFileNames: __PROD__ ? \"[name]-[hash].js\" : null,\n      entryFileNames: __PROD__ ? \"[name]-[hash].js\" : null,\n      assetFileNames,\n      sourcemap: true,\n      sourcemapExcludeSources: __PROD__,\n    },\n    plugins: [\n      stylesPlugin({\n        mode: \"extract\",\n        sourceMap: true,\n        config: {\n          target: \"browserslist:css\",\n          plugins: [autoprefixer({ env: \"css\" })],\n        },\n        minimize: __PROD__,\n        url: {\n          publicPath,\n          hash: assetFileNames,\n        },\n      }),\n      __PROD__ && (await import(\"rollup-plugin-terser\")).terser(),\n      __PROD__ &&\n        (await import(\"rollup-plugin-gzip\")).default({\n          filter: /\\.(?:js|css|svg|json|xml|txt)$/,\n          minSize: 1024,\n          gzipOptions: {\n            level: 9,\n            memLevel: 9,\n          },\n        }),\n      __PROD__ &&\n        !isWatch &&\n        (await import(\"rollup-plugin-visualizer\")).default(),\n      __PROD__ &&\n        !isWatch && {\n          name: \"bundle-visualizer-location\",\n          writeBundle() {\n            console.info(\n              `📊 Bundle visualizer at \\x1b[4;36mfile://${path.join(\n                __dirname,\n                \"../../\",\n                bundleAnalyzerFilename,\n              )}\\x1b[0m`,\n            );\n          },\n        },\n    ],\n  }),\n])();\n\nfunction compiler(target, config) {\n  const isBrowser = target === \"browser\";\n  const browserslistEnv = isBrowser ? \"js\" : \"server\";\n  const babelConfig = {\n    comments: false,\n    browserslistEnv,\n    compact: false,\n    babelrc: false,\n    caller: { target },\n  };\n  if (isBrowser) {\n    babelConfig.presets = [\n      [\n        \"@babel/preset-env\",\n        {\n          browserslistEnv,\n          bugfixes: true,\n        },\n      ],\n    ];\n  }\n\n  return {\n    ...config,\n    preserveEntrySignatures: false,\n    plugins: [\n      markoPlugin[target]({ babelConfig }),\n      nodeResolvePlugin({\n        browser: isBrowser,\n        preferBuiltins: !isBrowser,\n      }),\n      commonjsPlugin(),\n      replacePlugin({\n        preventAssignment: true,\n        values: { __DEV__, __PROD__ },\n      }),\n      babelPlugin({\n        babelHelpers: \"bundled\",\n        ...babelConfig,\n      }),\n      jsonPlugin(),\n      urlPlugin({\n        publicPath,\n        destDir: \"built/browser/\",\n        fileName: assetFileNames,\n        include: \"**/*.{svg,png,jpg,jpeg}\",\n        limit: 0, // Never Base64 & inline\n        emitFiles: !isBrowser,\n      }),\n      ...config.plugins,\n    ],\n  };\n}\n```\n\n</details>\n\n## `<rollup>` tag\n\nUsing both `.server()` and `.browser()` enables **the `<rollup>` tag**, which gives you complete control over how your app loads assets. That lets you do things like:\n\n- [Critical CSS](https://web.dev/extract-critical-css/) for components as they write out within a kB budget, or [as components first appear on the page](https://jakearchibald.com/2016/link-in-body/#a-simpler-better-way), or any other style-loading mad science\n- [`module`/`nomodule` scripts](https://philipwalton.com/articles/using-native-javascript-modules-in-production-today/) for smaller bundles in modern browsers\n- [Content-Security Policy `nonce`s](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce) or [Subresource `integrity` hashes](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)\n- Anything a web page can do, really. You can even combine `<rollup>` with [the `serialize` option](#options.serialize) to be as fancy as you wanna be.\n\nThe `<rollup>` tag provides two [tag parameters](https://markojs.com/docs/syntax/#parameters):\n\n1. `entry` is the generated `input` string that the `server` plugin gave to the `browser` plugin. You can use it to find the corresponding entry chunk from Rollup’s `output` (the next parameter).\n\n2. `output` is an array of `AssetInfo | ChunkInfo` objects with most of [the data returned from Rollup's `generateBundle` hook](https://rollupjs.org/guide/en/#generatebundle). Some properties are omitted, like `code` and `map`, since they’re often too large to inline directly. However, each chunk also has a `size` property, to let you filter out empty chunks, inline code yourself below a certain size, or other delightful devilishness.\n\nFor example, using the `entry` name and properties of `output` items to load scripts:\n\n```marko\n<head>\n  <rollup|entry, output|>\n    $ const entryChunk = output.find(chunk => chunk.name === entry);\n\n    <if(entryChunk.size /* only load non-empty JS entry points */)>\n      <for|fileName| of=entryChunk.imports>\n        <link rel=\"modulepreload\" href=fileName />\n      </for>\n\n      <script async type=\"module\" src=entryChunk.fileName></script>\n    </if>\n  </rollup>\n</head>\n```\n\n> **Note**: It’s up to you to transform the chunk data (also called the **manifest**) into `<link>`s, `<script>`s, and other HTML to load assets. Opting into complete control means we can’t do any of it for you.\n\nIf your Rollup `browser` config contains multiple `output` options, or you have multiple `browser` configs, every `output`’s chunk is passed to the `<rollup>` tag.\n\nFor example, if you have both `esm` and `iife` build outputs configured:\n\n```js\n{\n  output: [\n    { dir: \"dist/iife\", format: \"iife\" },\n    { dir: \"dist/esm\", format: \"esm\" },\n  ];\n}\n```\n\n…you could cross-reference assets from both…\n\n```marko\n<rollup|entry, iifeOutput, esmOutput|>\n  $ const iifeEntryChunk = iifeOutput.find(chunk => chunk.name === entry);\n  $ const esmEntryChunk = esmOutput.find(chunk => chunk.name === entry);\n\n  <script src=esmEntryChunk.fileName type=\"module\" async></script>\n  <script src=iifeEntryChunk.fileName nomodule async></script>\n</rollup>\n```\n\n…and _boom:_ you now have [a `module`/`nomodule` setup](https://philipwalton.com/articles/using-native-javascript-modules-in-production-today/).\n\n## Options\n\n### `options.babelConfig`\n\nBoth the `.server()` and `.browser()` plugins accept this option.\n\nYou can manually override the builtin Babel configuration by passing a `babelConfig` object. By default, [Babel’s regular config file resolution](https://babeljs.io/docs/en/config-files) will be used.\n\n```js\nmarko.browser({\n  babelConfig: {\n    presets: [\"@babel/preset-env\"],\n  },\n});\n```\n\n### `options.runtimeId`\n\nBoth the `.server()` and `.browser()` plugins accept this option. In fact, you _really_ want to use it with both simultaneously.\n\nIn some cases, you may want to embed multiple isolated copies of Marko on the page. (If you can’t think of why, then don’t worry about this option.)\n\nSince Marko uses some `window` properties to initialize, multiple instances can cause issues. For example, by default Marko checks `window.$components` for server-rendered hydration. Usually you can change these `window` properties by [rendering with `{ $global: { runtimeId: \"MY_MARKO_RUNTIME_ID\" } }` as input](https://markojs.com/docs/rendering/#global-data) on the server, but since `@marko/rollup` usually writes the autoinitialization code for you, instead this plugin exposes a `runtimeId` option to automatically set `$global.runtimeId` to initialize properly in the browser:\n\n```js\nconst runtimeId = \"MY_MARKO_RUNTIME_ID\";\n// Make the `runtimeId` the same across `server` and `browser`, or it’ll error!\nmarko.server({ runtimeId });\nmarko.browser({ runtimeId });\n```\n\n### `options.serialize`\n\nThis option is only available for the `.browser()` plugin. It lets you inspect and transform the `output` chunks before they’re passed to [the `<rollup>` tag](#rollup-tag).\n\nFor example, if you _did_ want to include the `code` property from the Rollup chunk — say, to inline code small enough that it’s not worth the overhead of an HTTP request, you’d try something like the following:\n\n```js\nmarko.browser({\n  serialize(output) {\n    return output.map(({ type, fileName, isEntry, code }) =>\n      type === \"asset\"\n        ? { type, fileName }\n        : {\n            type,\n            name,\n            isEntry,\n            fileName,\n            // only inline code chunks below 1kB\n            inline: code.trim().length < 1024 && code,\n          },\n    );\n  },\n});\n```\n","packages/runtime-class/docs/state.md":"# State\n\nThe output of a component is based on input properties passed from its parent as attributes. However, a component may also maintain internal state that it uses to control its view. If Marko detects a change to either input or to the internal state, the view will automatically be updated.\n\n> **ProTip:**\n> Only data that is owned and modified by the component should go into its `state`. State should be exclusively used for data that triggers rerenders. Parents control `input`, and the component controls its own `state`.\n\n## Initializing state\n\nTo use `state` in Marko, you must first create a [class component](./class-components.md) and initialize the state within the [`onCreate`](./class-components.md#oncreateinput-out) method. In class methods, `this.state` may be used and within the template section, a `state` variable is available.\n\n```marko\nclass {\n    onCreate() {\n        this.state = { count: 0 };\n    }\n}\n\n<div>The count is ${state.count}</div>\n```\n\n> **Note:** Only properties that exist when `this.state` is first defined will be watched for changes. If you don't need a property initially, you can set it to `null`.\n\n## Updating state\n\nYou can update `state` in response to DOM events, browser events, ajax calls, etc. When a property on the state changes, the view will be updated to match.\n\n```marko\nclass {\n    onCreate() {\n        this.state = { count: 0 };\n    }\n    increment() {\n        this.state.count++;\n    }\n}\n\n<div>The count is ${state.count}</div>\n<button on-click('increment')>Increment</button>\n```\n\nWe've extended our example above to add a button with an [event handler](./events.md), so that, when clicked, the `state.count` value is incremented.\n\n> **Note:**\n> When browsing existing code, you may see `this.setState('name', value)` being used. This is equivalent to `this.state.name = value`.\n\n### How updates work\n\nWhen a property on `state` is set, the component will be scheduled for an update if the property has changed. All updates are batched together for performance. This means you can update multiple state properties at the same time without causing multiple updates.\n\n> **ProTip:** If you need to know when the update has been applied, you can use `this.once('update', fn)` within a component method.\n\n> **Note:** The state object only watches its properties one level deep. This means updates to nested properties on the state (e.g. `this.state.object.something = newValue`) will not be detected.\n>\n> Using [immutable](https://wecodetheweb.com/2016/02/12/immutable-javascript-using-es6-and-beyond/) data structures is recommended, but if you want to mutate a state property (perhaps push a new item into an array) you can let Marko know it changed using `setStateDirty`.\n>\n> ```js\n> this.state.numbers.push(num);\n>\n> // mark numbers as dirty, because a `push`\n> // won't be automatically detected by Marko\n> this.setStateDirty(\"numbers\");\n> ```\n\n## Cross component state management\n\nThere are various tools available to manage state outside of a single component. Here are some basic guidelines.\n\nTypically we recommend using `attributes` to pass data in to a child component, and children can [emit events](./events.md#emitting-custom-events) to communicate back up to their parents. In some cases this can become cumbersome with deeply nested data dependencies or global state.\n\n### Global/Subtree\n\nFor passing state throughout a component tree without explicit attribute setting throughout the entire app, you can leverage the [`<context>`](https://github.com/marko-js/tags/tree/master/tags/context) tag. This tag can be [installed from npm](./custom-tags.md#using-tags-from-npm).\n\nThis tag allows you to pull state from any level above in the tree and can also be used to pass global state throughout your app.\nContext providers can register event handlers that any child in the tree can trigger similar to the [events API](./events.md).\n\n_fancy-form.marko_\n\n```marko\n<context coupon=input.coupon on-buy(handleBuy)>\n    <!-- Somewhere nested in the container will be the buy button -->\n    <fancy-container/>\n</context>\n```\n\n_fancy-save-button.marko_\n\n```marko\n<context|{ coupon }, emit| from=\"fancy-form\">\n    Coupon: ${coupon}.\n    <button on-click(emit, \"buy\")>Buy</button>\n</context>\n```\n\n> **Note:** Context _couples_ tags together and can limit reuse of components.\n\n### When to use a Redux like pattern\n\nOften the above two approaches are enough, and many people [jump to this part far too quickly](https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367). Like `<context>`, often anything stored in redux is `global`. This means that it can (if abused) create components that are hard to reuse, reason about and test. However it is important to understand when a tool like `redux` is useful in any UI library.\n\nRedux provides indirection to updating any state that it controls. This is useful if you need the following:\n\n- Single state update, multiple actions (eg: logging, computed data, etc).\n- Time travel debugging and other [redux-specific tooling](https://redux.js.org/introduction/ecosystem).\n","packages/runtime-class/docs/structure.json":"[\n  {\n    \"title\": \"Guides\",\n    \"docs\": [\n      \"Installing\",\n      \"Getting started\",\n      \"Conditionals and lists\",\n      \"Custom tags\",\n      \"State\",\n      \"Styles\",\n      \"Events\",\n      \"Body content\",\n      \"TypeScript\",\n      \"Marko 5 upgrade\",\n      \"Troubleshooting Streaming\"\n    ]\n  },\n  {\n    \"title\": \"Tutorials\",\n    \"docs\": [\"Color Picker\"]\n  },\n  {\n    \"title\": \"Reference\",\n    \"docs\": [\n      \"Rendering\",\n      \"Syntax\",\n      \"Core tags\",\n      \"Class components\",\n      \"marko.json\",\n      \"Compiler\"\n    ]\n  },\n  {\n    \"title\": \"Bundler Integrations\",\n    \"docs\": [\"Vite\", \"Webpack\", \"Rollup\", \"Lasso\"]\n  },\n  {\n    \"title\": \"Server Integrations\",\n    \"docs\": [\"Cloudflare Workers\", \"Express\", \"Fastify\", \"Koa\", \"HTTP\"]\n  },\n  {\n    \"title\": \"Tooling\",\n    \"docs\": [\"Editor plugins\"]\n  },\n  {\n    \"title\": \"Articles\",\n    \"docs\": [\"Marko vs React\", \"Why is Marko Fast\", \"10 Awesome Marko Features\"]\n  }\n]\n","packages/runtime-class/docs/styles.md":"# Styles\n\nBoth HTML and Marko provide support for `<style>` tags. However, Marko also provides a special syntax (called a style _block_) which adds support for CSS preprocessors and acts as a hint to bundlers to extract this static css from your templates into a common bundle.\n\n```marko\nstyle {\n    div {\n        color: green;\n    }\n}\n\n<div>Hello World</div>\n```\n\nThese blocks add global css to the page. The above example will not style just the `<div>` in the component, but all divs on the page. Because of this we recommend following a naming convention such as [BEM](https://getbem.com/introduction/). Marko will likely provide a way to automatically scope these styles to the current component [in the future](https://github.com/marko-js/marko/issues/666).\n\n> **Note:** Style blocks (unlike `<style>` tags) do not support `${placeholders}` and must be static.\n\n## Preprocessors\n\nIf you use a css preprocessor, you can add the extension right on `style`. This will cause your bundler of choice to run the contents of the style block through the appropriate processor.\n\n```marko\nstyle.less {\n    button.primary {\n        background-color: @primaryColor;\n    }\n}\n```\n","packages/runtime-class/docs/syntax.md":"# Syntax\n\nMarko is HTML _re-imagined_ as a language for building dynamic and reactive user interfaces.\nJust about any valid HTML is valid Marko, but Marko extends the HTML language to allow building modern applications in a declarative way.\n\n> **ProTip:** Marko also supports a [beautiful concise syntax](./concise.md). If you'd prefer to see the documentation using this syntax, just click the `switch syntax` button in the corner of any Marko code sample.\n\n> **Note:** Text at the root of a template (outside any tags) must be prefixed with the [concise syntax's `--`](./concise.md#text) to denote it is text. The parser starts in concise mode and would otherwise try to parse what you meant to be text as a concise tag declaration.\n>\n> ```marko\n> -- Root level text\n> ```\n\n## Tags\n\nAs you might expect, Marko supports all native HTML/SVG/whatever tags and attributes. In addition to these, it also comes with a set of useful [core tags](./core-tags.md). Beyond this, you can also build your own [custom tags](./custom-tags.md) and [install third-party tags](./custom-tags.md#using-tags-from-npm) from `npm`.\n\nAll of these types of tags use the same syntax:\n\n```marko\n<my-tag-name/>\n```\n\nYou don't need to import tags. Marko discovers them based on the folder structure—similar to how you don't specify a full path when referencing a module in `node_modules/`. Marko looks in [`components/`](./custom-tags.md#how-tags-are-discovered) by default and this directory can be configured in [`marko.json`](./marko-json.md).\n\n## Dynamic text\n\nYou can use placeholders (`${}`) to insert a value into the template:\nPlaceholders accept any JavaScript expression and the result of the expression will be inserted into the HTML output:\n\n```marko\n<div>\n    Hello ${\"world\".toUpperCase()}\n</div>\n```\n\nThese values are automatically escaped so you don't accidentally insert malicious code. If you do need to pass unescaped HTML, you can use `$!{}`:\n\n```marko\n<div>\n    Hello $!{\"<b>World</b>\"}\n</div>\n```\n\n> **ProTip:** If necessary, you can escape `$` using a backslash to have it be treated as text instead of a placeholder token:\n>\n> ```marko\n> <div>\n>     Placeholder example: <code>\\${someValue}</code>\n> </div>\n> ```\n\n## Attributes\n\nIn marko attributes are parsed as JavaScript expressions (instead of just strings).\n\n```marko\n<div class=myClassName/>\n<input type=\"checkbox\" checked=isChecked/>\n\n<custom-tag string=\"Hello\"/>\n<custom-tag number=1/>\n<custom-tag template-string=`Hello ${name}`/>\n<custom-tag boolean=true/>\n<custom-tag array=[1, 2, 3]/>\n<custom-tag object={ hello: \"world\" }/>\n<custom-tag variable=name/>\n<custom-tag function-call=user.getName()/>\n```\n\nAttributes that are passed to a custom tag are received as it's [`input`](https://markojs.com/docs/class-components/#input).\n\n> **Note:** Although in most cases you won't see a difference, strings are parsed as JavaScript strings, not HTML strings. Where this comes up most often is using the `pattern` attribute with the `<input>` tag: you need to \"double escape\" your regex escape sequences much like you were passing a string to the [`RegExp` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) (or you can use a literal `/regex/`).\n>\n> _Marko Source:_\n>\n> ```marko\n> <input pattern=\"\\\\w+\" type=\"text\"/>\n> <input pattern=/\\w+/ type=\"text\"/>\n> ```\n>\n> _HTML Output:_\n>\n> ```html\n> <input pattern=\"\\w+\" type=\"text\" />\n> ```\n\n### Complex expressions\n\nAny JavaScript expression is a valid attribute value, provided it meets the following criteria:\n\n_It does not contain any spaces_\n\n_It does not contain any right angle brackets (`>`)_\n\n```marko\n<custom-tag sum=1+2 difference=3-4/>\n```\n\n```marko\ncustom-tag sum=1+2 difference=3-4\n```\n\n_Spaces and `>` are contained within matching `()`, `[]`, `{}`, strings and regexps_\n\n```marko\n<custom-tag sum=(1 + 2) difference=(3 - 4) greater=(1 > 2)/>\n```\n\n```marko\ncustom-tag sum=(1 + 2) difference=(3 - 4) greater=(1 > 2)\n```\n\n### Boolean attributes\n\nHTML defines the following rules for [boolean attributes](https://www.w3.org/TR/2008/WD-html5-20080610/semantics.html#boolean):\n\n> The presence of a boolean attribute on an element represents the true value, and the absence of the attribute represents the false value.\n\nIn Marko when an attribute value evaluates to `false`, `null`, or `undefined`, the attribute is not included in the output. If an attribute value is `true`, only the attribute name is included in the output.\n\n_Marko Source:_\n\n```marko\n<input type=\"checkbox\" checked=true>\n<input type=\"checkbox\" checked=false>\n```\n\nRenders the following HTML:\n\n_HTML Output:_\n\n```html\n<input type=\"checkbox\" checked /> <input type=\"checkbox\" />\n```\n\nSimilarly, when only an attribute name is defined, it is equivalent to specifying the attribute with a value of `true`:\n\n```marko\n<!-- These are equivalent -->\n<custom-menu expanded/>\n<custom-menu expanded=true/>\n```\n\n> **ProTip:**\n> You can take advantage of the way Marko handles boolean attributes to conditionally render attributes:\n>\n> _Marko Source:_\n>\n> ```marko\n> <div class=(active && \"tab-active\")>Hello</div>\n> ```\n>\n> With a value of `true` for `active`, the output would be the following:\n>\n> _HTML Output:_\n>\n> ```html\n> <div class=\"tab-active\">Hello</div>\n> ```\n>\n> With a value of `false` for `active`, the output would be the following:\n>\n> _HTML Output:_\n>\n> ```html\n> <div>Hello</div>\n> ```\n\n### Dynamic attributes\n\nThe spread syntax (`...`) can be used to merge in an object as attributes to a tag:\n\n_Marko Source:_\n\n```marko\n<a ...attrs target=\"_blank\">eBay</a>\n```\n\nWith `attrs` as the following value:\n\n```js\n{\n    class: \"active\",\n    href: \"https://ebay.com/\"\n}\n```\n\nwould output the following HTML:\n\n_HTML Output:_\n\n```html\n<a class=\"active\" href=\"https://ebay.com/\" target=\"_blank\">eBay</a>\n```\n\n> **ProTip:**\n> With spread attributes order matters.\n> You can take advantage of this to implement both default attributes, and enforced attributes.\n>\n> ```marko\n> <custom-tag ...defaults ...userSupplied class=\"overridden\"/>\n> ```\n\n> **ProTip:**\n> You can provide `undefined` to a spread attribute which will output nothing.\n\n### Style attribute\n\nYou can pass a string as the value of `style` just as you would in HTML, in addition Marko supports passing an object or array as the value of the `style` attribute:\n\n_Marko Source:_\n\n```marko\n<!-- string: -->\n<div style=\"display:block;margin-right:16px\"/>\n\n<!-- object: -->\n<div style={ display: \"block\", color: false, marginRight: 16 }/>\n\n<!-- array: -->\n<div style=[\"display:block\", null, { marginRight: 16 }]/>\n```\n\nIn all cases, the output will be the same:\n\n_HTML Output:_\n\n```html\n<div style=\"display:block;margin-right:16px;\"></div>\n```\n\n### Class attribute\n\nThe `class` attribute also supports receiving an object or array (in addition to a string) as shown below:\n\n_Marko Source:_\n\n```marko\n<!-- string: -->\n<div class=\"a c\"/>\n\n<!-- object: -->\n<div class={ a:true, b:false, c:true }/>\n\n<!-- array: -->\n<div class=[\"a\", null, { c:true }]/>\n```\n\nIn all cases, the output will be the same:\n\n_HTML Output:_\n\n```html\n<div class=\"a c\"></div>\n```\n\n### Shorthand attributes\n\nMarko provides a shorthand for declaring classes and ids on an element, including interpolation. Given `size` is the string `small`:\n\n_Marko Source:_\n\n```marko\n<div.my-class/>\n<span#my-id/>\n<button#submit.primary.large/>\n<button.button--${size}></button>\n```\n\nRenders the following HTML:\n\n_HTML Output:_\n\n<!-- prettier-ignore -->\n```html\n<div class=\"my-class\"></div>\n<span id=\"my-id\"></span>\n<button id=\"submit\" class=\"primary large\"></button>\n<button class=\"button--small\"></button>\n```\n\n## Parameters\n\nWhen a tag renders its body content, it may provide data which can be received by defining parameters after the tagname. Parameters are available to the tag's body content.\n\nThis is a powerful feature that allows components to provide functionality and data while giving you full control over what gets rendered.\n\nIn the following example, `<mouse>` provides a parameter which we have named `position`:\n\n```marko\n<mouse|position|>\n   The mouse is at ${position.x}, ${position.y}!\n</mouse>\n```\n\n> `<mouse>` would [render its body](./body-content.md) and provide the position similar to this: `<${input.renderBody} x=0 y=0/>`.\n\n> **ProTip:** Tag `|parameters|` are treated as regular JavaScript function parameters. This means you can destructure, set default values, etc.\n>\n> ```marko\n> <mouse|{ x, y }|>\n>   The mouse is at ${x}, ${y}!\n> </mouse>\n> ```\n\n> **Note:** Parameters are not available to attributes, only to the tag body.\n>\n> ```marko\n> <mouse|position| something=position>\n>   ReferenceError when setting the \"something\" attribute\n> </mouse>\n> ```\n\nParameters are used by some of Marko's [core tags](./core-tags.md) like the [`<for>`](./core-tags.md#for) and [`<await>`](./core-tags.md#await) tags.\n\n## Arguments\n\nSome tags and attributes accept javascript style `arguments`. Arguments are denoted by parenthesis following the tag or attribute name. Arguments provide a way to pass unnamed data to a tag.\n\n```marko\n<if(true)>\n    <strong>Marko is awesome</strong>\n</if>\n\n<h1 body-only-if(skipHeading)>\n    Conditional display heading, but always show content!\n</h1>\n```\n\nArguments are used by some of Marko's [core tags](./core-tags.md) like the [`<if>`](./core-tags.md#if-else-if-else) tag and [`body-only-if`](./core-tags.md#body-only-if) attribute displayed above.\n\nPreviously you could also use them in your own [custom tags](./custom-tags.md) however it is now recommended to use [dynamic attributes](#dynamic-attributes).\n\n## Dynamic tagname\n\nThe `<${dynamic}>` syntax is used to render a tag or component that isn't determined until runtime. It can also be used within a [custom tag](./custom-tags.md) to render body content that was passed to that tag.\n\n_Marko Source:_\n\n```marko\n<${href ? 'a' : 'button'} href=href>\n    Click me!\n</>\n```\n\nWith `href` as `https://ebay.com` would output the following HTML:\n\n_HTML Output:_\n\n```html\n<a href=\"https://ebay.com\">Click me!</a>\n```\n\nAnd with `href` as `undefined` would output the following HTML:\n\n_HTML Output:_\n\n```html\n<button>Click me!</button>\n```\n\nAs a shorthand if there is a variable in scope and [no other matching tag is discovered](#how-tags-are-discovered) the wrapping `${}` is unnecessary.\n\nFor example the following are equivalent:\n\n```marko\n$ const MyTag = href ? 'a' : 'button';\n<${MyTag}/>\n<MyTag/>\n```\n\n> **ProTip:**\n> If you find that you have a wrapper element that is conditional, but whose body should always be rendered then you can use a null dynamic tag. For example, to only render a wrapping `<a>` tag if there is a valid URL then you could do the following:\n>\n> _Marko Source:_\n>\n> ```marko\n> <${input.linkUrl ? \"a\" : null} href=input.linkUrl >\n>    Some body content\n> </>\n> ```\n>\n> Given a value of `\"http://localhost/\"` for the `input.linkUrl` variable: , the output would be the following:\n>\n> _HTML Output:_\n>\n> ```html\n> <a href=\"http://localhost/\"> Some body content </a>\n> ```\n>\n> Given a value of `undefined` for the `input.linkUrl` variable: , the output would be the following:\n>\n> _HTML Output:_\n>\n> ```html\n> Some body content\n> ```\n\n### Dynamic components\n\nInstead of just strings, the dynamic tagname can also be a component:\n\n```marko\nimport componentA from \"<component-a>\";\nimport componentB from \"<component-b>\";\n\n<${useA ? componentA : componentB}/>\n```\n\n> **ProTip:**\n> You can also switch between a normal HTML tag and a component:\n>\n> ```marko\n> import FancyButton from \"<fancy-button>\";\n>\n> <${isFancy ? FancyButton : 'button'}>\n>     Button text\n> </>\n> ```\n\n> **Note:** You **cannot** reference a Marko custom tag or macro using a name string:\n>\n> _Marko Source:_\n>\n> ```marko\n> <${isFancy ? 'fancy-button' : 'button'}>\n>     Button text\n> </>\n> ```\n>\n> With `isFancy` as `true` would output the following HTML:\n>\n> _HTML Output:_\n>\n> ```html\n> <fancy-button>Button text</fancy-button>\n> ```\n\n### Dynamic body content\n\nWhen a custom tag receives [body content](./body-content.md), it is passed as a `renderBody` property. To render this content you can pass the `renderBody` as the dynamic tagname.\n\n```marko\n<div class=\"container\">\n    <${input.renderBody}/>\n</div>\n```\n\n## Attribute Tag\n\nAs the name implies, `<@attribute-tags>` are special attributes that take the form of tags. They allow you to pass named body sections to a [custom tag](./custom-tags.md).\n\nThe core `<await>` tag allows you to pass multiple body sections that it will conditionally render based on the state of the promise.\n\n```marko\n<await(somePromise)>\n    <@then|result|>\n        The promise resolved: ${result}\n    </@then>\n    <@catch|error|>\n        The promise rejected: ${error.message}\n    </@catch>\n</await>\n```\n\nThese body sections are also commonly used to create layouts:\n\n```marko\n<page-layout>\n    <@heading>\n        <h1>Hello</h1>\n    </@heading>\n    <@body>\n        <p>Lorem ipsum....</p>\n    </@body>\n</page-layout>\n```\n\nThese tags are passed to the custom tag as objects with a `renderBody`, it can then [render its body content](./body-content.md).\n\n> **Note:**\n> Attribute tags can have their own parameters, but like attributes, they cannot access the parameters of their parent tag:\n>\n> ```marko\n> <list|item|>\n>   ${item.name}\n>   <@separator>${item} (oops, ReferenceError)</@separator>\n> </list>\n> ```\n\n## Inline JavaScript\n\nTo execute JavaScript in your template you can insert a Javascript statement using the `$ <code>` syntax.\n\nA line that starts with a `$` followed by a space will execute the code that follows.\n\n```marko\n$ const name = \"World\";\n\n<div>\n    Hello, ${name}\n    $ console.log(\"The value rendered was\", name);\n</div>\n```\n\nA statement may continue onto subsequent lines if new lines are bounded by `{}`, `[]`, `()`, ` `` `, or `/**/`:\n\n```marko\n$ const person = {\n    name: \"Frank\",\n    age: 32\n};\n```\n\nMultiple statements or an unbounded statement may be used by wrapping the statement(s) in a block:\n\n```marko\n$ {\n    const bgColor = getRandomColor();\n    const textColor = isLight(bgColor)\n        ? \"black\"\n        : \"white\";\n}\n```\n\n> **ProTip:** Any JavaScript statement can be used here, even `debugger`:\n>\n> ```marko\n> <div>\n>     ${textColor}\n>     $ debugger; // Quickly debug `textColor`\n> </div>\n> ```\n\n> **ProTip:** If necessary, you can escape `$` using a backslash to have it be treated as text instead of a placeholder token:\n>\n> ```marko\n> <p>You can run JS in a Marko template like this:</p>\n> <code>\n>     \\$ var num = 123;\n> </code>\n> ```\n\n> **ProTip:** If you find yourself writing a lot of inline JS, consider moving it out to an external file and then [`import`](#importing-external-files) it.\n\n### Static JavaScript\n\nInline JavaScript will run each time your template is rendered, but the JavaScript code that follows `static` will only run once when the template is loaded. It must be declared at the top level and does not have access to values passed in at render time.\n\n```marko\nstatic var count = 0;\nstatic var formatter = new Formatter();\n\nstatic function sum(a, b) {\n    return a + b;\n};\n\n<div>${formatter.format(sum(2, 3))}</div>\n```\n\nLike inline Javascript, multiple statements or an unbounded statement may be used by wrapping the statement(s) in a block:\n\n```marko\nstatic {\n    var base = 2;\n    function sum(a, b) {\n        return base + a + b;\n    };\n}\n```\n\n### Importing external files\n\nThe `import` statement is used to access data and functions from external files. It follows the same syntax as the [JavaScript `import` statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import).\n\n```marko\nimport sum from './utils/sum';\n<div>The sum of 2 + 3 is ${sum(2, 3)}</div>\n```\n\nAs a shorthand you can also import components by providing it's html tag name wrapped in angle brackets, eg:\n\n```marko\nimport MyComponent from \"<my-component>\"\n```\n\nThis is especially useful with the [dynamic tag name syntax](./syntax.md#dynamic-tagname) and uses the same [component discovery](./custom-tags.md#how-tags-are-discovered) as if the tag was used in the template.\n\n## Comments\n\nStandard HTML comments can be used and will be stripped out of the rendered output.\nAt the top level of the template JavaScript comments (`// comment` and `/** comment */`) can also be used.\n\n```marko\n<!-- This is a comment that will not be rendered -->\n\n<h1>Hello</h1>\n```\n\nIf you would like for your HTML comment to show up in the final output then you can use the [`html-comment` core tag](./core-tags.md#html-comment).\n","packages/runtime-class/docs/troubleshooting-streaming.md":"# Troubleshooting HTTP Streams\n\n[The way Marko streams HTML](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding) is old and well-supported, but default configurations and assumptions by other software can foil it. This page describes some known culprits that may buffer your Node server’s output HTTP streams.\n\n## Reverse proxies/load balancers\n\n- Turn off proxy buffering, or if you can’t, set the proxy buffer sizes to be reasonably small.\n\n- Make sure the “upstream” HTTP version is 1.1 or higher; HTTP/1.0 and lower do not support streaming.\n\n- Some software doesn’t support HTTP/2 or higher “upstream” connections at all or very well — if your Node server uses HTTP/2, you may need to downgrade.\n\n- Check if “upstream” connections are `keep-alive`: overhead from closing and reopening connections may delay responses.\n\n- For typical modern webpage file sizes, the following bullet points probably won’t matter. But if you want to stream **small chunks of data with the lowest latency**, investigate these sources of buffering:\n  - Automatic gzip/brotli compression may have their buffer sizes set too high; you can tune their buffers to be smaller for faster streaming in exchange for slightly worse compression.\n\n  - You can [tune HTTPS record sizes for lower latency, as described in High Performance Browser Networking](https://hpbn.co/transport-layer-security-tls/#optimize-tls-record-size).\n\n  - Turning off MIME sniffing with [the `X-Content-Type-Options`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options) header eliminates browser buffering at the very beginning of HTTP responses\n\n### NGiNX\n\nMost of NGiNX’s relevant parameters are inside [its builtin `http_proxy` module](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering):\n\n```nginx\nproxy_http_version 1.1; # 1.0 by default\nproxy_buffering off; # on by default\n```\n\n### Apache\n\nApache’s default configuration works fine with streaming, but your host may have it configured differently. The relevant Apache configuration is inside [its `mod_proxy` and `mod_proxy_*` modules](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html) and their [associated environment variables](https://httpd.apache.org/docs/2.4/env.html).\n\n## CDNs\n\nContent Delivery Networks (CDNs) consider efficient streaming one of their best features, but it may be off by default or if certain features are enabled.\n\n- For Fastly or another provider that uses VCL configuration, check [if backend responses have `beresp.do_stream = true` set](https://developer.fastly.com/reference/vcl/variables/backend-response/beresp-do-stream/).\n\n- Some [Akamai features designed to mitigate slow backends can ironically slow down fast chunked responses](https://community.akamai.com/customers/s/question/0D50f00006n975d/enabling-chunked-transfer-encoding-responses). Try toggling off Adaptive Acceleration, Ion, mPulse, Prefetch, and/or similar performance features. Also check for the following in the configuration:\n\n  ```xml\n  <network:http.buffer-response-v2>off</network:http.buffer-response-v2>\n  ```\n\n## Node.js itself\n\nFor extreme cases where [Node streams very small HTML chunks with its built-in compression modules](https://github.com/marko-js/marko/pull/1641), you may need to tweak the compressor stream settings. Here’s an example with `createGzip` and its `Z_PARTIAL_FLUSH` flag:\n\n```js\nimport http from \"http\";\nimport zlib from \"zlib\";\n\nimport MarkoTemplate from \"./something.marko\";\n\nhttp\n  .createServer(function (request, response) {\n    response.writeHead(200, { \"content-type\": \"text/html;charset=utf-8\" });\n    const templateStream = MarkoTemplate.stream({});\n    const gzipStream = zlib.createGzip({\n      flush: zlib.constants.Z_PARTIAL_FLUSH,\n    });\n    templateStream.pipe(outputStream).pipe(response);\n  })\n  .listen(80);\n```\n","packages/runtime-class/docs/typescript.md":"# TypeScript in Marko\n\n> **Note:** Types are supported in Marko v5.22.7+ and Marko v4.24.6+\n\nMarko’s TypeScript support offers in-editor error checking, makes refactoring less scary, verifies that data matches expectations, and even helps with API design.\n\nOr maybe you just want more autocomplete in VSCode. That works too.\n\n## Enabling TypeScript in your Marko project\n\nThere are two (non-exclusive) ways to add TypeScript to a Marko project:\n\n- **For sites and web apps**, you can place [a `tsconfig.json` file](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) at the project root:\n  <pre>\n  📁 components/\n  📁 node_modules/\n  <img src=\"./icons/marko.svg\" width=16> index.marko\n  📦 package.json\n  <mark><img src=\"./icons/ts.svg\" width=16> tsconfig.json</mark>\n  </pre>\n- **If you’re [publishing packages of Marko tags](./custom-tags.md#publishing-tags-to-npm)**, publish the output of [`mtc`](#ci-type-checking). Each component gets a `.d.marko` file with its types, which editors and type checkers read in place of the `.marko` file. This exposes type-checking and autocomplete for the published tags.\n\n> **ProTip**: For mixed JavaScript and TypeScript code, such as an incremental migration, set `\"script-lang\": \"ts\"` or `\"js\"` in [a `marko.json`](./marko-json.md) to override these defaults. The nearest `marko.json` up the directory tree applies, so folders can opt in or out.\n\n## Typing a tag's `input`\n\nA `.marko` file will use any exported `Input` type for [that file’s `input` object](./class-components.md#input).\n\nThis can be `export type Input` or `export interface Input`.\n\n### Example\n\n_PriceField.marko_\n\n```marko\nexport interface Input {\n  currency: string;\n  amount: number;\n}\n\n<label>\n  Price in ${input.currency}:\n  <input type=\"number\" value=input.amount min=0 step=0.01>\n</label>\n```\n\nYou can also import, reuse, and extend `Input` interfaces from other `.marko` or `.ts` files:\n\n```marko\nimport { Input as PriceInput } from \"<PriceField>\";\nimport { ExtraTypes } from \"lib/utils.ts\";\nexport type Input = PriceInput & ExtraTypes;\n```\n\n```marko\nimport { Input as PriceInput } from \"<PriceField>\";\nexport interface Input extends PriceInput {\n  discounted: boolean;\n  expiresAt: Date;\n};\n```\n\n### Generic `Input`s\n\n[Generic Types and Type Parameters](https://www.typescriptlang.org/docs/handbook/2/generics.html) on `Input` are recognized throughout the entire `.marko` template (excluding [static statements](./syntax.md#static-javascript)).\n\nFor example, if you set up a component like this:\n\n_components/my-select.marko_\n\n```marko\nexport interface Input<T> {\n  options: T[];\n  onSelect: (newVal: T) => unknown;\n}\n\nstatic function staticFn() {\n  // can NOT use `T` here\n}\n\n$ const instanceFn = (val: T) => {\n  // can use `T` here\n}\n\n// can use `as T` here\n<select on-input(evt => input.onSelect(options[evt.target.value] as T))>\n  <for|value, i| of=input.options>\n    <option value=i>${value}</option>\n  </for>\n</select>\n```\n\n…then your editor will figure out the types of inputs to that component:\n\n```marko\n<my-select options=[1,2,3] onSelect=val => {}/>\n                                 // ^^^ number\n\n<my-select options=[\"M\",\"K\",\"O\"] onSelect=val => {}/>\n                                       // ^^^ string\n```\n\n## Built-in Marko Types\n\nMarko exposes [type definitions](https://github.com/marko-js/marko/blob/main/packages/runtime-class/index.d.ts) you can reuse in [a TypeScript namespace](https://www.typescriptlang.org/docs/handbook/namespaces.html) called `Marko`:\n\n- **`Marko.Template<Input, Return>`**\n  - The type of a `.marko` file\n  - `typeof import(\"./template.marko\")`\n- **`Marko.TemplateInput<Input>`**\n  - The object accepted by the render methods of a template. It includes the template's `Input` as well as `$global` values.\n- **`Marko.Body<Params, Return>`**\n  - The type of the [body content](./body-content.md) of a tag (`renderBody`)\n- **`Marko.Component<Input, State>`**\n  - The base class for a [class component](./class-components.md)\n- **`Marko.Renderable`**\n  - Values accepted by the [`<${dynamic}/>` tag](./syntax.md#dynamic-tagname)\n  - `string | Marko.Template | Marko.Body | { renderBody: Marko.Body}`\n- **`Marko.Out`**\n  - The render context with methods like `write`, `beginAsync`, etc.\n  - `ReturnType<template.render>`\n- **`Marko.Global`**\n  - The type of the object in `$global` and `out.global` that can be passed to a template's render methods as the `$global` property.\n- **`Marko.RenderResult`**\n  - The [result](./rendering.md#renderresult) of rendering a Marko template\n  - `ReturnType<template.renderSync>`\n  - `Awaited<ReturnType<template.render>>`\n- **`Marko.Emitter`**\n  - `EventEmitter` from `@types/node`\n- **`Marko.NativeTags`**\n  - `Marko.NativeTags`: An object containing all native tags and their types\n- **`Marko.Input<TagName>`** and **`Marko.Return<TagName>`**\n  - Helpers to extract the input and return types native tags (when a string is passed) or a custom tag.\n- **`Marko.BodyParameters<Body>`** and **`Marko.BodyReturnType<Body>`**\n  - Helpers to extract the parameters and return types from the specified `Marko.Body`\n- **`Marko.AttrTag<T>`**\n  - Used to represent types for [attributes tags](./body-content.md#named-body-content)\n  - A single attribute tag, with a `[Symbol.iterator]` to consume any repeated tags.\n\n### Typing `renderBody`\n\nThe most commonly used type from the `Marko` namespace is `Marko.Body` which can be used to type `input.renderBody`:\n\n_child.marko_\n\n```marko\nexport interface Input {\n  renderBody?: Marko.Body;\n}\n```\n\nHere, the following will be acceptable values:\n\n_index.marko_\n\n```marko\n<child/>\n<child>Text in render body</child>\n<child>\n  <div>Any combination of components</div>\n</child>\n```\n\nPassing other values (including components) will cause a type error:\n\n_index.marko_\n\n```marko\nimport OtherTag from \"<other-tag>\";\n<child renderBody=OtherTag/>\n```\n\n### Typing Tag Parameters\n\nTag parameters are passed to the `renderBody` by the child tag. For this reason, `Marko.Body` also allows typing of its parameters:\n\n_for-by-two.marko_\n\n```marko\nexport interface Input {\n  to: number;\n  renderBody: Marko.Body<[number]>\n}\n\n<for|i| from=0 to=input.to step=2>\n  <${input.renderBody}(i)/>\n</for>\n```\n\n_index.marko_\n\n```marko\n<for-by-two|i| to=10>\n  <div>${i}</div>\n</for-by-two>\n```\n\n### Extending native tag types within a Marko tag\n\nThe types for native tags are accessed via the global `Marko.Input` type. Here's an example of a component that extends the `button` html tag:\n\n_color-button.marko_\n\n```marko\nexport interface Input extends Marko.Input<\"button\"> {\n  color: string;\n  renderBody?: Marko.Body;\n}\n\n$ const { color, renderBody, ...restOfInput } = input;\n\n<button style=`color: ${color}` ...restOfInput>\n  <${renderBody}/>\n</button>\n```\n\n### Registering a new native tag (eg for custom elements).\n\n```ts\ninterface MyCustomElementAttributes {\n  // ...\n}\n\ndeclare global {\n  namespace Marko {\n    interface NativeTags {\n      // By adding this entry, you can now use `my-custom-element` as a native html tag.\n      \"my-custom-element\": MyCustomElementAttributes;\n    }\n  }\n}\n```\n\n### Registering new \"global\" HTML Attributes\n\n```ts\ndeclare global {\n  namespace Marko {\n    interface HTMLAttributes {\n      \"my-non-standard-attribute\"?: string; // Adds this attribute as available on all HTML tags.\n    }\n  }\n}\n```\n\n### Registering CSS Properties (eg for custom properties)\n\n```ts\ndeclare global {\n  namespace Marko {\n    namespace CSS {\n      interface Properties {\n        \"--foo\"?: string; // adds a support for a custom `--foo` css property.\n      }\n    }\n  }\n}\n```\n\n## TypeScript Syntax in `.marko`\n\nAny [JavaScript expression in Marko](./syntax.md#inline-javascript) can also be written as a TypeScript expression.\n\n### Tag Type Parameters\n\n```marko\n<child <T>|value: T|>\n  ...\n</child>\n```\n\n### Tag Type Arguments\n\n_components/child.marko_\n\n```marko\nexport interface Input<T> {\n  value: T;\n}\n```\n\n_index.marko_\n\n```marko\n// number would be inferred in this case, but we can be explicit\n<child<number> value=1 />\n```\n\n### Method Shorthand Type Parameters\n\n```marko\n<child process<T>() { /* ... */ } />\n```\n\n### Attribute Type Assertions\n\nThe types of attribute values can _usually_ be inferred. When needed, you can assert values to be more specific with [TypeScript’s `as` keyword](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-assertions):\n\n```marko\n<some-component\n  number=1 as const\n  names=[] as string[]\n/>\n```\n\n# JSDoc Support\n\nFor existing projects that want to incrementally add type safety, adding full TypeScript support is a big leap. This is why Marko also includes full support for [incremental typing via JSDoc](https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html).\n\n## Setup\n\nYou can enable type checking in an existing `.marko` file by adding a `// @ts-check` comment at the top:\n\n```js\n// @ts-check\n```\n\nIf you want to enable type checking for all Marko & JavaScript files in a JavaScript project, you can switch to using a [`jsconfig.json`](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#using-tsconfigjson-or-jsconfigjson). You can skip checking some files by adding a `// @ts-nocheck` comment to files.\n\nOnce that has been enabled, you can start by typing the input with JSDoc. Here's an example component with typed `input`:\n\n```marko\n// @ts-check\n\n/**\n * @typedef {{\n *   firstName: string,\n *   lastName: string,\n * }} Input\n */\n\n<div>${firstName} ${lastName}</div>\n```\n\n## With a separate `component.js` file\n\nMany components in existing projects adhere to the following structure:\n\n<pre>\n📁 components/\n  📁 color-rotate-button/\n    <img src=\"./icons/marko.svg\" width=16> index.marko\n    <img src=\"./icons/js.svg\" width=16> component.js\n</pre>\n\nThe `color-rotate-button` takes a list of colors and moves to the next one each time the button is clicked:\n\n```marko\n<color-rotate-button colors=[\"red\", \"blue\", \"yellow\"]>\n  Next Color\n</color-rotate-button>\n```\n\nHere is an example of how this `color-rotate-button` component could be typed:\n\n_components/color-rotate-button/component.js_\n\n```js\n// @ts-check\n\n/**\n * @typedef {{\n *   colors: string[],\n *   renderBody: Marko.Renderable\n * }} Input\n * @typedef {{\n *   colorIndex: number\n * }} State\n * @extends {Marko.Component<Input, State>}\n */\nexport default class extends Marko.Component {\n  onCreate() {\n    this.state = {\n      colorIndex: 0,\n    };\n  }\n\n  rotateColor() {\n    this.state.colorIndex =\n      (this.state.colorIndex + 1) % this.input.colors.length;\n  }\n}\n```\n\n_components/color-rotate-button/index.marko_\n\n```marko\n// @ts-check\n\n/* Input will be automatically imported from `component.js`! */\n\n<button\n  onClick('rotateColor')\n  style=`color: ${input.colors[state.colorIndex]}`>\n  <${input.renderBody}/>\n</button>\n```\n\n# CI Type Checking\n\nFor type checking Marko files outside of your editor there is the [\"@marko/type-check\" cli](https://github.com/marko-js/language-server/tree/main/packages/type-check).\nCheck out the CLI documentation for more information.\n","packages/runtime-class/docs/vite.md":"# Marko + Vite\n\n# Installation\n\n```console\nnpm install @marko/vite vite\n```\n\n# Example config\n\n```javascript\nimport { defineConfig } from \"vite\";\nimport marko from \"@marko/vite\";\nexport default defineConfig({\n  plugins: [marko()],\n});\n```\n\n# Linked Mode\n\nBy default this plugin operates in `linked` mode (you can disabled this by passing [`linked: false` as an option](#optionslinked)). In `linked` mode the plugin automatically discovers all of the entry `.marko` files while compiling the server, and tells `Vite` which modules to load in the browser.\n\nWith this you _do not_ create `.html` files for `Vite`, it's Marko all the way down!\nScripts, styles and other content that _would have_ been injected into the `.html` files is instead automatically injected into your `.marko` templates.\n\nIn this mode you must use the [Vite SSR API](https://vitejs.dev/guide/ssr.html#setting-up-the-dev-server).\n\nHere's an example using `express`.\n\n```js\nimport { createServer } from \"vite\";\n\nconst app = express();\nlet loadTemplate;\n\nif (process.env.NODE_ENV === \"production\") {\n  // Use Vite's built asset in prod mode.\n  loadTemplate = () => import(\"./dist\");\n} else {\n  // Hookup the vite dev server.\n  const vite = await createServer({\n    server: { middlewareMode: true }\n  });\n\n  app.use(vite.middlewares);\n  loadTemplate = () => vite.ssrLoadModule(\"./template.marko\");\n}\n\napp.get(\"/\", async (req, res) => {\n  const template = (await loadTemplate()).default;\n  // When the template is loaded, it will automatically have `vite` assets inlined.\n  template.render({ hello: \"world\" }, res);\n);\n\napp.listen(3000);\n```\n\n> For a more real world setup check out our [vite express](https://github.com/marko-js/examples/tree/master/examples/vite-express) example app.\n\n# Options\n\n### options.babelConfig\n\nYou can manually override Marko's Babel configuration by passing a `babelConfig` object to the `@marko/vite` plugin. By default Babel's regular [config file resolution](https://babeljs.io/docs/en/config-files) will be used.\n\n```javascript\nmarko({\n  babelConfig: {\n    presets: [\"@babel/preset-env\"],\n  },\n});\n```\n\n### options.runtimeId\n\nIn some cases you may want to embed multiple isolated copies of Marko on the page. Since Marko relies on some `window` properties to initialize this can cause issues. For example, by default Marko will read the server rendered hydration code from `window.$components`. In Marko you can change these `window` properties by rendering with `{ $global: { runtimeId: \"MY_MARKO_RUNTIME_ID\" } }` as input on the server side.\n\nThis plugin exposes a `runtimeId` option produces output that automatically sets `$global.runtimeId` on the server side and initializes properly in the browser.\n\n```js\nmarko({ runtimeId: \"MY_MARKO_RUNTIME_ID\" });\n```\n\n### options.linked\n\nSet this to `false` to opt out of [linked mode](#linked-mode). When this is false, the plugin will only handle resolving and transforming `.marko` files.\n","packages/runtime-class/docs/webpack.md":"# Marko + Webpack\n\n# Installation\n\n> `@marko/webpack` >= 7 Only supports Marko 5+.\n> For Marko 4 support use `@marko/webpack@6`.\n\n```console\nnpm install @marko/webpack\n```\n\n### Loader: `@marko/webpack/loader`\n\nThe loader portion of this module can be used standalone and simply transforms your Marko templates into the appropriate JavaScript depending on your webpack target.\n\nYou can override the output by adding a `target` option to the loader of `target: \"server\" | \"browser\"`.\n\n### Plugin: `@marko/webpack/plugin`\n\nThe plugin actually creates two separate webpack plugins, the `browser` plugin and the `server` plugin.\n\nThese are intended to be used in a isomorphic [webpack multi compiler](https://github.com/webpack/webpack/tree/master/examples/multi-compiler) where you are bundling both the server and the browser. The way it works is that the server plugin is going to analyze the top level Marko components in your server and automatically communicate with the browser compiler to retrieve the assets for that template.\n\nThis plugin also analyzes the top level Marko templates and determines if it is possible for them to rerender (currently the heuristic is simply does the component have an associated `class` or `component.js`). The plugin will automatically skip sending down any unnecessary top level templates to the browser.\n\nThe end result is that you setup a multi compiler (as shown below) and you can simply import Marko templates, and all assets are automatically generated and inlined into an optimized server response. No need to keep track of a webpack manifest yourself!\n\n### Tag: `<webpack-assets>`\n\nThe `<webpack-assets>` tag can be used along with the plugin in a multi-compiler setup. This tag allows you to inject `<script>`/`<style>` tags into a server-rendered template for the assets of an entry in the client compiler.\n\n#### Example Usage\n\n```marko\n<webpack-assets entry=\"tracking\"/>\n```\n\n#### Example Config\n\n```js\n// ...\nexport default [\n  {\n    entry: \"./server.js\",\n    plugins: [markoPlugin.server],\n    // ...\n  },\n  {\n    // ...\n    entry: {\n      tracking: \"./tracking.js\",\n    },\n    plugins: [markoPlugin.browser],\n  },\n];\n```\n\n# Example\n\n```javascript\nimport MarkoPlugin from \"@marko/webpack/plugin\";\n\nconst markoPlugin = new MarkoPlugin();\n\nexport default [\n  {\n    entry: \"./server.js\",\n    module: {\n      rules: [\n        {\n          test: /\\.marko$/,\n          loader: \"@marko/webpack/loader\",\n        },\n      ],\n    },\n    plugins: [markoPlugin.server],\n  },\n  {\n    rules: [\n      {\n        test: /\\.marko$/,\n        loader: \"@marko/webpack/loader\",\n      },\n      // If using `style` blocks with Marko you must use an appropriate loader\n      {\n        test: /\\.css$/,\n        use: [\"style-loader\", \"css-loader\"],\n      },\n    ],\n    plugins: [markoPlugin.browser],\n  },\n];\n```\n\n## Babel options (Marko 5+)\n\nIf you are using Marko 5 with this plugin you can manually override the Babel configuration used by passing a `babelConfig` object along side the `@marko/webpack/loader`. By default Babels regular [config file resolution](https://babeljs.io/docs/en/config-files) will be used.\n\n```javascript\nexport default {\n    module: {\n      rules: [\n        {\n          test: /\\.marko$/,\n          loader: \"@marko/webpack/loader\",\n          options: {\n            babelConfig: {\n              presets: [\n                [\"@babel/preset-env\", { node: \"current\" }]\n              ]\n            }\n          }\n        }\n      ]\n    }\n  },\n```\n\n## Multiple client-side compilers\n\nSometimes you need multiple compilers for your client-side bundles. For example, with [`i18n`](https://github.com/webpack/webpack/tree/master/examples/i18n) or [even shipping dynamic runtime bundles to the browser](https://github.com/eBay/arc/tree/master/packages/arc-webpack).\n\nThe `@marko/webpack` plugin’s `.browser` property can be passed to multiple Webpack compilers. While rendering at runtime, you can provide a `$global.buildName` property to choose which assets from the Webpack compiler are included in the page.\n\nFor example, with the Webpack internationalization plugin, you might have a config like the following:\n\n```js\nimport MarkoPlugin from \"@marko/webpack/plugin\";\nimport I18nPlugin from \"i18n-webpack-plugin\";\nimport germanTranslations from \"./de.json\";\n\nconst languages = {\n  en: null,\n  de: germanTranslations,\n};\n\nconst markoPlugin = new MarkoPlugin();\n\nexport default [\n  {\n    name: \"Server\",\n    entry: \"./server.js\",\n    module: {\n      rules: [\n        {\n          test: /\\.marko$/,\n          loader: \"@marko/webpack/loader\",\n        },\n      ],\n    },\n    plugins: [markoPlugin.server],\n  },\n  ...Object.keys(languages).map((language) => ({\n    name: `Browser-${language}`,\n    rules: [\n      {\n        test: /\\.marko$/,\n        loader: \"@marko/webpack/loader\",\n      },\n      // If using `style` blocks with Marko you must use an appropriate loader\n      {\n        test: /\\.css$/,\n        use: [\"style-loader\", \"css-loader\"],\n      },\n    ],\n    plugins: [new I18nPlugin(languages[language]), markoPlugin.browser],\n  })),\n];\n```\n\nWith the above config, you can render your top-level Marko template server-side with a `$global.buildName` like so:\n\n```javascript\ntemplate.render({ $global: { buildName: \"Browser-de\" } });\n```\n\nThat will automatically send German assets. However, what you _probably_ want instead of always serving German is conditionally sending appropriate assets for a user’s locale. This can be done like so:\n\n```javascript\ntemplate.render({ $global: { buildName: `Browser-${req.language}` } });\n```\n\n**Note:** If a bundle with the provided `buildName` does not exist, an error is thrown.\n\n## Multiple copies of Marko\n\nIn some cases you may want to embed multiple isolated copies of Marko on the page. Since Marko relies on some `window` properties to initialize this can cause issues. For example, by default Marko will read the server rendered hydration code from `window.$components`. In Marko you can change these `window` properties by rendering with `{ $global: { runtimeId: \"MY_MARKO_RUNTIME_ID\" } }` as input on the server side.\n\nThis plugin exposes a `runtimeId` option produces output that automatically sets `$global.runtimeId` on the server side and initializes properly in the browser.\nThe `runtimeId` will default to the [`uniqueName` option](https://webpack.js.org/configuration/output/#outputuniquename) from the server compiler in the webpack config.\n\n```js\nimport MarkoPlugin from \"@marko/webpack/plugin\";\n\nconst markoPlugin = new MarkoPlugin({\n  runtimeId: \"MY_MARKO_RUNTIME_ID\", // default to webpack `output.uniqueName` option.\n});\n```\n\nNote: This option will also override the default values for the `jsonpFunction`, `chunkCallbackName` and `hotUpdateFunction` webpack `output` options, which all use global variables, to be prefixed with the `runtimeId`.\n\n## Dynamic public paths\n\nWhen using the plugin, the server will automatically sync the runtime [`__webpack_public_path__`](https://webpack.js.org/guides/public-path/#on-the-fly) with the browser.\nThis means that you only need to setup the dynamic public path on the server side.\n","packages/runtime-class/docs/why-is-marko-fast.md":"# Why is Marko Fast?\n\n<a href=\"https://medium.com/@psteeleidem/why-is-marko-fast-a20796cb8ae3\">\n  <img src=\"https://user-images.githubusercontent.com/1958812/28104838-d0182f48-6691-11e7-808d-d1ae2d0fed6d.png\" alt=\"Marko logo\" width=\"100%\" />\n</a><br />\n\n> This article was published in May 2017. You can find the original [\"Why is Marko Fast?\" article here](https://medium.com/@psteeleidem/why-is-marko-fast-a20796cb8ae3)!\n\nAt eBay we are using [Marko](https://markojs.com/) to render over a billion\nrequests every day and this has required us to finely tune Marko, our open\nsource UI library. We have heavily optimized Marko for fast rendering, [advanced\nperformance\ntechniques](https://tech.ebayinc.com/engineering/async-fragments-rediscovering-progressive-html-rendering-with-marko/)\nand to achieve a minimal page weight (~10kb gzipped). Performance is only one\nconcern because we have also had to scale Marko to support development across\nhundreds of teams in a way that allows developers to efficiently create\nmaintainable and robust web apps.\n\nWe have created [our own\nbenchmarks](https://github.com/marko-js/isomorphic-ui-benchmarks) and we have\n[added Marko to other\nbenchmarks](https://github.com/raxjs/server-side-rendering-comparison/pull/11),\nbut benchmarks cannot always be trusted. While we make every effort to be fair\nwith our benchmarks, what matters most is performance in real world applications\nas opposed to focusing on micro benchmarks. This is one reason that the V8 team\nhas switched to [a new methodology to measure and understand real-world\nJavaScript\nperformance](https://v8project.blogspot.com/2016/12/how-v8-measures-real-world-performance.html).\n\nSimilarly, we’ve taken a look at how our developers are _actually_ writing their\nMarko components and have found patterns that could be further optimized.\nInstead of focusing on benchmarks in this article, I want to focus on the\ndetails of optimizations that we have applied to Marko.\n\n### Multiple Compilation Outputs\n\nMarko is an isomorphic UI library that runs on both the server and in the\nbrowser. As [Michael Rawlings](https://medium.com/@mlrawlings) mentioned in\n“[Server-side Rendering\nShootout](https://hackernoon.com/server-side-rendering-shootout-with-marko-preact-rax-react-and-vue-25e1ae17800f)”,\nwhen rendering on the server, Marko renders directly to a string representation\nof the document (HTML) that can be sent as the HTTP response.\n\nWhen rendering in the browser, an HTML string would have to be parsed in order\nto update the DOM. For this reason, Marko compiles a view to a program that\nrenders directly to a virtual document (VDOM) tree that can be used to\nefficiently update the real DOM when targeting the browser.\n\nGiven the following template:\n\n```marko\n<div>Hello ${input.name}!</div>\n```\n\n#### Compiled for the server\n\nThe compiled output is optimized for streaming HTML output on the server:\n\n```js\nvar marko_template = require(\"marko/html\").t(__filename),\n  marko_helpers = require(\"marko/runtime/html/helpers\"),\n  marko_escapeXml = marko_helpers.x;\n\nfunction render(input, out) {\n  out.w(\"<div>Hello \" + marko_escapeXml(input.name) + \"!</div>\");\n}\n```\n\n#### Compiled for the browser\n\n<!-- prettier-ignore -->\n```js\nvar marko_template = require(\"marko/vdom\").t(__filename);\n\nfunction render(input, out) {\n  out\n    .e(\"DIV\", null, 3)\n    .t(\"Hello \")\n    .t(input.name)\n    .t(\"!\");\n}\n```\n\nThe compiled output is optimized for virtual DOM rendering in the browser:\n\n### Modular Runtime\n\nThe Marko runtime is not distributed as a single JavaScript file. Instead, the\nMarko compiler generates a JavaScript module that will only import the parts of\nthe runtime that are actually needed. This allows us to add new features to\nMarko without bloating existing applications. For example, given the following\ntemplate:\n\n```marko\n$ var color = 'red';\n<div style={backgroundColor: color}></div>\n```\n\nIn the above example, extra runtime code is needed to render the `style` attribute\nbased on the JavaScript object that is provided. The compiled code that imports\nthe `styleAttr` helper is shown below:\n\n```js\nvar marko_styleAttr = require(\"marko/runtime/vdom/helper-styleAttr\");\n\nfunction render(input, out) {\n  var color = \"red\";\n  out.e(\n    \"DIV\",\n    {\n      style: marko_styleAttr({\n        backgroundColor: color,\n      }),\n    },\n    0,\n    4,\n  );\n}\n```\n\n### High performance server-side rendering\n\nCompared to solutions based on JSX that exclusively do virtual DOM rendering,\nMarko has a huge advantage for server-side rendering. When rendering to a\nvirtual DOM tree on the server it’s a two-step process to render HTML:\n\n- First pass to produce an entire virtual DOM tree in memory\n- Second pass to serialize the virtual DOM tree to an HTML string that can then be\n  sent over the wire (this requires traversing the entire tree structure)\n\nIn contrast, Marko renders directly to an HTML stream in a single pass. There is\nno intermediate tree data structure.\n\n### Compile-time optimization of static sub-trees\n\nGiven the following template:\n\n```marko\n<div>This is a <strong>static</strong> node</div>\n```\n\nMarko will recognize that the template fragment produces the same output every\ntime and it will thus create the virtual DOM node once as shown in the following\ncompiled output:\n\n```js\nvar marko_node0 = marko_createElement(\"DIV\", null, 3, ...)\n  .t(\"This is a \")\n  .e(\"STRONG\", null, 1)\n    .t(\"static\")\n  .t(\" node\");\n\nfunction render(input, out) {\n  out.n(marko_node0);\n}\n```\n\nRendering a static sub-tree has virtually zero cost. In addition, Marko will\nskip diffing/patching static sub-trees.\n\nSimilarly, on the server, Marko will merge static parts of the template into a\nsingle string:\n\n```js\nfunction render(input, out) {\n  out.w(\"<div>This is a <strong>static</strong> node</div>\");\n}\n```\n\n### Compile-time optimization of static attributes\n\nMarko will also optimize static attributes on dynamic elements.\n\nGiven the following template:\n\n```marko\n<div.hello>Hello ${input.name}!</div>\n```\n\nMarko will produce the following compiled output:\n\n<!-- prettier-ignore -->\n```js\nvar marko_attrs0 = {\n  class: \"hello\"\n};\n\nfunction render(input, out) {\n  out\n    .e(\"DIV\", marko_attrs0, 3)\n    .t(\"Hello \")\n    .t(input.name)\n    .t(\"!\");\n}\n```\n\nNotice that the attributes object is only created once and it is used for every\nrender. In addition, no diffing/patching will happen for static attributes.\n\n### Smart compiler\n\nWith Marko we favor doing as much at compile-time as possible. This has made our\ncompiler more complex, but it gives us significant gains at runtime. We have\n~90% code coverage and over 2,000 tests to ensure that the compiler is working\ncorrectly. In addition, in many cases the Marko compiler provides hints to the\nruntime for a given template so that the runtime can optimize for specific\npatterns. For example, Marko recognizes if an HTML element only has `class`/`id`/`style` defined\nand the runtime optimizes for these virtual DOM nodes when doing\ndiffing/patching (the Marko compiler generates code that flags simple virtual\nDOM nodes for targeted diffing/patching logic).\n\n### Event delegation\n\nIf you are building a UI component you will likely need to write code to handle\nvarious DOM events (`click`, `submit`, etc.). It is common for developers to write code that\nadds DOM event listeners using `dom.addEventListener(...)` or using a library such as jQuery. You can still\ndo that when building UI components using Marko, but there is overhead in\nattaching listeners when lots of components are being initialized. Instead,\nMarko recommends using declarative event binding as shown below:\n\n```marko\n<button type=\"button\" on-click(\"handleClick\")>\n  Click Me\n</button>\n```\n\nWhen using declarative event binding, no DOM event listeners are actually\nattached for events that bubble. Instead, Marko attaches a single listener on\nthe root DOM element of the page for each DOM event that bubbles (done at\nstartup). When Marko receives an event at the root it handles delegating the\nevent to the appropriate components that are interested in that event. This is\ndone by looking at the `event.target` property to see where the event originated and then\nwalking up the tree to find components that need to be notified. As a result,\nthere is slightly more work that is done when a DOM event is captured at the\nroot, but this approach uses much less memory and reduces the amount of work\nthat is done during initialization. The extra overhead of delegating events to\ncomponents will not be noticeable so it is a very beneficial optimization.\n\n_Cover image credit: [Superhero by Gan Khoon Lay from the Noun Project](https://thenounproject.com/search/?q=superhero&i=690775)_\n","packages/runtime-class/helpers/README.md":"# Marko Helpers\n\nThis directory contains helpers that were deprecated in Marko v3. Marko v4/5 no longer adds these helpers to every compiled template, but you can still import them if needed.\n","packages/runtime-tags/AGENTS.md":"# Marko 6 (runtime & translator)\n\nPublished as `marko@6` and `@marko/runtime-tags`. Contains both the runtime and the Babel translator that generates code against it; most changes touch both halves plus test fixtures.\n\n## Layout\n\n| Directory         | Purpose                                                                                                                |\n| ----------------- | ---------------------------------------------------------------------------------------------------------------------- |\n| `src/common/`     | Types, accessor enums, helpers shared by both runtimes                                                                 |\n| `src/dom/`        | CSR runtime: scopes, signals, control flow, resume, scheduling                                                         |\n| `src/html/`       | SSR runtime: streaming writer, value serializer, resume boilerplate                                                    |\n| `src/translator/` | Babel translator: `core/` (built-in tags), `visitors/` (per AST node), `util/` (analysis), `interop/` (Marko 5 compat) |\n\nEntries: `src/dom.ts`, `src/html.ts`, `src/translator/index.ts`. Type stubs for core tags: `tags/*.d.marko`.\n\n## Architecture\n\n[CONTEXT.md](CONTEXT.md) is the canonical glossary — use its terms (and respect\nits _Avoid_ lists) in code, comments, and discussion. Read the\n[resume architecture guide](RESUMABILITY.md) before changing reference analysis,\nsignals, serialization, resume, lazy loading, or generated DOM output; it traces\nthe compiler/runtime model end to end and routes each concept to its code.\n\nPrinciples that decide most proposals:\n\n- Client code, serialized data, and registrations ship only where analysis shows they can run or update.\n- Code ships because code that ships references it, never by force. Never keep a call or declaration for its side effect (a registration, a stamp) or to make an optimized build work: a kept value pins its whole reference graph (signals, joins, renders, runtime), which in real apps bundles subgraphs the plain build drops, so a fixture's small size delta proves nothing. Deliver the fact the client needs instead (serialized data or a compiler literal). An unreferenced top-level declaration in an optimized bundle snapshot is this bug.\n- A build contract (an id the compiler registered) is a `MARKO_DEBUG` assert, never a production check, and needs no fixture faking its violation.\n- An optimization may take any shape that idiomatic Marko code cannot observe.\n- HTML output targets what browsers parse, not validators.\n- No API may require `import \"marko\"`.\n\n## Translator\n\nThe compiler phase contract is strict:\n\n| Phase       | Contract                                                                                                                           |\n| ----------- | ---------------------------------------------------------------------------------------------------------------------------------- |\n| Parse       | Create the initial hybrid Marko/Babel AST.                                                                                         |\n| `migrate`   | Apply userland and translator-provided Marko-to-Marko codemods that may be written back to disk.                                   |\n| `transform` | Apply typically userland Marko-to-Marko codemods that affect compilation only and must never be written back.                      |\n| Pre-analyze | Technically part of `transform`; normalize/simplify Marko before analysis when the analyzer or translator needs a canonical shape. |\n| `analyze`   | Annotate the AST, usually via `node.extra`, and compute output-neutral graph data: bindings, signals, ids, reasons.                |\n| `translate` | Convert Marko to JavaScript for the configured `dom` or `html` output.                                                             |\n\nEverything through `analyze` is cached and reused across outputs. Therefore:\n\n- Mutating AST structure during `analyze` is an anti-pattern; perform reshaping in pre-analyze.\n- Analyze records facts about the template, never nodes. Never retain an AST node or `NodePath` across phases, including inside `node.extra` (or program extra/`Section`/`Binding` fields): the analyzed AST is cached and `t.cloneNode`d for each output, so a stored node points at the cache while translate walks a clone — reads go stale and identity checks fail silently. The metadata shell itself (`node.extra` objects, `Section`s, `Binding`s) is shared by reference across clones, so record facts there — flags, ids, `Section`/`Binding` references — and resolve current nodes within the current phase. If the fact concerns a child whose metadata does not exist yet at your visitor, flag it from an analyze `exit` hook (children are analyzed by then) rather than storing the child node for later.\n- Never make output-specific decisions before `translate`. Branch on `dom`/`html` only while translating.\n- Reach the current compilation through `getFile()`/`getProgram()` (from `@marko/compiler/babel-utils`), never `path.hub.file`: the hub chain re-derives what the compile state already tracks and reads inconsistently across contexts. There are currently zero `hub.file` uses in the translator; keep it that way.\n- `file.metadata.marko` is public compiler output (returned from the top-level compile APIs): never route internal channels through it. Internal analyze products belong on the extras shell (program extra, `Section`, `Binding`); metadata carries only deliberately public facts.\n- Naming follows the same contract: analyze metadata (Binding/Section/`node.extra` fields) records **what the template does** — observed facts, in template terms (sources, reads, uses, shapes). Translate names its **conclusions** — decisions, policies, and output mechanisms (ownership, wire channels, masks). A shared field named after a decision (e.g. server/client \"owned\", \"required\") is a smell: name the observation and derive the decision where it is made. Never coin a term the compiler does not already use; a new concept gets a `CONTEXT.md` entry first.\n- Keys on `node.extra` say who may use them: a symbol key is one module's private state and is never exported; a fact any other module reads is a string field declared on its node kind's extra (`MarkoTagExtra`, `FunctionExtra`, or `NodeExtra` for an expression root).\n- The translator has no `MARKO_DEBUG` checks: its published build drops them, so a check guards only local development. Design the invariant out instead: derive the value from what makes it true, type it so a violation does not compile, or leave misuse no path.\n- Gather in analyze, act in translate. There are currently zero Babel `traverse` calls in the translator; keep it that way. Before adding analysis, find the fact in what exists (`Section`, a binding's reads/aliases/sources, `node.extra`, reasons, tag-name and known-tag analysis) and extend it; after adding one, check what else can use it.\n- Analyze facts settle once. `Binding.reads`, `Binding.pruned`, and reasons are complete only once `finalizeReferences` runs at program analyze `exit`, so tag and expression analyze visitors never read them; an expression's resolved references are read through `getReferencedBindings`/`getLazyBindings`, which finalize sets. One exception: a known tag's call site reads its callee's params tree during analyze, which is complete for another template or for a `<define>` called from outside its body; a recursive tag waits for program exit (`analyzeRecursiveTags`) to read it. A fact about the template is a field (`Section`, `Binding`, `node.extra`, the program's extra), written once it is final, never un-set, and never read for a fact it was not built for. `createAnalysisState` holds analyze scratch and caches derived from facts, which every output reads; `createOutputState` holds what one output builds; the `…SectionState` forms key either by section.\n- A tag records its client markup into its section's structure stream (`util/structure.ts`) in render order, passing `structure.node`/`structure.marker` the dom binding that holds each node client code addresses (`structure.controlFlowNode` addresses a control flow tag by its only-child element or a marker). DOM derives the template and walk string from the stream, and the walker stores each node it reaches at the next scope index, so `allocateIds` numbers a section's dom bindings in stream order: creation order never matters.\n- Pruning drops a binding nothing reads, with its value. Translate emits a read only of a binding analysis kept: check `pruned`, and write each read as analysis resolved it (`getReadReplacement`), never by a name the graph does not track.\n- Reference analysis (`util/references.ts`, `finalize-references.ts`, `solve-reasons.ts`) is tag-agnostic: a tag records a generic fact on its expression's `node.extra`, and the analysis reads it without naming the tag. Known tags are the one exception: the solver maps each call site's param reason groups every pass (`addKnownTagReasons`). `solveReasons` repeats its steps until no reason moves, so each step is named for what it adds, merges or ensures (`addClosureReasons`, `mergeSlotReasons`, `ensureSectionReasonGroups`); `finalize*` names work that runs once, on settled facts (`finalizeReferences`).\n- A program-wide effect (`isInteractive`, an imported registration) follows the reason that needs it, never a feature's presence. Only an unconditional reason makes a template a bundle root: a value written only while a caller changes params ships with that caller, which imports the template.\n- Compile-context helpers (`isOptimize`, `isOutputHTML`, `getMarkoOpts`, `callRuntime`) are called where needed, never passed in as overridable parameters. Non-capturing callbacks become named file-level functions here too.\n\nNode visitors live in `visitors/` and are split per phase by `extractVisitors` (`util/visitors.ts`); `visitors/tag/index.ts` dispatches to `native-tag.ts` / `custom-tag.ts` / `dynamic-tag.ts` / `attribute-tag.ts` or a tag definition's own hooks.\n\nCore tags are one file per tag in `core/`, registered in `core/index.ts`:\n\n```ts\nexport default {\n  analyze(tag) { ... },\n  translate: translateByTarget({\n    html(tag) { ... },\n    dom(tag) { ... },\n  }),\n} as Tag;\n```\n\n- `callRuntime(\"_name\", ...args)` (`util/runtime.ts`) references runtime helpers with automatic imports; DOM helpers listed in `pureDOMFunctions` get `/*@__PURE__*/`.\n- Validate early: core tags share their checks and wording from `util/assert.ts` (`assertOnlyValueAttr`, `assertHasBody`, `assertHasVar`, `assertNoSpreadAttrs`, …), while `assertNoArgs` / `assertNoParams` / `assertNoVar` / `assertAllowedAttributes` come from `@marko/compiler/babel-utils`. Compile errors use `path.buildCodeFrameError` with backticked names and a markojs.com docs link — `util/assert.ts` is the canonical style.\n- `util/marko-config.ts` provides `isOutputHTML` / `isOutputDOM` / `isOptimize`.\n- `util/optional.ts` (`Opt`/`Sorted` list algebra) underpins reference tracking; a list a `Sorted` instance builds (`bindingUtil`, `propsUtil`, `sectionUtil`, `sourcesUtil`) is looked up by binary search, so it is typed `SortedOpt` and only that instance can write it (`push`/`concat` results do not type-check into one). Work on these lists with its helpers (`forEach`, `some`, `reduce`, `filter`, the `Sorted` utils): build-then-`reverse` and dedupe-on-add are smells; `util/known-tag.ts` holds the custom/dynamic tag input contracts. Native element work lives in `visitors/tag/native-tag.ts` (with `common/helpers.ts` and `util/tag-facts.ts`).\n\n## Runtime conventions\n\n- **`_name` exports** are runtime API called by generated code — public to codegen, not to app authors. Renames must update `callRuntime` call sites and `pureDOMFunctions`.\n- **`MARKO_DEBUG`** gates all validation, descriptive names, and detailed error messages (`if (MARKO_DEBUG) { ... }`); builds strip these. Write for the optimized build: debug-only code never leaves it a temporary or branch, so return directly. It is `true` for code loaded through the `~ts` register hook; fixture bundles define it per mode (`false` under optimize). Runtime error helpers live in `common/errors.ts`.\n- **`.debug.ts` pairs**: source imports the `.debug` module (e.g. `common/types.ts` imports `./constants/accessor-prop.debug`); the production build remaps `X.debug` → `X.ts`. Both files must export identical member names with unique string values. `src/__tests__/debug-pairs.test.ts` checks every pair because the types cannot — each module's `Value` is `typeof import(\"./<itself>\")` and `translator/util/get-accessor-enums.ts` casts `as any` — so a member added to only one half would otherwise type-check and show up as `undefined` in an optimize build. A runtime record that needs readable debug keys uses a pair, extending the module for the object type that owns the property (repeated short values compress better).\n- **Optional feature enablement** (tree-shakable runtime API) has two patterns:\n  - **`src/{dom,html}/**/*.feat.ts`** are compiler-injected side-effect modules for behavior a referenced import cannot keep alive (catch handling, controllable registration). The build emits them as extra entries of their runtime's bundle — a shared chunk keeps one state instance, so they import runtime internals directly. A feature body is direct registry/property assignments (plus at most one installer call, e.g. `installCatch`); the compiler emits it once per program via `importRuntimeFeature` (typed by `DOMRuntimeFeature`). `lazy.feat` is the exception: `translator/util/entry-builder.ts` › `builder.build` imports it (via `getRuntimeFeatureImport`) into a resuming entry that reaches a lazy import, since resume needs its latch even when no bundled template references lazy runtime.\n  - **Definition-site wrappers** gate behavior on a helper's own retention: `export const _if = /*@__PURE__*/ withBranches(...)`.\n  - Latches are `let`s written only by their enabler (`branchesEnabled`, `catchEnabled`) so bundlers fold latch and guarded code away together; object-property flags defeat that analysis and re-inflate resume bundles.\n  - Never statically import control-flow or a `.feat` module from a main-graph module (queue, resume, load) — it fuses the feature into every bundle.\n  - Base helpers and the writer take no feature-only params, hooks, or flags (a feature-only param goes last). A `.feat` imports the features it always needs.\n- **Size idioms** (client runtime): inline a helper, `const`, or `let` used once, and repeat a short member read rather than binding it (gzip favors repetition). Prefer truthiness with `0`/`1` over `undefined`/booleans, default params, `||=`, `for (let i = n; i--;)`, and `else` over an early `return`. Give every parameterless arrow an unused parameter, consistently, since `e=>` minifies a byte under `()=>`: `(_?: never) =>` where callers pass nothing, else typed as what they pass; generated client code takes `getUnusedParamIdentifier()` (not an IIFE, which the minifier inlines only bare), and the inlined runtimes a free letter. Tell nodes apart with `nodeType >`/`<` against the `NodeType` enum (a marker is `> NodeType.Element`), never the DOM's constants. Settle byte questions by measuring with `build:sizes`, and weigh a byte by how often an app pays it: once (the runtime) counts least, per template (generated code, across an app's thousands of templates) more, and per rendered instance (serialized data, per loop row) most; a fixture's delta shows only the one-time cost.\n- **Hot paths** (SSR writer, serializer, resume): never `delete`, copy with spread/rest, `unshift`/`reverse`, take rest params per tag, or create a promise or closure unconditionally. Never post-process output with string `replace`/`split`/`indexOf`; the serializer appends valid JavaScript. Keep object shapes consistent; put cheap checks first.\n- **Wire bytes**: before serializing a link or field, derive it from what the client already knows (walk and insertion order, id order). Rare tuple slots go last so trailing-empty trimming drops them.\n- Named/top-level functions use `function` declarations; arrows only for closures that must capture or for wrapped feature helpers (smaller output). Extract non-capturing closures into named file-level functions.\n\n## Testing\n\nFixture-based snapshot tests driven by `src/__tests__/main.test.ts`. Fixtures live in `src/__tests__/fixtures/`, plus `fixtures-interop/` (Marko 5 ↔ 6 mixing, suite name `translator-interop`). A dir suffixed `.skip` is ignored.\n\nFrom the repo root:\n\n```sh\npnpm test                                                            # whole suite, fanned across CPU cores\npnpm test -- --grep \"runtime-tags/translator <fixture> \"             # one fixture (note trailing space)\npnpm run test:update -- --grep \"runtime-tags/translator <fixture> \"  # regenerate its snapshots\npnpm test -- --grep \"translator-interop\"                             # interop suite (run after base suite passes)\n```\n\nIterate scoped, then run `pnpm test` for everything; it fans across cores and reports every failure. Repeating a grep as `pnpm run test:serial -- --grep \"...\"` runs it in one process, with `bail: true` and live output, for a debugger or a clean stack trace.\n\n### Fixture anatomy\n\n```\nfixtures/<name>/\n  template.marko    # entry (required); custom tags under tags/\n  test.ts           # optional: export const config: TestConfig = { ... }\n  sizes.json        # generated compiled-size tracking\n  __snapshots__/    # generated + auto-pruned by test:update; never edit or delete by hand\n    dom.bundle[.debug].js       # compiled CSR output\n    html.bundle[.debug].js      # compiled SSR output\n    render[.debug].md           # per-step rendered HTML + granular mutation log + `## Console` output\n    writes[.debug].html         # SSR stream chunks (joined by <!-- FLUSH -->)\n    diagnostics[.debug].md      # debug-only meta.diagnostics (warnings/deprecations)\n    error-compile-{html,dom}[.debug].txt   # expected compile failure (error_compiler)\n    {ssr,csr}.error[.debug].txt            # expected render failure (error_html/error_dom)\n```\n\nAdding or removing a recoverable diagnostic or deprecation therefore fails a `diagnostics.md` snapshot in every fixture that carries one.\n\n`TestConfig` (see `main.test.ts`): `steps` (`[initialInput, ...]` where later steps are input updates, `(container) => {}` interactions, or async `Wait`/`Flush`/`Throws` controls), `error_compiler` (expect compile failure), `error_html` / `error_dom` (expect a render failure), `equivalent: false` (separate `render-ssr`/`render-csr` snapshots), `embedded`, `load_order` / `reject_load` (lazy-chunk ordering and failure), `fix_guide`, `skip_optimize` / `skip_dom` / `skip_html` / `skip_csr` / `skip_ssr`, `skip_parity` (debug intentionally logs a diagnostic optimize cannot), `runtime_id`. Each fixture runs in `debug` and `optimize` modes; CSR only runs in `debug`.\n\nTo add a fixture: create the dir + `template.marko` (+ `test.ts` with steps exercising the behavior), run `test:update` scoped to it, then **read the generated snapshots as part of your change** — the mutation log in `render.md` shows update granularity (an unexpected extra `UPDATE:`/re-render is a regression), and the `.bundle.js` diff shows generated-code cost. Name a fixture for the behavior it pins, not the repro that found it; it fails without the change, uses current syntax (never deprecated features), and gets async values from `__tests__/utils/resolve.ts` (`resolveAfter`, `rejectAfter`). The summary names each changed snapshot family and why it changed.\n\n## Workflows\n\n**New/changed core tag** (see the `<show>` tag commit for a full example):\n\n1. `translator/core/<tag>.ts` + register in `core/index.ts` (and `util/is-core-tag.ts`), and give it an entry in `util/tag-facts.ts`.\n2. Runtime helpers in `src/dom/` / `src/html/`, exported from `src/dom.ts` / `src/html.ts`; add to `util/runtime.ts` lists as needed.\n3. Several small fixtures covering static values, dynamic updates, nesting, and interaction with `<for>`/`<if>`.\n4. `pnpm run change` — user-facing changes need a changeset.\n5. Update `cheatsheet.md` (the LLM syntax reference shipped in the published package) when the change affects user-facing syntax, idioms, or guidance. Keep it dense: a line earns its place only by preventing a real mistake.\n6. Expect broad snapshot/`sizes.json` churn and an update to `packages/runtime-class/test/taglib-lookup/fixtures/getTagsSorted/expected.json` (interop taglib lookup).\n\n**Changing generated output**: iterate with `pnpm run compile -- -o dom -d file.marko` (and `-o html`), then `test:update` and audit snapshot diffs — output shape changes ripple through hundreds of fixtures; verify a sample by hand, don't rubber-stamp.\n\n**Changing runtime behavior**: find the covering fixtures by grepping `__tests__/fixtures` for the runtime helper or syntax; extend `steps` before touching the runtime so the mutation log captures the before/after.\n\n## Gotchas\n\n- `translator/util/bindings.ts` imports `toAccess` from `html/serializer.ts` — serializer key encoding changes affect the translator.\n- Adding an accessor enum member: keep the `src/common/constants/*[.debug].ts` pair in lockstep (same members, char vs. readable string values).\n- Size regressions count as review findings: check the fixture `sizes.json` diffs and root `.sizes.json` (updated by the pre-commit hook).\n- Language semantics questions (what a tag/attribute should do) are answered by the docs, not inferred: <https://markojs.com/llms.txt>.\n","packages/runtime-tags/README.md":"<div align=\"center\">\n\n# [<img alt=\"Marko\" src=\"https://raw.githubusercontent.com/marko-js/website/refs/heads/main/public/assets/logo.svg\" width=\"250\">](https://markojs.com/)\n\n**A declarative, HTML-based language that makes building web apps fun 🔥**\n\n[![NPM](https://img.shields.io/npm/v/marko.svg)](https://www.npmjs.com/package/marko)\n[![Discord Chat](https://img.shields.io/badge/discord-chat-7188da.svg)](https://discord.gg/RFGxYGs)\n[![Continuous Integration status](https://github.com/marko-js/marko/actions/workflows/ci.yml/badge.svg)](https://github.com/marko-js/marko/actions/workflows/ci.yml)\n[![Code coverage %](https://codecov.io/gh/marko-js/marko/branch/master/graph/badge.svg)](https://codecov.io/gh/marko-js/marko)\n[![# of monthly downloads](https://img.shields.io/npm/dm/marko.svg)](https://npm-stat.com/charts.html?package=marko)\n[![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/7029/badge)](https://bestpractices.coreinfrastructure.org/projects/7029)\n\n[Docs](https://markojs.com/docs/introduction/getting-started) ∙ [Try Online](https://markojs.com/playground) ∙ [Contribute](#contributors) ∙ [Get Support](#community--support)\n\n</div>\n\n## Intro\n\nMarko is HTML _reimagined_ as a language for building dynamic and reactive user interfaces. Almost any valid HTML is valid Marko, and Marko extends HTML for building modern applications more declaratively. Among these extensions are [components](https://markojs.com/docs/reference/custom-tag), [conditionals](https://markojs.com/docs/reference/core-tag#if--else) and [loops](https://markojs.com/docs/reference/core-tag#for), and a full [reactivity system](https://markojs.com/docs/reference/reactivity).\n\n### Example Component\n\nThe following renders a button and a counter of how many times the button has been pressed:\n\n**click-count.marko**\n\n```marko\n// HTML + JavaScript = 💜\n<let/count=0>\n<button onClick() { count++ }>\n  Clicked ${count} times\n</button>\n```\n\n## Getting Started\n\n1. `npm init marko`\n2. Read the [docs](https://markojs.com/docs/introduction/getting-started)\n\n## Community & Support\n\n<table>\n<thead><tr>\n  <th><svg viewBox=\"0 0 576 512\"><path d=\"M492.5 69.8c-.2-.3-.4-.6-.8-.7-38.1-17.5-78.4-30-119.7-37.1-.4-.1-.8 0-1.1 .1s-.6 .4-.8 .8c-5.5 9.9-10.5 20.2-14.9 30.6-44.6-6.8-89.9-6.8-134.4 0-4.5-10.5-9.5-20.7-15.1-30.6-.2-.3-.5-.6-.8-.8s-.7-.2-1.1-.2c-41.3 7.1-81.6 19.6-119.7 37.1-.3 .1-.6 .4-.8 .7-76.2 113.8-97.1 224.9-86.9 334.5 0 .3 .1 .5 .2 .8s.3 .4 .5 .6c44.4 32.9 94 58 146.8 74.2 .4 .1 .8 .1 1.1 0s.7-.4 .9-.7c11.3-15.4 21.4-31.8 30-48.8 .1-.2 .2-.5 .2-.8s0-.5-.1-.8-.2-.5-.4-.6-.4-.3-.7-.4c-15.8-6.1-31.2-13.4-45.9-21.9-.3-.2-.5-.4-.7-.6s-.3-.6-.3-.9 0-.6 .2-.9 .3-.5 .6-.7c3.1-2.3 6.2-4.7 9.1-7.1 .3-.2 .6-.4 .9-.4s.7 0 1 .1c96.2 43.9 200.4 43.9 295.5 0 .3-.1 .7-.2 1-.2s.7 .2 .9 .4c2.9 2.4 6 4.9 9.1 7.2 .2 .2 .4 .4 .6 .7s.2 .6 .2 .9-.1 .6-.3 .9-.4 .5-.6 .6c-14.7 8.6-30 15.9-45.9 21.8-.2 .1-.5 .2-.7 .4s-.3 .4-.4 .7-.1 .5-.1 .8 .1 .5 .2 .8c8.8 17 18.8 33.3 30 48.8 .2 .3 .6 .6 .9 .7s.8 .1 1.1 0c52.9-16.2 102.6-41.3 147.1-74.2 .2-.2 .4-.4 .5-.6s.2-.5 .2-.8c12.3-126.8-20.5-236.9-86.9-334.5zm-302 267.7c-29 0-52.8-26.6-52.8-59.2s23.4-59.2 52.8-59.2c29.7 0 53.3 26.8 52.8 59.2 0 32.7-23.4 59.2-52.8 59.2zm195.4 0c-29 0-52.8-26.6-52.8-59.2s23.4-59.2 52.8-59.2c29.7 0 53.3 26.8 52.8 59.2 0 32.7-23.2 59.2-52.8 59.2z\"></path></svg>\n  <th><svg viewBox=\"0 0 576 512\"><path d=\"M407.8 294.7c-3.3-.4-6.7-.8-10-1.3 3.4 .4 6.7 .9 10 1.3zM288 227.1C261.9 176.4 190.9 81.9 124.9 35.3 61.6-9.4 37.5-1.7 21.6 5.5 3.3 13.8 0 41.9 0 58.4S9.1 194 15 213.9c19.5 65.7 89.1 87.9 153.2 80.7 3.3-.5 6.6-.9 10-1.4-3.3 .5-6.6 1-10 1.4-93.9 14-177.3 48.2-67.9 169.9 120.3 124.6 164.8-26.7 187.7-103.4 22.9 76.7 49.2 222.5 185.6 103.4 102.4-103.4 28.1-156-65.8-169.9-3.3-.4-6.7-.8-10-1.3 3.4 .4 6.7 .9 10 1.3 64.1 7.1 133.6-15.1 153.2-80.7 5.9-19.9 15-138.9 15-155.5s-3.3-44.7-21.6-52.9c-15.8-7.1-40-14.9-103.2 29.8-66.1 46.6-137.1 141.1-163.2 191.8z\"></path></svg>\n  <th><svg viewBox=\"0 0 448 512\"><path d=\"M357.2 48L427.8 48 273.6 224.2 455 464 313 464 201.7 318.6 74.5 464 3.8 464 168.7 275.5-5.2 48 140.4 48 240.9 180.9 357.2 48zM332.4 421.8l39.1 0-252.4-333.8-42 0 255.3 333.8z\"></path></svg>\n  <th><svg viewBox=\"0 0 512 512\"><path d=\"M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3 .3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5 .3-6.2 2.3zm44.2-1.7c-2.9 .7-4.9 2.6-4.6 4.9 .3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM252.8 8c-138.7 0-244.8 105.3-244.8 244 0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1 100-33.2 167.8-128.1 167.8-239 0-138.7-112.5-244-251.2-244zM105.2 352.9c-1.3 1-1 3.3 .7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3 .3 2.9 2.3 3.9 1.6 1 3.6 .7 4.3-.7 .7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3 .7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3 .7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z\"></path></svg>\n<tbody><tr><td>\n\nHang out in our [Discord server](https://discord.gg/marko) to ask questions & discuss marko<td>\n\nKeep up with the community on Bluesky at [@markojs.com](https://bsky.app/profile/markojs.com)<td>\n\nTweet to [@MarkoDevTeam](https://twitter.com/MarkoDevTeam) or use the [#markojs](https://twitter.com/search?q=%23markojs%20OR%20%40markodevteam&f=live) hashtag<td>\n\nBrowse the code, open issues, & make pull requests on [GitHub](https://github.com/marko-js/marko)\n\n</table>\n\n### Contributors\n\nMarko would not be what it is without all those who have contributed ✨\n\n[![All marko-js/marko GitHub contributors](https://opencollective.com/marko-js/contributors.svg?width=890&button=false)](https://github.com/marko-js/marko/graphs/contributors)\n\n### Get Involved!\n\n- Pull requests are welcome!\n- Submit [GitHub issues](https://github.com/marko-js/marko/issues) for any feature enhancements, bugs, or documentation problems\n- [Read the Contribution Tips and Guidelines](.github/CONTRIBUTING.md)\n- Participants in this project agree to abide by [its Code of Conduct](https://github.com/eBay/.github/blob/main/CODE_OF_CONDUCT.md)\n","skills/README.md":"# Skills\n\nAgent skills for AI coding assistants working with Marko. Each skill is a folder with a `SKILL.md` entry point (frontmatter `name`/`description` plus instructions); sibling `.md` files are references the agent loads on demand.\n\n| Skill                                                | Use it to                                                                                                                |\n| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |\n| [`marko-best-practices`](./marko-best-practices)     | write idiomatic Marko 6 when creating or editing `.marko` files                                                          |\n| [`marko-5-to-6-migration`](./marko-5-to-6-migration) | migrate Marko 5 (Class API / legacy widgets) apps and libraries to Marko 6, fully or incrementally via the interop layer |\n\n## Installation\n\nSkills run inside your own project, not this repo.\n\nWith the [skills CLI](https://skills.sh) (installs into the current project for Claude Code, Cursor, and other supported agents; pick the skills when prompted):\n\n```sh\nnpx skills add marko-js/marko\n```\n\nOr manually, for Claude Code: copy a skill folder into your project's `.claude/skills/` directory (or `~/.claude/skills/` to enable it globally):\n\n```sh\ncp -r skills/marko-5-to-6-migration YOUR_APP/.claude/skills/\n```\n\nAny agent that supports the `SKILL.md` convention can consume these folders the same way.\n\n## Usage\n\nOnce installed, the agent applies a skill automatically when a request matches its description, or invoke it explicitly (in Claude Code, type `/` plus the skill name). For example, in a Marko 5 project:\n\n```text\n/marko-5-to-6-migration plan an incremental migration of this app\n```\n\n```text\nMigrate this component library to Marko 6 and remove all class components.\n```\n","skills/marko-5-to-6-migration/SKILL.md":"---\nname: marko-5-to-6-migration\ndescription: Migrate Marko 5 (Class API / legacy widget API) applications and component libraries to Marko 6 (Tags API). Use when asked to upgrade Marko, convert class components to tags, remove the Class or widget API, or plan an incremental Marko 6 adoption using the Marko 5 interop layer.\n---\n\n# Marko 5 → Marko 6 Migration\n\nMarko 6 replaces the Class API (`class {}` blocks, `component.js` files, `this.state`, `this.emit`, legacy widgets) with the Tags API (`<let>`, `<const>`, tag variables, function-valued event attributes). `marko@6` is **not** backward compatible: it cannot compile Class API files at all. `marko@5` **is** forward compatible: through the interop layer built into modern `marko@5`, one app compiles Tags API and Class API files side by side, classifying each `.marko` file individually.\n\nThat gives two supported migration strategies. **Confirm with the user which one they want before editing code** (unless they already said):\n\n| Strategy                  | End state                                                                                                                                                              | Choose when                                                                                  |\n| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |\n| **Full migration**        | `marko@6` installed; zero Class/widget API anywhere                                                                                                                    | Small-to-medium codebase, you control all `.marko` sources, one big change is acceptable     |\n| **Incremental migration** | Stays on latest `marko@5`; files convert to Tags API one at a time via interop; app is shippable after every step; ends with the same final flip as the full migration | Large codebase, must keep shipping, third-party Marko 5 tag libraries in use, multiple teams |\n\nHard constraints that force the choice:\n\n- A dependency that ships Class API tags you cannot fork (e.g. `@ebay/ebayui-core`) blocks the final flip to `marko@6`. Use the incremental flow and stay on `marko@5` until every dependency has a Tags API release. For a small straggler module, converting it locally and carrying the diff with [`patch-package`](https://github.com/ds300/patch-package) is often practical — patch, verify, and upstream the conversion.\n- Legacy widget usage (`marko-widgets`, `@marko/compat-v4`, `w-bind`, `defineComponent`) has no interop with Marko 6 and no automated path. Those components must be rewritten to Tags API (or at minimum to the Class API first) in either flow.\n\nThere is **no automatic source-to-source converter** from Class API to Tags API. Every file is converted by hand (by you), using the mapping tables in this skill.\n\n## Reference files\n\nRead these on demand; do not guess at mappings from memory:\n\n- [`api-mapping.md`](./api-mapping.md) — exhaustive Marko 5 → 6 translation tables: template syntax, core tags, the full `Marko.Component` API, legacy widget API, server/template rendering APIs, taglib metadata, TypeScript types. **Read before converting your first file.**\n- [`patterns.md`](./patterns.md) — worked before/after conversions of the common component shapes (stateful, controllable, refs, third-party DOM libraries, attribute tags, `<await>`, split components, legacy widgets).\n- [`interop.md`](./interop.md) — exact file-classification rules, boundary semantics, limitations, and troubleshooting for running both APIs in one app. **Read before any incremental work**, and when debugging \"Cannot mix Tags API and Class API features\" or hydration issues in a mixed app.\n- The Marko 6 cheat sheet (`cheatsheet.md`, shipped with Marko 6) — compact rules for idiomatic Tags API code, including traps the files above don't cover: a top-level `>` in an attribute value silently ends the tag, and native inputs stay uncontrolled until their `*Change` handler is added. **Read before writing Tags API code.** While the app is still on `marko@5` it ships only in its `@marko/runtime-tags` dependency: `node -p \"require.resolve('@marko/runtime-tags/cheatsheet.md', { paths: [require.resolve('marko/package.json')] })\"`. Once on `marko@6` it is `node -p \"require.resolve('marko/cheatsheet.md')\"`, the file compile errors point to.\n\n## Step 1 — Assess\n\nGather facts before proposing anything:\n\n```sh\nnpm ls marko @marko/compiler   # current versions (use the project's package manager: pnpm ls / yarn why)\nfind . -type d \\( -name components -o -name tags \\) -not -path '*/node_modules/*'  # directory conventions in use\n```\n\nInventory the migration surface (run from the project root; counts of affected files). The greps are heuristics for sizing the work, not an exact list — review matches before acting on them, and extend the exclusions to cover this project's build output, docs, and any installed skills:\n\n```sh\ncf() { grep -rlE --exclude-dir={node_modules,.git,dist,build,coverage,.claude} \"$@\" . | wc -l; }  # count files matching\n\n# Class API\ncf '^\\s*class \\{' --include='*.marko'                 # inline class blocks\nfind . -not -path '*/node_modules/*' \\( -name 'component.js' -o -name 'component.ts' \\\n  -o -name 'component-browser.js' -o -name 'component-browser.ts' \\\n  -o -name '*.component.js' -o -name '*.component-browser.js' \\) | wc -l  # external/split components\ncf '^\\$ ' --include='*.marko'                         # $ scriptlets\ncf 'on-[a-zA-Z-]+\\(' --include='*.marko'              # attribute-argument event handlers\ncf 'renderBody' --include='*.marko'\ncf 'this\\.(state|emit|getEl|getComponent|subscribeTo|setState|forceUpdate)'\ncf ':scoped|:no-update|no-update' --include='*.marko'\ncf '<(while|macro|include-text|include-html|module-code|await-reorderer|init-components)' --include='*.marko'\ncf '<await' --include='*.marko'                       # async boundaries (interop-sensitive)\n\n# Legacy widget API (Marko 3/4 era) — must be rewritten in every flow\ncf 'w-bind|w-on-|widget-types|defineComponent|defineWidget|defineRenderer|legacy-components|marko-widgets|@marko/compat-v4'\n\n# Server / rendering API\ncf 'renderSync|renderToString|\\.stream\\(|out\\.global|beginAsync|res\\.marko|marko/node-require|marko/components'\n```\n\nAlso identify: the bundler (lasso / webpack / rollup / vite / `@marko/run` / `browser.json` files), the server integration (`@marko/express`, koa, fastify, raw http), the test setup, and whether TypeScript or `marko.json` `\"script-lang\": \"ts\"` is configured.\n\nReport the inventory to the user together with the recommended strategy, then proceed on the agreed flow.\n\n## Step 2 — Modernize the foundation (both flows, still on Marko 5)\n\nEach of these is an independently shippable change. Verify the app builds and tests pass after each.\n\n1. **Upgrade to the latest `marko@5`** and `@marko/compiler` 5.x. Modern `marko@5` (5.39+) depends on `@marko/runtime-tags` and its `marko/translator` entry _is_ the interop translator, so this alone enables Tags API files — no other configuration.\n2. **Clear existing deprecations** (they become hard errors or dead ends in 6): see \"Already deprecated in Marko 5\" in [`api-mapping.md`](./api-mapping.md). Run the app with `MARKO_DEBUG` / non-production `NODE_ENV` and fix every `complain()` deprecation warning.\n3. **Rewrite legacy widgets** (`defineComponent` / `defineWidget` / `w-bind` / `getInitialState`). Rewrite straight to Tags API when the component is small; otherwise to Class API first so it rides the normal conversion path later. Mapping table: \"Legacy widget API\" in `api-mapping.md`.\n4. **Delete explicit `<init-components/>` and `<await-reorderer/>` tags unconditionally.** Marko 5 injects both implicitly, so explicit usages are already redundant — removing them is safe today and required eventually (both are Class-only signals to the interop classifier).\n5. **Adopt `server` and `client` statements early.** These were backported to Marko 5 (5.38+) and are API-neutral for interop classification, so they work in Class files today. Replace environment guards (`typeof window` checks, browser-only `require`s) and — importantly — any `component-browser.js` that exists only as a glorified bundling trick to keep code out of the server build: `client import \"./browser-only\"` expresses that directly in the template. This shrinks the real migration surface before any API conversion.\n6. **Consider modernizing the bundler.** `@marko/vite`, `@marko/webpack`, `@marko/rollup`, and `@marko/run` all support Marko 5 _and_ 6 (e.g. `@marko/run` declares `\"marko\": \"5 - 6\"`), so this ships while still fully on Marko 5. Lasso also keeps working with Marko 6 — staying on it is viable; you only give up code-splitting of lazy imports (`with { load }` needs the bundler-provided `linkAssets`; without it those imports just load eagerly). `browser.json` component wiring should be retired regardless.\n7. **Baseline**: record SSR output of key pages (curl to files) and make the test suite green. These are your regression oracle.\n\n## Step 3 — Convert files\n\nThe per-file mechanics are identical in both flows; the flows differ in ordering and in when the dependency flips.\n\nFor each `.marko` component (work **leaf-first**, bottom-up):\n\n1. Read _everything_ that makes up the component: `index.marko`, `component.js` / `component-browser.js` (also `.ts` and `*.component[-browser].js` variants), `marko-tag.json`, `browser.json`, adjacent `style.*` files, plus every call site of the tag.\n2. Classify its shape and open the matching worked example in [`patterns.md`](./patterns.md): inert/presentational · stateful · controllable (state initialized from input + change events) · element refs / imperative DOM · third-party library host · attribute tags · async (`<await>`) · split component · legacy widget.\n3. Translate template syntax first, then the component class, using [`api-mapping.md`](./api-mapping.md). Everything from `component.js` / `component-browser.js` folds into the one `.marko` file; delete the JS files, `marko-tag.json` (types move into `export interface Input`), and `browser.json`.\n4. Convert state mutations to **immutable updates** (`items = items.concat(x)`, `obj = { ...obj, k: v }`). Marko 6 reactivity is assignment-driven; `setStateDirty`-style mutation has intentionally no equivalent. Marko 6 serializes to the browser only what client-side code actually references (the compiler computes serialization reasons/intersections per value) — so keep class instances, DOM nodes, and server-only resources out of values that browser code touches.\n5. Update call sites: `on-foo(\"method\")` → `onFoo=fn` function attributes, `renderBody` → `content`, `key=` on loop children → `by=` on `<for>`. In the incremental flow, Class API parents keep working for attributes and body content (the interop bridges `renderBody`/`content` and props automatically), but any `on-foo(\"method\")` bindings on the converted child **must** flip to function attributes in the same change — Class-style event bindings on a Tags API child compile but never fire (see `interop.md`).\n6. Place the file correctly. Incremental flow: converted files should live in a `tags/` directory or contain an unambiguous Tags signal; add a `// use tags` comment to converted route/page files that could be ambiguous. Never leave a file with signals from both APIs — that is a compile error, not a preference.\n7. Verify (Step 4) before moving to the next component.\n\n### Flow A — Full migration finish line\n\nWhen every `.marko` file uses the Tags API and the inventory greps from Step 1 return zero:\n\n1. Rename remaining `components/` directories to `tags/` (Marko 6 discovers relative tags from `tags/` only). For **published tag libraries**, move `marko.json` from `\"tags-dir\"` to `\"exports\"` — `exports` exists only for packages consumed from `node_modules`; `tags-dir` still works in both majors but is discouraged, and apps shouldn't need a `marko.json` at all.\n2. Migrate server entry points and any `template.render(input, cb/stream)` / `renderSync` / `renderToString` / `out.*` usage per \"Template & server API\" in `api-mapping.md`. Remove `marko/components` `init()` calls and `marko/node-require` (→ `@marko/compiler/register`); explicit `<init-components>` / `<await-reorderer>` tags should already be gone from Step 2.\n3. Swap the dependency to `marko@^6` using the project's package manager (npm/pnpm/yarn — detect via the `packageManager` field or the lockfile; e.g. `npm rm marko && npm i marko@^6`). `@marko/compiler` stays 5.x — that is expected; only the `marko` runtime major changes.\n4. Delete now-inert `// use tags` / `// use class` comments, run the full verification suite, and diff SSR output against the Step 2 baseline.\n5. Grep once more for stragglers. Unambiguous Class API tokens must be gone from app code: `renderBody`, `getEl(`, `subscribeTo`, `:scoped`, `no-update`, `<await-reorderer`, `legacy-components`. Broad patterns are review lists, not mandatory zeroes — inspect each match, since they also occur in unrelated code: `key=` (matches `apiKey=` etc.), `\\bout\\.`, `\\bcomponent\\.`, `\\.emit\\(`.\n\n### Flow B — Incremental migration loop\n\nRead [`interop.md`](./interop.md) first. The mechanism that makes per-file adoption safe is the compiler's **Class/Tags feature detection** — each `.marko` file is classified individually, so drive the classification deliberately instead of leaving files ambiguous:\n\n1. Files under a `tags/` directory are seeded **Tags API**.\n2. An exact `// use tags` or `// use class` comment pins a file explicitly.\n3. Class syntax anywhere in the file (a `$ scriptlet`, `class {}`, `style {}` block, attribute arguments like `on-click(\"m\")`, or `<while>`/`<macro>`/`<include-*>`/…) marks it Class; Tags syntax (a tag variable, `:=`, or `<let>`/`<const>`/`<id>`/`<return>`/…) marks it Tags. Signals from **both** APIs in one file are a compile error.\n4. A file with no signals is Tags only when _no_ `components/` directory is discoverable anywhere — otherwise it silently defaults to **Class**.\n\n(Full rules, escape hatches, and troubleshooting: `interop.md`.) In practice: converted and new components go under `tags/`, shells and route files get pinned with a comment when signal-free, and each conversion is completed fully so no file mixes APIs.\n\nThen repeat, in increments sized to one subtree/page per PR:\n\n1. Pick the next subtree (a page or a self-contained component cluster). Prefer converting **whole subtrees** so Tags components mostly reference Tags components — every Class↔Tags boundary costs compat runtime and serialization.\n2. Convert leaf components of that subtree first (inert/presentational ones are nearly free), parents next, using Step 3 mechanics. Route/page/layout files flip last, once their whole subtree is Tags — flipping a shell early maximizes boundary crossings below it.\n3. Do not put an `<await>`/async boundary across the API seam: a pending promise crossing the compat layer throws `Cannot serialize promise across tags/class compat layer`. Resolve async fully on one side.\n4. Ship the increment. Verify SSR + hydration + interactions on the affected pages (Step 4).\n5. When the last Class file is gone, run the Flow A finish line.\n\nNew code during the migration goes in `tags/` directories and uses the Tags API from day one.\n\n## Step 4 — Verify each change\n\n- **Build + typecheck**: run the app build; if TS/jsconfig is set up, run `mtc` (`@marko/type-check`). Format with `prettier` (v3 `prettier-plugin-marko` handles both syntaxes).\n- **Tests**: run the project's suite. `@marko/testing-library` supports both runtimes; update `rerender`-era assertions to reflect that Marko 6 batches updates (await a microtask / use `find*` queries).\n- **SSR parity**: render the affected page server-side and diff against the baseline HTML. Expect attribute-order/comment-marker noise; investigate _content_ differences.\n- **Hydration**: load the page in a browser; check the console for hydration/serialization errors and verify every interaction on the page (clicks, inputs, focus) still works. In mixed apps also confirm Class children inside Tags parents come alive (buttons actually respond, not just render).\n- **Common regressions to hunt**: state that silently stopped updating (mutation instead of assignment), event payload shape changes (`emit(\"change\", a, b)` → single object argument conventions), lost `:scoped` id uniqueness (→ `<id>`), form elements fighting Marko over state (→ change handlers / `:=`), `<select>`/`checked` behavior, and `no-update` regions that relied on Marko _not_ touching third-party DOM (→ `<lifecycle>` owning a container element).\n\n## Renamed / removed quick list\n\nThe ten highest-frequency rewrites (full tables in `api-mapping.md`):\n\n| Marko 5                                                             | Marko 6                                                                           |\n| ------------------------------------------------------------------- | --------------------------------------------------------------------------------- |\n| `$ const x = ...;` scriptlet                                        | `<const/x=...>` (derived) or `<let/x=...>` (mutable)                              |\n| `class { onCreate() { this.state = { n: 0 } } }` + `state.n`        | `<let/n=0>` per state key                                                         |\n| `this.state.n = v` / `setState(\"n\", v)`                             | `n = v` (plain assignment)                                                        |\n| `on-click(\"handleClick\")` / `once-click(...)`                       | `onClick() { ... }` or `onClick=fn`                                               |\n| `this.emit(\"select\", x)`                                            | call `(input.onSelect \\|\\| null)?.(x)` — events become function props             |\n| `<${input.renderBody}/>` / `renderBody`                             | `<${input.content}/>` / `content`                                                 |\n| `key=\"el\"` + `this.getEl(\"el\")`                                     | tag variable `<div/el>` … `el()` (browser getter)                                 |\n| `onMount`/`onUpdate`/`onDestroy`                                    | `<script>` (+ `$signal` for cleanup); `<lifecycle>` only for imperative libraries |\n| `key=` on loop children                                             | `by=` attribute on `<for>`                                                        |\n| `component-browser.js` as a bundling trick / `typeof window` guards | `client import` / `server` statements (backported to Marko 5.38+)                 |\n| `out.global`                                                        | `$global`                                                                         |\n\n## Escalate to the user\n\nStop and ask (with your analysis) when you hit:\n\n- `shouldUpdate`, `update_<state>` handlers, `forceUpdate`-driven flows, or `no-update` regions whose _behavior_ (not just syntax) has no 1:1 equivalent — the replacement is a design decision.\n- Public component APIs consumed by code you can't see (published libraries): event rename (`on-change` → `onChange`) and payload shape changes are breaking for consumers.\n- `out.beginAsync` / manual `out.write` streaming code, custom taglib `transformer`/codegen hooks, or `<module-code>` — these need bespoke redesign.\n- Anything where SSR baseline diffs show content changes you cannot explain.\n","skills/marko-5-to-6-migration/api-mapping.md":"# Marko 5 → Marko 6 API Mapping\n\nExhaustive translation reference. Marko 5 docs: <https://v5.markojs.com/docs/>; Marko 6 docs: <https://markojs.com/docs/> (append `.md` to any page URL for markdown). When unsure about Marko 6 behavior, check the docs — do not guess.\n\n## Template syntax\n\n| Marko 5                                                                                                     | Marko 6                                                                                                   | Notes                                                                                                                                                                                                                        |\n| ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `${expr}`                                                                                                   | `${expr}`                                                                                                 | unchanged (escaped)                                                                                                                                                                                                          |\n| `$!{expr}`                                                                                                  | `$!{expr}`                                                                                                | unchanged (unescaped; same XSS caution)                                                                                                                                                                                      |\n| `$ statement;` / `$ { ... }` scriptlet                                                                      | `<const/x=...>`, `<let/x=...>`, or an IIFE `<const/x=(() => { ... })()>` for multi-statement derivations  | Scriptlets are Class-only. Reassigned-during-render vars usually become a single `<const>` computing the final value                                                                                                         |\n| `static ...` / `static { }`                                                                                 | `static ...` / `static { }`                                                                               | unchanged (module scope, runs once)                                                                                                                                                                                          |\n| env guards (`typeof window` checks, browser-only `require`) and bundling-trick `component-browser.js` files | `server` / `client` statements: `client import \"./browser-only\"`, `server { ... }`                        | backported to Marko 5.38+ and neutral for interop classification — adopt in Class files **before** migrating; a `component-browser.js` that only exists to keep code out of the server bundle is a glorified `client import` |\n| `class { ... }` block                                                                                       | delete; migrate members per \"Component class API\" below                                                   |                                                                                                                                                                                                                              |\n| `style { ... }` / `style.scss { ... }` block                                                                | `<style>` / `<style.scss>` tag                                                                            | Marko 6 `<style>` additionally supports CSS Modules via a tag variable (`<style/styles>` → `styles.foo`) and reactive `${...}` values (compiled to CSS custom properties)                                                    |\n| `import x from \"<my-tag>\"`                                                                                  | unchanged                                                                                                 | Marko 6 adds lazy variant: `import X from \"<my-tag>\" with { load: \"visible#sel\" }`                                                                                                                                           |\n| `export ...`                                                                                                | unchanged                                                                                                 |                                                                                                                                                                                                                              |\n| attribute values `attr=expr`                                                                                | unchanged                                                                                                 | both parse values as JS expressions; in 6 an unparenthesized `>` inside a value is a parse hazard — wrap: `x=(a > b)`                                                                                                        |\n| spread `...expr`                                                                                            | unchanged                                                                                                 |                                                                                                                                                                                                                              |\n| `class=` / `style=` object & array values                                                                   | unchanged                                                                                                 |                                                                                                                                                                                                                              |\n| shorthand `.class` / `#id` (incl. `.icon-${name}`)                                                          | unchanged                                                                                                 |                                                                                                                                                                                                                              |\n| attribute arguments `attr(...)` (e.g. `on-click(\"m\")`, `no-update-if(x)`, `body-only-if(x)`)                | removed — the parenthesized-attribute syntax is Class-only                                                | see rows for each specific attribute                                                                                                                                                                                         |\n| `body-only-if(cond, tagName?)`                                                                              | conditional parent tag: `<${!cond && \"a\"} href=...>content</>`                                            | note the inversion: `body-only-if` drops the wrapper when `cond` is truthy; a falsy dynamic tag name renders content only                                                                                                    |\n| `key=\"name\"` (element/component reference)                                                                  | tag variable: `<div/name>`                                                                                | see \"Refs\" below                                                                                                                                                                                                             |\n| `key=\"name[]\"` (repeated)                                                                                   | tag variable inside `<for>`; iterate the hoisted var (`[...name]`)                                        |                                                                                                                                                                                                                              |\n| `key=expr` on children of `<for>`                                                                           | `by=` attribute on `<for>` itself (`by=\"id\"` or `by=(item) => item.id`)                                   |                                                                                                                                                                                                                              |\n| `on-event(\"method\", ...args)` / `on-event(fn)`                                                              | `onEvent() { ... }` or `onEvent=fn` function attributes                                                   | curried args become closure captures; `on-` dash-case still exists in 6 for case-preserving DOM event names (`on-DblClick`)                                                                                                  |\n| `once-event(...)`                                                                                           | no equivalent attribute                                                                                   | use a conditional handler (`onClick=!done && handler`) or `el().addEventListener(..., { once: true })` in a `<script>`                                                                                                       |\n| `no-update`, `no-update-if(...)`, `no-update-body`, `no-update-body-if(...)`, `attr:no-update`              | removed; updates are granular so most uses are obsolete                                                   | if the intent was \"Marko must not touch third-party-owned DOM\", give the library its own container element managed via `<lifecycle>`; if the intent was \"keep state/DOM alive while hidden\", use `<show>`                    |\n| `attr:scoped` (`id:scoped`, `for:scoped`, ...)                                                              | `<id/name>` tag + plain attributes (`id=name`, `for=name`)                                                |                                                                                                                                                                                                                              |\n| `<tag\\|params\\|>` body parameters                                                                           | unchanged                                                                                                 | Marko 6 adds tag _arguments_: `<${input.content}(a, b)/>` ↔ `<my-tag\\|a, b\\|>`                                                                                                                                               |\n| `<@section>` attribute tags                                                                                 | unchanged syntax; consumed as `input.section.content` (was `.renderBody`); repeated tags iterable in both | Marko 6: attribute tags inside `<if>`/`<for>` apply conditionally/repeatedly; typed with `Marko.AttrTag<T>`                                                                                                                  |\n| `<${dynamic}>` dynamic tags                                                                                 | unchanged                                                                                                 | in 6 a string always renders a _native_ tag; pass the component reference itself for custom tags                                                                                                                             |\n| `<${input.renderBody}/>`                                                                                    | `<${input.content}/>`                                                                                     | `content` also accepts attributes/arguments to pass tag parameters back                                                                                                                                                      |\n| PascalCase variables as tags `<MyTag/>`                                                                     | unchanged                                                                                                 |                                                                                                                                                                                                                              |\n| HTML/JS comments                                                                                            | unchanged (stripped)                                                                                      | literal comment: `<html-comment>` in both                                                                                                                                                                                    |\n| concise mode                                                                                                | unchanged in spirit                                                                                       | see <https://markojs.com/docs/reference/concise-syntax.md> for 6 specifics                                                                                                                                                   |\n| `<!-- use class -->` / `<!-- use tags -->`                                                                  | only meaningful under Marko 5 interop                                                                     | delete after the final flip to `marko@6`                                                                                                                                                                                     |\n\nNew in Marko 6 (no 5 equivalent — reach for these while converting):\n\n- `:=` bound attributes / change handlers (`value:=state`, refining form `value:parseFloat:=num`) — the controllable pattern.\n- Tag variables on custom tags via `<return>`; on native tags they expose a DOM-node getter.\n- `<show>` (toggle visibility, keep state/DOM), `<id>`, `<log>`, `<debug>`, `<define>`, `<try>`, `<lifecycle>`.\n- Controllable native attributes: `<input valueChange= checkedChange= checkedValueChange=>`, `<select value= valueChange=>`, `<textarea value=>`, `<details openChange=>`, `<dialog openChange=>`.\n- `$signal` (an `AbortSignal` for cleanup in any expression) and `$global`.\n- Lazy tag imports `with { load: \"visible|idle|media|on*|render\" }`.\n\n## Core tags\n\n| Marko 5                                     | Marko 6                                                                   | Notes                                                                                                                                              |\n| ------------------------------------------- | ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `<if(cond)>` / `<else-if(cond)>` / `<else>` | `<if=cond>` / `<else if=cond>` / `<else>`                                 | argument syntax → `value` attribute; `else-if` tag name → `else` with `if=` attribute                                                              |\n| `<for\\|item, index, list\\| of=list>`        | `<for\\|item, index\\| of=list>`                                            | third `list` param dropped; add `by=` for keyed diffing                                                                                            |\n| `<for\\|key, value\\| in=obj>`                | unchanged                                                                 |                                                                                                                                                    |\n| `<for\\|i\\| from=x to=y step=z>`             | unchanged; 6 adds exclusive `until=`                                      |                                                                                                                                                    |\n| `<while(cond)>`                             | removed                                                                   | restructure into `<for>` over a computed list/range                                                                                                |\n| `<macro\\|params\\| name=\"foo\">` + `<foo>`    | `<define/Foo\\|input\\|>` + `<Foo>`                                         | params become `input` properties/content                                                                                                           |\n| `<await(promise)>` + `<@then\\|res\\|>`       | `<await\\|res\\|=promise>`                                                  | body is the \"then\"                                                                                                                                 |\n| `<await>` `<@placeholder>`                  | `<try>` ancestor with `<@placeholder>`                                    | placeholder now lives on `<try>`, can wrap several awaits                                                                                          |\n| `<await>` `<@catch\\|err\\|>`                 | `<try>` ancestor with `<@catch\\|err\\|>`                                   |                                                                                                                                                    |\n| `<await client-reorder>`                    | automatic                                                                 | a `<try>` `@placeholder` opts into out-of-order streaming; no flag                                                                                 |\n| `<await timeout= show-after= name=>`        | removed                                                                   | implement timeouts on the promise itself (`AbortSignal.timeout` / `Promise.race`)                                                                  |\n| `<await-reorderer/>`                        | removed                                                                   | already implicitly injected by Marko 5 — explicit usages are redundant; delete unconditionally                                                     |\n| `<include-text('./f.txt')>`                 | bundler raw import (`import text from \"./f.txt?raw\"` in Vite) + `${text}` |                                                                                                                                                    |\n| `<include-html('./f.html')>`                | raw import + `$!{html}`                                                   | audit for XSS while converting                                                                                                                     |\n| `<init-components/>`                        | removed                                                                   | already implicitly injected by Marko 5 — explicit usages are redundant; delete unconditionally (Marko 6 emits hydration boilerplate automatically) |\n| `<module-code>`                             | removed                                                                   | library codegen hook; needs bespoke redesign (compiler hooks)                                                                                      |\n| `<html-comment>`                            | unchanged                                                                 | 6 version also exposes a comment-node tag variable                                                                                                 |\n| `<script>` (plain HTML script)              | `<html-script>`                                                           | in 6, `<script>` is the _effect_ tag (runs in browser, re-runs when referenced state changes)                                                      |\n| `<style>` (plain HTML style)                | `<html-style>`                                                            | in 6, `<style>` extracts to the CSS bundle                                                                                                         |\n| `<context>` (npm package)                   | no equivalent                                                             | pass data through `input` or `$global`                                                                                                             |\n\nIf the app used `@marko/tags-api-preview` (Tags API on Marko 5 before 6 shipped): remove that package; `<let>`/`<const>`/`<return>`/`<define>` carry over, `<effect>` → `<script>`, `<attrs>` → destructuring `<const/{...}=input>` (the Marko 6 compiler auto-fixes these two), and `<get>`/`<set>` context tags must be redesigned onto `input`/`$global`.\n\n## Component class API\n\nThe class (inline `class {}`, `component.js`, `component-browser.js`, or plain-object form) disappears entirely; each member maps to template-level constructs in the one `.marko` file.\n\n### State\n\n| Marko 5                                                     | Marko 6                                                                                                     |\n| ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |\n| `onCreate() { this.state = { a: 1, b: 2 } }`                | `<let/a=1>` `<let/b=2>` — one `<let>` per independently-changing key                                        |\n| read `state.a` / `this.state.a`                             | `a`                                                                                                         |\n| `this.state.a = v` / `setState(\"a\", v)` / `setState({ a })` | `a = v` (assignment is the reactive trigger)                                                                |\n| `setStateDirty(\"list\")` after mutation                      | intentionally no equivalent — make the update immutable: `list = [...list, item]`                           |\n| `replaceState(newState)`                                    | assign each `<let>`                                                                                         |\n| `shouldUpdate(input, state)`                                | none — updates are per-expression; if work must be gated, gate it in the deriving `<const>`/handler         |\n| `update_<name>(new, old)` partial-update handlers           | none — granular updates make them obsolete; side effects on change move to `<script>` reading that variable |\n| `this.forceUpdate()`                                        | none needed; state assignment schedules the update                                                          |\n| `this.update()` (sync flush)                                | none in-template (updates batch after a microtask); tests should await a tick                               |\n\nSerialization in 6 is **need-based, not blanket**: the compiler computes what must cross to the browser from what client-side code references (handlers, `<script>` bodies, reactive expressions, and their intersections) and serializes only that. Values that never reach client code aren't serialized at all. The practical rule while converting: anything browser code touches must be serializable (no class instances, DOM nodes, or server-only resources there) — see <https://markojs.com/docs/explanation/serializable-state.md>.\n\n### Derived data & input\n\n| Marko 5                                                                   | Marko 6                                                  |\n| ------------------------------------------------------------------------- | -------------------------------------------------------- |\n| `$ const full = a + b;`                                                   | `<const/full=a + b>`                                     |\n| `onInput(input) { input.x = normalize(input.x) }` (mutation anti-pattern) | `<const/x=normalize(input.x)>`                           |\n| `onInput` storing input into state (\"controllable\" components)            | `<let/x:=input.x>` — controllable let; see `patterns.md` |\n| `this.input` / template `input`                                           | `input` (unchanged)                                      |\n| template `state` variable                                                 | the individual tag variables                             |\n| template `component` variable                                             | none — every use maps to a specific pattern below        |\n| template `out` variable                                                   | none; `out.global` → `$global`                           |\n\nA Marko 5 getter (`get isFull() { return a + b >= max }`) recomputes on every read, so a handler that assigns `a` then reads `this.isFull` sees the new result. A `<const>` does not: within one handler it still holds its pre-assignment value until the update flushes, while the raw `<let>` reads back the value you just assigned. So after `moves = next`, `moves >= max` is current but a derived `<const/isFull=(moves >= max)>` is not — read the `<let>`s you just assigned (or recompute from them) inside the handler, never the derived `<const>`.\n\n### Lifecycle\n\n| Marko 5                                                                  | Marko 6                                                                                                                    |\n| ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------- |\n| `onMount() { ... }`                                                      | `<script>` (first run = mounted, browser-only) or `<lifecycle onMount() { ... }/>`                                         |\n| `onUpdate()`                                                             | `<script>` re-runs when any referenced tag variable/param changes; or `<lifecycle onUpdate>` (re-runs on its dependencies) |\n| `onDestroy()`                                                            | `$signal.onabort = () => {...}` inside `<script>`; or `<lifecycle onDestroy>`                                              |\n| `onRender(out)`                                                          | usually deleted — it was mostly used for derivations (→ `<const>`)                                                         |\n| `onCreate(input, out)`                                                   | initial values of `<let>` tags                                                                                             |\n| lifecycle _events_ (`this.on(\"update\", fn)`, `this.once(\"destroy\", fn)`) | same replacements as the methods                                                                                           |\n| `on-attach(fn)` on an element                                            | `<script>` or `<lifecycle onMount>` — both run with the element in the DOM                                                 |\n| `on-detach(fn)` on an element                                            | no equivalent — nothing can delay removal (see below)                                                                      |\n\nPrefer plain state and `<script>`; use `<lifecycle>` only to host imperative third-party instances (maps, charts) where a stable `this` across `onMount`/`onUpdate`/`onDestroy` is genuinely needed.\n\nExit animations need rework. Marko 5's `on-detach` handler could hold a node in the DOM (`event.preventDefault()`, then `event.detach()` once the animation finished); nothing in Marko 6 can delay removal — `<lifecycle onDestroy>` only observes teardown, and `<show=false>` parks its nodes in a detached fragment, so a transition never runs. Stage it in state instead: keep the item rendered while marking it exiting (`class={ exiting: id === leavingId }`), then drop it from the list in a `transitionend`/`animationend` handler.\n\n### Events\n\n| Marko 5                                                       | Marko 6                                                                                                                  |\n| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |\n| `this.emit(\"select\", a, b)`                                   | call the function prop: `(input.onSelect \\|\\| null)?.(a, b)` — declare `onSelect?: (a: A, b: B) => void` in `Input`      |\n| parent `<child on-select(\"handleSelect\")>` + class method     | `<child onSelect=handleSelect>` or `<child onSelect(a, b) { ... }>`                                                      |\n| parent `<child on-select(\"emit\", \"select\")>` (re-emit chains) | pass the prop through: `<child onSelect=input.onSelect>`                                                                 |\n| `this.on(...)` / `once` / `removeListener` on a component     | none — components are not emitters; use function props                                                                   |\n| `this.subscribeTo(window).on(\"resize\", fn)`                   | `<script>` + `window.addEventListener(\"resize\", fn, { signal: $signal })`                                                |\n| DOM `on-click(\"method\", extraArg)` on native tags             | `onClick(e) { method(extraArg, e) }` — handler receives the DOM event (and in 6, custom-tag conventions add the element) |\n| state-change notifications via emitted events                 | prefer the controllable pattern (`x` + `xChange`) — <https://markojs.com/docs/explanation/controllable-components.md>    |\n\nThe optional-handler idiom is `(input.onSelect || null)?.(a, b)`: handler attributes may legitimately be _falsy_, not just undefined (conditional handlers like `onClick=!clicked && handler` pass `false`), and `false?.()` still throws — `|| null` coerces any falsy value so the optional call short-circuits.\n\nEvent _naming_: Marko 5 events were dash-case strings (`on-page-change(\"m\")`); Marko 6 props are camelCase functions (`onPageChange=`). For published components this is a breaking API rename — call it out to consumers.\n\n### Refs & DOM access\n\n| Marko 5                                            | Marko 6                                                                                                                                                                                            |\n| -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `key=\"input\"` + `this.getEl(\"input\")`              | `<input/inputEl>` … `inputEl()` (getter; browser-only)                                                                                                                                             |\n| `this.getEls(\"item\")` + `key=\"item[]\"`             | tag variable inside the loop; iterate hoisted: `for (const el of item) ...` / `[...item]`                                                                                                          |\n| `this.el`                                          | tag variable on the root element                                                                                                                                                                   |\n| `this.getElId(...)` / `this.elId(...)` / `this.id` | `<id/myId>` (unique, SSR-stable string)                                                                                                                                                            |\n| `this.getComponent(\"child\")` / `getComponents`     | child exposes an API via `<return={ focus() {...} }>`; parent receives it as a tag variable: `<child/childApi>` … `childApi.focus()`. Often better: controllable props instead of imperative calls |\n| `component.appendTo(el)` etc. (DOM-insert mixins)  | `Template.mount(input, node, position)`                                                                                                                                                            |\n| `this.destroy()`                                   | `instance.destroy()` from `mount()`; inside templates, removal via `<if>`                                                                                                                          |\n| `this.isDestroyed()`                               | none; `$signal.aborted` covers most uses                                                                                                                                                           |\n| `this.rerender(...)` (legacy)                      | input-driven updates / `instance.update(input)`                                                                                                                                                    |\n\n## Legacy widget API (marko-widgets / `@marko/compat-v4`)\n\nNo interop and no automation — rewrite by hand. Mapping for the common members:\n\n| Widget API                                                               | Tags API                                                                                          |\n| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- |\n| `defineComponent({ template, ... })` / `defineWidget` / `defineRenderer` | a single `.marko` file                                                                            |\n| `init(config)` (browser attach)                                          | `<script>` (browser-only by construction)                                                         |\n| `getInitialState(input)`                                                 | `<let>` initial values                                                                            |\n| `getInitialProps(input, out)` / `getTemplateData(state, props)`          | `<const>` derivations from `input`                                                                |\n| `getWidgetConfig()`                                                      | plain values passed via attributes; state that must reach the browser is serialized automatically |\n| `w-bind` / `widget-types`                                                | the component boundary is the file itself                                                         |\n| `w-on-*` handlers                                                        | `onEvent=` function attributes                                                                    |\n| `w-id` / `this.getEl(id)`                                                | tag variables                                                                                     |\n| `widgetBody` / `w-body`                                                  | `content`                                                                                         |\n| `this.setProps(...)` / `this.rerender(...)`                              | input-driven updates from the parent                                                              |\n| `this.state = newState` (replace)                                        | assignments to `<let>` vars                                                                       |\n| jQuery `this.$()` helpers                                                | tag variable + direct DOM APIs (or the library inside `<lifecycle>`)                              |\n\n## Template & server API\n\n| Marko 5                                                                | Marko 6                                                                                                        | Notes                                                                                     |\n| ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |\n| `template.render(input)` (thenable out)                                | `template.render(input)`                                                                                       | 6 result: async-iterable + `.pipe(writable)` + `.toReadable()` + thenable + `.toString()` |\n| `template.render(input, callback)`                                     | `.then()` / `await`                                                                                            | callbacks removed                                                                         |\n| `template.render(input, stream)` / `template.stream(input).pipe(res)`  | `template.render(input).pipe(res)`                                                                             |                                                                                           |\n| `template.renderSync(input)` → `RenderResult`                          | `template.render(input).toString()`                                                                            | throws if anything async — same contract                                                  |\n| `template.renderToString(input)`                                       | `template.render(input).toString()`                                                                            |                                                                                           |\n| `renderResult.appendTo(el)` / `.getComponent()`                        | `template.mount(input, node, position?)` → `{ update(input), destroy(), value }`                               | `value` = the template's `<return>`                                                       |\n| `template.mount(input, el, pos)`                                       | unchanged shape                                                                                                |                                                                                           |\n| `out.global` / `$global`                                               | `$global`                                                                                                      | still passed as `input.$global` at the render call                                        |\n| `$global.serializedGlobals = { key: true }`                            | unchanged                                                                                                      | still the opt-in for serializing globals to the browser                                   |\n| `$global.componentIdPrefix` / `widgetIdPrefix`                         | `$global.renderId`                                                                                             |                                                                                           |\n| `$global.runtimeId` / CSP `cspNonce`                                   | unchanged                                                                                                      |                                                                                           |\n| `out.write(...)`, `out.beginAsync()`, `out.script(...)`, `out.flush()` | removed                                                                                                        | restructure with `<await>`/templates; escalate custom streaming code                      |\n| `require(\"marko/components\").init()` browser bootstrap                 | removed                                                                                                        | bundler plugin emits hydration automatically                                              |\n| `marko/node-require`                                                   | `@marko/compiler/register`                                                                                     | already the guidance in late 5                                                            |\n| `marko/env` (`isDebug`)                                                | none                                                                                                           | use bundler-provided env (`process.env.NODE_ENV`)                                         |\n| express `res.marko(template, input)` (`@marko/express`)                | verify the integration package's Marko 6 support; otherwise `template.render({ ...input, $global }).pipe(res)` | set `content-type` yourself when piping manually                                          |\n\n## Taglib & package metadata\n\n| Marko 5                                                         | Marko 6                                                                                                                                                                                                                                               |\n| --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| relative discovery from `components/`                           | from `tags/` (`tags/NAME.marko`, `tags/NAME/index.marko`, one grouping-folder level allowed)                                                                                                                                                          |\n| `marko.json` `\"tags-dir\": \"./dist/components\"`                  | `marko.json` `\"exports\": \"./dist/tags\"` — for **published `node_modules` tag libraries only**; `tags-dir` still works in both majors but is discouraged, and apps need no `marko.json`                                                                |\n| `marko-tag.json` attribute/nested-tag declarations              | delete; type everything via `export interface Input` (`Marko.AttrTag<T>` for attribute tags)                                                                                                                                                          |\n| `marko-tag.json` compiler hook overrides (`transform`, codegen) | custom compiler work — escalate                                                                                                                                                                                                                       |\n| `browser.json`                                                  | delete; use a modern bundler plugin                                                                                                                                                                                                                   |\n| `marko.json` `\"script-lang\": \"ts\"`                              | unchanged — but it exists for **incremental TS adoption** (opting folders in/out); a project `tsconfig.json` already makes `.marko` files TypeScript, and published packages normally ship compiled `.d.marko` types instead of setting `script-lang` |\n| adjacent `style.css` / `foo.style.css` supporting files         | unchanged                                                                                                                                                                                                                                             |\n\n## TypeScript\n\n| Marko 5                                                   | Marko 6                                                                                       |\n| --------------------------------------------------------- | --------------------------------------------------------------------------------------------- |\n| `export interface Input`                                  | unchanged                                                                                     |\n| `Marko.Component<Input, State>` base class                | removed with the class                                                                        |\n| `State` types                                             | become the inferred/annotated types of `<let>` values                                         |\n| `renderBody?: Marko.Body`                                 | `content?: Marko.Body` (params: `Marko.Body<[Arg1, Arg2]>`)                                   |\n| `Marko.Input<\"button\">`                                   | still exists; `Marko.HTML.Button` etc. is the common spelling for extending native tag inputs |\n| `Marko.AttrTag<T>` / deprecated `Marko.RepeatableAttrTag` | `Marko.AttrTag<T>` (always iterable)                                                          |\n| `Marko.Out`, `Marko.Emitter`, `Marko.RenderResult`        | removed in 6 (available from `marko@5` during interop)                                        |\n| `@marko/type-check` (`mtc`) CLI                           | works for both                                                                                |\n\n## Already deprecated in Marko 5 (clear these first)\n\nThese warn under `MARKO_DEBUG` in Marko 5 and have no future in 6 — fix them while still on 5 (Step 2 of the skill):\n\n- `data` template variable → `input` (auto-fixed by the 5 compiler's migrate stage).\n- `this.els` → `getEls(...)`; `getEl` reaching into child components; `getComponent` with repeated `key[]`; non-string `key` values.\n- `RenderResult.html` → `.toString()`; `RenderResult.context` → `.out`; `getWidget`/`getWidgets` → `getComponent`/`getComponents`.\n- `<await>` with a callback argument → pass a promise.\n- String values for spread/dynamic attributes → objects.\n- `marko/compiler` → `@marko/compiler`; `marko/node-require` → `@marko/compiler/register`.\n- `browser.json` `require:` paths → `marko-dependencies:` (or better: leave `browser.json` behind entirely).\n","skills/marko-5-to-6-migration/interop.md":"# Marko 5 ↔ 6 Interop (Incremental Migration)\n\nHow one Marko 5 app runs Class API and Tags API files together, and how to migrate through that state without regressing. Official doc: <https://markojs.com/docs/guide/marko-5-interop.md>. Source of truth for classification: `packages/runtime-tags/src/translator/interop/feature-detection.ts` in the marko repo.\n\n## Mental model\n\n- The interop is a **coexistence layer, not a converter**. The compiler classifies each `.marko` file as Class or Tags, compiles it with the matching translator, and inserts a runtime compat shim wherever a component of one API is rendered from a file of the other.\n- Classification is **per file** and all-or-nothing. A file cannot mix APIs; conflicting signals are a **compile error** (\"Cannot mix Tags API and Class API features in the same file\", with code frames pointing at both offending features). The heuristics are not a precedence list that picks a winner.\n- Pages that contain both APIs ship **both runtimes** and hydrate twice (a Marko 6 `init` and a Marko 5 `init`). Each Class↔Tags boundary also serializes extra scope-mapping data. This is fine as a transition state and wrong as an end state — keep boundaries few, and prefer converting whole subtrees.\n\n## Enabling\n\nNothing to configure. Modern `marko@5` (5.39+) depends on `@marko/runtime-tags` and its `marko/translator` entry wraps the Class translator with the interop translator. An app whose only Marko runtime dependency is `marko` (v5) gets interop automatically; an app that depends only on `@marko/runtime-tags`/`marko@6` gets **no** Class support.\n\nLazy tag imports (`with { load: ... }`) additionally rely on the `linkAssets` compiler option, which the bundler integrations (`@marko/vite`, `@marko/run`, `@marko/webpack`) provide — not something to set by hand. Lasso works with both APIs but does not provide `linkAssets`, so on it a `with { load }` import compiles as a normal eager import rather than code-splitting.\n\n## File classification rules\n\nEvaluated per file:\n\n1. **`tags/` directory seed.** A file under a `tags/` directory is seeded as Tags API — unless a `components/` directory sits _between_ the `tags/` dir and the file (`tags/components/x.marko` is _not_ seeded; this is the escape hatch for vendored Class code inside a tags tree), or that `tags/` dir is declared as a manual `tagsDir` in a `marko.json`.\n2. **Body scan.** The whole template (including nested tag bodies and attribute tags) is scanned in document order; every signal found is recorded, and signals from both APIs anywhere in one file are the mixing compile error.\n   - **Class signals**: a `// use class` / `<!-- use class -->` comment (exact trimmed match); a non-`static` `$ scriptlet;`; a `class {}` block; a `style { ... }` / `style.ext { ... }` block; any attribute _argument_ (`onClick(\"handler\")`, `no-update-if(x)`); one of these tags: `<await-reorderer>` `<class>` `<include-html>` `<include-text>` `<init-components>` `<macro>` `<module-code>` `<while>`.\n   - **Tags signals**: a `// use tags` / `<!-- use tags -->` comment; any tag variable (`<div/el>`); any bound attribute (`:=`); one of these tags: `<const>` `<debug>` `<define>` `<id>` `<let>` `<lifecycle>` `<log>` `<return>` `<try>`.\n   - `static`, `server`, and `client` statements and plain `<style>` elements are neutral — they force nothing and work in both APIs (`server`/`client` were backported to Marko 5.38+).\n3. **Ambiguous fallback.** A file with no signals (pure markup) is Tags **only if** every tag-discovery directory visible from it is a `tags/` dir; if even one `components/` dir exists anywhere in scope, ambiguous files default to **Class**. In a typical migrating app (which still has `components/` dirs), every ambiguous file is Class — so converted-but-signal-free files silently compile as Class. Pin such files with `// use tags`.\n\nPractical rules that follow:\n\n- Put every new/converted Tags file under a `tags/` directory, or make sure it contains a real Tags signal, or add `// use tags`.\n- When converting a file, convert it **completely** — one leftover `$ scriptlet` or `key=\"x\"` handler argument next to a new `<let>` is a build break, and one leftover neutral file is a silent Class fallback.\n- Route files (`+page.marko`, `+layout.marko`, express-rendered page templates) are frequently ambiguous — pin them explicitly in both directions during the transition.\n\n## Crossing the boundary\n\n### Tags parent → Class child\n\nUse the Class tag like any custom tag. The compat shim translates automatically:\n\n- Attributes pass through as the child's `input`.\n- The Tags body becomes the child's `input.renderBody`.\n- `onFoo=fn` / `onFoo(){}` / `on-foo(){}` attributes are converted to Class custom-event subscriptions: the child's `this.emit(\"foo\", a, b)` invokes the function with `(a, b)`. (`onClick` → event `\"click\"`, `on-Foo` → event `\"Foo\"` preserving case.)\n- Tag parameters work: `<class-layout|a, b|>` receives what the Class child passes via `<${input.renderBody}(a, b)/>`.\n- Split components (`component-browser.js`) hydrate and stay interactive.\n- A Class child with _no_ component (no `class {}`, no state, no handlers — an \"inert\" template) costs almost nothing: it renders on the server and is dropped from client bundles unless a Tags-side update forces re-render (in which case the compat morphs its DOM in place).\n\nYou cannot use Class-only _syntax_ on the call site (it's a Tags file): no `on-foo(\"stringMethod\")`, no `key=`-based `getComponent` into the child. If the parent needs to call into the child imperatively, that child is a good next conversion candidate (then expose `<return>`).\n\n### Class parent → Tags child\n\nAlso plain custom-tag usage, with these rules:\n\n- Attributes pass through as `input`; the Class body becomes the child's `input.content` (renamed from `renderBody` by the shim); attribute tags and tag parameters cross over.\n- Pass event handlers as **function-valued attributes** — the Tags child just calls `input.onSelect(...)`. Both of these compile and work in a Class API file (verified):\n  - `<tags-child onSelect(sel) { component.handleSelect(sel) }/>` (method shorthand — it is not a Class/Tags classification signal)\n  - `<tags-child onSelect=component.handleSelect.bind(component)/>`\n- **Do not use Class-style event bindings on Tags children.** `<tags-child on-select(\"handleSelect\")/>` compiles without error but never fires: it registers a Class custom-event subscription, and Tags components call function props instead of emitting events. This is a silent dead binding — audit for it when converting a child that Class parents consume.\n- Dynamic tags work, including conditional ones: `<${state.show && TagsChild}/>`.\n- Hydration needs no explicit wiring: Marko 5 injects its init/reorderer boilerplate implicitly, and on mixed pages the interop entry emits both hydrate programs. Explicit `<init-components/>` / `<await-reorderer/>` tags in templates are redundant — delete them on sight (they are also Class-only classification signals, so they block converting the file they sit in).\n\n### Hard limitations\n\n- **No async across the seam.** A pending promise (an `<await>` still unresolved) crossing the compat boundary throws `Cannot serialize promise across tags/class compat layer` at render time. Keep each `<await>` and everything it feeds on one side of the boundary.\n- **No shared component registry.** `getComponent`/`getComponents` cannot see Tags children; Tags tag variables cannot point at Class children (no `<return>` there). Communicate across the seam with attributes and function props only.\n- **`$global` / `out.global` is shared** — that part crosses cleanly in both directions.\n- Both runtimes ship while mixed; treat bundle size regressions during migration as expected and temporary, but budget them.\n\n## Incremental order of work\n\n1. **Foundation** (see SKILL.md Step 2): latest `marko@5`, modern bundler, deprecations cleared, legacy widgets rewritten, baseline recorded.\n2. **Create `tags/` directories** next to existing `components/`. This is non-disruptive: ambiguous files still default to Class as long as any `components/` dir exists.\n3. **Convert leaf components first** — inert/presentational ones are nearly free, then stateful leaves. Their Class parents keep consuming them through the shim without changes (though renamed events — `on-select` → `onSelect=` — do require touching call sites; do parent call-site edits in the same increment).\n4. **Work subtree-by-subtree, bottom-up**, so that Tags components mostly reference Tags components. A good increment: one page's component cluster, converted leaves-to-root, parents last.\n5. **Flip pages/layouts last.** Once a page's subtree is all Tags, convert the page file and pin it with `// use tags` if it ends up signal-free.\n6. **Bridge unconverted third-party stragglers with [`patch-package`](https://github.com/ds300/patch-package)** when practical: convert the small blocking module inside `node_modules`, commit the patch, and upstream the change — this keeps the final flip unblocked without forking.\n7. **Track the remaining Class surface** with the Step 1 inventory greps after each increment; the numbers only go down.\n8. When zero Class files remain, run the full-migration finish line (swap to `marko@6`, rename `components/` → `tags/`, remove pin comments and interop-era workarounds).\n\nDuring the whole period: new features are written Tags-first in `tags/`, and no new Class API code gets merged.\n\n## Troubleshooting\n\n| Symptom                                                                         | Cause                                                                                                                                                       | Fix                                                                                                                               |\n| ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |\n| `Cannot mix Tags API and Class API features in the same file` (two code frames) | leftover Class syntax in a converted file (scriptlet, `style {}`, attribute argument, `<macro>`/`<while>`/...) or a Tags construct pasted into a Class file | finish the conversion; the two frames point at the exact conflicting features                                                     |\n| Converted file renders but behaves like Class / new syntax rejected             | file is ambiguous and fell back to Class (a `components/` dir exists somewhere in scope)                                                                    | move under `tags/` or add `// use tags`                                                                                           |\n| File under `tags/` refuses Tags syntax                                          | a `components/` segment between the `tags/` dir and the file, or that dir is a `marko.json` `tagsDir`                                                       | check the full path and `marko.json`s up the tree                                                                                 |\n| `Cannot serialize promise across tags/class compat layer`                       | `<await>`/async content crossing the API boundary                                                                                                           | resolve the promise fully on one side; move the `<await>` into the same API as the content it wraps                               |\n| Class child inside Tags parent renders but is dead (no events)                  | its hydration was skipped — often it looked inert (no serialize reason)                                                                                     | upgrade `marko` — this had fixes in 5.39.x; confirm the child actually has a component; report upstream if reproducible on latest |\n| Tags child inside Class page doesn't hydrate                                    | bundler entry isn't the interop hydrate output (both `init` programs are emitted by the interop entry builder, not by any template-level tag)               | check the bundler integration is current and the page's hydrate entry is generated by it                                          |\n| `with { load }` component loads eagerly instead of code-splitting               | no `linkAssets` (eg `@marko/vite` with `linked: false`, or lasso), so lazy loading degrades to an eager import                                              | use `@marko/vite` (linked)/`@marko/run`/`@marko/webpack` to code-split; the eager fallback is otherwise harmless                  |\n| Duplicate/large client bundles                                                  | both runtimes on the page (expected while mixed); or boundaries scattered across many small islands                                                         | consolidate: convert whole subtrees; finish the migration                                                                         |\n","skills/marko-5-to-6-migration/patterns.md":"# Conversion Patterns\n\nWorked Marko 5 → Marko 6 conversions for the recurring component shapes. Each shows the Class API original, the Tags API result, and the traps. Combine as needed — real components mix several shapes.\n\n## Stateful component\n\n```marko\n/* marko 5 */\nclass {\n  onCreate() {\n    this.state = { count: 0 };\n  }\n  increment() {\n    this.state.count++;\n  }\n}\n\n<button on-click(\"increment\")>\n  Count: ${state.count}\n</button>\n```\n\n```marko\n/* marko 6 */\n<let/count=0>\n\n<button onClick() { count++ }>\n  Count: ${count}\n</button>\n```\n\nOne `<let>` per independently-updating state key. Reads of `state.x` become `x`; writes become plain assignment. Methods that only served as event handlers become inline handlers or `<const/fn() { ... }>` when shared.\n\n**Trap:** mutation. `this.state.list.push(x)` + `setStateDirty(\"list\")` must become `list = [...list, x]` — in Marko 6 only assignment triggers updates, and there is deliberately no dirty-marking escape hatch.\n\n## Derived values\n\n```marko\n/* marko 5 */\n$ const total = input.items.reduce((sum, item) => sum + item.price, 0);\n$ const formatted = total.toFixed(2);\n<div>Total: $${formatted}</div>\n```\n\n```marko\n/* marko 6 */\n<const/total=input.items.reduce((sum, item) => sum + item.price, 0)>\n<const/formatted=total.toFixed(2)>\n<div>Total: $${formatted}</div>\n```\n\nMulti-statement scriptlets that build one value collapse into an IIFE: `<const/list=(() => { ...; return list })()>`. Components that \"normalized\" input by mutating it in `onInput(input)` become `<const>` derivations — never mutate `input`.\n\nDestructuring input is the standard opener of a converted file:\n\n```marko\n<const/{ label, disabled = false, ...restAttrs } = input>\n```\n\n## Controllable state (state initialized from input + change events)\n\nThe Class API pattern of copying input into state and emitting on change:\n\n```marko\n/* marko 5 */\nclass {\n  onCreate(input) {\n    this.state = { open: input.open || false };\n  }\n  onInput(input) {\n    this.state.open = input.open || false;\n  }\n  toggle() {\n    this.setState(\"open\", !this.state.open);\n    this.emit(\"toggle\", { open: this.state.open });\n  }\n}\n\n<button on-click(\"toggle\")>Toggle</button>\n<if(state.open)>\n  <div>Drawer content</div>\n</if>\n```\n\nbecomes a controllable `<let>`:\n\n```marko\n/* marko 6 */\nexport interface Input {\n  open?: boolean;\n  openChange?: (open: boolean) => void;\n}\n\n<let/open=input.open || false valueChange=input.openChange>\n\n<button onClick() { open = !open }>Toggle</button>\n<if=open>\n  <div>Drawer content</div>\n</if>\n```\n\nWhen no default/transform is needed, the shorthand `<let/open:=input.open>` is equivalent. Semantics: with no `openChange` from the parent, the component owns its state (uncontrolled); when the parent passes `openChange`, the parent owns it (controlled) and `open` tracks `input.open`.\n\nCall sites:\n\n```marko\n/* parent.marko (marko 5, via interop) */\n<drawer open=state.drawerOpen openChange(open) { component.handleOpenChange(open) }/>\n```\n\nNote the Class API parent passes `openChange` as a **function attribute** — the converted child reads `input.openChange` and emits no events, so a Class-style `on-open-change(\"handleOpenChange\")` binding would compile but never fire (see `interop.md`).\n\n```marko\n/* parent.marko (marko 6) */\n<let/drawerOpen=false>\n<drawer open:=drawerOpen/>\n```\n\n**Traps:** name the change handler `<prop>Change` (that is what `:=` desugars to — `openChange`, `valueChange`); a differently-named event (`on-toggle`) forfeits the shorthand. Marko 5 events conventionally wrapped payloads (`{ originalEvent, open }`) — Marko 6 passes plain arguments; document the new signature for consumers.\n\n## Element refs and focus\n\n```marko\n/* marko 5 */\nclass {\n  focusName() {\n    this.getEl(\"name\").focus();\n  }\n}\n\n<input key=\"name\" placeholder=\"Name\"/>\n<button on-click(\"focusName\")>Focus</button>\n```\n\n```marko\n/* marko 6 */\n<input/nameInput placeholder=\"Name\">\n<button onClick() { nameInput().focus() }>Focus</button>\n```\n\nThe tag variable is a **getter function** (`nameInput()`), browser-only. For repeated elements (`key=\"opt[]\"` + `getEls(\"opt\")`), the hoisted variable is iterable:\n\n```marko\n<for|opt, i| of=input.options>\n  <input/optEl value=opt>\n</for>\n\n<button onClick() {\n  for (const el of optEl) console.log(el.value);\n  [...optEl][0]?.focus();\n}>Read all</button>\n```\n\n`getElId()` / `id:scoped` uses become the `<id>` tag:\n\n```marko\n<id/inputId>\n<label for=inputId>Name</label>\n<input id=inputId>\n```\n\n## Global listeners, timers, effects\n\n```marko\n/* marko 5 */\nclass {\n  onMount() {\n    this.subscribeTo(window).on(\"resize\", this.onResize.bind(this));\n    this.timer = setInterval(() => this.tick(), 1000);\n  }\n  onDestroy() {\n    clearInterval(this.timer);\n  }\n  onResize() { this.setState(\"width\", window.innerWidth); }\n  tick() { this.setState(\"now\", Date.now()); }\n}\n```\n\n```marko\n/* marko 6 */\n<let/width=0>\n<let/now=Date.now()>\n\n<script>\n  window.addEventListener(\"resize\", () => { width = window.innerWidth }, { signal: $signal });\n\n  const timer = setInterval(() => { now = Date.now() }, 1000);\n  $signal.onabort = () => clearInterval(timer);\n</script>\n```\n\n`<script>` runs in the browser after mount and **re-runs whenever a tag variable it references changes**; `$signal` aborts on cleanup (before re-run and on removal). Keep effect scripts free of incidental state reads or they re-run more than intended — split unrelated effects into separate `<script>` tags.\n\n## Third-party imperative libraries\n\nWhen an instance must persist across updates (charts, maps, editors), `<script>` re-running is the wrong shape — use `<lifecycle>`:\n\n```marko\n/* marko 5 */\nclass {\n  onMount() {\n    this.chart = new Chart(this.getEl(\"canvas\"), { data: this.input.data });\n  }\n  onUpdate() {\n    this.chart.setData(this.input.data);\n  }\n  onDestroy() {\n    this.chart.destroy();\n  }\n}\n\n<canvas key=\"canvas\"/>\n```\n\n```marko\n/* marko 6 */\nclient import { Chart } from \"chart-lib\"\n\n<canvas/canvas/>\n<lifecycle\n  onMount() {\n    return { chart: new Chart(canvas(), { data: input.data }) };\n  }\n  onUpdate() {\n    this.chart.setData(input.data);\n  }\n  onDestroy() {\n    this.chart.destroy();\n  }\n/>\n```\n\n`this` is stable across the three hooks; `onMount`'s returned object merges into it. `onUpdate` re-runs when its own referenced dependencies change. The `client import` keeps the library out of the server bundle (replaces `component-browser.js` tricks).\n\n## Attribute tags (named/nested content)\n\n```marko\n/* marko 5: my-menu.marko + marko-tag.json declaring \"@item\" */\n<ul>\n  <for|item| of=input.item>\n    <li on-click(\"handleSelect\", item.value)>\n      <${item.renderBody}/>\n    </li>\n  </for>\n</ul>\n```\n\n```marko\n/* marko 6: my-menu.marko (marko-tag.json deleted) */\nexport interface Input {\n  item?: Marko.AttrTag<{\n    value: string;\n    content?: Marko.Body;\n  }>;\n  onSelect?: (value: string) => void;\n}\n\n<ul>\n  <for|item| of=input.item>\n    <li onClick() { (input.onSelect || null)?.(item.value) }>\n      <${item.content}/>\n    </li>\n  </for>\n</ul>\n```\n\nCall sites are unchanged (`<my-menu><@item value=\"a\">A</@item>...</my-menu>`). The type declarations from `marko-tag.json` (`\"@item <item>[]\"`, attribute lists) move into `Input` with `Marko.AttrTag<T>`; repeated tags are consumed by iterating the singular property. `(input.onSelect || null)?.(...)` is the standard optional-handler call — handler props may be conditionally _falsy_, and `false?.()` would throw.\n\n## Async content (`<await>`)\n\n```marko\n/* marko 5 */\n<await(getUser()) client-reorder>\n  <@placeholder>Loading…</@placeholder>\n  <@then|user|>Hi ${user.name}</@then>\n  <@catch|err|>${err.message}</@catch>\n</await>\n```\n\n```marko\n/* marko 6 */\n<try>\n  <await|user|=getUser()>\n    Hi ${user.name}\n  </await>\n\n  <@placeholder>Loading…</@placeholder>\n  <@catch|err|>${err.message}</@catch>\n</try>\n```\n\nThe body of `<await>` is the \"then\"; placeholder and error handling move to a wrapping `<try>` (which may cover several awaits). A `@placeholder` opts the section into out-of-order streaming automatically — `client-reorder`, `<await-reorderer>`, `timeout=`, and `show-after=` are removed (implement timeouts on the promise itself, e.g. `AbortSignal.timeout`). Explicit `<await-reorderer/>` (and `<init-components/>`) tags were implicitly injected by Marko 5 anyway — delete them unconditionally, even before migrating.\n\n**Interop trap:** while mixed 5/6, keep an `<await>` and the components it renders on the same side of the Class/Tags boundary — pending promises cannot cross it.\n\n## Split components (`component-browser.js`)\n\nMarko 5 split components separate server-safe rendering from browser behavior:\n\n```text\ncomponents/fancy-toggle/\n  index.marko            # template + component.js lifecycle\n  component-browser.js   # onMount/onUpdate + handlers, browser-only bundle\n```\n\nSplit components exist for two different reasons — treat them differently:\n\n1. **A glorified `client import`.** Many `component-browser.js` files carry no real lifecycle logic; they exist only to keep browser-only code out of the server bundle. Replace these directly with a `client import` in the template — even **before** migrating, since `server`/`client` statements were backported to Marko 5 (5.38+) and are neutral for interop classification:\n\n   ```marko\n   client import \"./browser-only-setup\"\n   ```\n\n2. **Real browser lifecycle** (`onMount`/`onUpdate` + handlers). These collapse into `index.marko` during conversion. There is nothing to preserve about the split itself: targeted compilation already generates separate server/client outputs per template, and only the reactive/handler code ships to the browser.\n\nEither way the end state is one `.marko` file: browser-only imports become `client import`, server-only ones `server import`. Convert the template plus _both_ JS files as one unit using the patterns above, then delete the JS files.\n\n## Parent calls child methods (`getComponent`)\n\n```marko\n/* marko 5 parent */\nclass {\n  reset() {\n    this.getComponent(\"picker\").setColor(\"#ffffff\");\n  }\n}\n<color-picker key=\"picker\"/>\n<button on-click(\"reset\")>Reset</button>\n```\n\nMarko 6 children export an API with `<return>`, received as a tag variable:\n\n```marko\n/* color-picker.marko (marko 6) */\n<let/color=\"#ff8000\">\n<input type=\"color\" value:=color>\n<return={ setColor(c) { color = c } }/>\n```\n\n```marko\n/* parent.marko (marko 6) */\n<color-picker/picker/>\n<button onClick() { picker.setColor(\"#ffffff\") }>Reset</button>\n```\n\nBefore reaching for this, check whether the controllable pattern (`color:=`) removes the need for imperative calls entirely — it usually does.\n\n## Legacy widgets (marko-widgets / `@marko/compat-v4`)\n\n```js\n// marko 5-era legacy widget (widget.js)\nmodule.exports = require(\"marko-widgets\").defineComponent({\n  template: require(\"./template.marko\"),\n  getInitialState(input) {\n    return { expanded: !!input.expanded };\n  },\n  init() {\n    this.el.classList.add(\"ready\");\n  },\n  handleHeaderClick() {\n    this.setState(\"expanded\", !this.state.expanded);\n  },\n});\n```\n\nRewrite directly as one Tags API file — the same shapes apply: `getInitialState` → `<let>` initials, `getTemplateData`/`getInitialProps` → `<const>`, `init()` → `<script>`, `w-on-*`/`w-id` in the template → `onEvent=` handlers and tag variables, `w-body` → `content`. There is no interop for widgets, so this rewrite cannot be deferred in either migration flow. For sprawling widgets, an intermediate rewrite to the Class API (which _does_ interop) is acceptable to unblock the incremental flow, but budget the second pass.\n","skills/marko-best-practices/SKILL.md":"---\nname: marko-best-practices\ndescription: Apply Marko syntax and best practices when editing `.marko` files and building Marko components.\n---\n\n# Marko Best Practices\n\nMarko is a modern UI framework for building web applications. It features a declarative component-based syntax, fine-grained reactivity, and a highly optimized compiler. Marko is designed for both server-rendered and interactive client-side experiences with a focus on streaming, partial hydration, and shipping the smallest possible amount of JavaScript to each page.\n\n## Marko Documentation\n\nThe Marko documentation is the source of truth for all Marko-related information. Always refer to the official docs for information about syntax and behavior. Marko changes over time, so prefer fetching current docs over relying on training data.\n\nThe [docs index](https://markojs.com/llms.txt) lists every available page with its URL and a short description.\n\nAll Marko docs pages can be fetched as markdown by appending `.md` to the URL (<https://markojs.com/docs/introduction/getting-started.md>)\n\n## Marko 6 Syntax\n\nDocumentation and this skill target **Marko 6**. Do not use Marko 5 syntax.\n\n## Checklist for New or Edited .marko Files\n\n- [ ] Uses Marko 6 syntax only (no scriptlets, old event syntax, or Marko 5 blocks).\n- [ ] `<script>` is never used when state (`<let>` or `<const>`) could accomplish the same behavior.\n- [ ] Event handlers use function form: `onClick() { ... }` or a reference, not string names.\n- [ ] `<show=cond>` for toggled content that should keep its state; `<if>` destroys and rebuilds.\n- [ ] Component stays small and readable; consider splitting large templates.\n- [ ] No unnecessary client-side JS; prefer built-in browser APIs and HTML/CSS features over scripts.\n- [ ] Props are declared with an exported `Input` interface, and templates are type checked with `mtc` (`@marko/type-check`) — `tsc` skips `.marko` files and reports nothing.\n"},"files":{"AGENTS.md":"# Marko Monorepo\n\nMarko compiles `.marko` templates into optimized server (streaming HTML) and client (fine-grained DOM) JavaScript. pnpm workspaces; Node >= 22.18 (native TS type stripping + module.registerHooks). Primary development happens in `packages/runtime-tags`.\n\n## Packages\n\n- [`packages/compiler`](packages/compiler/AGENTS.md) — `@marko/compiler`. Translator-agnostic: parses `.marko` into a (patched) Babel AST, then hands off to a translator for codegen.\n- [`packages/runtime-tags`](packages/runtime-tags/AGENTS.md) — `marko@6` / `@marko/runtime-tags`. The Marko 6 runtime **and** its translator. **Primary development.**\n- [`packages/runtime-class`](packages/runtime-class/AGENTS.md) — `marko@5` (private package, published only as `marko`). Marko 5, in maintenance; its translator wraps the class-API translator with runtime-tags' interop layer.\n\nA \"translator\" is the Babel-plugin half of a runtime package; the compiler loads it as `<pkg>/translator`. \"Marko 6\" is the runtime-tags version — the compiler stays 5.x.\n\n## Commands\n\nAll from repo root. Tests and tooling run directly from TS source (native Node type stripping plus the `~ts` resolve hook for extensionless imports; package `exports` point at `src/` until publish), so no build step is needed to iterate.\n\n```sh\npnpm test                                                 # whole suite fanned across CPU cores (~3x faster than serial)\npnpm test -- --grep \"runtime-tags/translator <fixture> \"  # scoped test run\npnpm run test:serial -- --grep \"...\"                      # same run in one process: bail at first failure, live output, --inspect-brk\npnpm test -- <file.test.ts>                               # only the given spec files (dirs and globs work too)\npnpm run test:update -- --grep \"...\"                      # regenerate snapshots (review the diff!)\npnpm run compile -- -o dom -d foo.marko                   # print compiled output (-o html for SSR; omit -d for optimized)\npnpm run build                                            # all packages -> dist/ + .d.ts\npnpm run build:sizes                                      # bundle-size table; diffs vs .sizes.json\npnpm run lint                                             # oxlint + oxfmt check\npnpm run format                                           # oxlint --fix + oxfmt write\npnpm run change                                           # add a changeset (required for user-facing changes)\n```\n\n`pnpm run compile` is the fastest way to inspect what the translator generates. It writes nothing: each compiled module, and then any module the translator generates for it, prints to stdout under a `// <resolved path>` header. (Pass `-t class` for the Marko 5 translator; `-t` also accepts a full translator module id.)\n\n`pnpm run change` prompts, so write `.changeset/<name>.md` directly, naming the package that owns the changed code: `packages/compiler` is `@marko/compiler`, `packages/runtime-tags` is `@marko/runtime-tags`, `packages/runtime-class` is `marko`. `pnpm exec changeset status` fails on a name that is no workspace package (which would break the release on `main`), but not on the wrong one: `marko` for a runtime-tags fix passes and publishes the wrong package. Restricting behavior that was already broken is a fix (`patch`), never described as a breaking change.\n\n## Repo invariants\n\n- **Dependencies are patched.** `patches/` (applied by pnpm patchedDependencies on install) adds Marko AST node types to `@babel/types`/`traverse`/`generator`, and makes mocha print the `require()` error it otherwise drops when its `import()` fallback rescues a spec. The Babel patches only add Marko AST support; never patch Babel's own behavior. Import Babel only via `@marko/compiler/internal/babel` and helpers via `@marko/compiler/babel-utils`, never `@babel/*` directly. Bumping any patched dependency requires regenerating its patch.\n- **Bundle size is a feature.** The pre-commit hook runs lint-staged, a full build, and `build:sizes`, staging `.sizes.json`/`.sizes/` — that diff is the size impact of the change. Commits are slow by design. The floor is `.sizes/counter.ssr` and `.sizes/comments.ssr` (a resumed page with no async, reorder, lazy, or dynamic html): code for an optional feature, even one `?.`, must fold out of them. Lint rules whose fix rewrites runtime code into larger output stay off in `.oxlintrc.json` (`unicorn/prefer-string-starts-ends-with`, `unicorn/no-new-array`); enabling one means checking `build:sizes` first.\n- **Snapshots and sizes are generated.** Never hand-edit _or delete_ `__snapshots__/**`, fixture `sizes.json`, or `.sizes*`; regenerate with `pnpm run test:update` (which also prunes stale snapshots after a green run) and the commit hook.\n- **CI** (`.github/workflows/ci.yml`): build + lint on Node 26; tests on Node 22/24/26 (zcov coverage). Releases go out via changesets on push to `main`.\n\n## Conventions\n\nOrganize files top-down (progressive disclosure): public API/exports first, then orchestration, helpers, and low-level detail last — use function-declaration hoisting.\n\nComments are a last resort and never exceed two lines: prefer self-describing code, and when one is needed it captures intent — never what the code was or what was removed. Wording is plain and direct, with no invented shorthand.\n\nDerive before adding. Before a new field, flag, helper, state container, parameter, test config, or module, find the existing analysis, helper, or runtime structure that already answers it and extend that. A parallel mechanism for one feature (one the rest of the code never needed) is a smell: say in the summary why nothing existing fits.\n\nEvery line needs a reason you can name. No guards, `?.`, fallbacks, casts (`as never`, `as any`, or one the type already satisfies), or parameters for states the design rules out; lean on the invariant (`!`, or a `MARKO_DEBUG` assert). Name checks, dependency method overrides, and machine heuristics are hacks: find the structural fix. A perf or config knob ships only with a measured win, and never restates a default. Measure performance on the bundled build that ships (`pnpm run build`), not the TS source that tests and tooling run: V8 inlines the bundle's module-level function declarations but not those of an ES module, so source timings can mislead.\n\nDon't bend the code around an edge case. Input the design has no reason to support (a `NaN` loop key, say) gets a compile error or a `MARKO_DEBUG` error that rules it out, not runtime handling that every caller pays for in size or speed. Harden the invariant, then rely on it.\n\nWrite the direct form. No rest or spread to copy, extend, or strip an object: share one record, or key a collection by the field it lacks. Client runtime code, where bundle size comes first, may keep a spread that `build:sizes` shows is smallest, but it is still a red flag to justify. No function that only forwards, and no type named for a single use. A helper every caller guards takes the `undefined` itself, and a flag is set as `flag ||= condition`.\n\nDon't add Babel `NodePath` helper calls (`findParent`, `find`, `getFunctionParent`, …): walk `parentPath` and compare node types directly; existing uses are migrated later.\n\nNames come from the code. Reuse the vocabulary of neighboring code, [`CONTEXT.md`](packages/runtime-tags/CONTEXT.md), and the markojs.com docs; never coin a term the codebase does not already use.\n\nTest through existing fixture families; add a test file only when no fixture can reach the behavior. A fix adds a fixture that fails without it, and so does every branch or statement a change adds: revert each one and confirm a fixture fails. Code no fixture needs is deleted, never kept behind a fixture that passes either way.\n\nMarko language reference: <https://markojs.com/llms.txt> lists every docs page; append `.md` to any docs URL for markdown.\n\n## Agent feedback\n\nAnything actionable but out of scope for the current task (suspected bug, cleanup, perf or size win, tooling friction, confusing code) must be filed in [`agent-feedback/`](agent-feedback/README.md) before finishing. Never drop it silently. Never fix it inside an unrelated diff. In scope, so fixed rather than filed: a defect in code the diff touches or exposes, and anything in the unreleased feature a branch builds (which also takes no changesets). A deliberate limitation gets a site comment, not an item.\n","CLAUDE.md":"AGENTS.md","packages/compiler/AGENTS.md":"# `@marko/compiler`\n\nTranslator-agnostic compiler: parses `.marko` into a Babel AST (custom node types like `MarkoTag`, `MarkoAttribute` — added to Babel by the root `patches/`), runs migrate/transform passes, then hands the AST to a **translator** (`@marko/runtime-tags/translator` or `marko/translator`) for codegen. Stays at v5.x; language changes belong in the translators, not here.\n\n## Map\n\n- `src/index.js` — public API: `compile[File][Sync](src, filename, config)` → `{ code, map, meta, ast }`, `configure`, `taglib`, `types`.\n- `src/config.js` — config defaults, and the `globalConfig` that `configure()` sets (both re-exported by `index.js`); an omitted translator in `getRuntimeEntryFiles`, `getRuntimeVersion` and `taglib.buildLookup` reads it. Key options: `output` (`\"html\"` | `\"dom\"` | `\"source\"` | `\"migrate\"`), `optimize`, `translator`, `modules` (`\"esm\"`/`\"cjs\"`), `optimizeKnownTemplates`, `errorRecovery`, `cache`, `fileSystem`.\n- `src/babel-plugin/` — pipeline core. Stages: `parse → migrate → transform → analyze` (cached per template) then `translate` on a clone. Taglib visitors run in `migrate`, `transform` and `translate` — including those from the taglibs a translator registers via `taglibs`/`optionalTaglibs`, which is how a translator contributes migrators. The translator's own hooks are `transform` (optional), `analyze` and `translate`; there is no `translator.migrate` hook, and `analyze` is translator-only — a taglib-level `analyze` prop is a hard load error. Taglib `translate` is skipped for `output: \"hydrate\"`.\n- `src/taglib/` — tag registry/discovery: built-in HTML/SVG/MathML JSON taglibs, `marko.json` / `marko-tag.json` discovery walking up from the template, `buildLookup`.\n- `src/babel-utils/` — the helper API for translator authors (`assert*`, `diagnostic*`, `import*`, `parse*`, `getTagDef`, `isNativeTag`, `resolveTagImport`, ...). Exported as `@marko/compiler/babel-utils`.\n- `internal/babel/index.ts` — the single controlled Babel entry, re-exported as `@marko/compiler/internal/babel`. All Babel access (here and in translators) goes through it, never `@babel/*` directly.\n\n## Translator contract\n\nA translator module exports: `translate` (required visitor), `taglibs` (required, `[[id, props]]`), optional `transform` / `analyze` visitors, `tagDiscoveryDirs`, `optionalTaglibs`, `preferAPI` (`\"tags\"` | `\"class\"`), `getRuntimeEntryFiles(output, optimize)`, and optionally `cheatsheet` (a module-relative path to an LLM syntax reference; `tryLoadTranslator` resolves it to a cwd-relative path and `util/agent-fix-guide.js` points coding agents at it on compile errors). Loading is resolved from `config.translator` or auto-detected from the app's dependencies (`util/try-load-translator.js`, default logic in `config.js`).\n\n## Notes\n\n- `output: \"source\"` / `\"migrate\"` re-print `.marko` source (tooling/codemods) — no translator codegen.\n- Bumping any `@babel/*` version requires regenerating the corresponding patch in root `patches/` (pnpm patchedDependencies); the custom AST types and generated `dist/types.d.ts` (`pnpm --filter @marko/compiler run build-babel-types`) depend on them.\n- Adding a core tag in a translator shows up in taglib-lookup expectations here and in `packages/runtime-class/test/taglib-lookup/`.\n- `util/agent-fix-guide.js` — when a terminal coding agent is detected (env markers; `AI_AGENT=1` is the generic opt-in for harnesses not on the list) and the loaded translator declares a `cheatsheet`, thrown compile errors get a one-line pointer to it (relative to `cwd`) appended at the `compile[Sync]` boundary (to `message`, and to a `CompileError`'s `label`, which bundler plugins like `@marko/vite` print in place of the framed message), and under `errorRecovery` — where nothing throws — the same pointer is appended to the first error in `meta.diagnostics` instead. `MARKO_AGENT_FIX_GUIDE` overrides the sniff in either direction: `0` suppresses the guide, any other value forces it on (e.g. when compiling in a subprocess that drops the inherited marker). No-op for humans, for runtimes without a cheat sheet, and for inline translator objects (so error snapshots, which compile with an inline translator object, are unaffected).\n","packages/compiler/README.md":"# @marko/compiler\n\nCompiles [Marko](https://markojs.com/) templates into JavaScript modules.\n\nThe [bundler integrations](https://markojs.com/docs/introduction/integrations#bundlers) call the compiler for every template, so applications rarely use it directly. It is the API for building a bundler integration, a test transform, or other tooling around Marko templates.\n\n```sh\nnpm install @marko/compiler\n```\n\n```js\nimport * as compiler from \"@marko/compiler\";\n\nconst { code, map } = await compiler.compileFile(\"./src/card.marko\", {\n  output: \"dom\",\n  sourceMaps: true,\n});\n```\n\nSee the [Compiler API reference](https://markojs.com/docs/reference/compiler) for the compile functions, their options and the compile result.\n","packages/runtime-class/AGENTS.md":"# Marko 5 (runtime & translator)\n\n## Architecture\n\nThe package is organized into four layers:\n\n| Directory              | Purpose                                                                |\n| ---------------------- | ---------------------------------------------------------------------- |\n| `src/runtime/helpers/` | Shared runtime helpers (class/style values, dynamic tags, attr-tags)   |\n| `src/runtime/html/`    | SSR runtime: streaming HTML output, helpers, hot reload                |\n| `src/runtime/vdom/`    | CSR runtime: virtual DOM, morphdom reconciliation, component lifecycle |\n| `src/translator/`      | Babel-based compiler that transforms `.marko` into SSR/CSR JavaScript  |\n\nThe compiler/translator entry is `src/translator/index.js`, but the package's exported translator (`src/translator.js`) wraps it with `createInteropTranslator` from `@marko/runtime-tags/translator`, so Marko 5 projects can mix in Marko 6 (Tags API) components. Interop behavior changes are usually made in `packages/runtime-tags/src/translator/interop/`, not here.\n\nNote: the package is private (named `marko`); `scripts/publish-alias.mts` publishes it as `marko` under the `m5` dist-tag.\n\nCompiled templates import runtime helpers by string path (`marko/src/runtime/helpers/...`, see `translator/util/load-import.js`), so a source search for importers misses those uses.\n\n`src` mixes ESM and CommonJS `.js` with no `\"type\"`, so Node warns `MODULE_TYPELESS_PACKAGE_JSON` under `-t class`. Accepted: Marko 5 is in maintenance and `src` ships in `files`, so a `{\"type\":\"module\"}` marker would force converting every CJS file.\n\n## Naming Conventions\n\n### Triple-underscore prefix (`___name`)\n\nAll internal properties and methods on runtime objects use a triple-underscore prefix:\n\n```js\nthis.___state;\ncomponent.___queueUpdate();\nexports.___batchUpdate = batchUpdate;\n```\n\nThe build step mangles these names into short single-character identifiers.\n\n### `MARKO_DEBUG` pattern\n\nDebug-only code is wrapped in string-compared conditionals that tree-shake in prod:\n\n```js\n// eslint-disable-next-line no-constant-binary-expression\nvar complain = \"MARKO_DEBUG\" && require(\"complain\");\nif (\"MARKO_DEBUG\") {\n  complain(\"Deprecated: ...\");\n}\n```\n\nThe build step replaces `\"MARKO_DEBUG\"` with `false` and dead-code-eliminates the branches.\n\n## Output Modes\n\n- **HTML (SSR)** — `src/runtime/html/index.js` creates a `Template` produces `AsyncStream`. Output is HTML strings piped to a Node.js stream.\n- **VDOM (browser)** — `src/runtime/vdom/index.js` creates a `Template` produces `AsyncVDOMBuilder`. Output is a virtual DOM tree reconciled via local morphdom .\n\nBoth stacks share `src/runtime/renderable.js`, which mixes `render()`, `renderSync()`, `renderToString()`, and `mount()` into `Template.prototype`.\n\n## Error Handling\n\n- Compile-time errors use Babel's `path.buildCodeFrameError(message)` to include source locations\n- Most validation happens at compile time; runtime errors in production are minimal\n\n## Testing\n\n### Test structure\n\n```\ntest/\n  translator/              # Snapshot tests for compiler output\n  components-pages/        # Full page hydration (ssr + csr) tests\n  components-browser/      # jsdom-based browser component tests\n  components-server/       # SSR rendering tests\n  morphdom/                # morphdom unit tests\n  vdom-create/             # VNode construction unit tests\n  async-stream/            # AsyncStream unit tests\n```\n\n### Translator tests\n\nEach fixture has a `template.marko` input and a `snapshots/` directory:\n\n```\nfixtures/<name>/\n  template.marko\n  snapshots/\n    vdom-expected.js\n    html-expected.js\n    htmlProduction-expected.js\n    hydrate-expected.js\n    cjs-expected.js\n    generated-expected.marko\n```\n\n### Running tests\n\nFrom the repo root:\n\n```sh\npnpm test # all tests\npnpm test -- --grep \"<fixture> \" # specific fixture\npnpm run test:update # update snapshots\n```\n","packages/runtime-class/README.md":"<div align=\"center\">\n\n# [<img alt=\"Marko\" src=\"https://raw.githubusercontent.com/marko-js/branding/master/marko-logo-medium-cropped.png\" width=\"250\">](https://markojs.com/)\n\n**A declarative, HTML-based language that makes building web apps fun 🔥**\n\n[![NPM](https://img.shields.io/npm/v/marko.svg)](https://www.npmjs.com/package/marko)\n[![Discord Chat](https://img.shields.io/badge/discord-chat-7188da.svg)](https://discord.gg/RFGxYGs)\n[![Continuous Integration status](https://github.com/marko-js/marko/actions/workflows/ci.yml/badge.svg)](https://github.com/marko-js/marko/actions/workflows/ci.yml)\n[![Code coverage %](https://codecov.io/gh/marko-js/marko/branch/master/graph/badge.svg)](https://codecov.io/gh/marko-js/marko)\n[![# of monthly downloads](https://img.shields.io/npm/dm/marko.svg)](https://npm-stat.com/charts.html?package=marko)\n[![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/7029/badge)](https://bestpractices.coreinfrastructure.org/projects/7029)\n\n[Docs](https://markojs.com/docs/getting-started/) ∙ [Try Online](https://markojs.com/try-online/) ∙ [Contribute](#contributors) ∙ [Get Support](#community--support)\n\n</div>\n\n## Intro\n\nMarko is HTML _reimagined_ as a language for building dynamic and reactive user interfaces. Almost any valid HTML is valid Marko, and Marko extends HTML for building modern applications more declaratively. Among these extensions are [conditionals and lists](https://markojs.com/docs/conditionals-and-lists/), [state](https://markojs.com/docs/state/), and [components](https://markojs.com/docs/class-components/).\n\nMarko supports both single-file components and components across separate files.\n\n### Single-file component\n\nThe following renders a button and a counter of how many times the button has been pressed:\n\n**click-count.marko**\n\n```marko\nclass {\n  onCreate() {\n    this.state = { count: 0 };\n  }\n  increment() {\n    this.state.count++;\n  }\n}\n\nstyle {\n  .count {\n    color: #09c;\n    font-size: 3em;\n  }\n  .press-me {\n    padding: 0.5em;\n  }\n}\n\n<output.count>\n  ${state.count}\n</output>\n<button.press-me on-click('increment')>\n  Press me!\n</button>\n```\n\n### Multi-file component\n\nThe same component as above, but split into:\n\n- `index.marko` template file\n- `component.js` component JS logic file\n- `style.css` component styles file\n\n**index.marko**\n\n```marko\n<output.count>\n  ${state.count}\n</output>\n<button.press-me on-click('increment')>\n  Press me!\n</button>\n```\n\n**component.js**\n\n```js\nexport default {\n  onCreate() {\n    this.state = { count: 0 };\n  },\n  increment() {\n    this.state.count++;\n  },\n};\n```\n\n**style.css**\n\n```css\n.count {\n  color: #09c;\n  font-size: 3em;\n}\n.press-me {\n  padding: 0.5em;\n}\n```\n\n## Concise Syntax\n\nMarko also supports [a beautifully concise syntax as an alternative](https://markojs.com/docs/concise/) to its HTML syntax:\n\n<table><thead><tr><th>Concise syntax<th>HTML syntax\n<tbody><tr>\n<td>\n\n```marko\nul.example-list\n  for|color| of=[a, b, c]\n    li -- ${color}\n```\n\n<td>\n\n```marko\n<ul class=\"example-list\">\n  <for|color| of=[a, b, c]>\n    <li>${color}</li>\n  </for>\n</ul>\n```\n\n</table>\n\n## Getting Started\n\n1. `npm install marko`\n2. Read the [docs](https://markojs.com/docs/getting-started/)\n\n## Community & Support\n\n<table>\n<thead><tr>\n  <th><img alt=\"Stack Overflow\" src=\"https://user-images.githubusercontent.com/1958812/56055468-619b3e00-5d0e-11e9-92ae-200c212cafb8.png\" width=\"205\"> \n  <th><img alt=\"Discord\" src=\"https://user-images.githubusercontent.com/4985201/89313514-6edbea80-d62d-11ea-8447-ca2fd8983661.png\" width=\"162\">\n  <th><img alt=\"Twitter\" src=\"https://user-images.githubusercontent.com/1958812/56055707-07e74380-5d0f-11e9-8a59-d529fbb5a81e.png\" width=\"53\">\n<tbody><tr><td>\n\nAsk and answer [StackOverflow questions with the `#marko` tag](https://stackoverflow.com/questions/tagged/marko)<td>\n\nCome [hang out in our Discord chat](https://discord.gg/RFGxYGs), ask questions, and discuss project direction<td>\n\n[Tweet to `@MarkoDevTeam`](https://twitter.com/MarkoDevTeam), or with the [`#markojs` hashtag](https://twitter.com/search?q=%23markojs&f=live)\n\n</table>\n\n### Contributors\n\nMarko would not be what it is without all those who have contributed ✨\n\n[![All marko-js/marko GitHub contributors](https://opencollective.com/marko-js/contributors.svg?width=890&button=false)](https://github.com/marko-js/marko/graphs/contributors)\n\n### Get Involved!\n\n- Pull requests are welcome!\n- Submit [GitHub issues](https://github.com/marko-js/marko/issues) for any feature enhancements, bugs, or documentation problems\n- [Read the Contribution Tips and Guidelines](.github/CONTRIBUTING.md)\n- Participants in this project agree to abide by [its Code of Conduct](https://github.com/eBay/.github/blob/main/CODE_OF_CONDUCT.md)\n","packages/runtime-class/docs/10-awesome-marko-features.md":"<a href=\"#\">\n  <img src=\"https://cdn-images-1.medium.com/max/1000/1*Cmy6UutD5-ogL8dr1DySMQ.png\" alt=\"Marko logo\" width=\"100%\" />\n</a><br />\n\n> This article was published in August 2017. You can find the original [\"10 Awesome Marko Features\" article here](https://medium.com/@austinkelleher/10-awesome-marko-features-afba9d094d42)!\n\n# 10 Awesome Marko Features\n\n[Marko](https://markojs.com/) is a friendly and super fast UI library that makes\nbuilding web apps<br> fun! In celebration of rapidly approaching [5,000 stars on\nGitHub](https://github.com/marko-js/marko) (the ultimate open source vanity\nmetric), here are 10 features that will make you more productive in no\nparticular order...\n\n#### 1. Shorthand Attributes\n\nTired of constantly typing out `class` and `id` attributes? No need with Marko.\nSimply utilize the shorthand based on CSS selectors:\n\n```marko\nstyle {\n  .count {\n    color:#09c;\n  }\n}\n\n// Equivalent to <div class=\"count\"/>\n<div.count/>\n\n// Equivalent to <span id=\"my-id\"/>\n<span#my-id/>\n\n// Combined\n<button#submit.primary/>\n```\n\n#### 2. All attribute values are Just JavaScript™\n\nUnlike with HTML, you are not limited to string attribute values when using\nMarko. Attributes can have types, which makes it really easy to pass data to\ncustom tags and it works for standard HTML tags too:\n\n```marko\n<div class=input.myClassName/>\n<input type=\"checkbox\" checked=input.isChecked/>\n<awesome-component myString=\"Hello\"/>\n<awesome-component myNumber=1/>\n<awesome-component myTemplateString=`Hello ${name}`/>\n<awesome-component myBoolean=true/>\n<awesome-component myArray=[1, 2, 3]/>\n<awesome-component myObject={hello: 'world'}/>\n<awesome-component myVariable=name/>\n<awesome-component myFunctionCall=input.foo()/>\n```\n\n#### 3. Isomorphic UI components made easy\n\nTired of boilerplate code and trouble managing component input and state? Marko\nmakes it a breeze to develop self-contained and individually testable\ncomponents. Changing state is completely synchronous, so there won’t be any\nheadaches. You can also use inline styles making it very easy to develop small\ncomponents quickly.\n\n```marko\nclass {\n  onInput(input) {\n    this.state = {\n      count: input.count || 0\n    };\n  }\n  increment() {\n    this.state.count++;\n  }\n}\n\nstyle {\n  .count {\n    color:#09c;\n  }\n}\n\n<div.count>${state.count}</div>\n<button on-click('increment')>\n  Click me!\n</button>\n```\n\nDo you see references to “Marko” in the snippet above? Yeah, me neither.\n\nIs your component becoming too large? Do you prefer separating your CSS,\nJavaScript, and markup code? No problem. You can easily [rip out your code into\nmultiple files](https://markojs.com/docs/class-components/#multi-file-components):\n\n```\ncomponents/\n  click-counter/\n    component.js\n    index.marko\n    style.css\n```\n\n#### 4. Concise syntax\n\nThe DOM is just a tree structure. Indentation is a great way to describe a DOM\ntree without having to worry about matching up beginning and ending tags. Marko\nlets you choose between a concise, indentation-based syntax, and a familiar HTML\nsyntax:\n\n```marko\n<!-- Count our clicks! -->\n<div.count>\n  <p>Count: ${state.count}</p>\n</div>\n<button.example-button on-click('increment')>\n  Click me!\n</button>\n```\n\nHere’s the same thing with the concise syntax:\n\n```marko\n// Count our clicks!\ndiv.count\n  p -- Count: ${state.count}\nbutton.example-button on-click('increment') -- Click me!\n```\n\nCan’t make up your mind or just want to paste in that code snippet from\nStackOverflow? HTML syntax can be used within in the concise syntax. You’ll come\nback and make it consistent…_one day_.\n\n#### 5. Import JavaScript modules\n\nDo you have some helper JavaScript functions that you need to use in your views?\nMarko lets you import any JavaScript module into your template using the same\nsyntax as the JavaScript `import` statement without using Babel or any other\nbuild tool. No need for problematic globals (you could do that too, but please\ndon’t or your coworkers will hate you).\n\n```marko\nimport sum from './utils/sum';\n\n<div>The sum of 2 + 3 is ${sum(2, 3)}</div>\n```\n\n#### 6. No need to import custom tags (it’s a good thing, trust me)\n\nMarko uses your directory structure as a method for automatically registering\ncustom tags. This means that Marko can implicitly import tags based on where the\ntemplate is located on disk. Marko will search up the directory looking for\ncustom tags in `components/`directories similar to how Node.js discovers modules\nin `node_modules/` directories.\n\nGiven the following directory structure:\n\n```\ncomponents/\n  fancy-button/\n    index.marko\n  fancy-container/\n    index.marko\n```\n\nIf `fancy-button` is used inside of `fancy-container`, it will be implicitly<br>\nimported:\n\n```marko\n<!-- No need to use `require` or `import` because it will implicitly import custom tags -->\n<div>\n  <fancy-button color=input.buttonColor/>\n</div>\n```\n\n#### 7. Use JavaScript to set CSS classes and styles\n\nSetting CSS classes and styles is made easy using JavaScript! Marko will happily\naccept simple strings, JavaScript objects and arrays (_falsy values will be\nignored)._\n\n```marko\n$ const fontColor = input.color || 'blue';\n$ const isActive = input.active === true;\n\n<div class=['person', isActive && 'active']\n  style={color: fontColor} />\n```\n\n#### 8. Inline JavaScript Statements\n\nMarko takes HTML and makes it more like JavaScript. You can exit out of HTML\nmode to embed a JavaScript statement by starting the line with a `$`. You can\nuse this feature to embed JavaScript variables, functions, etc. where they are\nneeded (take that, “separation of concerns”).\n\n```marko\n$ const randomNumber = Math.random();\n$ const person = {\n  name: 'Frank',\n  age: 32\n};\n\n<div>Random number: ${randomNumber}</div>\n<div>${person.name} is ${person.age} years old</div>\n```\n\nIf you want to combine multiple JavaScript statements you can do that too:\n\n```marko\n$ {\n  const randomNumber = Math.random();\n  const person = {\n    name: 'Frank',\n    age: 32\n  };\n}\n\n<div>Random number: ${randomNumber}</div>\n<div>${person.name} is ${person.age} years old</div>\n```\n\n#### 9. Async rendering with the `<await>` tag\n\nNode.js is asynchronous. Browsers are asynchronous. Why should rendering be\nsynchronous? Pass your promise along to your template and Marko will\nasynchronously render parts of your view. Turns out, [this is good for\nperformance](https://tech.ebayinc.com/engineering/async-fragments-rediscovering-progressive-html-rendering-with-marko/).\n\n```marko\n$ const searchResultsPromise = searchService.performSearch(keywords);\n\n<await(searchResultsPromise)>\n  <@then|person|>\n    Hello ${person.name}!\n  </@then>\n  <@catch|err|>\n    The error was: ${err.message}.\n  </@catch>\n</await>\n```\n\n#### 10. Server side rendering is easy\n\nCan’t decide if you want to do server-side rendering or client-side rendering?\nWhy are we even talking about this in 2017? It doesn’t matter. Seriously, just\ndo both. Marko makes this a no-brainer since you can render a Marko template\ndirectly to a stream (oh, and Marko will automatically mount UI\ncomponents rendered on the server when the page loads in the browser):\n\n```js\nrequire(\"@marko/compiler/register\"); // require .marko files!\n\nconst http = require(\"http\");\nconst template = require(\"./template\");\n\nhttp\n  .createServer()\n  .on(\"request\", (req, res) => {\n    template.render(\n      {\n        name: \"Frank\",\n        count: 30,\n        colors: [\"red\", \"green\", \"blue\"],\n      },\n      res,\n    );\n  })\n  .listen(8080);\n```\n\n#### Bonus: Friendly compile-time errors\n\nWe all make mistakes _every now and then_. Typo in your custom tag? Forgot an\nending tag? No worries! Marko will give you a friendly error message and point\nyou right to the problematic code.\n\n```marko\n<!-- Ahhhh typo! This should be <fancy-button/> -->\n<fancy-buttn/>\n```\n\nYou may have missed it, but it was obvious to Marko:\n\n```\nUnrecognized tag: fancy-buttn — More details: https://github.com/marko-js/marko/wiki/Error:-Unrecognized-Tag at line 2 col 1\n```\n\nComing soon: auto correction and autonomous coding\n\n---\n\n[_Cover image from Wikipedia_](https://commons.wikimedia.org/wiki/File:Amanhecer_no_Hercules_--.jpg)\n","packages/runtime-class/docs/body-content.md":"# Body content\n\nWe're used to passing body content to HTML tags. When you do this, the tag has control over where and when this content is rendered. A good example of this is the [HTML `<details>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details):\n\n```html\n<details>\n  <summary>Hello <strong>World</strong></summary>\n  This is some <em>content</em> that can be toggled.\n</details>\n```\n\nThis is what it renders (try clicking it):\n\n---\n\n<details>\n    <summary>Hello <strong>World</strong></summary>\n    This is some <em>content</em> that can be toggled.\n</details>\n\n---\n\nCustom tags can also receive content in the same way. This allows a component to give its user full control over _how_ some section of the content is rendered, but control _where_, _when_, and with _what_ data it is rendered. This feature is necessary to build composable components like overlays, layouts, dropdowns, etc. Imagine a `<table>` that didn't give you control over how its cells were rendered. That would be pretty limited!\n\n## Rendering body content\n\nWhen a custom tag is passed body content, it is received as a special `renderBody` property on the component's `input`. You can include this content anywhere in your component by using the [`<${dynamic}>` syntax](./syntax.md#dynamic-tagname).\n\n_components/fancy-container.marko:_\n\n```marko\n<div class=\"container fancy\">\n    <${input.renderBody}/>\n</div>\n```\n\nIf we were to use this tag like this:\n\n_Marko Source:_\n\n```marko\n<fancy-container>\n    <p>Content goes here...</p>\n</fancy-container>\n```\n\nThe rendered output would be:\n\n_HTML Output:_\n\n```html\n<div class=\"container fancy\"><p>Content goes here...</p></div>\n```\n\nThis is a pretty basic example, but you can imagine how this could be incorporated into a more advanced component to render passed content where/when needed.\n\n> **ProTip:**\n> Body content can be rendered multiple times. Or not at all.\n\n## Passing attributes to body content\n\nWhen rendering body content with `<${dynamic}>`, attributes may also be passed:\n\n_components/random-value.marko:_\n\n```marko\n<!-- heh, it's not actually random -->\n<${input.renderBody} number=1337 />\n```\n\nThese attribute values can be received as a [tag parameter](./syntax.md#parameters):\n\n```marko\n<random-value|{ number }|>\n    The number is ${number}\n</random-value>\n```\n\n> **ProTip:**\n> Some tags (like the above tag) may not render anything except their body content with some data. This can be quite useful, just look at the `<for>` and `<await>` tags!\n\n## Named body content\n\nYou can also pass named content sections to a tag using [attribute tags](./syntax.md#attribute-tag) which are denoted by the `@` prefix.\n\n```marko\n<layout>\n    <@heading>\n        <h1>Hello Marko</h1>\n    </@heading>\n    <@content>\n        <p>...</p>\n    </@content>\n</layout>\n```\n\nLike attributes, these attribute tags are received as `input.heading` and `input.content`, but they each have a `renderBody` property which we can now use:\n\n_components/layout.marko_\n\n```marko\n<!doctype html>\n<html>\n    <body>\n        <${input.heading.renderBody}/>\n        <hr/>\n        <${input.content.renderBody}/>\n    </body>\n</html>\n```\n\n> **ProTip:** The `renderBody` property can be omitted. You could use `<${input.heading}/>`, for example.\n\n### Repeated body content\n\nWhen an attribute tag is repeated, the child component can consume all instances using the [iterable protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol).\n\nThis allows us to, for example, build a custom table component which allows its user to specify any number of columns, while still giving the user control over how each column is rendered.\n\n_Marko Source:_\n\n```marko\n<fancy-table data=people>\n    <@column|person|>\n        Name: ${person.name}\n    </@column>\n    <@column|person|>\n        Age: ${person.age}\n    </@column>\n</fancy-table>\n```\n\n> _Note_\n> For TypeScript the [`Marko.AttrTag` helper](./typescript.md#built-in-marko-types) should be used here.\n\n> _Protip_\n> Since attribute tags are iterable you could pass `input.column` to a `for of` loop, or `[...spread]` it into an array.\n> To `.map`, `.filter` or otherwise work with attribute tags as an array you can use the following pattern:\n>\n> ```marko\n> $ const columns = [...input.column || []];\n> ```\n\nWe can then use the `<for>` tag to render the body content into table, passing the row data to each column's body.\n\n_components/fancy-table/index.marko:_\n\n```marko {4-8}\n<table class=\"fancy\">\n    <for|row| of=input.data>\n        <tr>\n            <for|column| of=input.column>\n                <td>\n                    <${column.renderBody} ...row/>\n                </td>\n            </for>\n        </tr>\n    </for>\n</table>\n```\n\nWe now have a working `<fancy-table>`. Let's see what it renders:\n\n_Example Data:_\n\n```js\n[\n  {\n    name: \"Patrick\",\n    age: 63,\n  },\n  {\n    name: \"Austin\",\n    age: 12,\n  },\n];\n```\n\n_HTML Output:_\n\n```html\n<table class=\"fancy\">\n  <tr>\n    <td>Name: Patrick</td>\n    <td>Age: 63</td>\n  </tr>\n  <tr>\n    <td>Name: Austin</td>\n    <td>Age: 12</td>\n  </tr>\n</table>\n```\n\n### Attributes on attribute tags\n\nIf you look at our previous example, we had to prefix each cell with the column label. It would be better if we could give a name to each column instead and only render that once.\n\n_Marko Source:_\n\n```marko\n<fancy-table>\n    <@column|person| heading=\"Name\">\n        ${person.name}\n    </@column>\n    <@column|person| heading=\"Age\">\n        ${person.age}\n    </@column>\n</fancy-table>\n```\n\nNow, each attribute tag in `input.column` will contain a `heading` property in addition to its `renderBody`. We can use another `<for>` and render the headings in `<th>` tags:\n\n_components/fancy-table/index.marko:_\n\n```marko {3-5}\n<table class=\"fancy\">\n    <tr>\n        <for|column| of=input.column>\n            <th>${column.heading}</th>\n        </for>\n    </tr>\n    <for|row| of=input.data>\n        <tr>\n            <for|column| of=input.column>\n                <td>\n                    <${column.renderBody} ...row/>\n                </td>\n            </for>\n        </tr>\n    </for>\n</table>\n```\n\nWe'll now get a row of headings when we render our `<fancy-table>`\n\n_HTML Output:_\n\n```html\n<table class=\"fancy\">\n  <tr>\n    <th>Name</th>\n    <th>Age</th>\n  </tr>\n  <tr>\n    <td>Patrick</td>\n    <td>63</td>\n  </tr>\n  <tr>\n    <td>Austin</td>\n    <td>12</td>\n  </tr>\n</table>\n```\n\n### Nested attribute tags\n\nContinuing to build on our example, what if we want to add some custom content or even components into the column headings? In this case, we can extend our `<fancy-table>` to use nested attribute tags. We'll now have `<@heading>` and `<@cell>` tags nested under `<@column>`. This gives users of our tag full control over how to render both column headings and the cells within the column!\n\n_Marko Source:_\n\n```marko {3-8}\n<fancy-table>\n    <@column>\n        <@heading>\n            <app-icon type=\"profile\"/> Name\n        </@heading>\n        <@cell|person|>\n            ${person.name}\n        </@cell>\n    </@column>\n    <@column>\n        <@heading>\n            <app-icon type=\"calendar\"/> Age\n        </@heading>\n        <@cell|person|>\n            ${person.age}\n        </@cell>\n    </@column>\n</fancy-table>\n```\n\nNow instead of rendering the heading as text, we'll render the heading's body content.\n\n_components/fancy-table/index.marko:_\n\n```marko {5}\n<table class=\"fancy\">\n    <tr>\n        <for|column| of=input.column>\n            <th>\n                <${column.heading.renderBody}/>\n            </th>\n        </for>\n    </tr>\n    <for|row| of=input.data>\n        <tr>\n            <for|column| of=input.column>\n                <td>\n                    <${column.cell.renderBody} ...row/>\n                </td>\n            </for>\n        </tr>\n    </for>\n</table>\n```\n\nOur headings can now include icons (and anything else)!\n\n_HTML Output:_\n\n```html\n<table class=\"fancy\">\n  <tr>\n    <th><img class=\"icon\" src=\"profile.svg\" /> Name</th>\n    <th><img class=\"icon\" src=\"calendar.svg\" /> Age</th>\n  </tr>\n  <tr>\n    <td>Patrick</td>\n    <td>63</td>\n  </tr>\n  <tr>\n    <td>Austin</td>\n    <td>12</td>\n  </tr>\n</table>\n```\n\n### Dynamic attribute tags\n\nThe flexibility of the `<fancy-table>` is great if you want to render columns differently or have columns that display the data in a special way (such as displaying an age derived from a date of birth). However, if all columns are basically the same, the user might feel they're repeating themselves. As you might expect, you can use `<for>` (and `<if>`) to dynamically render attribute tags.\n\n```marko\n$ const columns = [{\n    property: \"name\",\n    title: \"Name\",\n    icon: \"profile\"\n}, {\n    property: \"age\",\n    title: \"Age\",\n    icon: \"calendar\"\n}]\n\n<fancy-table>\n    <for|{ property, title, icon }|>\n        <@column>\n            <@heading>\n                <app-icon type=icon/> ${title}\n            </@heading>\n            <@cell|person|>\n                ${person[property]}\n            </@cell>\n        </@column>\n    </for>\n</fancy-table>\n```\n","packages/runtime-class/docs/class-components.md":"# Class Components\n\nMarko makes it easy to create user interface components to use as building blocks for web pages and applications of any complexity.\n\nMarko promotes self-contained components that:\n\n- Are independently testable\n- Encapsulate the view, client-side behavior (like event handling) and styling\n- Can easily be combined to create composite UI components.\n\nMarko components compile into small, efficient JavaScript modules that hide implementation details from consumers. Components can be published to [npm](https://www.npmjs.com) for reuse across applications.\n\n## UI component diagram\n\n![Component diagram](./component-diagram.svg)\n\nIn Marko, the DOM output of a UI component is based on _input properties_ and optional _internal state_ used to control the view.\n\nIf Marko detects changes to `input` or the internal `state`, then the view (that is, the DOM) will automatically update to reflect the new input and state. Internally, Marko uses virtual DOM diffing/patching to update the view, but that’s an implementation detail that could change at any time.\n\n## Component structure\n\nMarko makes it easy to keep your component’s class and styles next to the HTML view that they correspond to. The following are the key parts of any UI component:\n\n- **View** - The HTML template for your UI component. Receives input properties and states, and renders to either server-side HTML or browser-side virtual DOM nodes.\n- **Client-side behavior** - A JavaScript `class` with methods and properties for initialization, event handling (including DOM events, custom events and lifecycle events), and state management.\n- **Styles** - Cascading StyleSheets, including support for CSS preprocessors like [Less](https://lesscss.org/) or [Sass](https://sass-lang.com/).\n\n## Server-side rendering\n\nA UI component can be rendered on the server or in the browser, but stateful component instances will be automatically mounted to the DOM in the browser for both. If a UI component tree is rendered on the server, then Marko will recreate the UI component tree in the browser with no extra code required. For more details, please see [Rendering](/docs/rendering/).\n\n## Single-file components\n\nMarko lets you define a `class` for a component right in the `.marko` file, and call that class’s methods with `on-*` attributes:\n\n```marko\nclass {\n    onCreate() {\n        this.state = {\n            count: 0\n        };\n    }\n    increment() {\n        this.state.count++;\n    }\n}\n\n<label>The current count is <output>${state.count}</output></label>\n<p><button on-click('increment')>+1</button></p>\n```\n\n### Styles\n\nAdding styles in your view is also made easy:\n\n```marko\nstyle {\n    .primary {\n        background: #09c;\n    }\n}\n\n<label>The current count is <output>${state.count}</output></label>\n<p><button.primary on-click('increment')>+1</button></p>\n```\n\nThese styles aren’t output in a `<style>` tag as inline styles usually are, but are externalized to deduplicate them across multiple component instances on a page.\n\nIf you use a CSS preprocessor, you can add its file extension on `style`:\n\n```marko\nstyle.less {\n    .primary {\n        background: @primaryColor;\n    }\n}\n```\n\n> **Note:** The code in the `style` section is processed in a context separate from the rest of the template, so you can’t use JavaScript variables inside it. If you need variables in your CSS, use a CSS preprocessor that supports them.\n\n## Multi-file components\n\nYou might prefer to keep your component’s class and styles in separate files from the view — the classical separation of HTML, CSS, and JavaScript. Marko makes this possible with a filename-based convention.\n\n> **ProTip:** If your’re moving the component’s class and styles to separate files is because the code is getting too large, consider splitting the component into smaller, more manageable components.\n\n### Supporting files\n\nMarko discovers supporting files in the same directory as a Marko view. For example, if you have a view named `counter.marko`, Marko will automatically look for `counter.component.js` and `counter.style.css`.\n\n```\ncounter.marko\ncounter.component.js\ncounter.style.css\n```\n\nMarko also handles views named `index.marko` specially. It will look for `component.js` and `style.css` in addition to `index.component.js` and `index.style.css`. This allows easily grouping component files into a directory:\n\n```\ncounter/\n    index.marko\n    component.js\n    style.css\n```\n\nIn your `component.js` file, export the component’s class:\n\n```js\nexport default class {\n  onCreate() {\n    this.state = {\n      count: 0,\n    };\n  }\n  increment() {\n    this.state.count++;\n  }\n}\n```\n\nIn your `index.marko` file, you can reference methods from that class with `on-*` attributes:\n\n```marko\n<label>The current count is <output>${state.count}</output></label>\n<p><button.primary on-click('increment')>+1</button></p>\n```\n\nAnd in your `style.css`, define the styles:\n\n```css\n.primary {\n  background: #09c;\n}\n```\n\n> **ProTip:** Marko actually looks any filenames with the pattern `[name].style.*`, so it will pick up any CSS preprocessor file extensions you use: `.less`, `.stylus`, `.scss`, etc.\n\n### Components with plain objects\n\nIf you target browsers that does not support classes, a plain object of methods can be exported:\n\n```js\nexport default {\n  onCreate: function () {\n    this.state = {\n      count: 0,\n    };\n  },\n  increment: function () {\n    this.state.count++;\n  },\n};\n```\n\n## Split components\n\nSplit components optimize for when a component renders on the server, and doesn’t need to dynamically rerender in the browser. As a result, its template and logic aren’t sent to the browser, reducing load time and download size.\n\n> **Note:** If a split component is the child of a stateful component, its full rendering logic will still be sent because the parent may pass new input to the split component and rerender it.\n\nAdditionally, if _all_ components rendered on a page are split components, Marko’s VDOM and rendering runtime is unnecessary, and therefore not sent to the browser.\n\n> **ProTip:** Don’t over-optimize. If your component really doesn’t need rerendering, go ahead and split, but don’t forgo stateful rerendering when it would make your code more maintainable.\n\n### Usage\n\nMarko discovers split components similarly to how it discovers an external component class. For example, if you have a view named `button.marko`, it will automatically look for `button.component-browser.js`. If your view is named `index.marko`, it will look for `component-browser.js` in addition to `index.component-browser.js`.\n\n```\ncounter/\n    index.marko\n    component-browser.js\n```\n\nA split component might need to do some setup as part of its initial render. In this case, the component may define a second component class to use the `onCreate`, `onInput`, and `onRender` [lifecycle methods](#lifecycle-events).\n\nThis class can be exported from `component.js`, or defined right in the template as a single-file components. In this case, your component folder may contain a `component.js` file, and must contain a `component-browser.js`. The following [lifecycle methods](#lifecycle-events) can go inside the `component.js` file:\n\n```\nclass {\n  onCreate(input, out) { }\n  onInput(input, out) { }\n  onRender(out) { }\n  onDestroy() { }\n}\n```\n\nAnd the following [lifecycle methods](#lifecycle-events) can go inside the `component-browser.js` file:\n\n```\nclass {\n  onMount() { }\n  onUpdate() { }\n}\n```\n\nAny JavaScript code related to the DOM or browser should also be inside `component-browser.js`.\n\n### Example\n\n`index.marko`\n\n```marko\nclass {\n    onCreate() {\n        this.number = 123;\n    }\n}\n\n<button on-click('shout')>What’s my favorite number?</button>\n```\n\n`component-browser.js`\n\n```js\nexport default {\n  shout() {\n    alert(`My favorite number is ${this.number}!`);\n  },\n};\n```\n\n## Event handling\n\nThe `on-[event](methodName|function, ...args)` attributes allow event listeners to be attached for either:\n\n- A native DOM event, when used on a native DOM element such as a `<button>`\n- Or a UI component event, when used on a custom tag for a UI component such as `<my-component>`\n\nThe `on-*` attributes are used to associate event handler methods with an event name. Event handlers may be specified by `'methodName'` — a string that matches a method on the component instance, or they may be a `function`. Attaching listeners for native DOM events and UI component custom events is explained in more detail in the sections below.\n\nYou may also use the `once-[event](methodName|function, ...args)` syntax, which will listen for only the first event, and then remove the listener.\n\n### Attaching DOM event listeners\n\nThe code below illustrates how to attach an event listener for native DOM events:\n\n```marko\nclass {\n  onButtonClick(name, event, el) {\n    alert(`Hello ${name}!`);\n  }\n}\n\nstatic function fadeIn(event, el) {\n  el.hidden = false;\n  el.style.opacity = 0;\n  el.style.transition = 'opacity 1s';\n  setTimeout(() => el.style.opacity = 1);\n}\n\n<button on-click('onButtonClick', 'Frank')>\n  Say Hello to Frank\n</button>\n\n<button on-click('onButtonClick', 'John')>\n  Say Hello to John\n</button>\n\n<img src='foo.jpg' once-load(fadeIn) hidden />\n```\n\nThe following arguments are passed to the event handler when the event occurs:\n\n1.  `...args` - Any extra bound arguments are _prepended_ to the arguments passed to the component’s handler method.\n    For example: `on-click('onButtonClick', arg1, arg2)` → `onButtonClick(arg1, arg2, event, el)`\n2.  `event` - The native DOM event object.\n3.  `el` - The DOM element that the event listener was attached to.\n\nWhen using the `on-*` or `once-*` attributes to attach event listeners, Marko uses event delegation that is more efficient than direct attachment of `el.addEventListener()`. Please see [Why is Marko Fast? § Event delegation](/docs/why-is-marko-fast/#event-delegation) for more details.\n\n<a id=\"declarative-custom-events\"></a>\n\n### Attaching custom event listeners\n\nThe code below illustrates how to attach an event listener for a UI component’s custom event:\n\n```marko\nclass {\n  onCounterChange(newValue, el) {\n    alert(`New value: ${newValue}!`);\n  }\n  onCounterMax(max) {\n    alert(`It reached the max: ${max}!`);\n  }\n}\n\n<counter on-change('onCounterChange') once-max('onCounterMax') />\n```\n\nThe following arguments are passed to the event handler when the event occurs:\n\n1.  `...args` - Any extra bound arguments are _prepended_ to the arguments passed to the component’s handler method.\n2.  `...eventArgs` - The arguments passed to `this.emit()` by the target UI component.\n3.  `component` - The component instance that the event listener was attached to.\n\nThe following code illustrates how the UI component for `<counter>` might emit its `change` event:\n\n`counter/index.marko`\n\n```marko\nclass {\n  onCreate() {\n    this.max = 50;\n    this.state = { count: 0 };\n  }\n  increment() {\n    if (this.state.count < this.max) {\n        this.emit('change', ++this.state.count);\n    }\n    if (this.state.count === this.max) {\n        this.emit('max', this.state.count);\n    }\n  }\n}\n\n\n<button.example-button on-click('increment')>\n  Increment\n</button>\n```\n\n> **ProTip:** Unlike native DOM events, UI component custom events may be emitted with multiple arguments. For example:\n>\n> ```js\n> this.emit(\"foo\", \"bar\", \"baz\");\n> ```\n\n## Attributes\n\n### `on-[event](methodName|function, ...args)`\n\nThe `on-*` attribute syntax attaches an event listener to either a native DOM event or a UI component event. The `on-*` attribute associates an event handler method with an event name. Please see the [Event handling](#event-handling) section above for details.\n\n### `once-[event](methodName|function, ...args)`\n\nThe same as the `on-*` attribute, except that its listener is only invoked for the first event, and then removed from memory. Please see the [Event handling](#event-handling) section above for more details.\n\n### `key`\n\nThe `key` property does 2 things in Marko:\n\n- Obtains references to nested HTML elements and nested UI components.\n- Matches corresponding elements together when DOM diffing/patching after a rerender. When updating the DOM, keyed elements/components are matched up and reused rather than discarded and recreated.\n\nInternally, Marko assigns a unique key to all HTML elements and UI components in a `.marko` file, based on the order they appear in the file. If you have repeated elements or elements that move between locations in the DOM, then you likely want to assign a custom `key` by adding a `key` attribute. The `key` attribute can be applied to both HTML elements and custom tags.\n\n#### Referencing nested HTML elements and components\n\n```marko\nclass {\n  onMount() {\n    const headerElement = this.getEl('header');\n    const colorListItems = this.getEls('colors');\n    const myFancyButton = this.getComponent('myFancyButton');\n  }\n}\n\n<h1 key=\"header\">Hello</h1>\n\n<ul>\n  <for|color| of=['red', 'green', 'blue']>\n      <li key=\"colors[]\">${color}</li>\n  </for>\n</ul>\n\n<fancy-button key=\"myFancyButton\"/>\n```\n\n> **Note:** The `[]` suffix (e.g. `key=\"colors[]\"`) lets Marko know that the element will be repeated multiple times with the same key.\n\n#### Keyed matching\n\nThe `key` attribute can pair an HTML element or UI component that moves to a new location in the DOM. For example:\n\n```marko\nclass {\n  onCreate() {\n    this.state = {\n      swapped: false\n    }\n  }\n}\n\n<if(state.swapped)>\n  <p key=\"b\">B</p>\n  <p key=\"a\">A</p>\n</if>\n<else>\n  <p key=\"a\">A</p>\n  <p key=\"b\">B</p>\n</else>\n```\n\nThe `key` attribute can be used to pair HTML elements or UI components that are repeated:\n\n```marko\n<ul>\n  <for|user| of=input.users>\n      <li key=user.id>${user.name}</li>\n  </for>\n</ul>\n```\n\nThis way, if the order of `input.users` changes, the DOM will be rerendered more efficiently.\n\n#### `*:scoped`\n\nThe `:scoped` attribute modifier results in the attribute value getting prefixed with a unique ID associated with the current UI component. `:scoped` attribute modifiers can be used to assign a globally unique attribute value from a value that only needs to be unique to the current UI component.\n\nHere’s a use-case: certain HTML attributes reference the `id` of other elements on the page. For example, the [HTML `<label>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label) `for` attribute takes an `id` as its value. Many `ARIA` attributes like [`aria-describedby`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-describedby_attribute) also take an `id` as their value.\n\nThe `:scoped` modifier on an attribute allows you to reference another element without fear of duplicate `id`s, as shown in the following examples:\n\n**`for:scoped`**\n\n```marko\n<label for:scoped=\"name\">Name</label>\n<input id:scoped=\"name\" value=\"Frank\"/>\n```\n\nThe above code will output HTML similar to the following:\n\n```html\n<label for=\"c0-name\">Name</label> <input id=\"c0-name\" value=\"Frank\" />\n```\n\n**`aria-describedby:scoped`**\n\n```marko\n<button\n   aria-describedby:scoped=\"closeDisclaimer\"\n   on-click('closeDialog')>Close</button>\n\n<p id:scoped=\"closeDisclaimer\">\n   Closing this window will discard any entered information and return you to the main page.\n</p>\n```\n\n```html\n<button aria-describedby=\"c0-closeDisclaimer\">Close</button>\n\n<p id=\"c0-closeDisclaimer\">\n  Closing this window will discard any entered information and return you to the\n  main page.\n</p>\n```\n\n**`href:scoped`**\n\n```marko\n<a href:scoped=\"#anchor\">Jump to section</a>\n<section id:scoped=\"anchor\"></section>\n```\n\n```html\n<a href=\"#c0-anchor\">Jump to section</a>\n<section id=\"c0-anchor\"></section>\n```\n\n### `no-update`\n\nPreserves the DOM subtree associated with the element or component, so it won’t be modified when rerendering.\n\n```marko\n<!-- Never rerender this table -->\n<table no-update>\n  …\n</table>\n```\n\n```marko\n<!-- N ever rerender this UI component -->\n<app-map no-update/>\n```\n\nThis is most useful when other JavaScript modifies the DOM tree of an element, like for embeds.\n\n### `no-update-if`\n\nSimilar to [no-update](#no-update), except that the DOM subtree is _conditionally_ preserved:\n\n```marko\n<!-- Don’t re-render this table without table data -->\n<table no-update-if(input.tableData == null)>\n  …\n</table>\n```\n\n### `no-update-body`\n\nSimilar to [no-update](#no-update), except that only the descendant DOM nodes are preserved:\n\n```marko\n<!-- Never rerender any nested DOM elements -->\n<div no-update-body>\n  …\n</div>\n```\n\n### `no-update-body-if`\n\nSimilar to [no-update-body](#no-update-body), except that its descendant DOM nodes are _conditionally_ preserved:\n\n```marko\n<!-- Never rerender any nested DOM elements without table data -->\n<table no-update-body-if(input.tableData == null)>\n  …\n</table>\n```\n\n### `:no-update`\n\nPrevents certain attributes from being modified during a rerender. The attribute(s) that should not be modified should have a `:no-update` modifier:\n\n```marko\n<!-- Never modify the `class` attribute -->\n<div class:no-update=input.className>\n  …\n</div>\n```\n\n## Properties\n\n### `this.id`\n\nA string identifier for the root HTML element that the component is bound to. (Not the `id` attribute.)\n\n### `this.state`\n\nThe current state for the component. Changing `this.state` or its direct properties will cause the component to rerender.\n\nOnly properties that exist when `this.state` is first defined will be watched for changes. If you don’t need a property initially, you can set its value to `null`:\n\n```marko\nclass {\n    onCreate() {\n        this.state = {\n            data: null,\n            error: null\n        }\n    }\n    getData() {\n        fetch('/endpoint')\n            .then(data => this.state.data = data)\n            .catch(error => this.state.error = error);\n    }\n}\n```\n\nBeware: setting a `state` property only _nominates_ the component for a possible rerender, and properties are only watched one level deep. Thus, the component is only rerendered if at least one of the component state properties changed (`oldValue !== newValue`).\n\nIf none of the properties changed (because the new value is identical, or no difference is detected by a shallow comparison), the assignment is considered a no-operation (great for performance).\n\nWe recommend using [immutable data structures](https://wecodetheweb.com/2016/02/12/immutable-javascript-using-es6-and-beyond/), but if you want to mutate a state property (perhaps push a new item into an array), you can mark it as dirty with `setStateDirty`:\n\n```js\nthis.state.numbers.push(num);\n\n// Mark numbers as dirty, because a `push`\n// won’t be automatically detected by Marko\nthis.setStateDirty(\"numbers\");\n```\n\n### `this.input`\n\nThe current input for the component. Setting `this.input` will rerender the component which can be useful for testing, but generally avoided (prefer `state` instead).\n\n## Variables\n\nWhen a Marko component is compiled, some additional variables are available to the rendering function. These variables are described below.\n\n### `component`\n\nThe `component` variable refers to the instance of the currently rendering UI component. This variable can be used to call methods on the UI component instance:\n\n```marko\nclass {\n    getFullName() {\n        const { person } = this.input;\n        return `${person.firstName} ${person.lastName}`;\n    }\n}\n\n<h1>Hello, ${component.getFullName()}</h1>\n```\n\n### `input`\n\nThe `input` variable refers to the `input` object, and is equivalent to `component.input`|`this.input`.\n\n```marko\n<h1>Hello, ${input.name}</h1>\n```\n\n### `state`\n\nThe `state` variable refers to the UI component’s `state` object, and is the _unwatched_ equivalent of `component.state`|`this.state`.\n\n```marko\n<h1>Hello ${state.name}</h1>\n```\n\n## Methods\n\n### `destroy([options])`\n\n| Option       | Type      | Default | Description                                                                       |\n| ------------ | --------- | ------- | --------------------------------------------------------------------------------- |\n| `removeNode` | `Boolean` | `true`  | `false` will keep the component in the DOM while unsubscribing all events from it |\n| `recursive`  | `Boolean` | `true`  | `false` will prevent child components from being destroyed                        |\n\nDestroys the component by unsubscribing from all listeners made using the `subscribeTo` method, and then detaching the component’s root element from the DOM. All nested components (discovered by querying the DOM) are also destroyed.\n\n```js\ncomponent.destroy({\n  removeNode: false, // true by default\n  recursive: false, // true by default\n});\n```\n\n### `forceUpdate()`\n\nQueue the component to re-render and skip all checks to see if it actually needs it.\n\n> When using `forceUpdate()` the updating of the DOM will be queued up. If you want to immediately update the DOM\n> then call `this.update()` after calling `this.forceUpdate()`.\n\n### `getEl([key, index])`\n\n| Signature    | Type          | Description                                                                       |\n| ------------ | ------------- | --------------------------------------------------------------------------------- |\n| `key`        | `String`      | _optional_ — the scoped identifier for the element                                |\n| `index`      | `Number`      | _optional_ — the index of the component, if `key` references a repeated component |\n| return value | `HTMLElement` | The element matching the key, or `this.el` if no key is provided                  |\n\nReturns a nested DOM element by prefixing the provided `key` with the component’s ID. For Marko, nested DOM elements should be assigned an ID with the `key` attribute.\n\n### `getEls(key)`\n\n| Signature    | Type                 | Description                                           |\n| ------------ | -------------------- | ----------------------------------------------------- |\n| `key`        | `String`             | The scoped identifier for the element                 |\n| return value | `Array<HTMLElement>` | An array of _repeated_ DOM elements for the given key |\n\nRepeated DOM elements must have a value for the `key` attribute that ends with `[]`. For example, `key=\"items[]\"`.\n\n### `getElId([key, index])`\n\n| Signature    | Type     | Description                                                                       |\n| ------------ | -------- | --------------------------------------------------------------------------------- |\n| `key`        | `String` | _optional_ — The scoped identifier for the element                                |\n| `index`      | `Number` | _optional_ — The index of the component, if `key` references a repeated component |\n| return value | `String` | The element ID matching the key, or `this.el.id` if `key` is undefined            |\n\nSimilar to `getEl`, but only returns the String ID of the nested DOM element instead of the actual DOM element.\n\n### `getComponent(key[, index])`\n\n| Signature    | Type        | Description                                                                                                                                                                                                       |\n| ------------ | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `key`        | `String`    | The scoped identifier for the element                                                                                                                                                                             |\n| `index`      | `Number`    | _optional_ — The index of the component, if `key` references a repeated component                                                                                                                                 |\n| return value | `Component` | A reference to a nested `Component` for the given key. If an `index` is provided and the target component is a repeated component (i.e. `key=\"items[]\"`), then the component at the given index will be returned. |\n\nFor example, given the following component,\n\n```marko\n<app-main>\n  <app-child key=\"child\"/>\n</app-main>\n```\n\nThe following code can be used to get the `<app-child/>` component:\n\n```js\nconst childComponent = this.getComponent(\"child\");\n```\n\n### `getComponents(key, [, index])`\n\n| Signature    | Type               | Description                                                                       |\n| ------------ | ------------------ | --------------------------------------------------------------------------------- |\n| `key`        | `String`           | The scoped identifier for the element                                             |\n| `index`      | `Number`           | _optional_ — The index of the component, if `key` references a repeated component |\n| return value | `Array<Component>` | An array of _repeated_ `Component` instances for the given key                    |\n\nRepeated components must have a value for the `key` attribute that ends with `[]`, like `key=\"items[]\"`.\n\n### `isDestroyed()`\n\nReturns `true` if a component has been destroyed using [`component.destroy()`](#ondestroy), otherwise `false`.\n\n### `isDirty()`\n\nReturns `true` if the component needs a bath.\n\n### `replaceState(newState)`\n\n| Signature  | Type     | Description                                      |\n| ---------- | -------- | ------------------------------------------------ |\n| `newState` | `Object` | A new state object to replace the previous state |\n\nReplaces the state with an entirely new state. Equivalent to `this.state = newState`.\n\n> **Note:** While `setState()` is additive and will not remove properties that are in the old state but not in the new state, `replaceState()` _will_ add the new state and remove the old state properties that are not found in the new state. Thus, if `replaceState()` is used, consider possible side effects if the new state contains less or other properties than the replaced state.\n\n### `rerender([input])`\n\n| Signature | Type     | Description                                         |\n| --------- | -------- | --------------------------------------------------- |\n| `input`   | `Object` | _optional_ — New input data to use when rerendering |\n\nRerenders the component using its `renderer`, and either supplied `input` or internal `input` and `state`.\n\n### `setState(name, value)`\n\n| Signature | Type     | Description                                |\n| --------- | -------- | ------------------------------------------ |\n| `name`    | `String` | The name of the `state` property to update |\n| `value`   | `Any`    | The new value for the `state` property     |\n\nChanges the value of a single `state` property. Equivalent to `this.state[name] = value`, except it will also work for adding new properties to the component state.\n\n```js\nthis.setState(\"disabled\", true);\n```\n\n### `setState(newState)`\n\n| Signature  | Type     | Description                                         |\n| ---------- | -------- | --------------------------------------------------- |\n| `newState` | `Object` | A new state object to merge into the previous state |\n\nChanges the value of multiple state properties:\n\n```js\nthis.setState({\n  disabled: true,\n  size: \"large\",\n});\n```\n\n### `setStateDirty(name[, value])`\n\n| Signature | Type     | Description                                       |\n| --------- | -------- | ------------------------------------------------- |\n| `name`    | `String` | The name of the `state` property to mark as dirty |\n| `value`   | `Any`    | _optional_ — A new value for the `state` property |\n\nForces a state property change, even if the value is equal to the old value. This is helpful in cases where a change occurs to a complex object that would not be detected by a shallow compare. Invoking this function completely circumvents all property equality checks (shallow compares) and always rerenders the component.\n\n#### More details\n\nThe first parameter, `name`, is used to allow update handlers (e.g. `update_foo(newValue)`) to handle the state transition for the specific state property that was marked dirty.\n\nThe second parameter, `value`, is used as the new value that is given to update handlers. Because `setStateDirty()` always bypasses all property equality checks, this parameter is optional. If not given or equal to the old value, the old value will be used for the update handler.\n\nImportant: the given parameters do not affect how or if `setStateDirty()` rerenders a component; they are only considered as additional information to update handlers.\n\n```js\n// Because this does not create a new array, the change\n// would not be detected by a shallow property comparison\nthis.state.colors.push(\"red\");\n\n// Force that particular state property to be considered dirty so\n// that it will trigger the component's view to be updated\nthis.setStateDirty(\"colors\");\n```\n\n### `subscribeTo(emitter)`\n\n| Signature    | Description                                                                                                                                           |\n| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `emitter`    | A [Node.js `EventEmitter`](https://nodejs.org/api/events.html#events_class_eventemitter) or DOM object that emits events (`window`, `document`, etc.) |\n| return value | A tracked subscription                                                                                                                                |\n\nWhen a component is destroyed, it is necessary to remove any listeners that were attached by the component to prevent memory leaks. By using `subscribeTo`, Marko will automatically track and remove any listeners you attach when the component is destroyed.\n\nMarko uses [`listener-tracker`](https://github.com/patrick-steele-idem/listener-tracker) to provide this feature.\n\n```js\nthis.subscribeTo(window).on(\"scroll\", () =>\n  console.log(\"The user scrolled the window!\"),\n);\n```\n\n### `update()`\n\nImmediately executes any pending updates to the DOM, rather than following the normal queued update mechanism for rendering.\n\n```js\nthis.setState(\"foo\", \"bar\");\nthis.update(); // Force the DOM to update\nthis.setState(\"hello\", \"world\");\nthis.update(); // Force the DOM to update\n```\n\n## Event methods\n\nMarko components inherit from [`EventEmitter`](https://nodejs.org/api/events.html#events_class_eventemitter). Below are a few commonly used methods — view the Node.js docs for the full list.\n\n### `emit(eventName, ...args)`\n\n| Signature   | Type     | Description                                           |\n| ----------- | -------- | ----------------------------------------------------- |\n| `eventName` | `String` | Name of the event                                     |\n| `...args`   | `Any`    | All subsequent parameters are passed to the listeners |\n\nEmits a UI component custom event. If a UI component attached a listener with the matching `eventName`, then the corresponding event listener method will be invoked. Event listeners can be attached using either the [`on-[event](methodName|function, ...args)`](#declarative-custom-events) attribute syntax, or `targetComponent.on()`.\n\n### `on(eventName, handler)`\n\n| Signature   | Type       | Description                               |\n| ----------- | ---------- | ----------------------------------------- |\n| `eventName` | `String`   | Name of the event to listen for           |\n| `handler`   | `Function` | The function to call when the event fires |\n\nAdds the listener function to the end of the listeners array for the `eventName` event. Does not check to see if the listener has already been added. Multiple calls passing the same combination of `eventName` and `handler` will result in the listener being added and called multiple times.\n\n### `once(eventName, handler)`\n\n| Signature   | Type       | Description                               |\n| ----------- | ---------- | ----------------------------------------- |\n| `eventName` | `String`   | Name of the event to listen for           |\n| `handler`   | `Function` | The function to call when the event fires |\n\nAdds a one-time listener function for the `eventName` event. The next time `eventName` triggers, this listener is removed and then invoked.\n\n## Lifecycle events\n\nMarko defines six lifecycle events:\n\n- `create`\n- `input`\n- `render`\n- `mount`\n- `update`\n- `destroy`\n\nThese events are emitted at specific points over the lifecycle of a component, as shown below:\n\n**First render**\n\n```js\nemit('create') → emit('input') → emit('render') → emit('mount')\n```\n\n**New input**\n\n```js\nemit('input') → emit('render') → emit('update')\n```\n\n**Internal state change**\n\n```js\nemit('render') → emit('update')\n```\n\n**Destroy**\n\n```js\nemit(\"destroy\");\n```\n\n### Lifecycle event methods\n\nEach lifecycle event has a corresponding component lifecycle method that can listen for the event:\n\n```js\nclass {\n  onCreate(input, out) { }\n  onInput(input, out) { }\n  onRender(out) { }\n  onMount() { }\n  onUpdate() { }\n  onDestroy() { }\n}\n```\n\n> **ProTip:** When a lifecycle event occurs in the browser, the corresponding event is emitted on the component instance. A parent component, or other code that has access to the component instance, can listen for these events. For example:\n>\n> ```js\n> component.on(\"input\", function (input, out) {\n>   // The component received an input\n> });\n> ```\n\n### `onCreate(input, out)`\n\n| Signature | Description                                                     |\n| --------- | --------------------------------------------------------------- |\n| `input`   | The input data used to render the component for the first time  |\n| `out`     | The async `out` used to render the component for the first time |\n\nThe `create` event is emitted (and `onCreate` is called) when the component is first created.\n\n`onCreate` is typically used to set the initial state for stateful components:\n\n```marko\nclass {\n    onCreate(input) {\n        this.state = { count: input.initialCount };\n    }\n}\n```\n\n### `onInput(input, out)`\n\n| Signature | Description        |\n| --------- | ------------------ |\n| `input`   | The new input data |\n\nThe `input` event is emitted (and `onInput` is called) when the component receives input: both the initial input, and for any subsequent updates to its input.\n\n### `onRender(out)`\n\n| Signature | Description                            |\n| --------- | -------------------------------------- |\n| `out`     | The async `out` for the current render |\n\nThe `render` event is emitted (and `onRender` is called) when the component is about to render or rerender.\n\n### `onMount()`\n\nThe `mount` event is emitted (and `onMount` is called) when the component is first mounted to the DOM. For server-rendered components, this is the first event that is emitted only in the browser.\n\nThis is the first point at which `this.el` and `this.els` are defined. `onMount` is commonly used to attach third-party JavaScript to the newly-mounted DOM.\n\nFor example, attaching a library that monitors if the component is in the viewport:\n\n```marko\nimport scrollmonitor from 'scrollmonitor';\n\nclass {\n    onMount() {\n        this.watcher = scrollmonitor.create(this.el);\n        this.watcher.enterViewport(() => console.log('I have entered the viewport'));\n        this.watcher.exitViewport(() => console.log('I have left the viewport'));\n    }\n}\n```\n\n### `onUpdate()`\n\nThe `update` event is emitted (and `onUpdate` is called) when the component is called after a component rerenders and the DOM has been updated. If a rerender does not update the DOM (nothing changed), this event will not fire.\n\n### `onDestroy()`\n\nThe `destroy` event is emitted (and `onDestroy` is called) when the component is about to unmount from the DOM and cleaned up. `onDestroy` should be used to do any additional cleanup beyond what Marko handles itself.\n\nFor example, cleaning up from our `scrollmonitor` example in [`onMount`](#onmount):\n\n```marko\nimport scrollmonitor from 'scrollmonitor';\n\nclass {\n    onMount() {\n        this.watcher = scrollmonitor.create(this.el);\n        this.watcher.enterViewport(() => console.log('Entered the viewport'));\n        this.watcher.exitViewport(() => console.log('Left the viewport'));\n    }\n    onDestroy() {\n        this.watcher.destroy();\n    }\n}\n```\n\n## DOM manipulation methods\n\nThe following methods move the component’s root DOM node(s) from the current parent element to a new parent element (or out of the DOM in the case of `detach`).\n\n### `appendTo(targetEl)`\n\nMoves the UI component’s DOM elements into the position after the target element’s last child.\n\n```js\nthis.appendTo(document.body);\n```\n\n### `insertAfter(targetEl)`\n\nMoves the UI component’s DOM elements into the position after the target DOM element.\n\n### `insertBefore(targetEl)`\n\nMoves the UI component’s DOM elements into the position before the target DOM element.\n\n### `prependTo(targetEl)`\n\nMoves the UI component’s DOM elements into the position before the target element’s first child.\n\n### `replace(targetEl)`\n\nReplaces the target element with the UI component’s DOM elements.\n\n### `replaceChildrenOf(targetEl)`\n\nReplaces the target element’s children with the UI component’s DOM elements.\n","packages/runtime-class/docs/cloudflare-workers.md":"# Marko + Cloudflare Workers\n\nSee the [the cloudflare sample](https://github.com/marko-js/examples/tree/master/examples/vite-cloudflare)\nproject for a working example.\n\n## Usage\n\nWhen using Marko with [Cloudflare Workers](https://workers.cloudflare.com/), make sure that Marko is loaded with a `worker` [export condition](https://nodejs.org/api/packages.html#conditional-exports). Most bundlers support defining export conditions.\n\nAfter that point, imported `.marko` files will export a `.stream` method that returns a worker compatible [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream). You can then respond with that returned stream:\n\n```js\nimport Template from \"./index.marko\";\n\naddEventListener(\"fetch\", (event) => {\n  event.respondWith(handleRequest(event.request));\n});\n\nasync function handleRequest(request) {\n  return new Response(Template.stream(), {\n    headers: {\n      status: 200,\n      headers: { \"content-type\": \"text/html;charset=UTF-8\" },\n    },\n  });\n}\n```\n\n### BYOB (Bring your own bundler)\n\nFor the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.\nMarko supports a number of bundlers, [take a look through our supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) and pick what works best for you.\n","packages/runtime-class/docs/compiler.md":"# Compiler\n\n> **Note**:\n> This page documents the compiler for Marko 5. The [Compiler API reference](https://markojs.com/docs/reference/compiler) covers the current compiler, including the options Marko 6 adds.\n\n> **Warning**:\n> The compiler API and hooks are not terribly stable. They’re intended for advanced integrations or userland experimentation with new language features.\n>\n> Prefer existing official plugins and the standard tag library when possible.\n\n## Compile API\n\n> **Warning**:\n> The Compile API is intended for advanced integration with build tools, like Webpack and Rollup. Unless you’re doing that, you probably instead want [`build`/`serve` in the Marko CLI](https://github.com/marko-js/cli#readme), or one of [Marko’s bundler integrations](https://markojs.com/docs/bundler-integrations-overview/).\n\n### Compile Functions\n\nCompile functions take two arguments:\n\n1. A source Marko template\n2. [`CompileOptions`](#options)\n\nThen, they return a `CompileResult`:\n\n```ts\ntype CompileResult = {\n  code: string;\n  map?: SourceMap;\n  meta: Record<string, unknown>;\n};\n```\n\n- `code`: The compiled output of executable JavaScript code.\n- `map`: [A source map, used for debugging.](https://firefox-source-docs.mozilla.org/devtools-user/debugger/how_to/use_a_source_map/index.html)\n- `meta`: Metadata gathered while compiling — nothing terribly useful, probably going to get deprecated.\n  - Data about child dependencies. Was useful back when it was primarily the bundlers that handled tree-shaking out server components. Now that happens in the compiler, so we don’t use this anymore and therefore might become inaccurate in the future.\n  - A list of `watchFiles`: files that were used to compile the template (e.g. `marko.json`). Used to tell bundlers which files should be watched in dev mode.\n\n#### `compileFile()` and `compileFileSync`\n\n```ts\ncompiler.compileFile(filename: string, options?: CompileOptions): Promise<CompileResult>\ncompiler.compileFileSync(filename: string, options?: CompileOptions): CompileResult\n```\n\n`compileFile` and `compileFileSync` load `filename` from disk to use as a source template, then translate it into JavaScript.\n\n```js\nimport * as compiler from \"@marko/compiler\";\n\nconst asyncResult = await compiler.compileFile(\"./src/index.marko\", {\n  modules: \"cjs\",\n});\nconst syncResult = compiler.compileFileSync(\"./src/index.marko\", {\n  modules: \"cjs\",\n});\n```\n\n#### `compile()` and `compileSync()`\n\n```ts\ncompiler.compile(src: string, filename: string, options?: CompileOptions): Promise<CompileResult>\ncompiler.compileSync(src: string, filename: string, options?: CompileOptions): CompileResult\n```\n\n`compile` and `compileSync` accept source templates as a string, rather than loading from disk.\n\nThe `filename` location is used for resolving taglibs and imports, but does not have to be an actually existing file. <!-- TODO: should it be renamed to baseFile or importBase or something? -->\n\n```js\nimport * as compiler from \"@marko/compiler\";\n\nconst asyncResult = await compiler.compile(\n  \"<h1>Hello!</>\",\n  \"./src/index.marko\",\n  { modules: \"cjs\" },\n);\nconst syncResult = compiler.compileSync(\"<h1>Hello!</>\", \"./src/index.marko\", {\n  modules: \"cjs\",\n});\n```\n\n### Options\n\nThe compiler may be configured globally to change its default options:\n\n```js\nimport * as compiler from \"@marko/compiler\";\ncompiler.configure({ output: \"dom\" });\n```\n\nOr you can pass options objects when calling compile functions. Each property will override individual properties set by `configure()`:\n\n```js\nimport * as compiler from \"@marko/compiler\";\ncompiler.configure({\n  output: \"dom\",\n  sourceMaps: true,\n});\nconst result = compiler.compileFileSync(\"./example.marko\", {\n  output: \"html\",\n});\n```\n\nIn the above example, `result` would be compiled with the options of `{ output: \"html\", sourceMaps: true }`.\n\n#### `output`\n\nType: `string`<br>\nDefault: `\"html\"`\n\n- `\"html\"`: compiles templates to JavaScript that generates HTML strings for server HTTP responses, writing `.html` files, or maybe even constructing `Response`s in Web Workers.\n- `\"dom\"`: compiles templates to JavaScript that generates DOM nodes for client-side rendering in browsers.\n- `\"hydrate\"`: like `\"dom\"`, but only includes assets & components needed in-browser, assuming the page was rendered on the server.\n- `\"migrate\"`: only runs migrations (no transforms or translation) and returns the migrated template code.\n- `\"source\"`: parses templates without running any migrations or transforms. (Useful with `ast: true`)\n\n> **Note**:\n> For `dom` or `hydrate` outputs, you should also specify a [`resolveVirtualDependency`](#resolvevirtualdependency) function.\n\n#### `code`\n\nType: `boolean`<br>\nDefault: `true`\n\nIf `false`, will not generate or return the compiled `code` string.\n\n#### `ast`\n\nType: `boolean`<br>\nDefault: `false`\n\nIf `true`, the compiler will provide the `ast` in its output.\n\n#### `stripTypes`\n\nType: `boolean|undefined`<br>\nDefault: `undefined`\n\nIf `true`, removes all TypeScript types from the output.\nIf the value is `undefined` (the default), the compiler will remove types if the `output` option is not `source` or `migrate`.\n\nFor example, to run migrations _and_ strip types, you can set both `output: \"migrate\"` and `stripTypes: true`.\n\n#### `runtimeId`\n\nType: `string`<br>\nDefault: `undefined`\n\nOptionally use to override the runtime ID used to differentiate multiple copies of Marko on the same page, which is passed to `marko/components.init(runtimeId)` when compiling in the `hydrate` output.\n\n#### `writeVersionComment`\n\nType: `boolean`<br>\nDefault: `true`\n\nWhether the Marko version should be written to the template in a comment, like so:\n\n```js\n// Compiled using marko@x.x.x - DO NOT EDIT\n```\n\n#### `ignoreUnrecognizedTags`\n\nType: `boolean`<br>\nDefault: `false`\n\nWhether unrecognized tags should be silently ignored or throw a compile error. Ignored tags will be output as native elements.\n\n> **ProTip**:\n> Some test setups use this alongside `taglib.excludeDir` and `taglib.excludePackage` from `@marko/compiler` to simulate \"shallow\" rendering.\n\n#### `sourceMaps`\n\nType: `boolean` or `string`<br>\nDefault: `false`\n\nWhether source maps should be output with the compiled templates.\n\n- When `true` a `map` property will be available on the compile result.\n- When `\"inline\"` the sourcemap will be inlined as a comment in the output code.\n- When `\"both\"` both of the above will be used.\n\n#### `meta`\n\nType: `boolean`<br>\nDefault: `false`\n\n_Deprecated_. This option inlines the metadata in the output Javascript code. Metadata should be accessed instead from the `CompileResult`.\n\n#### `fileSystem`\n\nType: typeof [`fs`](https://nodejs.org/api/fs.html) (specifically read APIs)<br>\nDefault: Cached `fs`\n\nUse a different file system object (eg. webpack's [CachedInputFileSystem](https://github.com/webpack/enhanced-resolve/blob/f08fe3f1a22c90c722eca14b38a9300ad00c62e8/lib/CachedInputFileSystem.js) or [`arc-fs`](https://github.com/eBay/arc/tree/master/packages/arc-fs))\n\n#### `modules`\n\nType: `string` (`\"esm\"` or `\"cjs\"`)<br>\nDefault: `\"esm\"`\n\nBy default Marko outputs ES Modules. You can optionally specify `\"cjs\"` for CommonJS/`require()`.\n\n#### `optimize`\n\nType: `boolean`<br>\nDefault: [environment based](https://github.com/marko-js/marko/blob/0f212897d2d3ec30b12c2f18ba950818bccb83b4/packages/compiler/src/babel-plugin/index.js#L277-L284) (`false` in development, `true` in production)\n\nEnables production mode optimizations.\n\n#### `optimizeKnownTemplates`\n\nType: `string[]`<br>\nDefault: `undefined`\n\nIf `optimize` is enabled you can provide an array of template paths which the compiler will use to generate shorter registry/template ids using incrementing ids. This can only be used if the same `optimizeKnownTemplates` are used for both server and client compilations.\n\n#### `resolveVirtualDependency`\n\nType:\n\n```ts\n(\n  filename: string,\n  dep: {\n    code: string;\n    virtualPath: string;\n    map?: SourceMap;\n  },\n) => string;\n```\n\nDefault: `undefined`\n\nThis option should be set for `dom` or `hydrate` outputs. Since Marko templates can represent multiple output files (eg. JS renderer and CSS styles), a single source `.marko` file must be treated as potentially multiple virtual files.\n\nDifferent build tools have different mechanisms for handling virtual files. You should pass a function that returns a virtual path that can be handled by your build tool.\n\n##### Example based on `@marko/webpack/loader`:\n\n```js\n// lookup is shared between resolveVirtualDependency and markoLoader\nconst virtualSources = new Map();\n\nfunction resolveVirtualDependency(filename, { virtualPath, code, map }) {\n  const virtualFilename = `${filename}?virtual=${virtualPath}`;\n\n  // Add virtual source to the lookup to be later accessed by the loader\n  virtualSources.set(virtualFilename, { code, map });\n\n  // Generate the webpack path, from right to left...\n  // 1. Pass the virtualFilename so webpack can find the real file\n  //    located at sourceFilename, but the virtualPath is also present\n  //    (eg. \"./index.marko?virtual=./index.marko.css\")\n  // 2. Use an inline loader to run this file through @marko/webpack/loader\n  //    https://webpack.js.org/concepts/loaders/#inline\n  // 3. Use an inline matchResource to redefine this as the virtualPath\n  //    which allows the appropriate loaders to match the virtual dependency\n  //    https://webpack.js.org/api/loaders/#inline-matchresource\n  return `${virtualPath}!=!@marko/webpack/loader!${virtualFilename}`;\n}\n\nexport default function markoLoader(source) {\n  let code, map;\n\n  if (virtualSources.has(this.resource)) {\n    // If the resource has a ?virtual query param, we should\n    // find it in the lookup and then return the virtual code\n    // rather than performing the normal compilation\n    ({ code, map } = virtualSources.get(this.resource));\n    virtualSources.delete(this.resource);\n  } else {\n    // The default behavior is to compile the template in dom output mode\n    ({ code, map } = markoCompiler.compileSync(source, this.resourcePath, {\n      output: \"dom\",\n      resolveVirtualDependency,\n    }));\n  }\n\n  return this.callback(null, code, map);\n}\n```\n\n#### `hydrateIncludeImports`\n\nThis option is only used for `output: \"hydrate\"`. By default, `import`s in server-only files are not included in the hydrate output. However, for some assets, like stylesheets, it is useful to have them included in hydrate mode.\n\nThe `hydrateIncludeImports` option allows you to provide a function which receives an import path, or a regexp to match against that path which tells Marko to include that import in the hydrate mode output.\n\nThe default regexp includes a list of common known asset file extensions, and is as follows:\n\n```js\n/\\.(css(\\.[cm]?[jt]s)?|less|s[ac]ss|styl(us)?|p(ost)?css|sss|png|jpe?g|gif|svg|ico|webp|avif|mp4|webm|ogg|mp3|wav|flac|aac|woff2?|eot|ttf|otf)$/;\n```\n\nLooking at a partial Marko file such as:\n\n```marko\nimport \"./bar\"\nimport \"./foo.css\";\nimport \"./baz.wasm\";\n\n<div/>\n```\n\nFor `hydrate` output, with the default `hydrateIncludeImports`, would only cause `./foo.css` to be loaded in the browser.\n\n#### `hydrateInit`\n\nThis option is only used for `output: \"hydrate\"`. It defaults to `true` and causes the hydrate output to include code which tells the Marko runtime to begin hydrating any registered components.\n\nSetting to false will disable that `init` call and allow you to generate code which _just_ imports any hydrate dependencies for a template.\n\n#### `cache`\n\nType: typeof [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) (specifically, `.get()` is required)<br>\nDefault: `new Map()`\n\nCompiling a Marko template may require other (used) Marko templates to compile. To prevent compiling templates more than once, most of the compilation is cached.\n\nThe default cache strategy is to clear the cache each macrotask. If the default cache is overwritten, it is up to the user to determine when the cache is cleared.\n\n#### `babelConfig`\n\nType: see [babel options](https://babeljs.io/docs/en/options)<br>\nDefault: babel defaults, plus\n\n```js\n{\n  filename,\n  sourceType: \"module\",\n  sourceMaps: config.sourceMaps\n}\n```\n\n#### `translator`\n\nType: `{ analyze: Visitor, transform:Visitor }`<br>\nDefault: [autodiscovers](https://github.com/marko-js/marko/blob/0f212897d2d3ec30b12c2f18ba950818bccb83b4/packages/compiler/src/config.js#L46-L89) a translator package starting with `@marko/translator-` or `marko-translator-`\n\nThe translator is a collection of transforms that translates the Marko AST into a valid JavaScript AST based on the `output` option. There is a default translator in Marko, but this option may be used to switch to experimental translators for alternate runtimes.\n\nThe translator is an object with `analyze` and `transform` [Babel Visitors](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#visitors):\n\n- The result of the `analyze` visitor is cached and may be requested by other templates.\n- The `transform` visitor transforms the AST to its final JavaScript AST.\n\nSee [`@marko/translator-default`](https://github.com/marko-js/marko/blob/11a10f82cdb5389880e6deca5f77d17727acb831/packages/translator-default/src/index.js) for a reference implementation.\n\n## Hooks\n\n> **Note**:\n> These compiler hooks aren’t terribly stable either. Using hooks for one-time migrations, like a codemod, is the best-supported way to use the compiler hooks, since you won’t have to worry about the code changing underneath you in the future.\n\n![1. Parse (angle bracket source code) 2. Migrate (old Marko to new Marko) 3. Transform (objects to different objects) 4. Translate (Marko to JavaScript.)](./compiler-hooks.png)\n\nThe Marko compiler runs a series of stages to produce its final JavaScript output. These stages handle different steps of template processing, and can be tweaked, extended, and hooked into with [`marko.json` configuration files](./marko-json.md).\n\n- All compiler hooks must have a default export of a [Babel-style visitor function](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#toc-visitors), which will receive a [babel `NodePath`](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#paths) with a `MarkoTag` node.\n\n- Hooks will also receive a `types` object that matches the [`@babel/types`](https://babeljs.io/docs/en/babel-types) API extended with the [Marko AST types](#marko-ast). (You may also reference the types by importing `{ types } from \"@marko/compiler\"`.)\n\n- Hooks may alternatively export an `enter` function (alias of `default`), and optionally an `exit` function. These map to [`@babel/traverse`’s `enter` and `exit` methods](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#babel-traverse).\n\nHere is an example hook:\n\n```js\nexport default (tag, types) => {\n  if (types.isStringLiteral(tag.node.name)) {\n    console.log(`Found a tag called ${tag.node.name.value}`);\n    tag.remove();\n  }\n};\n```\n\n### Parse\n\nMarko compilation starts by converting the raw text of your Marko template into an [AST (Abstract Syntax Tree)](https://en.wikipedia.org/wiki/Abstract_syntax_tree) — an object representation of your code.\n\n```marko\n<h1>Hello!</h1>\n```\n\n…will roughly become:\n\n```json\n{\n  \"type\": \"MarkoTag\",\n  \"name\": {\n    \"type\": \"StringLiteral\",\n    \"value\": \"h1\"\n  },\n  \"body\": {\n    \"type\": \"MarkoTagBody\",\n    \"body\": [\n      {\n        \"type\": \"MarkoText\",\n        \"value\": \"Hello!\"\n      }\n    ]\n  }\n}\n```\n\nThis might look a bit verbose, but ASTs aim for completeness, not terseness.\n\nMarko parses in two steps to stay flexible with the ever-changing syntax of JavaScript:\n\n1. The first parsing pass happens in our [`htmljs-parser`](https://github.com/marko-js/htmljs-parser), which understands the HTML and HTML-like parts of your template.\n\n2. For JavaScript expressions, Marko defers to [`@babel/parser`](https://babeljs.io/docs/en/babel-parser). The resulting [Marko AST](#marko-ast) is a superset of what `@babel/parser` would return.\n\nTo hook into the `parse` stage, use [the `parse` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n> **Note**: The `parse` hook deviates from the other compiler hooks:\n>\n> - It does not support the `enter` & `exit` API.\n> - You _must return_ a replacement AST node.\n\n### Migrate\n\nThat’s right, Marko has _first-class_ support for migrations. The **migration stage** can translate outdated APIs into modern counterparts, leaving the rest of the compilation none the wiser.\n\nMigrations run automatically in the background, and can be written to disk when users are ready by running the [`@marko/migrate` CLI command](https://github.com/marko-js/cli/blob/master/packages/migrate/README.md).\n\nTo hook into the `migrate` stage, [use the `migrate` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n> **Note:**\n> To make the compiler stop at this point and output the migrated template, rather than continuing to produce the JavaScript output, [set `output: \"migrate\"`](#output) in the [compilation options](#options).\n\n### Transform\n\nThe **transform stage** is meant for userland transformations of Marko code into different Marko code. Think of it like [`babel.transform`](https://babeljs.io/docs/en/babel-core#transform) for Marko templates.\nAt this stage, you are given a fully parsed and migrated AST to do what you will with.\n\nTo hook into the `transform` stage, [use the `transform` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n### Analyze\n\nNext is the **analyze stage**, intended for non-mutative analysis of the entire AST in a way that can be cached in RAM.\n\n> **Note**:\n> “Non-mutative analysis” means that if you modify the AST during this stage, _you’ll probably regret it_ someday.\n\nMetadata should be stored on nodes’ `.extra` property. These `.extra` properties are typically read in [the translate stage](#translate), or when using the child template analysis helpers.\n\nTo hook into the `analyze` stage, [use the `analyze` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n### Translate\n\nFinally, we have the **translation stage**. This stage is Marko’s “Rosetta Stone”, and is responsible for turning your beautiful `.marko` code into different versions of optimized JavaScript you’d rather not write yourself.\n\nTo hook into the `translate` stage, [use the `translate` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n## Utilities\n\n[The `@marko/babel-utils` package](https://github.com/marko-js/marko/tree/master/packages/babel-utils/index.d.ts) exposes a handful of utilities for various tasks on [Marko ASTs](#marko-ast).\n\n### Marko AST\n\nMarko extends Babel’s AST types to add nodes for `MarkoTag`, `MarkoAttribute`, etc.\n\nFor AST creation and assertion utilities, you can import Marko’s `@babel/types` superset from the compiler package:\n\n```js\nimport { types } from \"@marko/compiler\";\n```\n\nThe [`@babel/types` documentation](https://babeljs.io/docs/en/babel-types) shows all utility methods available for Babel AST nodes. When importing `types` from `@marko/compiler`, you also get the same types of utilities for Marko nodes: `types.markoTag`, `types.isMarkoTag`, `types.assertMarkoTag`, and so on.\n\nFor full definitions, view the source code for Babel and Marko:\n\n- [Babel’s Core Definitions](https://github.com/babel/babel/blob/master/packages/babel-types/src/definitions/core.js)\n- [Babel’s Extended Definitions](https://github.com/babel/babel/tree/master/packages/babel-types/src/definitions)\n- [Marko’s Definitions](https://github.com/marko-js/marko/blob/main/packages/compiler/src/babel-types/types/definitions.js)\n","packages/runtime-class/docs/concise.md":"# Concise syntax\n\nMarko's concise syntax is very similar to the HTML syntax, except it's more... concise. Essentially, you take an HTML tag, remove the angle brackets (`<>`) and use indentation rather than a closing tag:\n\n_input.marko_\n\n```marko\ndiv class=\"thumbnail\"\n    img src=\"https://example.com/thumb.png\"\n```\n\n_output.html_\n\n```html\n<div class=\"thumbnail\"><img src=\"https://example.com/thumb.png\" /></div>\n```\n\n## Shorthand attributes\n\nMarko provides a shorthand for declaring classes and ids on an element:\n\n_input.marko_\n\n```marko\ndiv.my-class\nspan#my-id\nbutton#submit.primary.large\n```\n\nYields this HTML:\n\n_output.html_\n\n```html\n<div class=\"my-class\"></div>\n<span id=\"my-id\"></span> <button id=\"submit\" class=\"primary large\"></button>\n```\n\n> **ProTip:** These shorthand attributes are available within the HTML syntax as well\n\n## Attributes on multiple lines\n\nIf a component has lots of attributes, you can spread them across multiple lines by surrounding them with square brackets\n\n_input.marko_\n\n```marko\ndiv [\n    id=\"hello\"\n    class=[\"class1\", \"class2\", \"class3\"]\n    style={ border: \"1px solid red\" }\n] -- hello\n```\n\n_output.html_\n\n```html\n<div id=\"hello\" class=\"class1 class2 class3\" style=\"border:1px solid red\">\n  hello\n</div>\n```\n\n## Text\n\nText in concise mode is denoted by two or more dashes (`--`).\n\nIf there is text on the same line following `--`, it is single-line text:\n\n_single-line-text.marko_\n\n```marko\n-- Hello world\n```\n\nThe dashes can also follow an element to give it a single text node as a child\n\n_single-line-text.marko_\n\n```marko\ndiv -- Hello world\n```\n\nIf there is a line break immediately following `--`, everything following the `--` at the current indentation is parsed as multi-line line text.\n\n_multi-line-text.marko_\n\n```marko\ndiv\n    --\n    Hello world\n    this text\n    is multi-line\n\ndiv\n    --\n    this is more\n    text\n```\n\nA multi-line text block can be ended by the same number of dashes that opened it. This allows it to have siblings:\n\n_multi-line-text.marko_\n\n```marko\ndiv\n    img src=\"https://example.com/photo.png\"\n    --\n    Hello world\n    this text\n    is multi-line\n    --\n    span -- text after\n```\n\n### Root level text\n\nThere is one \"gotcha\" that you need to be aware of. The Marko parser starts out in the concise mode. Therefore, given the following template:\n\n_input.marko_\n\n```marko\nHello World\nWelcome to Marko\n```\n\nThe output would be the following:\n\n_output.html_\n\n```html\n<Hello World></Hello> <Welcome to Marko></Welcome>\n```\n\nInstead, prefix the lines with `--` so they are parsed as text:\n\n_input.marko_\n\n```marko\n-- Hello World\n-- Welcome to Marko\n```\n","packages/runtime-class/docs/conditionals-and-lists.md":"# Conditionals and Lists\n\nWhile HTML itself does not support conditionally displaying elements or repeating elements, it is a critical part of building any web application. In Marko, this functionality is provided by the `<if>` and `<for>` tags.\n\n## Conditionals\n\nThe `<if>` tag receives an [argument](./syntax.md#arguments) which is used to determine if its body content should be present.\n\n```marko\n<if(user.loggedOut)>\n    <a href=\"/login\">Log in</a>\n</if>\n```\n\nAs you might expect, there are also `<else>` and `<else-if>` tags as well:\n\n```marko\n<if(user.loggedOut)>\n    <a href=\"/login\">Log in</a>\n</if>\n<else-if(!user.trappedForever)>\n    <a href=\"/logout\">Log out</a>\n</else-if>\n<else>\n    Hey ${user.name}!\n</else>\n```\n\n## Lists\n\nIf you have a list of data and need to represent it in the UI, the `<for>` tag is probably what you're looking for. The `<for>` tag passes each item and its index to its body as [parameters](./syntax.md#parameters).\n\n```marko\n<ul>\n    <for|color, index| of=colors>\n        <li>${index}: ${color}</li>\n    </for>\n</ul>\n```\n\nThe `<for>` tag actually support 3 different flavors:\n\n- [`<for|item, index, array| of=array>`](./core-tags.md#iterating-over-a-list) renders its body for each item of an array. It's similar to the JavaScript [`for...of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) loop.\n- [`<for|key, value| in=object>`](./core-tags.md#iterating-over-an-objects-properties) renders its body for each property in an object. It's similar to the JavaScript [`for...in`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in) loop.\n- [`<for|value| from=first to=last step=increment>`](./core-tags.md#iterating-between-a-range-of-numbers) renders its body for each value in between and including `from` and `to`.\n\n### Always set a `key`\n\nMarko automatically keeps your UI in sync with the state behind it, but one place where it needs a little extra help is repeated content. Specifying keys gives Marko a way to identify items in a list and keep track of which items have been changed, added, or removed.\n\nA key should be a string or number that uniquely identifies an item in the list and differentiates it from its siblings. The same key value should never be used twice! Often, you will use something like an `id` property.\n\n```marko\n<for|user| of=users>\n    <user-card key=user.id data=user/>\n</for>\n```\n\n> **ProTip:** If you have multiple tags underneath `<for>`, you can key only the first tag and that is enough to properly identify its siblings as well\n>\n> ```marko\n> <dl>\n>     <for|entry| of=entries>\n>         <!-- only the first tag needs a key -->\n>         <dt key=entry.id>${entry.word}</dt>\n>         <!-- This key can be omitted -->\n>         <dd>${entry.definition}</dd>\n>     </for>\n> </dl>\n> ```\n\n> **Note:** If a key is not set, Marko will use the index of an item as its key. However this only works perfectly if items are only ever added or removed at the end of a list. Here's an example where things break down: if we have a list of `[\"A\", \"B\", \"C\"]` and reverse the order, index keys would cause \"A\" to be transformed into \"C\" (and \"C\" into \"A\"), rather than just swapping them. Additionally if these components contained state, the new \"C\" would contain the state from the old \"A\" (and vice-versa). Be aware, stateful components include tags like the native `<input>` element. For this reason **it is always recommended to set a `key` on tags in a `<for>`.**\n","packages/runtime-class/docs/core-tags.md":"# Core tags and attributes\n\nMuch like [HTML has its own native tags](https://developer.mozilla.org/en-US/docs/Web/HTML/Element), Marko includes **core tags** and **global attributes** for declaratively building modern applications.\n\n## `<if>`, `<else-if>`, `<else>`\n\nLike the [equivalent JavaScript statements](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else), these tags render [conditional content](./conditionals-and-lists.md#conditionals):\n\n```marko\n<if(arriving)>\n  Hey there\n</if>\n<else-if(leaving)>\n  Bye now\n</else-if>\n<else>\n  What’s up?\n</else>\n```\n\nThey support any JavaScript expression in their [tag arguments](./syntax.md#arguments):\n\n```marko\n<if(Math.random() > 0.5)>\n  <p>50% chance to see this</p>\n</if>\n```\n\n## `<for>`\n\nThe `<for>` tag iterates over [arrays/array-likes](#iterating-over-a-list), [object properties](#iterating-over-an-objects-properties), and [ranges of numbers](#iterating-between-a-range-of-numbers).\n\n### Iterating over a list\n\nLike the [JavaScript `for...of` loop statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of), giving `<for>`’s `of` attribute a value will loop over that value as an array or iterable.\n\nThe current **item**, **index**, and the **iterating list** are provided as [tag parameters](./syntax.md#parameters):\n\n```marko\n$ const colors = [\"red\", \"green\", \"blue\"];\n<ol>\n  <for|color, index, colorList| of=colors>\n    <li value=index>${color}</li>\n  </for>\n</ol>\n```\n\nThe output HTML would be:\n\n```html\n<ol>\n  <li value=\"0\">red</li>\n  <li value=\"1\">green</li>\n  <li value=\"2\">blue</li>\n</ol>\n```\n\n> **Pro Tip**: `<for>`’s `of` attribute can loop over any iterable, just like JavaScript’s [`for...of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of). This includes strings, `NodeList`s, `Set`s… any object with zero-indexed numeric properties and a `.length`, basically.\n\n### Iterating over an object’s properties\n\nLike [JavaScript’s `for...in` loop statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in), giving `<for>` an object as its `in` attribute will loop over that object’s properties.\n\nThe current **property name** and **property value** are provided as [tag parameters](./syntax.md#parameters):\n\n```marko\n$ const settings = {\n  \"Dark Mode\": false,\n  \"Fullscreen\": true\n};\n\n<dl>\n  <for|name, enabled| in=settings>\n    <dt>${name}:</dt>\n    <dd>${enabled ? \"on\" : \"off\"}</dd>\n  </for>\n</dl>\n```\n\nThe output HTML would be:\n\n```html\n<dl>\n  <dt>Dark Mode:</dt>\n  <dd>off</dd>\n  <dt>Fullscreen:</dt>\n  <dd>on</dd>\n</dl>\n```\n\n### Iterating between a range of numbers\n\nThe final `<for>` variant loops between two numbers, by providing `from` and `to` attributes. The current number in the range will be provided as a [tag parameter](./syntax.md#parameters):\n\n```marko\n<ol type=\"I\">\n  <for|i| from=0 to=10>\n    <li value=i>${i}</li>\n  </for>\n</ol>\n```\n\nYou can also pass an optional `step` attribute, which defaults to 1 otherwise. `step` lets you increment by a specific amount:\n\n```marko\n<ol type=\"I\">\n  <for|i| from=0 to=10 step=2>\n    <li value=i>${i}</li>\n  </for>\n</ol>\n```\n\n…becomes:\n\n```marko\n<ol type=\"I\">\n  <li value=\"0\">0</li>\n  <li value=\"2\">2</li>\n  <li value=\"4\">4</li>\n  <li value=\"6\">6</li>\n  <li value=\"8\">8</li>\n  <li value=\"10\">10</li>\n</ol>\n```\n\n> **ProTip:** This syntax is for generating numbers from nothing. Don’t use it to iterate over an object, like so:\n>\n> ```marko\n> <!-- Inefficient code, do not copy -->\n> <ul>\n>   <for|i| from=0 to=(myArray.length - 1)>\n>     <li>${myArray[i]}</li>\n>   </for>\n> </ul>\n> ```\n>\n> Use [`<for of>`](#iterating-over-a-list) instead.\n\n## `<while>`\n\n> **Warning:** Using `<while>` is not recommended. Instead, replicate it with [an iterable and `<for>`](#iterating-over-a-list).\n>\n> In the future, Marko may restrict value mutation during rendering, for runtime optimizations.\n\nYou can repeat a chunk of markup _until a condition is met_ with the `while` tag:\n\n```marko\n$ let n = 0;\n\n<while(n < 4)>\n  <p>${n++}</p>\n</while>\n```\n\n…becomes:\n\n```html\n<p>0</p>\n<p>1</p>\n<p>2</p>\n<p>3</p>\n```\n\n## `<macro>`\n\nMacros create reusable markup fragments for later use in the same template they were defined in.\n\nThe `<macro>` tag defines a macro as a tag via the `name` attribute. For example, the following macro is registered as the `<greeting>` tag:\n\n```marko\n<macro name=\"greeting\">\n  <p>Welcome!</p>\n</macro>\n\n<greeting/>\n<greeting/>\n```\n\n…the output HTML would be:\n\n```html\n<p>Welcome!</p>\n<p>Welcome!</p>\n```\n\nMacros become more useful with [tag parameters](./syntax.md#parameters), allowing complex templates. In this next example, `<greeting>` can now receive `firstName` and `count` parameters from its parent:\n\n```marko\n<macro|{ firstName, count }| name=\"greeting\">\n  <p>Hello ${firstName}!\n    <output>You have ${count} new messages.</output>\n  </p>\n</macro>\n\n<greeting firstName=\"Frank\" count=20/>\n```\n\n…the output HTML would be:\n\n```html\n<p>\n  Hello Frank!\n  <output>You have 20 new messages.</output>\n</p>\n```\n\nMacros receive input like components do, including [a `renderBody` for provided body content](./body-content.md):\n\n```marko\n<macro|{ renderBody }| name=\"special-heading\">\n  <h1>\n    <${renderBody}/>!\n  </h1>\n</macro>\n\n<special-heading>\n  Hello\n</special-heading>\n```\n\n…the output HTML would be:\n\n```html\n<h1>Hello!</h1>\n```\n\n> **ProTip:** You can use a macro inside itself for recursive layouts, like displaying directory contents.\n\n## `<await>`\n\nThe `<await>` tag **renders markup asynchronously using a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)**.\n\n- Its `<@then>` [attribute tag](./syntax.md#attribute-tag) displays when the Promise _resolves_, optionally receiving the resolved value as a [tag parameter](./syntax.md#parameters).\n- Its `<@catch>` attribute tag displays when the Promise _rejects_, optionally receiving the rejected value as a tag parameter.\n- Its optional `<@placeholder>` attribute tag displays while the Promise is pending.\n\n```marko\n$ const personPromise = new Promise((resolve, reject) => {\n  setTimeout(() => resolve({ name: 'Frank' }), 1000);\n});\n\n<await(personPromise) client-reorder=true>\n  <@placeholder>\n    <!-- Displays while promise is pending -->\n    <label>Loading…\n      <progress></progress>\n    </label>\n  </@placeholder>\n\n  <@then|person|>\n    <!-- Displays if promise resolves -->\n    <p>Hello ${person.name}!</p>\n  </@then>\n\n  <@catch|err|>\n    <!-- Displays if promise rejects -->\n    ${err.name} error: ${err.message}\n  </@catch>\n</await>\n```\n\nOptional attributes for `<await>`:\n\n|        Attribute | Type    | Description                                                                                                                                                                   |\n| ---------------: | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n|        `timeout` | integer | An optional timeout. If reached, rejects the promise with a `TimeoutError`.                                                                                                   |\n|           `name` | string  | Improves debugging and ensures ordering with the `show-after` attribute.                                                                                                      |\n|     `show-after` | string  | Another `<await>` tag’s `name`. Use with `client-reorder` to ensure that the current `<await>` will always render alongside or after the named `<await>`.                     |\n| `client-reorder` | boolean | If true, anything after this `<await>` will be server-rendered before the Promise completes, then the fulfilled Promise’s result will be updated with client-side JavaScript. |\n\nRegardless of these attributes, the promise is executed as eagerly as possible. The attributes control how to coordinate rendering with the rest of the page:\n\n- `client-reorder` prevents `<await>` blocks from delaying the HTTP stream, at the expense of making their rendering rely on client-side JS. Useful for making non-critical page sections not block HTML streaming of important content.\n\n- Using `show-after` with `client-reorder` ensures that the current `<await>` block will always render simultaneously with or after the named `<await>`. Useful for cutting down on [layout shift](https://web.dev/debug-layout-shifts/). `<@placeholder>`s can help fine-tune the user experience while loading.\n\n- `timeout` is useful for limiting non-critical content from slowing down the rest of the page too much.\n\n> **Pro Tip**: When using `timeout`, you can distinguish between `TimeoutError`s and promise rejections by checking the error’s `name`:\n>\n> ```marko\n> <await(slowPromise) timeout=5000>\n>   <@then>Done</@then>\n>   <@catch|err|>\n>     <if(err.name === \"TimeoutError\")>\n>       Took too long to fetch the data!\n>     </if>\n>     <else>\n>       Promise failed with ${err.message}.\n>     </else>\n>   </@catch>\n> </await>\n> ```\n\n## `<include-text>`\n\n`<include-text>` inlines text files into a template, escaping HTML syntax characters (`<`, `\"`, etc.).\n\n```marko\n<include-text('./foo.txt')/>\n```\n\nIf you do not want escaping, use [`<include-html>`](#include-html) instead.\n\n## `<include-html>`\n\nLike `<include-text>`, `<include-html>` inlines the contents of a file. However, this tag **does _not_ escape** special HTML characters.\n\n```marko\n<include-html('./foo.html')/>\n```\n\n## `<html-comment>`\n\nMarko removes HTML comment tags from its output. But if you need comments in the output, that’s what `<html-comment>` is for:\n\n```marko\n<html-comment>[if IE]><script src=\"html-shiv.js\"></script><![endif]</html-comment>\n```\n\n…becomes:\n\n```html\n<!--[if IE]><script src=\"html-shiv.js\"></script><![endif]-->\n```\n","packages/runtime-class/docs/custom-tags.md":"# Custom tags\n\nCustom tags allow you to break up your application UI into encapsulated, reusable components.\n\n## Your first custom tag\n\nLet's say we have a page with the following content:\n\n_page.marko_\n\n```marko\n<!doctype html>\n<html>\n<body>\n    <h1>Hello World!</h1>\n</body>\n</html>\n```\n\nHowever, this page is getting pretty complex and unmaintainable. Let's split out the content into a separate component. To do this, we'll create a `components/` folder and inside it a `hello.marko` file:\n\n_components/hello.marko_\n\n```marko\n<h1>Hello World!</h1>\n```\n\nMarko [automatically discovers](#how-tags-are-discovered) `.marko` files under a `components/` directory, so we can now use the `<hello>` tag in our page:\n\n_page.marko_\n\n```marko\n<!doctype html>\n<html>\n<body>\n    <hello/>\n</body>\n</html>\n```\n\nNow this `<hello>` tag can be used multiple times, and even on multiple pages. But what if we don't only want to say hello to the world? Let's pass some attributes.\n\n_page.marko_\n\n```marko\n<!doctype html>\n<html>\n<body>\n    <hello name=\"World\"/>\n</body>\n</html>\n```\n\nThe component will receive these attributes as `input`:\n\n_components/hello.marko_\n\n```marko\n<h1>Hello ${input.name}!</h1>\n```\n\nNice.\n\n## How tags are discovered\n\nMarko discovers components relative to the `.marko` file where a custom tag is used. From this file, Marko walks up directories until it finds a `components/` folder which contains a component matching the name of the custom tag. If it reaches the project root without finding anything, it will then check installed packages for the component.\n\nLet's take a look at an example directory structure to better understand this:\n\n```dir\ncomponents/\n    app-header.marko\n    app-footer.marko\npages/\n    about/\n        components/\n            team-members.marko\n        page.marko\n    home/\n        components/\n            home-banner.marko\n        page.marko\n```\n\nThe file `pages/home/page.marko` can use the following tags:\n\n- `<app-header>`\n- `<app-footer>`\n- `<home-banner>`\n\nAnd the file `pages/about/page.marko` can use the following tags:\n\n- `<app-header>`\n- `<app-footer>`\n- `<team-members>`\n\nThe home page can't see `<team-members>` and the about page can't see `<home-banner>`. By using nested `component/` directories, we've scoped our page-specific components to their respective pages.\n\n## Tag directories\n\nIn addition to a Marko template, the children of `components/` can be a directory with an `index.marko` template:\n\n```dir\ncomponents/\n    app-header/\n        index.marko\n        logo.png\n        style.css\n    app-footer/\n        index.marko\n```\n\nOr a directory with a template whose name matches its parent directory:\n\n```dir\ncomponents/\n    app-header/\n        app-header.marko\n        app-header.style.css\n        logo.png\n    app-footer/\n        app-footer.marko\n```\n\nThis allows you to create components that have other files associated with them and keep those files together in the directory structure.\n\n> **ProTip:**\n> You can take advantage of nested `components/` directories to create \"subcomponents\" that are only available to the component that contains them.\n>\n> ```dir\n> components/\n>     app-header/\n>         components/\n>             navigation.marko\n>             user-info.marko\n>         app-header.marko\n>     app-footer/\n>         app-footer.marko\n> ```\n\n## Using tags from npm\n\nTo use [tags from npm](https://www.npmjs.com/search?q=keywords%3Amarko%20components), ensure that the package is installed and listed in your `package.json` dependencies:\n\n```\nnpm install --save @marko-tags/match-media\n```\n\nMarko discovers tags from packages defined in your `package.json`, so you can start using them right away:\n\n```marko\n<div>\n    <match-media|{ mobile }| mobile=\"max-width:30em\">\n        <!-- nice -->\n    </match-media>\n</div>\n```\n\n## Publishing tags to npm\n\nWe saw above that tags from npm are automatically discovered. In order to make this work, your package must include a [`marko.json`](./marko-json.md) at the root.\n\n_marko.json_\n\n```json\n{\n  \"tags-dir\": \"./dist/components\"\n}\n```\n\nThis example file tells Marko to expose all components directly under the `dist/components/` directory to the application using your package.\n\nIf your components are written in TypeScript, publish the output of [`mtc`](https://github.com/marko-js/language-server/tree/main/packages/type-check). Editors and type checkers read components under `node_modules` as JavaScript, so consumers get their types from the `.d.marko` files it emits. See [TypeScript in Marko](./typescript.md).\n\nWe recommend adding the `marko` and `components` keywords to your `package.json` so others can find your components. Then `npm publish`!\n\n# Macros\n\nThe [`<macro>`](./core-tags.md#macro) tag allows you to create custom tags in the same file that they are used in.\n\n```marko\n<macro|{ name }| name=\"welcome-message\">\n    <h1>Hello ${name}!</h1>\n</macro>\n\n<welcome-message name=\"Patrick\"/>\n<welcome-message name=\"Austin\"/>\n```\n\n# From Variables\n\nIf no other tag would be discovered Marko will check for an in scope variable that matches the tag name.\n\n```marko\nimport SomeTag from \"./somewhere.marko\"\n\n$ const { renderBody } = input;\n$ const MyTag = input.href ? \"a\" : \"button\";\n\n<SomeTag/>\n<MyTag/>\n<renderBody/>\n```\n","packages/runtime-class/docs/editor-plugins.md":"# Editor Plugins\n\n## Visual Studio Code\n\n[Documentation](https://marketplace.visualstudio.com/items?itemName=Marko-JS.marko-vscode)\n\n- Syntax highlighting\n- Tag matching\n- Tag, attribute and css autocompletion\n- Hyperclick (clickable tags and attributes)\n- Surfaces errors within the templates.\n- Prettyprinting ([marko-prettyprint](https://github.com/marko-js/marko-prettyprint) is used internally)\n\n## Atom\n\n[Documentation](https://atom.io/packages/language-marko)\n\n- Syntax highlighting\n- Tag matching\n- Tag and attribute autocompletion\n- Code snippets\n- Hyperclick (clickable tags and attributes)\n- Prettyprinting ([marko-prettyprint](https://github.com/marko-js/marko-prettyprint) is used internally)\n\n## Sublime\n\n[Documentation](https://github.com/merwan7/sublime-marko)\n\n- Syntax highlighting\n\n## WebStorm\n\n[Documentation](https://github.com/marko-js/marko-tmbundle)\n\n- Syntax highlighting\n\n## TextMate\n\n[Documentation](https://github.com/marko-js/marko-tmbundle)\n\n- Syntax highlighting\n\n## CodeMirror\n\n[codemirror-atom-modes](https://github.com/patrick-steele-idem/codemirror-atom-modes) + [atom-language-marko](https://github.com/marko-js/atom-language-marko)\n","packages/runtime-class/docs/events.md":"# Events\n\nMarko’s event API supports:\n\n- [Browser events](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Events) on native tags\n- Custom events from [custom tags](./custom-tags.md)\n\nNote that **you can’t mix event targets and event types**: custom tags can only listen for custom events, and native tags can only listen for native events.\n\n## Listening to events\n\nBoth kinds of events are received with an `on-*` attribute and the [attribute arguments syntax](./syntax.md#arguments):\n\n```marko\n<input type=\"checkbox\"\n  on-change(event => console.info(`Checked? ${event.target.checked}`))\n/>\n```\n\nThe [first argument for the attribute can be a function](#function-handler), or [a string matching a method name](#method-handler) on the [component’s `class` declaration](./class-components.md).\n\n### Function handler\n\nIf you provide a function as the first argument of the `on-*` attribute, the function is called whenever the event fires, like standard event listeners.\n\nBelow we use the [`static` prefix](./syntax.md#static-javascript) to define a function, then use it as a `click` handler:\n\n```marko\nstatic function handleClick(event) {\n  event.preventDefault();\n  console.log(\"Clicked!\");\n}\n\n<button on-click(handleClick)>\n  Log click\n</button>\n```\n\nIn the above example, any time the `<button>` is clicked the `handleClick` function is called.\n\nYou can also use an inline arrow function:\n\n```marko\n<button on-click(() => alert(\"Clicked! 🎉\"))>\n  Celebrate click\n</button>\n```\n\n…or anything that evaluates to a function:\n\n```marko\n$ const handler = (\n  input.dontBreakMyApp ?\n    () => console.error(\"Clicked!\") :\n    () => { throw Error(\"Clicked!\") }\n);\n\n<button on-click(handler)>\n  Do not click\n</button>\n```\n\n### Method handler\n\nWhen a string is the first argument, Marko calls a matching method on the component's `class`.\n\n```marko\nclass {\n  logChange(newTab) {\n    console.log(`changed to: ${newTab}`);\n  }\n}\n\n<my-tabs on-switch-tab(\"logChange\")>\n  …\n</my-tabs>\n```\n\nWhen `<my-tabs>` emits the `switch-tab` event, it will call its `logChange` method.\n\nWithin the handler you can access the current component instance, read data, emit events, update state, etc.\n\n### Binding additional arguments\n\nArguments after the handler are prepended when the handler is called:\n\n```marko\nstatic function removeFriend(friendId, event) {\n  event.preventDefault();\n  window.myAPI.unfriend(friendId);\n}\n\n<for|friend| of=input.friends>\n  <button on-click(removeFriend, friend.id)>\n    Unfriend ${friend.name}\n  </button>\n</for>\n```\n\nHere we share the logic for `removeFriend()` with each `friend` in the `friends` array. When the `<button>` is clicked, the `id` of the removed `friend` is passed to the `removeFriend()`, handler followed by the DOM `click` event.\n\n## Emitting custom events\n\nThe recommended way for a [custom tag](./custom-tags.md) to communicate with its parent is through **custom events**.\n\nAll components implement a [Node.js-style event emitter](https://nodejs.org/api/events.html#events_class_eventemitter) to send events to parent components.\n\n_email-input.marko_\n\n```marko\nclass {\n  handleChange(event) {\n    if (event.target.validity.valid) {\n      // Only emit email-changes if they are valid.\n      this.emit(\"email-change\", { email: event.target.value });\n    }\n  }\n}\n\n<input type=\"email\" name=input.name on-change(\"handleChange\")/>\n```\n\nThe above code listens to native `change` events from the `<input>` element, and then emits its own `email-change` event if the change was valid.\n\n```marko\n<form>\n  <email-input name=\"email\" on-email-change(\"...\")/>\n</form>\n```\n\n> **Note:** Events are not received as `input`; you cannot access `input.onEmailChange`. Instead, they set up subscriptions.\n","packages/runtime-class/docs/express.md":"# Marko + Express\n\n## Quick Start\n\n```sh\nnpm init marko -- --template vite-express\n# Or `npx create-marko --template vite-express`\n```\n\nSee [Marko’s example projects](https://github.com/marko-js/examples) for working [Express](https://expressjs.com/) integration code, such as:\n\n- [`examples/vite-express`](https://github.com/marko-js/examples/tree/master/examples/vite-express)\n- [`examples/rollup-express`](https://github.com/marko-js/examples/tree/master/examples/rollup-express)\n- [`examples/webpack-express`](https://github.com/marko-js/examples/tree/master/examples/webpack-express)\n\nBut if you want to do things the hard way…\n\n## Doing things the hard way\n\nFirst, install Marko, Express, and the glue to hold them together:\n\n```sh\nnpm install marko express @marko/express --save\n```\n\n### Skip the view engine\n\nExpress’s builtin view engine may be asynchronous, but it doesn’t support streaming — see [Rediscovering Progressive HTML Rendering](https://tech.ebayinc.com/engineering/async-fragments-rediscovering-progressive-html-rendering-with-marko/) for why that’s important. So instead, we [bypass Express’s view engine](https://strongloop.com/strongblog/bypassing-express-view-rendering-for-speed-and-modularity/) to use `@marko/express` instead.\n\n[The `@marko/express` package](https://www.npmjs.com/package/@marko/express) adds a `res.marko()` method to [Express’s response object](https://expressjs.com/en/api.html#res). This method works like [`res.render()`](https://expressjs.com/en/api.html#res.render), but without the restrictions of Express’s view engine, letting you take full advantage of Marko’s streaming and modular template organization.\n\n> **ProTip**: By using `res.marko()`, properties from [`app.locals`](https://expressjs.com/en/api.html#app.locals) and [`res.locals`](https://expressjs.com/en/api.html#res.locals) are automatically [available on `$global`](https://markojs.com/docs/rendering/#global-data).\n\n```js\nimport express from \"express\";\nimport markoPlugin from \"@marko/express\";\nimport template from \"./template.marko\";\n\nconst app = express();\napp.use(markoPlugin()); // Enables `res.marko(template, input)`\n\napp.get(\"/\", function (req, res) {\n  res.marko(template, {\n    name: \"Frank\",\n    count: 30,\n    colors: [\"red\", \"green\", \"blue\"],\n  });\n});\n\napp.listen(8080);\n```\n\n> **Note**: Older versions of `@marko/express` used to also attach Express’s `app`, `req`, and `res` objects onto `$global`. This meant uncontrolled network data could cause new and exciting surprises in your app code. Nowadays we recommend explicitly accessing the specific pieces of the HTTP exchange you’re interested in, like this:\n>\n> ```js\n> app.get(\"/\", function (req, res) {\n>   res.marko(template, {\n>     params: req.params,\n>     submitted: req.method === \"POST\" && req.body,\n>   });\n> });\n> ```\n\n### BYOB (Bring Your Own Bundler)\n\nMost of Marko’s API requires a bundler: the example code above assumes that `.marko` files can be `import`ed in your environment. [Check out Marko’s supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) to see what works best for you.\n","packages/runtime-class/docs/fastify.md":"# Marko + Fastify\n\n## Quick Start\n\n```terminal\nnpm init marko -- --template vite-fastify\n```\n\nSee the [the fastify sample](https://github.com/marko-js/examples/tree/master/examples/vite-fastify)\nproject for a working example.\n\n## From Scratch\n\nFirst install Marko and the fastify related dependencies:\n\n```terminal\nnpm install marko @marko/fastify fastify --save\n```\n\n### Usage\n\nThe [`@marko/fastify`](https://github.com/marko-js/fastify/) adds a `reply.marko` decorator to the `reply` object. This function allows us to pass in a Marko template and supports Marko's streaming and modular approach to templates.\n\nBy using `reply.marko` you'll automatically have access to `app.locals`, and `reply.locals` from within your Marko template and custom tags. These values are added to `$global`.\n\n```javascript\nimport fastify from \"fastify\";\nimport markoPlugin from \"@marko/fastify\";\nimport Template from \"./template.marko\";\n\nconst app = fastify();\n\napp.register(markoPlugin);\n\napp.get(\"/\", (request, reply) => {\n  // Streams Marko template into the response.\n  // Forwards errors into fa error handler.\n  reply.marko(Template, { hello: \"world\" });\n});\n\nawait fastify.listen(3000);\n```\n\n### Global Outputs\n\nWe can add global outputs from the server side using the reply object or fastify instance.\n\n```javascript\nreply.locals.newProperty = \"Your value\";\n```\n\nTo use this in marko components we just need to refer out.global\n\n```marko\n$ const { newProperty } = $global;\n```\n\nTo know more about sending the data to the browser checkout:\n\n### [Sending global data to browsers](https://markojs.com/docs/rendering/#sending-global-data-to-browsers)\n\n### BYOB (Bring your own bundler)\n\nFor the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.\nMarko supports a number of bundlers, [take a look through our supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) and pick what works best for you.\n","packages/runtime-class/docs/getting-started.md":"# Getting started\n\n## Setup\n\n### Marko Run (Recommended)\n\n[Marko Run](https://github.com/marko-js/run) makes it easy to get started with little to no config and is the recommended starting point for a new Marko project.\n\nTo set up your project:\n\n1. `npm init marko -- -t basic`\n2. `cd ./<PROJECT_NAME>`\n3. `npm run dev`\n\nOpen `src/routes/_index/+page.marko` in your editor to change the index page. See the [routing documentation](https://github.com/marko-js/run#file-based-routing) to learn how to add additional pages to your project.\n\n### Other setups\n\nIf you just want to test out Marko in your browser, use the [Try Online](https://markojs.com/try-online) feature. You can open it in another tab and follow along. For other setups, check out the [Installation](./installing.md) page.\n\n## Hello world\n\nMarko makes it easy to represent your UI using a [syntax](./syntax.md) that is like HTML:\n\n_hello.marko_\n\n```marko\n<h1>Hello World</h1>\n```\n\nIn fact, Marko is so much like HTML, that you can use it as a replacement for a templating language like handlebars, mustache, or pug:\n\n_template.marko_\n\n```marko\n<!doctype html>\n<html>\n<head>\n    <title>Hello World</title>\n</head>\n<body>\n    <h1>Hello World</h1>\n</body>\n</html>\n```\n\nHowever, Marko is much more than a templating language. It's a language that allows you to declaratively build an application by describing how the application view changes over time and in response to user actions.\n\nIn the browser, when the data representing your UI changes, Marko will automatically and efficiently update the DOM to reflect the changes.\n\n## A simple component\n\nLet's say we want to perform an action once a `<button>` is clicked:\n\n_button.marko_\n\n```marko\n<button>Click me!</button>\n```\n\nMarko makes this really easy, allowing you to define a `class` for a component right in the `.marko` view and call methods of that class with `on-` attributes:\n\n_button.marko_\n\n```marko\nclass {\n    sayHi() {\n        alert(\"Hi!\");\n    }\n}\n\n<button on-click(\"sayHi\")>Click me!</button>\n```\n\n### Adding state\n\nAlerting when a button is clicked is great, but what about updating your UI in response to an action? Marko's stateful components make this easy. All you need to do is set `this.state` from inside your component's class. This makes a new `state` variable available to your view. When a value in `this.state` is changed, the view will automatically re-render and only update the part of the DOM that changed.\n\n_counter.marko_\n\n```marko\nclass {\n    onCreate() {\n        this.state = {\n            count: 0\n        };\n    }\n    increment() {\n        this.state.count++;\n    }\n}\n\n<div>The current count is ${state.count}</div>\n<button on-click(\"increment\")>Click me!</button>\n```\n","packages/runtime-class/docs/http.md":"# Marko + HTTP Server\n\nSee the [the http sample](https://github.com/marko-js/examples/tree/master/examples/vite-http)\nproject for a working example.\n\n## Usage\n\n```js\nimport http from \"http\";\nimport Template from \"./index.marko\";\n\nconst port = 8080;\nconst server = http.createServer();\n\nserver.on(\"request\", (req, res) => {\n  Template.render(\n    {\n      name: \"Frank\",\n      count: 30,\n      colors: [\"red\", \"green\", \"blue\"],\n    },\n    res,\n  ).on(\"error\", (err) => {\n    // Without a listener, a render error crashes the process.\n    console.error(err);\n  });\n});\n\nserver.listen(port, () => {\n  console.log(`Successfully started server on port ${port}`);\n});\n```\n\n### BYOB (Bring your own bundler)\n\nFor the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.\nMarko supports a number of bundlers, [take a look through our supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) and pick what works best for you.\n","packages/runtime-class/docs/installing.md":"# Installation\n\n## Trying out Marko\n\nIf you just want to play around with Marko in the browser, head on over to our [Try Online](https://markojs.com/try-online) feature. You'll be able to develop a Marko application right in your browser.\n\n## Creating new apps (Recommended)\n\nIf you're starting from scratch, you can use Marko's [CLI](https://github.com/marko-js/cli) commands to quickly create a starter app:\n\n```bash\nnpm init marko\n```\n\nThis will use an interactive [CLI](https://github.com/marko-js/cli) to automatically create a project for you using the pre-made starter template of your choosing. The `basic` template is the most minimal and the easiest way to get started. It uses our recommended app framework [Marko Run](https://github.com/marko-js/run) that handles building, bundling, and serving your web application. These projects are config-free with built-in file based routing and automatic code reloading.\n\n## Custom Bundling\n\nMarko relies on JavaScript bundlers to package your code on both the client and the server. This is because Marko's client and server bundling works closely together to optimize the smallest client bundles and handle shared assets properly.\n\nUsing the CLI is still the easiest way to get started even when you want to get your hands dirty tweaking every last part of your config files. Marko currently supports Webpack, Lasso, and Rollup.\n\n### Webpack\n\n[Webpack Integration Docs](https://markojs.com/docs/webpack/)\n\n[Marko Webpack Plugin](https://github.com/marko-js/webpack)\n\n[Webpack Example](https://github.com/marko-js/examples/tree/master/examples/webpack-express)\n\nCLI Command: `npx @marko/create --template webpack-express`\n\n### Lasso\n\n[Lasso Integration Docs](https://markojs.com/docs/lasso/)\n\n[Marko Lasso Plugin](https://github.com/lasso-js/lasso-marko)\n\n[Lasso Example](https://github.com/marko-js/examples/tree/master/examples/lasso-express)\n\nCLI Command: `npx @marko/create --template lasso-express`\n\n### Rollup\n\n[Rollup Integration Docs](https://markojs.com/docs/rollup/)\n\n[Marko Rollup Plugin](https://github.com/marko-js/rollup)\n\n<!-- [Rollup Example](https://github.com/marko-js/examples/tree/master/examples/rollup)\n\nCLI Command: `npx @marko/create --template rollup` -->\n","packages/runtime-class/docs/koa.md":"# Marko + Koa\n\nSee the [the koa sample](https://github.com/marko-js/examples/tree/master/examples/vite-koa)\nproject for a working example.\n\n## Installation\n\n```terminal\nnpm install koa marko --save\n```\n\n## Usage\n\n```javascript\nimport Koa from \"koa\";\nimport Template from \"./index.marko\";\n\nconst app = new Koa();\n\napp.use((ctx, next) => {\n  ctx.type = \"html\";\n  ctx.body = Template.stream({\n    name: \"Frank\",\n    count: 30,\n    colors: [\"red\", \"green\", \"blue\"],\n  });\n});\n\napp.listen(8080);\n```\n\n### BYOB (Bring your own bundler)\n\nFor the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.\nMarko supports a number of bundlers, [take a look through our supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) and pick what works best for you.\n","packages/runtime-class/docs/lasso.md":"# Marko + Lasso\n\nThe [lasso-marko](https://github.com/lasso-js/lasso-marko) plugin for [Lasso.js](https://github.com/lasso-js/lasso) will automatically compile all imported Marko templates during bundling. In addition, the `lasso-marko` plugin will automatically bundle any template dependencies (including required CSS).\n\nLasso.js provides Marko custom tags for injecting JavaScript and CSS bundles, images and other resources.\n\nThe sample [lasso-express](https://github.com/marko-js/examples/tree/master/examples/lasso-express) app demonstrates how to build a production-ready web application using Marko and Lasso. Run `npx @marko/create --template lasso-express` to use this sample as a starting point for a new app.\n\n## Installation\n\n```\nnpm install lasso-marko --save\n```\n\n## Registering the plugin\n\n```js\nrequire('lasso').configure({\n    \"plugins\": [\n        ...\n        \"lasso-marko\"\n    ]\n    ...\n});\n```\n\n## Lasso custom tags\n\nTo inject the required JavaScript and CSS into the page you will want to use the `<lasso-page>`, `<lasso-head>` and `<lasso-body>` tags.\n\nIf you are using lasso@^3 (latest), make sure to install the [lasso-marko-taglib](https://github.com/lasso-js/lasso-marko-taglib), so that you can use the lasso custom tags.\n\n```\nnpm install lasso-marko\nnpm install @lasso/marko-taglib\n```\n\nAfter installing, the lasso custom tags can be used in your templates:\n\n```html\n<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>Marko + Lasso</title>\n    <lasso-head />\n  </head>\n  <body>\n    <lasso-body />\n  </body>\n</html>\n```\n\nLasso.js will automatically bundle up transitive dependencies by building and walking a dependency graph.\n\n## Client-side rendering\n\nMarko templates can be imported and rendered by any JavaScript module. The code below shows how to render a top-level UI component and have it be mounted to the DOM as a child `document.body`:\n\n_client.js_\n\n<!-- prettier-ignore -->\n```js\nrequire(\"./components/app/index.marko\")\n  .renderSync({})\n  .appendTo(document.body);\n```\n\nWhen Lasso.js bundles up the code above it will automatically bundle up the required `./components/app/index.marko` file.\n\n## Server-side rendering\n\nIf you are rendering the initial UI on the server then it is necessary to make sure that all UI components are bundled and sent to the browser so that UI components can be mounted in the browser. For example:\n\n_about-me/index.marko_\n\n```marko\n<!DOCTYPE html>\n<html lang=\"en\">\n    <head>\n        <meta charset=\"UTF-8\">\n        <title>Marko + Lasso</title>\n\n        <!-- CSS will be inserted here -->\n        <lasso-head/>\n    </head>\n    <body>\n        <!-- Top-level UI component: -->\n        <app/>\n\n        <!-- JS will be inserted here -->\n        <lasso-body/>\n    </body>\n</html>\n```\n\n## Browser refresh\n\n[browser-refresh](https://github.com/patrick-steele-idem/browser-refresh) is recommended in development for instant page refreshes and hot reloading of Marko templates, styles and other resources. `browser-refresh` works well with Lasso and Marko and is very easy to use as a drop-in replacement for `node`:\n\n```bash\nbrowser-refresh server.js\n```\n\n## Lasso package types commonly used with Marko\n\nFor many use cases, the combination of `lasso-marko` and `@lasso/marko-taglib` is sufficient to render and bundle components without the need for explicit `browser.json` files. For more advanced use cases, the following bundle types may be defined in a `browser.json` for Lasso.\n\n#### `marko-dependencies` _(provided by `lasso-marko`)_\n\nIncludes all the dependencies needed by template and the code to register all components that would be rendered by the template. It does not automatically initialize the component, so is most useful if you need to initialize components manually.\n\n```json\n{\n  \"type\": \"marko-dependencies\",\n  \"path\": \"src/ui-modules/outdated-browser-banner/index.marko\"\n}\n```\n\n**Note:** To initialize the server rendered components, there are 2 steps:\n\n**Step 1:** Manually _retrieve_ server rendered components, shipped via `marko-dependencies`.\n\nTo retrieve the list of server rendered components, do:\n\n```javascript\ntemplate.render(data, (err, output) => {\n  const renderedComponentsList =\n    require(\"marko/components\").getRenderedComponents(output.out);\n  const html = output.getOutput();\n});\nres.json({\n  renderedComponentsList,\n  html,\n});\n```\n\n**Step 2:** Manually _initialize_ server rendered components, shipped via `marko-dependencies`.\n\nTo initialize the list of server rendered components, do:\n\n```javascript\n// from the response received, retrieve as\nrequire(\"marko/components\").init(response.renderedComponentsList);\n```\n\n**Note:** Ensure Step 2 is inside a DOM-ready wrapper, for the legacy widgets layer to load (if there are widgets built out of Marko 3, that is being used inside a Marko 4 component.)\n\n#### `marko-hydrate` _(provided by `lasso-marko`)_\n\nIncludes all the dependencies needed by template and the code to register all components that would be rendered by the template. This also includes the code to initialize the rendered components. Including this bundle on the page will automatically hydrate server rendered components.\n\n```json\n{\n  \"type\": \"marko-hydrate\",\n  \"path\": \"src/ui-modules/outdated-browser-banner/index.marko\"\n}\n```\n\n**Note:** `marko-hydrate` will initialize the component if its defined on the global `window.$components` which is inserted by `Marko` when it sees a `<body>` tag. Else, if you are just rendering out and lasso-ing the a portion of a page with a set of components, include `<init-components/>` at the end of the associated `template.marko` file that builds out the page fragment.\n\n#### `package`\n\nA collection of dependencies. `browser.json` is the most common package type.\nIt could be used to point to another `browser.json` from within one component's `browser.json`.\nTypically also used when the dependencies of the referred `browser.json` have to be packaged inline.\n\n```json\n{\n  \"type\": \"package\",\n  \"path\": \"src/ui-modules/show-diag/browser.json\"\n}\n```\n\n#### `require`\n\nIf a javascript file has to be wrapped over for its common JS syntax, to a browser understandable format.\n\n```json\n{\n  \"type\": \"require\",\n  \"path\": \"src/ui-modules/dynamic-module-loader/dynamic-init-client.js\"\n}\n```\n\n#### `require` and `run`\n\nIf a javascript file has to be wrapped over for its common JS syntax, to a browser understandable format and be executed immediately.\n\n```json\n{\n  \"run\": true,\n  \"type\": \"require\",\n  \"path\": \"src/ui-modules/my-module/init.js\"\n}\n```\n","packages/runtime-class/docs/marko-5-upgrade.md":"# Upgrading to Marko 5\n\n## Step 0 - Ensure you're in a working state on the latest version of Marko 4\n\nBefore we start, you'll want to make sure that you are already on the latest `4.x` release of `marko`.\n\n```bash\n# Upgrade using yarn\nyarn upgrade marko@^4\n```\n\n```bash\n# Upgrade using npm\nnpm install marko@^4\n```\n\n> [!Warning]\n> Do _not_ run `npm install marko` (without the `@^4`). This will put you on Marko 5 and we're not quite there yet.\n\n> [!Tip]\n> If upgrading from Marko 3 you may want to reference [this guide](https://marko-v4.github.io/docs/marko-4-upgrade/).\n\nRun your application and tests to ensure your project is in a working state. There's little worse than finding an issue after you've started the upgrade process only to figure out the issue existed beforehand.\n\n## Step 1 - Upgrade Marko & Dependencies\n\n**TL;DR**: Paste & run this random shell script. It's safe. Trust us.\n\n```bash\n# Update Marko, and related ecosystem dependencies\nnpx -y npm-check-updates -u \\\n  marko \\\n  `# for webpack projects` \\\n  @marko/webpack \\\n  `# for lasso projects` \\\n  lasso lasso-marko @lasso/marko-taglib \\\n  `# for jest test runner` \\\n  @marko/jest \\\n  `# for projects with v3 widgets` \\\n  marko-widgets\n\n# Install @marko/compat-v4 unless `marko-widgets` is already installed\ngrep -q \"marko-widgets\" package.json || { [[ -f yarn.lock ]] && yarn add @marko/compat-v4 || npm install @marko/compat-v4; }\n[[ -f yarn.lock ]] && npx -y yarn-deduplicate && yarn\n[[ -f yarn.lock ]] || npm i\n```\n\nThis script automates the following steps for you:\n\n- Install the compat package\n  - `marko-widgets` if using Marko 3's Widgets\n  - `@marko/compat-v4` if not using Widgets\n- Update `marko` to 5.x\n- Update any ecosystem packages used by your app (lasso, webpack, jest, etc)\n\n> [!Note]\n> Check your `package.json`. If you have other third-party Marko packages not covered by the script, you may need to update them as well.\n\nYour application should continue to work. Run your tests to ensure everything is working. Congratulations! You've upgraded to Marko 5.\n","packages/runtime-class/docs/marko-json.md":"# `marko.json` & `marko-tag.json`\n\nMarko supports configuration files for validation, enabling experimental features, and custom paths for component files.\n\nThese configuration files are automatically found with [the same discovery mechanism as custom tags](./custom-tags.md#how-tags-are-discovered).\n\nThere are 2 types of configuration files:\n\n1. `marko.json` describes an entire suite of components.\n2. `marko-tag.json` describes a single component.\n\n## Single component definition\n\n`marko-tag.json` configures a single component. It’s automatically discovered if placed inside a [tag directory](./custom-tags.md#tag-directories).\n\n### Options\n\n```js\n{\n  \"html\": true, // Treat as a native HTML tag, not a custom tag.\n  \"htmlType\": \"svg\", // Optimizes for specific types of native tags (currently only `svg` and `html`).\n  \"open-tag-only\": true, // Forbids passing body content to this tag.\n  \"featureFlags\": [ \"feature-a\" ], // Enable beta features by passing feature flags.\n  \"nested-tags\": { // This section configures attribute tags.\n    \"tab\": {\n      \"target-property\": \"tabs\", // Puts `<@tab>` tags into `input.tabs`.\n      \"is-repeated\": true,  // Allow more than one nested `<@tab>`.\n      \"attributes\": {\n        // Same as the “Attributes” section below.\n      }\n    }\n  }\n}\n```\n\n### Attributes\n\nOne commonly-used feature of this config file is compile-time checks for attributes.\n\n```js\n{\n  \"attributes\": {\n    \"heading\": \"string\"\n  }\n}\n```\n\nThe above code ensures that the `heading` attribute is the _only_ attribute supplied to this tag.\n\nThe `string` value is used as documentation for the custom tag. It may be picked up by tooling, like Marko’s editor plugins, to provide hints to the user.\n\nThe recommended list of attribute types are as follows:\n\n- `expression` (any JavaScript expression)\n- `string`\n- `number`\n- `boolean`\n- `regexp`\n- `date`\n- `object`\n- `array`\n- `function`\n\nYou can also provide an object for an attribute definition’s value for additional options:\n\n```js\n{\n  \"attributes\": {\n    \"heading\": {\n      \"type\": \"string\", // Same as setting \"string\" above.\n      \"default-value\": 0, // The attribute will default to this value.\n      \"required\": true, // Error during compilation if this attribute is undefined. (Mutually exclusive with \"default-value\"\n      \"preserve-name\": true, // By default component attributes are camelCased; this disables that feature.\n      \"remove-dashes\": true, // By default native tag attributes are dash-cased; this disables that feature.\n\n      // The following attributes do nothing, but are picked up by tooling.\n      \"deprecated\": true,\n      \"description\": \"The component’s heading text\" // Describes the attribute’s purpose.\n    }\n  }\n}\n```\n\nWe can also describe a _pattern_ of attributes to match a definition:\n\n```js\n{\n    \"attributes\": {\n        \"data-*\": {\n          \"type\": \"string\",\n          \"pattern\": true\n        }\n    }\n}\n```\n\nIn the above, all attributes prefixed with `data-` are configured to be a `string`.\n\n> **Note:** Future Marko versions will describe these definitions/types in the component itself, reducing the need for this configuration file.\n\n### Paths\n\nThere are several options that override the default discovery of component files, such as the template.\n\nTypically, you should let Marko find these files automatically, but here is a reference in case you encounter these settings in the wild.\n\n```javascript\n{\n  \"template\": \"./template.marko\", // Custom path to the `.marko` template.\n  \"renderer\": \"./renderer.js\", // Custom path to the `renderer.js` file.\n\n  // Compiler file hooks\n  \"parse\": \"./parse.js\", // Used to augment parsing.\n  \"migrate\": \"./migrate.js\", // Used for migrating deprecated features.\n  \"transform\": \"./transform.js\", // Used to modify the AST before generating it.\n  \"analyze\": \"./analyze.js\" // Used to analyze metadata the entire ast before beginning to translate it.\n  \"translate\": \"./translate.js\" // Used to generate custom JS.\n}\n```\n\nFor more information about the compiler hooks [jump over here](./compiler.md#hooks).\n\n## Tag library definition\n\nAlong with configuring a single component, you can use a `marko.json` file to configure an _entire library of components_.\n\nSimilar to [`marko-tag.json`](#single-component-definition), this file is discovered if placed within a [tag directory](./custom-tags.md#tag-directories). It will also be discovered at the root directory of a project, or [in a `node_module` package](./custom-tags.md#publishing-tags-to-npm).\n\n### Options\n\n```js\n{\n  \"taglib-id\": \"my-custom-tag-library\", // Names the component library, for better errors.\n  \"exports\": \"./dist\", // Where to export the compiled components.\n  \"tags-dir\": \"./ui-modules\", // What directory to crawl to autodiscover components. Default:`./components/`\n  \"taglib-imports\": [\"./some-folder/marko.json\", \"./other-folder/marko.json\"], // Creates a _combined_ tag library by referencing others.\n  \"script-lang\": \"ts\", // Overrides the default script language, \"js\" or \"ts\", for mixed code such as an incremental TypeScript migration.\n\n  \"tags\": { // Definitions for individual tags.\n    \"my-tag\": {\n      // Same options as “marko-tag.json”.\n    }\n  },\n\n  \"attributes\": {\n    // Defines attributes on all tags.\n    // Options are the same as the “attributes” section in “marko-tag.json”.\n  },\n\n  // Compiler file hooks (run on all templates)\n  \"migrator\": \"./migrator.js\", // Hooks into the migration stage for migrating deprecated features.\n  \"transformer\": \"./transformer.js\", // Used to modify the AST before generating it.\n  \"text-transformer\": \"./text-transformer.js\", // Used to transform all static text in the template.\n}\n```\n\n> **⚠️ Note:** Compiler hooks are currently undocumented: avoid using them. The compiler API is overhauled in Marko 5, and will be documented once that transition is complete.\n\n## Shorthands\n\nBoth configuration files support _shorthands_ for defining `tags` and `attributes`. For example, take this `marko.json` file:\n\n_marko.json_\n\n```js\n{\n  \"taglib-id\": \"my-custom-tag-library\",\n  \"tags\": {\n    \"my-layout\": {\n      \"attributes\": {\n        \"name\": \"string\",\n        \"age\": \"number\"\n      },\n      \"nested-tags\": {\n        \"heading\": {\n          \"attributes\": {\n            \"color\": \"string\"\n          }\n        },\n        \"body\": {\n          \"attributes\": {\n            \"color\": \"string\"\n          }\n        }\n      }\n    }\n  }\n}\n```\n\nAs a shorthand, anywhere `tags` or `nested-tags` is used, you can remove the outer object and wrap the individual tags in `<angle-brackets>`.\n\nFor `attributes`, you can remove the outer object and prefix the attributes with an `@`.\n\nThe above example using the shorthand syntax would become:\n\n_marko.json_\n\n```js\n{\n  \"taglib-id\": \"my-custom-tag-library\",\n  \"<my-layout>\": {\n    \"@name\": \"string\",\n    \"@age\": \"number\",\n    \"<heading>\": {\n      \"@color\": \"string\"\n    },\n    \"<body>\": {\n      \"@color\": \"string\"\n    }\n  }\n}\n```\n\nFor `nested-tags`, there is also a shorthand for `is-repeated` (a postfix of `[]`) and `target-property` (a prefix of `@newName`):\n\n_marko.json_\n\n```javascript\n{\n  \"<my-layout>\": {\n    \"@sections <section>[]\": {\n      \"@color\": \"string\"\n    }\n  }\n}\n```\n\nIs equivalent to:\n\n_marko.json_\n\n```javascript\n{\n  \"tags\": {\n    \"my-layout\": {\n      \"nested-tags\": {\n        \"section\": {\n          \"target-property\": \"sections\",\n          \"is-repeated\": true,\n          \"attributes\": {\n            \"color\": \"string\"\n          }\n        }\n      }\n    }\n  }\n}\n```\n","packages/runtime-class/docs/marko-vs-react.md":"# Marko vs React: An In-depth Look\n\n<a href=\"https://hackernoon.com/marko-vs-react-an-in-depth-look-767de0a5f9a6\">\n  <img src=\"https://cdn-images-1.medium.com/max/2000/1*4BP6tPQtwImj6_QseeybwQ.png\" alt=\"Marko logo\" width=\"100%\" />\n</a><br />\n\n> This article was published March 2017. Both frameworks have gone through several updates since. You can find the original [\"Marko vs React: An In-depth Look\" article here](https://hackernoon.com/marko-vs-react-an-in-depth-look-767de0a5f9a6)!\n\nIn this article we will take an in-depth look at the differences and\nsimilarities between [Marko](https://markojs.com/) and React from the perspective\nof the maintainers of Marko.\n\nOn the surface, Marko and React have a lot in common and both are trying to\nsolve very similar problems. Specifically, both Marko and React allow developers\nto build web applications based on UI components and both free developers from\nhaving to write code to manually update the DOM. While many of the features in\nMarko were inspired by React, Marko and React offer very different usability and\nperformance characteristics. Marko was designed to avoid almost all boilerplate\nand is more closely aligned with HTML. In almost all cases, a Marko UI component\nwill require less lines of code than its React JSX equivalent while maintaining\nreadability and allowing the same expressiveness as JSX. In addition, Marko is\nhighly optimized for use on the server and in the browser and has a much smaller\nweight:\n\n<img src=\"https://cdn-images-1.medium.com/max/1600/1*a9hL_pfNrRq1UU3Mxkf3Jg.png\" alt=\"Marko logo\" width=\"100%\" /><br />\n\nBecause the Marko JavaScript library is much smaller than React, it will require\nless time to load and parse and this will drastically improve page load times on\nslow connections or on older devices. Based on [our\nbenchmarks](https://markojs.com/#benchmarks), Marko consistently outperforms\nReact by a significant margin on both the server and in the browser.\n\n### Example\n\nThe following code highlights some of the differences between Marko and React\nJSX using a somewhat contrived UI component as an example:\n\n#### React JSX\n\n```jsx\nclass Counter extends React.Component {\n  constructor(props) {\n    super(props);\n\n    this.state = { count: 0 };\n  }\n\n  increment(delta) {\n    this.setState({ count: this.state.count + delta });\n  }\n\n  render() {\n    const count = this.state.count;\n    let countClassName = \"count\";\n\n    if (count > 0) {\n      countClassName += \" positive\";\n    } else if (count < 0) {\n      countClassName += \" negative\";\n    }\n\n    return (\n      <div className=\"click-count\">\n        <div className={countClassName}>{count}</div>\n        <button\n          onClick={() => {\n            this.increment(-1);\n          }}\n        >\n          -1\n        </button>\n        <button\n          onClick={() => {\n            this.increment(1);\n          }}\n        >\n          +1\n        </button>\n      </div>\n    );\n  }\n}\n```\n\n<span class=\"figcaption_hack\">[▶ Try Online](https://codepen.io/mlrawlings/pen/wJXOWR?editors=0010)</span>\n\n#### Marko\n\n```marko\nclass {\n  onCreate() {\n    this.state = { count: 0 };\n  }\n  increment(delta) {\n    this.state.count += delta;\n  }\n}\n\n$ var count = state.count;\n\n<div.click-count>\n  <div.count class={\n      positive: count > 0,\n      negative: count < 0\n    }>\n    ${count}\n  </div>\n  <button on-click('increment', -1)>\n    -1\n  </button>\n  <button on-click('increment', 1)>\n    +1\n  </button>\n</div>\n```\n\n<span class=\"figcaption_hack\">[▶ Try\nOnline](https://markojs.com/try-online/?gist=8fe46bc5866605aca0dfeec202604011)</span>\n\n### Similarities\n\nMarko and React have the following in common:\n\n- UI component-based\n- JavaScript and HTML markup can be intertwined\n- No restrictions on JavaScript (use ES5 or ES2015+, your choice)\n- Virtual DOM rendering in the browser\n- DOM diffing/patching is used to reconcile views\n- Both support keyed element matching\n- UI components can have input properties\n- UI components can have internal state\n- Changes to state trigger an asynchronous update to the DOM\n- Updates to the DOM are batched\n- Compatible with central application state stores such as Redux and MobX\n- UI components can be embedded using custom tags\n- Declarative event binding (no `domEl.addEventListener()` needed)\n- Support for all DOM events\n- Event delegation utilized internally for DOM events that bubble\n- IE9+ support\n- Similar lifecycle events for UI components\n- JSX and Marko both compile to JavaScript\n\n### Differences\n\nAt a high level here are some differences:\n\n#### Differences in rendering\n\n- **Improved performance:** Marko renders to a virtual DOM in the browser and\n  directly to an HTML stream on the server (Marko supports multiple compilation\n  targets).\n- **Improved performance:** Marko supports asynchronous rendering with [early\n  flushing of\n  HTML](https://tech.ebayinc.com/engineering/async-fragments-rediscovering-progressive-html-rendering-with-marko/)\n  for improvements in actual and perceived page load times.\n- **Improved performance:** React requires an additional client-side re-render if\n  a page is initially rendered on the server while Marko does not.\n- **Improved ease of use:** Marko automatically serializes UI component state and\n  input down to the browser so that the browser can pick up right where the server\n  left off.\n- **Improved ease of use:** Marko is suitable for rendering an entire HTML page on\n  the server with support for tags such as `<doctype>` and `<html>`\n\n#### Differences in syntax\n\n- **Improved ease of use:** Marko uses the\n  [HTML-JS](https://markojs.com/docs/syntax/) syntax and the\n  [JSX](https://facebook.github.io/react/docs/jsx-in-depth.html) syntax is offered\n  for React.\n- **Improved ease of use:** Marko supports both a concise syntax and a familiar\n  HTML syntax.\n- **Improved ease of use:** JSX requires strict XML while Marko aligns with less\n  strict HTML that web developers are used to.\n- **Improved ease of use:** With Marko, _all_ HTML attribute values are parsed as\n  JavaScript expressions.\n- **Improved ease of use:** Marko supports simple directives for conditionals,\n  looping, etc.\n- **JSX limitation:** JSX is “just JavaScript” but requires expressions that\n  preclude the usage of JavaScript statements such as in certain places.\n\n#### Differences in compilation\n\n- **Improved performance:** Marko supports multiple compilation outputs (Marko\n  VDOM and HTML streaming are currently supported).\n- **Improved ease of use:** Marko compiles UI components to JavaScript modules\n  that export a rendering API.\n- **Expanded capabilities:** Marko supports a robust API for controlling how\n  custom tags and custom attributes get compiled and it supports compile-time\n  transforms based on a friendly Abstract Syntax Tree (AST).\n- **Improved performance:** JSX is just syntactic sugar that translates elements\n  to `createElement()` function calls while the Marko compiler has full control over how things are\n  compiled and optimized.\n- **Improved ease of use:** React requires all UI components to be explicitly\n  imported before they can be used as custom tags while Marko supports both\n  explicit importing and implicit importing.\n- **Improved performance:** Marko has a modular runtime and the compiler generates\n  code that only imports the parts of the Marko runtime that are needed for much\n  smaller builds.\n- **Improved ease of use:** Marko supports optional compile-time checks to ensure\n  that only allowed attributes are passed to custom tags. (React `PropTypes` only provide\n  validation at render-time)\n- **Improved ease of use:** Marko validates _all_ tag names at compile-time.\n- **Improved ease of use:** Marko provides its own compiler that integrates with\n  Node.js and JavaScript module bundlers while React JSX requires babel and custom\n  babel transforms.\n\n#### Differences in UI components\n\n- **Reduced boilerplate:** No explicit extending of JavaScript classes in Marko\n  (in contrast to `class Counter extends React.Component` in React).\n- **Improved ease of use:** Modifications to UI component state are synchronous\n  with Marko while [the rules for React are more\n  complicated](https://facebook.github.io/react/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous).\n- **Improved ease of use:** Marko watches UI component state objects to allow\n  state to be modified directly (e.g., `this.state.count++`).\n- **Improved ease of use:** Marko supports single-file UI components combining\n  JavaScript behavior, CSS styling (with support for CSS preprocessors) and HTML\n  markup. (React requires using one of the many [CSS in JS\n  solutions](https://github.com/MicheleBertoli/css-in-js) if you want styles in\n  the same file as your component and there is no standard in the community)\n- **Improved maintainability:** Marko supports a seamless transition from a\n  single-file UI component to a multi-file UI component.\n- **Improved performance:** Marko assumes UI components are pure by default and\n  skips re-rendering when input properties and state are unchanged (React requires\n  extending\n  [React.PureComponent](https://facebook.github.io/react/docs/react-api.html#react.purecomponent)).\n\n#### Differences in event systems\n\n- **Reduced complexity:** React utilizes [synthetic\n  events](https://facebook.github.io/react/docs/events.html) while Marko utilizes\n  real DOM events.\n- **Improved ease of use:** Custom events are emitted using the [EventEmitter\n  API](https://nodejs.org/api/events.html) in Marko (e.g., `this.emit('myCustomEvent', arg1, arg2)`).\n- **Improved ease of use:** Marko has a consistent approach for listening to both\n  native DOM events and custom events.\n- **Improved ease of use:** React requires passing around `Function` references for custom\n  events while Marko automatically delegates emitted custom events to event\n  handler methods on components.\n- **Improved ease of use:** Marko provides a simple mechanism for binding\n  additional arguments to event handler methods and `this` will be the component\n  instance.\n\n#### Differences in compatibility\n\n- **Marko limitation:** Marko has no support for native mobile similar to React\n  Native (although with Marko VDOM rendering, this is possible).\n- **Marko limitation:** Marko requires a JavaScript module bundler (such as\n  [Lasso](https://markojs.com/docs/lasso/),\n  [Webpack](https://markojs.com/docs/webpack/),\n  [Rollup](https://markojs.com/docs/rollup/)\n  since Marko UI components compile down to JavaScript modules. (we consider using\n  a JavaScript module bundler a best practice)\n\n---\n\nIn the sections below we will take a closer look at some of the differences\nbetween Marko and React.\n\n### Syntax\n\nBoth Marko and React JSX allow HTML markup and JavaScript to be combined into a\nsingle file and both support building web applications based on UI components.\nMarko utilizes an [HTML-JS syntax](https://markojs.com/docs/syntax/) while most\nReact apps use the JSX syntax.\n\n> React JSX makes JavaScript more like HTML and Marko makes HTML more like\n> JavaScript.\n\nIn the end, both Marko and React allow JavaScript and HTML to be intertwined.\n\n### Syntax: attributes\n\n#### React JSX\n\nIn React JSX, all attribute values are parsed as string values unless `{}` is used.\n\n```jsx\n<MyComponent\n  name=\"Frank\"\n  messageCount={30}\n  visible={true}\n  person={{ firstName: 'John', lastName: 'Doe' }}\n  colors={['red', 'green', 'blue']} />\n\n<div id=\"content\" className=\"foo\">Hello</div>\n```\n\n#### Marko\n\nWith Marko, _all_ attribute values are parsed as JavaScript expressions. The\nfollowing Marko code is equivalent to the React JSX code above:\n\n```marko\n<my-component\n  name=\"Frank\"\n  message-count=30\n  visible=true\n  person={ firstName: 'John', lastName: 'Doe' }\n  colors=['red', 'green', 'blue'] />\n\n<div id=\"content\" class=\"foo\">Hello</div>\n```\n\n### Syntax: inline JavaScript\n\n#### React JSX\n\nReact JSX starts with JavaScript and allows XML elements to be inlined as shown\nbelow:\n\n```jsx\nimport { formatDate } from \"./util\";\n\nfunction formatName(person) {\n  return person.firstName + \" \" + person.lastName.charAt(0) + \".\";\n}\n\nexport default function HelloMessage(props) {\n  var person = props.person;\n\n  return (\n    <div>\n      Hello {formatName(person)}!\n      <span>You were born on {formatDate(person.birthday)}.</span>\n    </div>\n  );\n}\n```\n\n#### Marko\n\nMarko starts out in HTML, but it allows JavaScript to be inlined in a clean and\nmaintainable way. Unlike other template languages, Marko aims to allow the full\npower of JavaScript. The following Marko code is equivalent to the React JSX\ncode above:\n\n```marko\nimport { formatDate } from './util';\n\nstatic function formatName(person) {\n    return person.firstName + ' ' + person.lastName.charAt(0) + '.';\n}\n\n$ var person = input.person;\n\n<div>\n    Hello ${formatName(person)}!\n    <span>\n      You were born on ${formatDate(person.birthday)}.\n    </span>\n</div>\n```\n\nLines prefixed with `$` are directly added to the compiled JavaScript output inside\nthe compiled `render()` function (for JavaScript code that should run for every render).\nLines prefixed with `static` are directly added to the compiled JavaScript output\noutside the `render()` function (for code that should only run _once_ when the template is\nloaded).\n\n### Syntax: HTML support\n\nWith Marko any valid HTML markup can be used inside a Marko template. This is\nnot the case with React. The following quote is from the [React\ndocumentation](https://facebook.github.io/react/docs/introducing-jsx.html#specifying-children-with-jsx):\n\n> **Caveat:**\n\n> Since JSX is closer to JavaScript than HTML, React DOM uses `camelCase` property naming\n> convention instead of HTML attribute names.\n\n> For example, `class` becomes `className` in JSX, and `tabindex` becomes `tabIndex`.\n\nAs a result of this caveat for React, [tools for converting HTML to JSX\nexist](https://magic.reactjs.net/htmltojsx.htm).\n\n#### React JSX\n\n```jsx\n<div id=\"content\" className=\"my-component\">Hello</div>\n\n<input type=\"text\" name=\"firstName\" value=\"John\" />\n```\n\n#### Marko\n\n```marko\n<div id=\"content\" class=\"my-component\">Hello</div>\n\n<input type=\"text\" name=\"firstName\" value=\"John\">\n```\n\n### Syntax: conditionals\n\nJSX is syntactic sugar on top of JavaScript, but it requires expressions, so\nsimple things like an `if/else/for` statement don’t work on their own within a JSX element. As\na result, you must either use a ternary expression, an immediately invoked\nfunction expression, function call expression, or the experimental `do {}` expression\n(stage 0 at the time of writing). This is not an issue for Marko, and tags\nsuch as `if()` and `for` can be used anywhere as shown below:\n\n#### React JSX\n\n```jsx\nfunction counterMessage(count) {\n  return (\n    <div className=\"counter-message\">\n      (function() {\n        if (count < 0) {\n          return <div>Count is negative</div>\n        } else if (count === 0) {\n          return <div>Count is zero</div>\n        } else {\n          return <div>Count is positive</div>\n        }\n      }())\n    </div>\n  )\n}\n```\n\n#### Marko\n\n```marko\n<div.counter-message>\n  <if(count < 0)>\n    <div>Count is negative</div>\n  </if>\n  <else if(count === 0)>\n    <div>Count is zero</div>\n  </else>\n  <else>\n    <div>Count is positive</div>\n  </else>\n</div>\n```\n\nMarko also allows directives to be used as attributes for a more condensed\ntemplate:\n\n```marko\n<div.counter-message>\n  <div if(count < 0)>Count is negative</div>\n  <div if(count === 0)>Count is zero</div>\n  <div else>Count is positive</div>\n</div>\n```\n\n### Syntax: looping\n\n#### React JSX\n\n```jsx\nfunction renderColors(colors) {\n  return (\n    <ul>\n      {colors.map((color) => (\n        <li\n          className=\"color\"\n          style={{\n            backgroundColor: color,\n          }}\n        >\n          {color}\n        </li>\n      ))}\n    </ul>\n  );\n}\n```\n\n#### Marko\n\n```marko\n<ul>\n  <for|color| of=colors>\n    <li.color style={ backgroundColor: color }>\n        ${color}\n    </li>\n  </for>\n</ul>\n```\n\n### Syntax: HTML shorthand\n\n```marko\n<div id=\"content\"/>\n<h1 class=\"subheader\"/>\n<h1 id=\"pageTitle\" class=\"foo bar\"/>\n\n<!-- Shorthand equivalent: -->\n<div#content/>\n<h1.subheader/>\n<h1#pageTitle.foo.bar/>\n```\n\nMarko supports a shorthand based on CSS selectors for less code.\n\nReact does not support these helpful shorthands.\n\n### Syntax: concise\n\nMarko supports a concise syntax that drops angled brackets and ending tags in\nfavor of indentation. Here’s how the Marko syntax options compare:\n\n#### Marko HTML syntax\n\n```marko\n<ul>\n  <for|color| of=colors>\n    <li>${color}</li>\n  </for>\n</ul>\n```\n\n#### Marko concise syntax\n\n```marko\nul\n  for|color| of=colors\n    li -- ${color}\n```\n\n#### Marko mixed syntax\n\n```marko\nul\n  for|color| of=colors\n    <li>${color}</li>\n```\n\nThe HTML syntax and the concise syntax can be used together:\n\n#### React JSX\n\nReact does not offer a concise syntax.\n\n### Components\n\nMarko starts with simple HTML and allows UI component logic to easily be layered\non top.\n\n#### React JSX\n\nA React UI component is typically implemented as a class that extends `ReactComponent`:\n\n```jsx\nclass HelloMessage extends React.Component {\n  render() {\n    return <div>Hello {this.props.name.toUpperCase()}</div>;\n  }\n}\n```\n\nReact also supports a more concise functional component:\n\n```jsx\nfunction HelloMessage(props) {\n  return <div>Hello {props.name.toUpperCase()}</div>;\n}\n```\n\nHowever, if state or lifecycle events are needed then a functional UI component\nmust be converted to a class component:\n\n```jsx\nclass HelloMessage extends React.Component {\n  componentDidMount() {\n    // ...\n  }\n  render() {\n    return <div>Hello {this.props.name.toUpperCase()}</div>;\n  }\n}\n```\n\n#### Marko\n\nHere is the same component in Marko:\n\n```marko\n<div>Hello ${input.name.toUpperCase()}</div>\n```\n\nBehavior can easily be added to any Marko UI component:\n\n```marko\nclass {\n  onMount() {\n    // ...\n  }\n}\n\n<div>Hello ${input.name.toUpperCase()}</div>\n```\n\nMarko also allows JavaScript behavior, CSS styling and HTML markup to be\nembedded in the Marko template as a single file UI component:\n\n```marko\nclass {\n  onMount() {\n    // ...\n  }\n}\n\nstyle.less {\n  .hello {\n    color: red;\n  }\n}\n\n<div.hello>\n  Hello ${input.name.toUpperCase()}\n</div>\n```\n\n### API\n\nMarko compiles components to JavaScript modules that export their rendering APIs,\nas shown below:\n\n```js\nimport Greeting from \"./components/greeting.marko\";\nGreeting.renderSync({ name: \"Frank\" }).appendTo(document.body);\n```\n\nThe same UI component can render to streams, such as a writable HTTP\nresponse stream:\n\n```js\nimport Greeting from \"./components/greeting.marko\";\nGreeting.render({ name: \"John\" }, res);\n```\n\n> The users of a Marko UI component do not need to know that the component was\n> implemented using Marko.\n\nContrast this with React as an example:\n\n```jsx\nimport ReactDOM from \"react-dom\";\n\nReactDOM.render(\n  <HelloMessage name=\"John\" />,\n  document.getElementById(\"container\"),\n);\n```\n\nOn top of that, React requires that a different module be imported to render the\nexact same UI component on the server:\n\n```jsx\nimport ReactDOMServer from \"react-dom/server\";\n\nvar html = ReactDOMServer.renderToString(<HelloMessage name=\"John\" />);\n```\n\n### Custom tags\n\n#### React JSX\n\nWith React, all custom tags for UI components must be explicitly imported:\n\n```jsx\nimport Hello from \"./components/Hello\";\nimport GoodBye from \"./components/GoodBye\";\n\nexport default function HelloGoodBye(props) {\n  return (\n    <div>\n      <Hello name={props.name} />\n      <GoodBye name={props.name} />\n    </div>\n  );\n}\n```\n\n#### Marko\n\nMarko supports a mechanism for [automatically discovering custom\ntags](https://markojs.com/docs/custom-tags/#discovering-tags) for UI components\nbased on the project directory structure. Marko walks up the directory tree to\ndiscover all directories and it will also automatically discover custom tags\nexported by installed packages. This approach negates the need for explicitly\nimporting a custom tag to reduce the amount of code needed in a Marko template.\nFor example given the following directory structure:\n\n```\n    .\n    ├── components/\n    │   ├── hello.marko\n    │   └── good-bye.marko\n    └── index.marko\n```\n\nThe `<hello>` tag and the `<good-bye>` tag nested below the `components/`\ndirectory will automatically be made available to the `index.marko` at the root:\n\n```marko\n<div>\n  <hello name=input.name />\n  <good-bye name=input.name />\n</div>\n```\n\nThis approach also allows editors and IDEs to offer autocompletion for custom\ntags.\n\n### Async\n\nEven after rendering has started, Marko allows parts of the view to be rendered\nasynchronously using the [`<await>`](https://markojs.com/docs/core-tags#await)\ntag as shown in the following Marko template:\n\n```marko\nimport fsp from 'fs-promise';\n\n$ var filePath = __dirname + '/hello.txt';\n$ var readPromise = fsp.readFile(filePath, {encoding: 'utf8'});\n\n<await(readPromise)>\n  <@then|helloText|>\n    <p>${helloText}</p>\n  </@then>\n</await>\n```\n\n### Compiler\n\nMarko compiles a template differently based on whether or not it will be used on\nthe server or in the browser. For example, given the following template:\n\n```marko\n<div>Hello ${input.name}!</div>\n```\n\n#### Compiled for the server:\n\n```js\nvar marko_template = require(\"marko/html\").t(__filename),\n  marko_helpers = require(\"marko/runtime/html/helpers\"),\n  marko_escapeXml = marko_helpers.x;\n\nfunction render(input, out) {\n  out.w(\"<div>Hello \" + marko_escapeXml(input.name) + \"!</div>\");\n}\n```\n\n#### Compiled for the browser:\n\n```js\nvar marko_template = require(\"marko/vdom\").t(__filename);\n\nfunction render(input, out) {\n  out.e(\"DIV\", null, 3).t(\"Hello \").t(input.name).t(\"!\");\n}\n```\n\n### Compile-time code transforms\n\nThe Marko compiler was built to support compile-time code generators for custom\ntags and it also provides support for compile-time transforms. While Babel\nallows code transformations of JavaScript, the Marko compiler provides support\nfor resolving custom tags declaratively and the Marko AST provides for very\npowerful and simple transformations as shown in the following code for rendering\nMarkdown to HTML at _compile-time_:\n\n**components/markdown/code-generator.js:**\n\n```js\nimport marked from \"marked\";\nimport { removeIndentation } from \"./util\";\n\nexport default function generateCode(el, codegen) {\n  var bodyText = removeIndentation(el.bodyText);\n  var html = marked(bodyText);\n  var builder = codegen.builder;\n  return builder.html(builder.literal(html));\n}\n```\n\nThe `<markdown>` tag can then be used as shown below:\n\n```marko\n<markdown>\n\n> This section demonstrates Markdown in Marko\n\n# Marko is awesome!\n\n- High performance\n- Small\n- Intuitive\n\n</markdown>\n```\n\nIn this example, after the template is compiled, the\n[marked](https://github.com/chjj/marked) library is no longer needed at\nrender-time.\n\n### Tools\n\nMarko and React offer a variety of developer tools. The [Marko developer\ntools](https://github.com/marko-js/marko-devtools) are constantly evolving, but\nMarko currently provides tools for unit testing UI components, precompiling `.marko`\nfiles and generating configuration-less apps (similar to\n[create-react-app](https://github.com/facebookincubator/create-react-app)).\nCurrently, there are no Marko developer tools that integrate with the browser,\nbut this is something we would like to see in the future. We will go into more\ndetail on the Marko developer tools in a future post.\n\n#### IDE and editor support\n\nMarko offers syntax highlighting across all major IDEs and editors, as well as\non GitHub. Marko provides first-class support for the Atom editor with syntax\nhighlighting,\n[Autocomplete](https://github.com/marko-js/atom-language-marko#autocomplete) for\nboth HTML and custom tags,\n[Hyperclick](https://github.com/marko-js/atom-language-marko#hyperclick) to\nquickly jump to referenced files and methods, and [Pretty\nprinting](https://github.com/marko-js/atom-language-marko#prettyprint) to keep\nyour code readable.\n\n---\n\n### Why Marko?\n\nHere are just a few reasons you should consider using\n[Marko](https://markojs.com/) over React:\n\n- Marko requires much less boilerplate.\n- Marko has much better performance based on our benchmarks.\n- Marko offers a clean and powerful syntax that aligns with HTML while also\n  allowing the full power of JavaScript.\n- Marko has much less complexity and a very small runtime.\n- Marko has a much lower page weight for faster page loads.\n- Marko has strong integrations with Node.js.\n- Marko allows for extremely powerful IDE and editor plugins (see the [Marko\n  plugin for Atom](https://github.com/marko-js/atom-language-marko) as an\n  example).\n- Marko has a powerful compiler that allows new features to be added without\n  introducing bloat.\n- eBay relies heavily on Marko and it is being used to build ebay.com (including\n  the mobile web).\n- Marko has a strong and growing community on\n  [GitHub](https://github.com/marko-js/marko) and in\n  [Discord](https://discord.gg/RFGxYGs).\n\nInterested in learning more about Marko? If so, you can get additional\ninformation on the [Marko website](https://markojs.com/). Join the conversation\nand contribute on [GitHub](https://github.com/marko-js/marko) and follow us on\n[Twitter](https://twitter.com/MarkoDevTeam).\n","packages/runtime-class/docs/redux.md":"# Redux + Marko\n\nSee the [`marko-redux` sample project](https://github.com/marko-js/examples/tree/master/examples/redux) for a fully-working example.\n\n## Installation\n\nFirst, save the [`marko`](https://www.npmjs.com/package/marko) and [`redux`](https://www.npmjs.com/package/redux) packages to your project’s dependencies:\n\n```bash\nnpm i marko redux\n```\n\n## Usage\n\nThe partial code below shows how a Marko UI component can connect to a Redux store, using Redux’s `store.subscribe()` method and Marko’s `forceUpdate()` method:\n\n### `counter.marko`\n\n```marko\nimport store from './store.js';\n\nclass {\n  onMount () {\n    store.subscribe(() => {\n      // Force this UI component to rerender\n      this.forceUpdate();\n\n      // The UI component will rerender with the new\n      // state returned by `store.getState()`\n      //\n      // You could also force an update like this:\n      // this.input = store.getState();\n    });\n  }\n}\n\n<counter(store.getState()) />\n```\n\n### `reducer.js`\n\n```js\nexport default function (state, action) {\n  state = state || { value: 0 };\n\n  // Additional reducer logic here…\n\n  return state;\n}\n```\n\n### `store.js`\n\nIn `counter.marko`, the imported store module exports a Redux store created with the following code:\n\n```js\nimport redux from \"redux\";\nimport counter from \"./reducer.js\";\n\nexport default redux.createStore(counter);\n```\n","packages/runtime-class/docs/rendering.md":"# Rendering\n\nTo render a Marko view, you need to `import` it.\n\n_example.js_\n\n```js\nimport FancyButton from \"./components/fancy-button.marko\";\n```\n\n> **Note:** If you are targeting node.js, you will need to enable the [require extension](./installing.md#require-marko-views) in order to require `.marko` files or you will need to precompile all of your templates using [Marko CLI](https://github.com/marko-js/cli). If you are targeting the browser, you will need to use a bundler like [`lasso`](./lasso.md), [`webpack`](./webpack.md) or [`rollup`](./rollup.md).\n\nOnce you have a view, you can pass input data and render it:\n\n_example.js_\n\n```js\nimport FancyButton from \"./components/fancy-button.marko\";\nconst html = FancyButton.renderToString({ label: \"Click me!\" });\n\nconsole.log(html);\n```\n\nThe data passed to `renderToString` becomes available as `input` in the component, so if `fancy-button.marko` looked like this:\n\n_./components/fancy-button.marko_\n\n```marko\n<button>${input.label}</button>\n```\n\nThe output HTML would be:\n\n```html\n<button>Click me!</button>\n```\n\n## Rendering methods\n\nWe used the `renderToString` method above to render the view, but there are a number of different method signatures that can be used to render.\n\nMany of these methods return a [`RenderResult`](#renderresult) which is an object with helper methods for working with the rendered output.\n\n### `renderSync(input)`\n\n| params       | type                            | description                            |\n| ------------ | ------------------------------- | -------------------------------------- |\n| `input`      | `Object`                        | the input data used to render the view |\n| return value | [`RenderResult`](#renderresult) | The result of the render               |\n\nUsing `renderSync` forces the render to complete synchronously. If a tag attempts to run asynchronously, an error will be thrown.\n\n```js\nimport View from \"./view.marko\";\nvar result = View.renderSync({});\n\nresult.appendTo(document.body);\n```\n\n### `render(input)`\n\n| params       | type                             | description                            |\n| ------------ | -------------------------------- | -------------------------------------- |\n| `input`      | `Object`                         | the input data used to render the view |\n| return value | `AsyncStream`/`AsyncVDOMBuilder` | the async `out` render target          |\n\nThe `render` method returns an async `out` which is used to generate HTML on the server or a virtual DOM in the browser. In either case, the async `out` has a `then` method that follows the Promises/A+ spec, so it can be used as if it were a Promise. This promise resolves to a [`RenderResult`](#renderresult).\n\n```js\nimport View from \"./view.marko\";\nvar resultPromise = View.render({});\n\nresultPromise.then((result) => {\n  result.appendTo(document.body);\n});\n```\n\n### `render(input, callback)`\n\n| params         | type                             | description                                    |\n| -------------- | -------------------------------- | ---------------------------------------------- |\n| `input`        | `Object`                         | the input data used to render the view         |\n| `callback`     | `Function`                       | a function to call when the render is complete |\n| callback value | [`RenderResult`](#renderresult)  | The result of the render                       |\n| return value   | `AsyncStream`/`AsyncVDOMBuilder` | the async `out` render target                  |\n\n```js\nimport View from \"./view.marko\";\n\nView.render({}, (err, result) => {\n  result.appendTo(document.body);\n});\n```\n\n### `render(input, stream)`\n\n| params       | type                             | description                            |\n| ------------ | -------------------------------- | -------------------------------------- |\n| `input`      | `Object`                         | the input data used to render the view |\n| `stream`     | `WritableStream`                 | a writeable stream                     |\n| return value | `AsyncStream`/`AsyncVDOMBuilder` | the async `out` render target          |\n\nThe HTML output is written to the passed `stream`. Render errors are emitted as `\"error\"` events on the stream, and like any unhandled stream `\"error\"` event, one without a listener crashes the process, so always attach one:\n\n```js\nimport http from \"http\";\nimport View from \"./view.marko\";\n\nhttp.createServer((req, res) => {\n  res.setHeader(\"content-type\", \"text/html\");\n  View.render({}, res).on(\"error\", (err) => {\n    console.error(err);\n  });\n});\n```\n\n### `render(input, out)`\n\n| params       | type                             | description                            |\n| ------------ | -------------------------------- | -------------------------------------- |\n| `input`      | `Object`                         | the input data used to render the view |\n| `out`        | `AsyncStream`/`AsyncVDOMBuilder` | The async `out` to render to           |\n| return value | `AsyncStream`/`AsyncVDOMBuilder` | The `out` that was passed              |\n\nThe `render` method also allows passing an existing async `out`. If you do this, `render` will not automatically end the async `out` (this allows rendering a view in the middle of another view). If the async `out` won't be ended by other means, you are responsible for ending it.\n\n```js\nimport View from \"./view.marko\";\nvar out = View.createOut();\n\nView.render({}, out);\n\nout.on(\"finish\", () => {\n  console.log(out.getOutput());\n});\n\nout.end();\n```\n\n### `renderToString(input)`\n\n| params       | type     | description                            |\n| ------------ | -------- | -------------------------------------- |\n| `input`      | `Object` | the input data used to render the view |\n| return value | `String` | The HTML string produced by the render |\n\nReturns an HTML string and forces the render to complete synchronously. If a tag attempts to run asynchronously, an error will be thrown.\n\n```js\nimport View from \"./view.marko\";\nvar html = View.renderToString({});\n\ndocument.body.innerHTML = html;\n```\n\n### `renderToString(input, callback)`\n\n| params         | type        | description                            |\n| -------------- | ----------- | -------------------------------------- |\n| `input`        | `Object`    | the input data used to render the view |\n| callback value | `String`    | The HTML string produced by the render |\n| return value   | `undefined` | N/A                                    |\n\nAn HTML string is passed to the callback.\n\n```js\nimport View from \"./view.marko\";\n\nView.renderToString({}, (err, html) => {\n  document.body.innerHTML = html;\n});\n```\n\n### `stream(input)`\n\nThe `stream` method returns a Node.js-style stream of the output HTML.\n\n```js\nimport fs from \"fs\";\nimport View from \"./view.marko\";\nconst writeStream = fs.createWriteStream(\"output.html\");\n\nView.stream({}).pipe(writeStream);\n```\n\nThis method is available on the server, but not available by default in the browser. If you need to use streams in the browser, you may `import 'marko/stream'` as part of your client-side bundle.\n\n## RenderResult\n\n### `getComponent()`\n\n### `getComponents(selector)`\n\n### `afterInsert(doc)`\n\n### `getNode(doc)`\n\n### `getOutput()`\n\n### `appendTo(targetEl)`\n\n### `insertAfter(targetEl)`\n\n### `insertBefore(targetEl)`\n\n### `prependTo(targetEl)`\n\n### `replace(targetEl)`\n\n### `replaceChildrenOf(targetEl)`\n\n## Global data\n\nIf you need to make data available to all rendered views, use the `$global` property on the input data object. This property will be removed from `input` and provided to the template through a variable called `$global`. It is also made available on the `out.global` property.\n\nGlobal values persist across renders.\n\n```js\nView.render({\n  $global: {\n    flags: [\"mobile\"],\n  },\n});\n```\n\nWithin the template you can access `$global` similar to accessing `input`.\n\n```marko\n<div>\n  You are on ${$global.flags.includes(\"mobile\") ? \"mobile\" : \"desktop\"}\n</div>\n```\n\n> **Note:** `$global` is not available within [`static`](./syntax.md#static-javascript) parts of the template. In order to reference `$global` within the component class you must use `out.global` from one of the lifecycle methods that provide it.\n\n> **Warning:** Use `$global` with caution; it is visible in any component.\n\n### Sending global data to browsers\n\n⚠️ To prevent accidentally exposing sensitive data, by default **no keys** in `$global` are sent to browsers. To serialize data to the frontend, name the desired properties in `$global.serializedGlobals`.\n\nValues must be serializable by [the `warp10` module](https://www.npmjs.com/package/warp10).\n\n```js\nimport Page from \"./index.marko\";\n\napp.get(\"/\", (req, res) => {\n  const ua = req.get(\"User-Agent\");\n\n  Page.render(\n    {\n      $global: {\n        isIos: /iPad|iPhone/.test(ua), // Serialized and available on the server and browser as `$global.isIos`\n        isAndroid: /Android/.test(ua), // Serialized and available on the server and browser as `$global.isAndroid`\n        req, // Only available server-side and not serialized, because it’s not in `serializedGlobals`\n\n        serializedGlobals: {\n          isIos: true, // Tell Marko to serialize `isIos`\n          isAndroid: true, // Tell Marko to serialize `isAndroid`\n        },\n      },\n    },\n    res,\n  );\n});\n```\n\n> **Warning:** Ensure that you serialize only data which is necessary for the browser. Serialization is expensive for both server rendering performance and HTML output size.\n\nFor details, check [#672: “Serialize only input and state on top-level server-rendered UI components”](https://github.com/marko-js/marko/pull/672).\n","packages/runtime-class/docs/rollup.md":"# Marko + Rollup\n\nThis is Marko’s official integration plugin for [the Rollup bundler](https://rollupjs.org/).\n\n## Installation\n\n```sh\nnpm install --save-dev \\\n  @marko/rollup \\\n  rollup \\\n  @rollup/plugin-node-resolve \\\n  @rollup/plugin-commonjs\n```\n\n> **Note**: The Marko runtime is CommonJS, so don’t forget the `@rollup/plugin-commonjs` package!\n\n## Configuration\n\n`@marko/rollup` exports two methods for use in [Rollup configuration files](https://rollupjs.org/guide/en/#configuration-files): `.browser()` and `.server()`.\n\nYou _probably_ want to use both, since that’ll get you…\n\n- Automatic [`input` entrypoint configuration](https://rollupjs.org/guide/en/#input) for route-based bundle splitting\n- Complete control over asset loading with [the `<rollup>` tag](#rollup-tag)\n- The strengths behind why Marko exists in the first place: cooperation between servers and browsers for high performance in both\n\n> **ProTip**: You _could_ use only `.browser()` or only `.server()` to build a completely client-side-rendered or server-side-rendered app. That would be a little odd, but you could.\n\n### Config example\n\n```js\nimport nodeResolve from \"@rollup/plugin-node-resolve\";\nimport commonjs from \"@rollup/plugin-commonjs\";\nimport marko from \"@marko/rollup\";\n\nconst sharedPlugins = [\n  commonjs({\n    extensions: [\".js\", \".marko\"]\n  }),\n  // If using Marko’s `style {}` blocks, you’ll need an appropriate plugin, like npmjs.com/rollup-plugin-postcss\n  postcss({ external: true })\n]\n\nconst serverAssetsConfig = {\n  input: \"src/start-server.js\",\n  plugins: [\n    marko.server(),\n    nodeResolve({ preferBuiltins: true })\n    ...sharedPlugins\n  ]\n};\nconst browsersAssetsConfig = {\n  plugins: [\n    marko.browser(),\n    nodeResolve({ browser: true })\n    ...sharedPlugins\n  ]\n};\n\nexport default [serverAssetsConfig, browsersAssetsConfig];\n```\n\n### Advanced config example\n\nThe following configuration file is long and hairy, which may be upsetting to some viewers. However, it does show how to accomplish the following:\n\n- Support for Rollup’s watch mode\n- A bundle analyzer\n- The ability to `import` JSON files to use their data\n- The ability to `import` image files to use their asset URLs for `img[src]` and such\n- Dead-code elimination for development-only code\n- Static compression of assets for something like [NGiNX’s `gzip_static`](https://nginx.org/en/docs/http/ngx_http_gzip_static_module.html)\n- A CSS preprocessor (Sass, in this case)\n- Browserslist to automatically configure:\n  - Babel for JS transpilation\n  - Autoprefixer for CSS transpilation\n\n<details><summary>Big ugly production-esque Rollup config</summary>\n\n```js\nimport { builtinModules } from \"module\";\nimport path from \"path\";\nimport autoprefixer from \"autoprefixer\";\nimport babelPlugin from \"@rollup/plugin-babel\";\nimport commonjsPlugin from \"@rollup/plugin-commonjs\";\nimport jsonPlugin from \"@rollup/plugin-json\";\nimport markoPlugin from \"@marko/rollup\";\nimport nodeResolvePlugin from \"@rollup/plugin-node-resolve\";\nimport replacePlugin from \"@rollup/plugin-replace\";\nimport runPlugin from \"@rollup/plugin-run\";\nimport stylesPlugin from \"rollup-plugin-styles\";\nimport urlPlugin from \"@rollup/plugin-url\";\nimport pkg from \"./package.json\";\n\nconst __DEV__ = process.env.NODE_ENV === \"development\";\nconst __PROD__ = !__DEV__;\n\nconst isWatch = Boolean(process.env.ROLLUP_WATCH);\n\nconst publicPath = \"/s/\"; // Guess what character is only 5 bits under HPACK\nconst assetFileNames = \"[name]-[hash][extname]\";\n\nconst externalDependencies = [\n  ...Object.keys(pkg.dependencies),\n  ...builtinModules,\n];\n\nprocess.env.SASS_PATH = \"./:./node_modules\";\n\nexport default (async () => [\n  compiler(\"server\", {\n    input: \"index.js\",\n    output: {\n      dir: \"built/server/\",\n      assetFileNames: `../browser/${assetFileNames}`,\n      format: \"cjs\",\n      sourcemap: true,\n    },\n    external: (id) =>\n      externalDependencies.some(\n        (dependency) => id === dependency || id.startsWith(dependency + \"/\"),\n      ),\n    plugins: [isWatch && runPlugin({ execArgv: [\"--enable-source-maps\"] })],\n  }),\n\n  compiler(\"browser\", {\n    output: {\n      dir: \"built/browser/\",\n      chunkFileNames: __PROD__ ? \"[name]-[hash].js\" : null,\n      entryFileNames: __PROD__ ? \"[name]-[hash].js\" : null,\n      assetFileNames,\n      sourcemap: true,\n      sourcemapExcludeSources: __PROD__,\n    },\n    plugins: [\n      stylesPlugin({\n        mode: \"extract\",\n        sourceMap: true,\n        config: {\n          target: \"browserslist:css\",\n          plugins: [autoprefixer({ env: \"css\" })],\n        },\n        minimize: __PROD__,\n        url: {\n          publicPath,\n          hash: assetFileNames,\n        },\n      }),\n      __PROD__ && (await import(\"rollup-plugin-terser\")).terser(),\n      __PROD__ &&\n        (await import(\"rollup-plugin-gzip\")).default({\n          filter: /\\.(?:js|css|svg|json|xml|txt)$/,\n          minSize: 1024,\n          gzipOptions: {\n            level: 9,\n            memLevel: 9,\n          },\n        }),\n      __PROD__ &&\n        !isWatch &&\n        (await import(\"rollup-plugin-visualizer\")).default(),\n      __PROD__ &&\n        !isWatch && {\n          name: \"bundle-visualizer-location\",\n          writeBundle() {\n            console.info(\n              `📊 Bundle visualizer at \\x1b[4;36mfile://${path.join(\n                __dirname,\n                \"../../\",\n                bundleAnalyzerFilename,\n              )}\\x1b[0m`,\n            );\n          },\n        },\n    ],\n  }),\n])();\n\nfunction compiler(target, config) {\n  const isBrowser = target === \"browser\";\n  const browserslistEnv = isBrowser ? \"js\" : \"server\";\n  const babelConfig = {\n    comments: false,\n    browserslistEnv,\n    compact: false,\n    babelrc: false,\n    caller: { target },\n  };\n  if (isBrowser) {\n    babelConfig.presets = [\n      [\n        \"@babel/preset-env\",\n        {\n          browserslistEnv,\n          bugfixes: true,\n        },\n      ],\n    ];\n  }\n\n  return {\n    ...config,\n    preserveEntrySignatures: false,\n    plugins: [\n      markoPlugin[target]({ babelConfig }),\n      nodeResolvePlugin({\n        browser: isBrowser,\n        preferBuiltins: !isBrowser,\n      }),\n      commonjsPlugin(),\n      replacePlugin({\n        preventAssignment: true,\n        values: { __DEV__, __PROD__ },\n      }),\n      babelPlugin({\n        babelHelpers: \"bundled\",\n        ...babelConfig,\n      }),\n      jsonPlugin(),\n      urlPlugin({\n        publicPath,\n        destDir: \"built/browser/\",\n        fileName: assetFileNames,\n        include: \"**/*.{svg,png,jpg,jpeg}\",\n        limit: 0, // Never Base64 & inline\n        emitFiles: !isBrowser,\n      }),\n      ...config.plugins,\n    ],\n  };\n}\n```\n\n</details>\n\n## `<rollup>` tag\n\nUsing both `.server()` and `.browser()` enables **the `<rollup>` tag**, which gives you complete control over how your app loads assets. That lets you do things like:\n\n- [Critical CSS](https://web.dev/extract-critical-css/) for components as they write out within a kB budget, or [as components first appear on the page](https://jakearchibald.com/2016/link-in-body/#a-simpler-better-way), or any other style-loading mad science\n- [`module`/`nomodule` scripts](https://philipwalton.com/articles/using-native-javascript-modules-in-production-today/) for smaller bundles in modern browsers\n- [Content-Security Policy `nonce`s](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce) or [Subresource `integrity` hashes](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)\n- Anything a web page can do, really. You can even combine `<rollup>` with [the `serialize` option](#options.serialize) to be as fancy as you wanna be.\n\nThe `<rollup>` tag provides two [tag parameters](https://markojs.com/docs/syntax/#parameters):\n\n1. `entry` is the generated `input` string that the `server` plugin gave to the `browser` plugin. You can use it to find the corresponding entry chunk from Rollup’s `output` (the next parameter).\n\n2. `output` is an array of `AssetInfo | ChunkInfo` objects with most of [the data returned from Rollup's `generateBundle` hook](https://rollupjs.org/guide/en/#generatebundle). Some properties are omitted, like `code` and `map`, since they’re often too large to inline directly. However, each chunk also has a `size` property, to let you filter out empty chunks, inline code yourself below a certain size, or other delightful devilishness.\n\nFor example, using the `entry` name and properties of `output` items to load scripts:\n\n```marko\n<head>\n  <rollup|entry, output|>\n    $ const entryChunk = output.find(chunk => chunk.name === entry);\n\n    <if(entryChunk.size /* only load non-empty JS entry points */)>\n      <for|fileName| of=entryChunk.imports>\n        <link rel=\"modulepreload\" href=fileName />\n      </for>\n\n      <script async type=\"module\" src=entryChunk.fileName></script>\n    </if>\n  </rollup>\n</head>\n```\n\n> **Note**: It’s up to you to transform the chunk data (also called the **manifest**) into `<link>`s, `<script>`s, and other HTML to load assets. Opting into complete control means we can’t do any of it for you.\n\nIf your Rollup `browser` config contains multiple `output` options, or you have multiple `browser` configs, every `output`’s chunk is passed to the `<rollup>` tag.\n\nFor example, if you have both `esm` and `iife` build outputs configured:\n\n```js\n{\n  output: [\n    { dir: \"dist/iife\", format: \"iife\" },\n    { dir: \"dist/esm\", format: \"esm\" },\n  ];\n}\n```\n\n…you could cross-reference assets from both…\n\n```marko\n<rollup|entry, iifeOutput, esmOutput|>\n  $ const iifeEntryChunk = iifeOutput.find(chunk => chunk.name === entry);\n  $ const esmEntryChunk = esmOutput.find(chunk => chunk.name === entry);\n\n  <script src=esmEntryChunk.fileName type=\"module\" async></script>\n  <script src=iifeEntryChunk.fileName nomodule async></script>\n</rollup>\n```\n\n…and _boom:_ you now have [a `module`/`nomodule` setup](https://philipwalton.com/articles/using-native-javascript-modules-in-production-today/).\n\n## Options\n\n### `options.babelConfig`\n\nBoth the `.server()` and `.browser()` plugins accept this option.\n\nYou can manually override the builtin Babel configuration by passing a `babelConfig` object. By default, [Babel’s regular config file resolution](https://babeljs.io/docs/en/config-files) will be used.\n\n```js\nmarko.browser({\n  babelConfig: {\n    presets: [\"@babel/preset-env\"],\n  },\n});\n```\n\n### `options.runtimeId`\n\nBoth the `.server()` and `.browser()` plugins accept this option. In fact, you _really_ want to use it with both simultaneously.\n\nIn some cases, you may want to embed multiple isolated copies of Marko on the page. (If you can’t think of why, then don’t worry about this option.)\n\nSince Marko uses some `window` properties to initialize, multiple instances can cause issues. For example, by default Marko checks `window.$components` for server-rendered hydration. Usually you can change these `window` properties by [rendering with `{ $global: { runtimeId: \"MY_MARKO_RUNTIME_ID\" } }` as input](https://markojs.com/docs/rendering/#global-data) on the server, but since `@marko/rollup` usually writes the autoinitialization code for you, instead this plugin exposes a `runtimeId` option to automatically set `$global.runtimeId` to initialize properly in the browser:\n\n```js\nconst runtimeId = \"MY_MARKO_RUNTIME_ID\";\n// Make the `runtimeId` the same across `server` and `browser`, or it’ll error!\nmarko.server({ runtimeId });\nmarko.browser({ runtimeId });\n```\n\n### `options.serialize`\n\nThis option is only available for the `.browser()` plugin. It lets you inspect and transform the `output` chunks before they’re passed to [the `<rollup>` tag](#rollup-tag).\n\nFor example, if you _did_ want to include the `code` property from the Rollup chunk — say, to inline code small enough that it’s not worth the overhead of an HTTP request, you’d try something like the following:\n\n```js\nmarko.browser({\n  serialize(output) {\n    return output.map(({ type, fileName, isEntry, code }) =>\n      type === \"asset\"\n        ? { type, fileName }\n        : {\n            type,\n            name,\n            isEntry,\n            fileName,\n            // only inline code chunks below 1kB\n            inline: code.trim().length < 1024 && code,\n          },\n    );\n  },\n});\n```\n","packages/runtime-class/docs/state.md":"# State\n\nThe output of a component is based on input properties passed from its parent as attributes. However, a component may also maintain internal state that it uses to control its view. If Marko detects a change to either input or to the internal state, the view will automatically be updated.\n\n> **ProTip:**\n> Only data that is owned and modified by the component should go into its `state`. State should be exclusively used for data that triggers rerenders. Parents control `input`, and the component controls its own `state`.\n\n## Initializing state\n\nTo use `state` in Marko, you must first create a [class component](./class-components.md) and initialize the state within the [`onCreate`](./class-components.md#oncreateinput-out) method. In class methods, `this.state` may be used and within the template section, a `state` variable is available.\n\n```marko\nclass {\n    onCreate() {\n        this.state = { count: 0 };\n    }\n}\n\n<div>The count is ${state.count}</div>\n```\n\n> **Note:** Only properties that exist when `this.state` is first defined will be watched for changes. If you don't need a property initially, you can set it to `null`.\n\n## Updating state\n\nYou can update `state` in response to DOM events, browser events, ajax calls, etc. When a property on the state changes, the view will be updated to match.\n\n```marko\nclass {\n    onCreate() {\n        this.state = { count: 0 };\n    }\n    increment() {\n        this.state.count++;\n    }\n}\n\n<div>The count is ${state.count}</div>\n<button on-click('increment')>Increment</button>\n```\n\nWe've extended our example above to add a button with an [event handler](./events.md), so that, when clicked, the `state.count` value is incremented.\n\n> **Note:**\n> When browsing existing code, you may see `this.setState('name', value)` being used. This is equivalent to `this.state.name = value`.\n\n### How updates work\n\nWhen a property on `state` is set, the component will be scheduled for an update if the property has changed. All updates are batched together for performance. This means you can update multiple state properties at the same time without causing multiple updates.\n\n> **ProTip:** If you need to know when the update has been applied, you can use `this.once('update', fn)` within a component method.\n\n> **Note:** The state object only watches its properties one level deep. This means updates to nested properties on the state (e.g. `this.state.object.something = newValue`) will not be detected.\n>\n> Using [immutable](https://wecodetheweb.com/2016/02/12/immutable-javascript-using-es6-and-beyond/) data structures is recommended, but if you want to mutate a state property (perhaps push a new item into an array) you can let Marko know it changed using `setStateDirty`.\n>\n> ```js\n> this.state.numbers.push(num);\n>\n> // mark numbers as dirty, because a `push`\n> // won't be automatically detected by Marko\n> this.setStateDirty(\"numbers\");\n> ```\n\n## Cross component state management\n\nThere are various tools available to manage state outside of a single component. Here are some basic guidelines.\n\nTypically we recommend using `attributes` to pass data in to a child component, and children can [emit events](./events.md#emitting-custom-events) to communicate back up to their parents. In some cases this can become cumbersome with deeply nested data dependencies or global state.\n\n### Global/Subtree\n\nFor passing state throughout a component tree without explicit attribute setting throughout the entire app, you can leverage the [`<context>`](https://github.com/marko-js/tags/tree/master/tags/context) tag. This tag can be [installed from npm](./custom-tags.md#using-tags-from-npm).\n\nThis tag allows you to pull state from any level above in the tree and can also be used to pass global state throughout your app.\nContext providers can register event handlers that any child in the tree can trigger similar to the [events API](./events.md).\n\n_fancy-form.marko_\n\n```marko\n<context coupon=input.coupon on-buy(handleBuy)>\n    <!-- Somewhere nested in the container will be the buy button -->\n    <fancy-container/>\n</context>\n```\n\n_fancy-save-button.marko_\n\n```marko\n<context|{ coupon }, emit| from=\"fancy-form\">\n    Coupon: ${coupon}.\n    <button on-click(emit, \"buy\")>Buy</button>\n</context>\n```\n\n> **Note:** Context _couples_ tags together and can limit reuse of components.\n\n### When to use a Redux like pattern\n\nOften the above two approaches are enough, and many people [jump to this part far too quickly](https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367). Like `<context>`, often anything stored in redux is `global`. This means that it can (if abused) create components that are hard to reuse, reason about and test. However it is important to understand when a tool like `redux` is useful in any UI library.\n\nRedux provides indirection to updating any state that it controls. This is useful if you need the following:\n\n- Single state update, multiple actions (eg: logging, computed data, etc).\n- Time travel debugging and other [redux-specific tooling](https://redux.js.org/introduction/ecosystem).\n","packages/runtime-class/docs/structure.json":"[\n  {\n    \"title\": \"Guides\",\n    \"docs\": [\n      \"Installing\",\n      \"Getting started\",\n      \"Conditionals and lists\",\n      \"Custom tags\",\n      \"State\",\n      \"Styles\",\n      \"Events\",\n      \"Body content\",\n      \"TypeScript\",\n      \"Marko 5 upgrade\",\n      \"Troubleshooting Streaming\"\n    ]\n  },\n  {\n    \"title\": \"Tutorials\",\n    \"docs\": [\"Color Picker\"]\n  },\n  {\n    \"title\": \"Reference\",\n    \"docs\": [\n      \"Rendering\",\n      \"Syntax\",\n      \"Core tags\",\n      \"Class components\",\n      \"marko.json\",\n      \"Compiler\"\n    ]\n  },\n  {\n    \"title\": \"Bundler Integrations\",\n    \"docs\": [\"Vite\", \"Webpack\", \"Rollup\", \"Lasso\"]\n  },\n  {\n    \"title\": \"Server Integrations\",\n    \"docs\": [\"Cloudflare Workers\", \"Express\", \"Fastify\", \"Koa\", \"HTTP\"]\n  },\n  {\n    \"title\": \"Tooling\",\n    \"docs\": [\"Editor plugins\"]\n  },\n  {\n    \"title\": \"Articles\",\n    \"docs\": [\"Marko vs React\", \"Why is Marko Fast\", \"10 Awesome Marko Features\"]\n  }\n]\n","packages/runtime-class/docs/styles.md":"# Styles\n\nBoth HTML and Marko provide support for `<style>` tags. However, Marko also provides a special syntax (called a style _block_) which adds support for CSS preprocessors and acts as a hint to bundlers to extract this static css from your templates into a common bundle.\n\n```marko\nstyle {\n    div {\n        color: green;\n    }\n}\n\n<div>Hello World</div>\n```\n\nThese blocks add global css to the page. The above example will not style just the `<div>` in the component, but all divs on the page. Because of this we recommend following a naming convention such as [BEM](https://getbem.com/introduction/). Marko will likely provide a way to automatically scope these styles to the current component [in the future](https://github.com/marko-js/marko/issues/666).\n\n> **Note:** Style blocks (unlike `<style>` tags) do not support `${placeholders}` and must be static.\n\n## Preprocessors\n\nIf you use a css preprocessor, you can add the extension right on `style`. This will cause your bundler of choice to run the contents of the style block through the appropriate processor.\n\n```marko\nstyle.less {\n    button.primary {\n        background-color: @primaryColor;\n    }\n}\n```\n","packages/runtime-class/docs/syntax.md":"# Syntax\n\nMarko is HTML _re-imagined_ as a language for building dynamic and reactive user interfaces.\nJust about any valid HTML is valid Marko, but Marko extends the HTML language to allow building modern applications in a declarative way.\n\n> **ProTip:** Marko also supports a [beautiful concise syntax](./concise.md). If you'd prefer to see the documentation using this syntax, just click the `switch syntax` button in the corner of any Marko code sample.\n\n> **Note:** Text at the root of a template (outside any tags) must be prefixed with the [concise syntax's `--`](./concise.md#text) to denote it is text. The parser starts in concise mode and would otherwise try to parse what you meant to be text as a concise tag declaration.\n>\n> ```marko\n> -- Root level text\n> ```\n\n## Tags\n\nAs you might expect, Marko supports all native HTML/SVG/whatever tags and attributes. In addition to these, it also comes with a set of useful [core tags](./core-tags.md). Beyond this, you can also build your own [custom tags](./custom-tags.md) and [install third-party tags](./custom-tags.md#using-tags-from-npm) from `npm`.\n\nAll of these types of tags use the same syntax:\n\n```marko\n<my-tag-name/>\n```\n\nYou don't need to import tags. Marko discovers them based on the folder structure—similar to how you don't specify a full path when referencing a module in `node_modules/`. Marko looks in [`components/`](./custom-tags.md#how-tags-are-discovered) by default and this directory can be configured in [`marko.json`](./marko-json.md).\n\n## Dynamic text\n\nYou can use placeholders (`${}`) to insert a value into the template:\nPlaceholders accept any JavaScript expression and the result of the expression will be inserted into the HTML output:\n\n```marko\n<div>\n    Hello ${\"world\".toUpperCase()}\n</div>\n```\n\nThese values are automatically escaped so you don't accidentally insert malicious code. If you do need to pass unescaped HTML, you can use `$!{}`:\n\n```marko\n<div>\n    Hello $!{\"<b>World</b>\"}\n</div>\n```\n\n> **ProTip:** If necessary, you can escape `$` using a backslash to have it be treated as text instead of a placeholder token:\n>\n> ```marko\n> <div>\n>     Placeholder example: <code>\\${someValue}</code>\n> </div>\n> ```\n\n## Attributes\n\nIn marko attributes are parsed as JavaScript expressions (instead of just strings).\n\n```marko\n<div class=myClassName/>\n<input type=\"checkbox\" checked=isChecked/>\n\n<custom-tag string=\"Hello\"/>\n<custom-tag number=1/>\n<custom-tag template-string=`Hello ${name}`/>\n<custom-tag boolean=true/>\n<custom-tag array=[1, 2, 3]/>\n<custom-tag object={ hello: \"world\" }/>\n<custom-tag variable=name/>\n<custom-tag function-call=user.getName()/>\n```\n\nAttributes that are passed to a custom tag are received as it's [`input`](https://markojs.com/docs/class-components/#input).\n\n> **Note:** Although in most cases you won't see a difference, strings are parsed as JavaScript strings, not HTML strings. Where this comes up most often is using the `pattern` attribute with the `<input>` tag: you need to \"double escape\" your regex escape sequences much like you were passing a string to the [`RegExp` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) (or you can use a literal `/regex/`).\n>\n> _Marko Source:_\n>\n> ```marko\n> <input pattern=\"\\\\w+\" type=\"text\"/>\n> <input pattern=/\\w+/ type=\"text\"/>\n> ```\n>\n> _HTML Output:_\n>\n> ```html\n> <input pattern=\"\\w+\" type=\"text\" />\n> ```\n\n### Complex expressions\n\nAny JavaScript expression is a valid attribute value, provided it meets the following criteria:\n\n_It does not contain any spaces_\n\n_It does not contain any right angle brackets (`>`)_\n\n```marko\n<custom-tag sum=1+2 difference=3-4/>\n```\n\n```marko\ncustom-tag sum=1+2 difference=3-4\n```\n\n_Spaces and `>` are contained within matching `()`, `[]`, `{}`, strings and regexps_\n\n```marko\n<custom-tag sum=(1 + 2) difference=(3 - 4) greater=(1 > 2)/>\n```\n\n```marko\ncustom-tag sum=(1 + 2) difference=(3 - 4) greater=(1 > 2)\n```\n\n### Boolean attributes\n\nHTML defines the following rules for [boolean attributes](https://www.w3.org/TR/2008/WD-html5-20080610/semantics.html#boolean):\n\n> The presence of a boolean attribute on an element represents the true value, and the absence of the attribute represents the false value.\n\nIn Marko when an attribute value evaluates to `false`, `null`, or `undefined`, the attribute is not included in the output. If an attribute value is `true`, only the attribute name is included in the output.\n\n_Marko Source:_\n\n```marko\n<input type=\"checkbox\" checked=true>\n<input type=\"checkbox\" checked=false>\n```\n\nRenders the following HTML:\n\n_HTML Output:_\n\n```html\n<input type=\"checkbox\" checked /> <input type=\"checkbox\" />\n```\n\nSimilarly, when only an attribute name is defined, it is equivalent to specifying the attribute with a value of `true`:\n\n```marko\n<!-- These are equivalent -->\n<custom-menu expanded/>\n<custom-menu expanded=true/>\n```\n\n> **ProTip:**\n> You can take advantage of the way Marko handles boolean attributes to conditionally render attributes:\n>\n> _Marko Source:_\n>\n> ```marko\n> <div class=(active && \"tab-active\")>Hello</div>\n> ```\n>\n> With a value of `true` for `active`, the output would be the following:\n>\n> _HTML Output:_\n>\n> ```html\n> <div class=\"tab-active\">Hello</div>\n> ```\n>\n> With a value of `false` for `active`, the output would be the following:\n>\n> _HTML Output:_\n>\n> ```html\n> <div>Hello</div>\n> ```\n\n### Dynamic attributes\n\nThe spread syntax (`...`) can be used to merge in an object as attributes to a tag:\n\n_Marko Source:_\n\n```marko\n<a ...attrs target=\"_blank\">eBay</a>\n```\n\nWith `attrs` as the following value:\n\n```js\n{\n    class: \"active\",\n    href: \"https://ebay.com/\"\n}\n```\n\nwould output the following HTML:\n\n_HTML Output:_\n\n```html\n<a class=\"active\" href=\"https://ebay.com/\" target=\"_blank\">eBay</a>\n```\n\n> **ProTip:**\n> With spread attributes order matters.\n> You can take advantage of this to implement both default attributes, and enforced attributes.\n>\n> ```marko\n> <custom-tag ...defaults ...userSupplied class=\"overridden\"/>\n> ```\n\n> **ProTip:**\n> You can provide `undefined` to a spread attribute which will output nothing.\n\n### Style attribute\n\nYou can pass a string as the value of `style` just as you would in HTML, in addition Marko supports passing an object or array as the value of the `style` attribute:\n\n_Marko Source:_\n\n```marko\n<!-- string: -->\n<div style=\"display:block;margin-right:16px\"/>\n\n<!-- object: -->\n<div style={ display: \"block\", color: false, marginRight: 16 }/>\n\n<!-- array: -->\n<div style=[\"display:block\", null, { marginRight: 16 }]/>\n```\n\nIn all cases, the output will be the same:\n\n_HTML Output:_\n\n```html\n<div style=\"display:block;margin-right:16px;\"></div>\n```\n\n### Class attribute\n\nThe `class` attribute also supports receiving an object or array (in addition to a string) as shown below:\n\n_Marko Source:_\n\n```marko\n<!-- string: -->\n<div class=\"a c\"/>\n\n<!-- object: -->\n<div class={ a:true, b:false, c:true }/>\n\n<!-- array: -->\n<div class=[\"a\", null, { c:true }]/>\n```\n\nIn all cases, the output will be the same:\n\n_HTML Output:_\n\n```html\n<div class=\"a c\"></div>\n```\n\n### Shorthand attributes\n\nMarko provides a shorthand for declaring classes and ids on an element, including interpolation. Given `size` is the string `small`:\n\n_Marko Source:_\n\n```marko\n<div.my-class/>\n<span#my-id/>\n<button#submit.primary.large/>\n<button.button--${size}></button>\n```\n\nRenders the following HTML:\n\n_HTML Output:_\n\n<!-- prettier-ignore -->\n```html\n<div class=\"my-class\"></div>\n<span id=\"my-id\"></span>\n<button id=\"submit\" class=\"primary large\"></button>\n<button class=\"button--small\"></button>\n```\n\n## Parameters\n\nWhen a tag renders its body content, it may provide data which can be received by defining parameters after the tagname. Parameters are available to the tag's body content.\n\nThis is a powerful feature that allows components to provide functionality and data while giving you full control over what gets rendered.\n\nIn the following example, `<mouse>` provides a parameter which we have named `position`:\n\n```marko\n<mouse|position|>\n   The mouse is at ${position.x}, ${position.y}!\n</mouse>\n```\n\n> `<mouse>` would [render its body](./body-content.md) and provide the position similar to this: `<${input.renderBody} x=0 y=0/>`.\n\n> **ProTip:** Tag `|parameters|` are treated as regular JavaScript function parameters. This means you can destructure, set default values, etc.\n>\n> ```marko\n> <mouse|{ x, y }|>\n>   The mouse is at ${x}, ${y}!\n> </mouse>\n> ```\n\n> **Note:** Parameters are not available to attributes, only to the tag body.\n>\n> ```marko\n> <mouse|position| something=position>\n>   ReferenceError when setting the \"something\" attribute\n> </mouse>\n> ```\n\nParameters are used by some of Marko's [core tags](./core-tags.md) like the [`<for>`](./core-tags.md#for) and [`<await>`](./core-tags.md#await) tags.\n\n## Arguments\n\nSome tags and attributes accept javascript style `arguments`. Arguments are denoted by parenthesis following the tag or attribute name. Arguments provide a way to pass unnamed data to a tag.\n\n```marko\n<if(true)>\n    <strong>Marko is awesome</strong>\n</if>\n\n<h1 body-only-if(skipHeading)>\n    Conditional display heading, but always show content!\n</h1>\n```\n\nArguments are used by some of Marko's [core tags](./core-tags.md) like the [`<if>`](./core-tags.md#if-else-if-else) tag and [`body-only-if`](./core-tags.md#body-only-if) attribute displayed above.\n\nPreviously you could also use them in your own [custom tags](./custom-tags.md) however it is now recommended to use [dynamic attributes](#dynamic-attributes).\n\n## Dynamic tagname\n\nThe `<${dynamic}>` syntax is used to render a tag or component that isn't determined until runtime. It can also be used within a [custom tag](./custom-tags.md) to render body content that was passed to that tag.\n\n_Marko Source:_\n\n```marko\n<${href ? 'a' : 'button'} href=href>\n    Click me!\n</>\n```\n\nWith `href` as `https://ebay.com` would output the following HTML:\n\n_HTML Output:_\n\n```html\n<a href=\"https://ebay.com\">Click me!</a>\n```\n\nAnd with `href` as `undefined` would output the following HTML:\n\n_HTML Output:_\n\n```html\n<button>Click me!</button>\n```\n\nAs a shorthand if there is a variable in scope and [no other matching tag is discovered](#how-tags-are-discovered) the wrapping `${}` is unnecessary.\n\nFor example the following are equivalent:\n\n```marko\n$ const MyTag = href ? 'a' : 'button';\n<${MyTag}/>\n<MyTag/>\n```\n\n> **ProTip:**\n> If you find that you have a wrapper element that is conditional, but whose body should always be rendered then you can use a null dynamic tag. For example, to only render a wrapping `<a>` tag if there is a valid URL then you could do the following:\n>\n> _Marko Source:_\n>\n> ```marko\n> <${input.linkUrl ? \"a\" : null} href=input.linkUrl >\n>    Some body content\n> </>\n> ```\n>\n> Given a value of `\"http://localhost/\"` for the `input.linkUrl` variable: , the output would be the following:\n>\n> _HTML Output:_\n>\n> ```html\n> <a href=\"http://localhost/\"> Some body content </a>\n> ```\n>\n> Given a value of `undefined` for the `input.linkUrl` variable: , the output would be the following:\n>\n> _HTML Output:_\n>\n> ```html\n> Some body content\n> ```\n\n### Dynamic components\n\nInstead of just strings, the dynamic tagname can also be a component:\n\n```marko\nimport componentA from \"<component-a>\";\nimport componentB from \"<component-b>\";\n\n<${useA ? componentA : componentB}/>\n```\n\n> **ProTip:**\n> You can also switch between a normal HTML tag and a component:\n>\n> ```marko\n> import FancyButton from \"<fancy-button>\";\n>\n> <${isFancy ? FancyButton : 'button'}>\n>     Button text\n> </>\n> ```\n\n> **Note:** You **cannot** reference a Marko custom tag or macro using a name string:\n>\n> _Marko Source:_\n>\n> ```marko\n> <${isFancy ? 'fancy-button' : 'button'}>\n>     Button text\n> </>\n> ```\n>\n> With `isFancy` as `true` would output the following HTML:\n>\n> _HTML Output:_\n>\n> ```html\n> <fancy-button>Button text</fancy-button>\n> ```\n\n### Dynamic body content\n\nWhen a custom tag receives [body content](./body-content.md), it is passed as a `renderBody` property. To render this content you can pass the `renderBody` as the dynamic tagname.\n\n```marko\n<div class=\"container\">\n    <${input.renderBody}/>\n</div>\n```\n\n## Attribute Tag\n\nAs the name implies, `<@attribute-tags>` are special attributes that take the form of tags. They allow you to pass named body sections to a [custom tag](./custom-tags.md).\n\nThe core `<await>` tag allows you to pass multiple body sections that it will conditionally render based on the state of the promise.\n\n```marko\n<await(somePromise)>\n    <@then|result|>\n        The promise resolved: ${result}\n    </@then>\n    <@catch|error|>\n        The promise rejected: ${error.message}\n    </@catch>\n</await>\n```\n\nThese body sections are also commonly used to create layouts:\n\n```marko\n<page-layout>\n    <@heading>\n        <h1>Hello</h1>\n    </@heading>\n    <@body>\n        <p>Lorem ipsum....</p>\n    </@body>\n</page-layout>\n```\n\nThese tags are passed to the custom tag as objects with a `renderBody`, it can then [render its body content](./body-content.md).\n\n> **Note:**\n> Attribute tags can have their own parameters, but like attributes, they cannot access the parameters of their parent tag:\n>\n> ```marko\n> <list|item|>\n>   ${item.name}\n>   <@separator>${item} (oops, ReferenceError)</@separator>\n> </list>\n> ```\n\n## Inline JavaScript\n\nTo execute JavaScript in your template you can insert a Javascript statement using the `$ <code>` syntax.\n\nA line that starts with a `$` followed by a space will execute the code that follows.\n\n```marko\n$ const name = \"World\";\n\n<div>\n    Hello, ${name}\n    $ console.log(\"The value rendered was\", name);\n</div>\n```\n\nA statement may continue onto subsequent lines if new lines are bounded by `{}`, `[]`, `()`, ` `` `, or `/**/`:\n\n```marko\n$ const person = {\n    name: \"Frank\",\n    age: 32\n};\n```\n\nMultiple statements or an unbounded statement may be used by wrapping the statement(s) in a block:\n\n```marko\n$ {\n    const bgColor = getRandomColor();\n    const textColor = isLight(bgColor)\n        ? \"black\"\n        : \"white\";\n}\n```\n\n> **ProTip:** Any JavaScript statement can be used here, even `debugger`:\n>\n> ```marko\n> <div>\n>     ${textColor}\n>     $ debugger; // Quickly debug `textColor`\n> </div>\n> ```\n\n> **ProTip:** If necessary, you can escape `$` using a backslash to have it be treated as text instead of a placeholder token:\n>\n> ```marko\n> <p>You can run JS in a Marko template like this:</p>\n> <code>\n>     \\$ var num = 123;\n> </code>\n> ```\n\n> **ProTip:** If you find yourself writing a lot of inline JS, consider moving it out to an external file and then [`import`](#importing-external-files) it.\n\n### Static JavaScript\n\nInline JavaScript will run each time your template is rendered, but the JavaScript code that follows `static` will only run once when the template is loaded. It must be declared at the top level and does not have access to values passed in at render time.\n\n```marko\nstatic var count = 0;\nstatic var formatter = new Formatter();\n\nstatic function sum(a, b) {\n    return a + b;\n};\n\n<div>${formatter.format(sum(2, 3))}</div>\n```\n\nLike inline Javascript, multiple statements or an unbounded statement may be used by wrapping the statement(s) in a block:\n\n```marko\nstatic {\n    var base = 2;\n    function sum(a, b) {\n        return base + a + b;\n    };\n}\n```\n\n### Importing external files\n\nThe `import` statement is used to access data and functions from external files. It follows the same syntax as the [JavaScript `import` statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import).\n\n```marko\nimport sum from './utils/sum';\n<div>The sum of 2 + 3 is ${sum(2, 3)}</div>\n```\n\nAs a shorthand you can also import components by providing it's html tag name wrapped in angle brackets, eg:\n\n```marko\nimport MyComponent from \"<my-component>\"\n```\n\nThis is especially useful with the [dynamic tag name syntax](./syntax.md#dynamic-tagname) and uses the same [component discovery](./custom-tags.md#how-tags-are-discovered) as if the tag was used in the template.\n\n## Comments\n\nStandard HTML comments can be used and will be stripped out of the rendered output.\nAt the top level of the template JavaScript comments (`// comment` and `/** comment */`) can also be used.\n\n```marko\n<!-- This is a comment that will not be rendered -->\n\n<h1>Hello</h1>\n```\n\nIf you would like for your HTML comment to show up in the final output then you can use the [`html-comment` core tag](./core-tags.md#html-comment).\n","packages/runtime-class/docs/troubleshooting-streaming.md":"# Troubleshooting HTTP Streams\n\n[The way Marko streams HTML](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding) is old and well-supported, but default configurations and assumptions by other software can foil it. This page describes some known culprits that may buffer your Node server’s output HTTP streams.\n\n## Reverse proxies/load balancers\n\n- Turn off proxy buffering, or if you can’t, set the proxy buffer sizes to be reasonably small.\n\n- Make sure the “upstream” HTTP version is 1.1 or higher; HTTP/1.0 and lower do not support streaming.\n\n- Some software doesn’t support HTTP/2 or higher “upstream” connections at all or very well — if your Node server uses HTTP/2, you may need to downgrade.\n\n- Check if “upstream” connections are `keep-alive`: overhead from closing and reopening connections may delay responses.\n\n- For typical modern webpage file sizes, the following bullet points probably won’t matter. But if you want to stream **small chunks of data with the lowest latency**, investigate these sources of buffering:\n  - Automatic gzip/brotli compression may have their buffer sizes set too high; you can tune their buffers to be smaller for faster streaming in exchange for slightly worse compression.\n\n  - You can [tune HTTPS record sizes for lower latency, as described in High Performance Browser Networking](https://hpbn.co/transport-layer-security-tls/#optimize-tls-record-size).\n\n  - Turning off MIME sniffing with [the `X-Content-Type-Options`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options) header eliminates browser buffering at the very beginning of HTTP responses\n\n### NGiNX\n\nMost of NGiNX’s relevant parameters are inside [its builtin `http_proxy` module](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering):\n\n```nginx\nproxy_http_version 1.1; # 1.0 by default\nproxy_buffering off; # on by default\n```\n\n### Apache\n\nApache’s default configuration works fine with streaming, but your host may have it configured differently. The relevant Apache configuration is inside [its `mod_proxy` and `mod_proxy_*` modules](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html) and their [associated environment variables](https://httpd.apache.org/docs/2.4/env.html).\n\n## CDNs\n\nContent Delivery Networks (CDNs) consider efficient streaming one of their best features, but it may be off by default or if certain features are enabled.\n\n- For Fastly or another provider that uses VCL configuration, check [if backend responses have `beresp.do_stream = true` set](https://developer.fastly.com/reference/vcl/variables/backend-response/beresp-do-stream/).\n\n- Some [Akamai features designed to mitigate slow backends can ironically slow down fast chunked responses](https://community.akamai.com/customers/s/question/0D50f00006n975d/enabling-chunked-transfer-encoding-responses). Try toggling off Adaptive Acceleration, Ion, mPulse, Prefetch, and/or similar performance features. Also check for the following in the configuration:\n\n  ```xml\n  <network:http.buffer-response-v2>off</network:http.buffer-response-v2>\n  ```\n\n## Node.js itself\n\nFor extreme cases where [Node streams very small HTML chunks with its built-in compression modules](https://github.com/marko-js/marko/pull/1641), you may need to tweak the compressor stream settings. Here’s an example with `createGzip` and its `Z_PARTIAL_FLUSH` flag:\n\n```js\nimport http from \"http\";\nimport zlib from \"zlib\";\n\nimport MarkoTemplate from \"./something.marko\";\n\nhttp\n  .createServer(function (request, response) {\n    response.writeHead(200, { \"content-type\": \"text/html;charset=utf-8\" });\n    const templateStream = MarkoTemplate.stream({});\n    const gzipStream = zlib.createGzip({\n      flush: zlib.constants.Z_PARTIAL_FLUSH,\n    });\n    templateStream.pipe(outputStream).pipe(response);\n  })\n  .listen(80);\n```\n","packages/runtime-class/docs/typescript.md":"# TypeScript in Marko\n\n> **Note:** Types are supported in Marko v5.22.7+ and Marko v4.24.6+\n\nMarko’s TypeScript support offers in-editor error checking, makes refactoring less scary, verifies that data matches expectations, and even helps with API design.\n\nOr maybe you just want more autocomplete in VSCode. That works too.\n\n## Enabling TypeScript in your Marko project\n\nThere are two (non-exclusive) ways to add TypeScript to a Marko project:\n\n- **For sites and web apps**, you can place [a `tsconfig.json` file](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) at the project root:\n  <pre>\n  📁 components/\n  📁 node_modules/\n  <img src=\"./icons/marko.svg\" width=16> index.marko\n  📦 package.json\n  <mark><img src=\"./icons/ts.svg\" width=16> tsconfig.json</mark>\n  </pre>\n- **If you’re [publishing packages of Marko tags](./custom-tags.md#publishing-tags-to-npm)**, publish the output of [`mtc`](#ci-type-checking). Each component gets a `.d.marko` file with its types, which editors and type checkers read in place of the `.marko` file. This exposes type-checking and autocomplete for the published tags.\n\n> **ProTip**: For mixed JavaScript and TypeScript code, such as an incremental migration, set `\"script-lang\": \"ts\"` or `\"js\"` in [a `marko.json`](./marko-json.md) to override these defaults. The nearest `marko.json` up the directory tree applies, so folders can opt in or out.\n\n## Typing a tag's `input`\n\nA `.marko` file will use any exported `Input` type for [that file’s `input` object](./class-components.md#input).\n\nThis can be `export type Input` or `export interface Input`.\n\n### Example\n\n_PriceField.marko_\n\n```marko\nexport interface Input {\n  currency: string;\n  amount: number;\n}\n\n<label>\n  Price in ${input.currency}:\n  <input type=\"number\" value=input.amount min=0 step=0.01>\n</label>\n```\n\nYou can also import, reuse, and extend `Input` interfaces from other `.marko` or `.ts` files:\n\n```marko\nimport { Input as PriceInput } from \"<PriceField>\";\nimport { ExtraTypes } from \"lib/utils.ts\";\nexport type Input = PriceInput & ExtraTypes;\n```\n\n```marko\nimport { Input as PriceInput } from \"<PriceField>\";\nexport interface Input extends PriceInput {\n  discounted: boolean;\n  expiresAt: Date;\n};\n```\n\n### Generic `Input`s\n\n[Generic Types and Type Parameters](https://www.typescriptlang.org/docs/handbook/2/generics.html) on `Input` are recognized throughout the entire `.marko` template (excluding [static statements](./syntax.md#static-javascript)).\n\nFor example, if you set up a component like this:\n\n_components/my-select.marko_\n\n```marko\nexport interface Input<T> {\n  options: T[];\n  onSelect: (newVal: T) => unknown;\n}\n\nstatic function staticFn() {\n  // can NOT use `T` here\n}\n\n$ const instanceFn = (val: T) => {\n  // can use `T` here\n}\n\n// can use `as T` here\n<select on-input(evt => input.onSelect(options[evt.target.value] as T))>\n  <for|value, i| of=input.options>\n    <option value=i>${value}</option>\n  </for>\n</select>\n```\n\n…then your editor will figure out the types of inputs to that component:\n\n```marko\n<my-select options=[1,2,3] onSelect=val => {}/>\n                                 // ^^^ number\n\n<my-select options=[\"M\",\"K\",\"O\"] onSelect=val => {}/>\n                                       // ^^^ string\n```\n\n## Built-in Marko Types\n\nMarko exposes [type definitions](https://github.com/marko-js/marko/blob/main/packages/runtime-class/index.d.ts) you can reuse in [a TypeScript namespace](https://www.typescriptlang.org/docs/handbook/namespaces.html) called `Marko`:\n\n- **`Marko.Template<Input, Return>`**\n  - The type of a `.marko` file\n  - `typeof import(\"./template.marko\")`\n- **`Marko.TemplateInput<Input>`**\n  - The object accepted by the render methods of a template. It includes the template's `Input` as well as `$global` values.\n- **`Marko.Body<Params, Return>`**\n  - The type of the [body content](./body-content.md) of a tag (`renderBody`)\n- **`Marko.Component<Input, State>`**\n  - The base class for a [class component](./class-components.md)\n- **`Marko.Renderable`**\n  - Values accepted by the [`<${dynamic}/>` tag](./syntax.md#dynamic-tagname)\n  - `string | Marko.Template | Marko.Body | { renderBody: Marko.Body}`\n- **`Marko.Out`**\n  - The render context with methods like `write`, `beginAsync`, etc.\n  - `ReturnType<template.render>`\n- **`Marko.Global`**\n  - The type of the object in `$global` and `out.global` that can be passed to a template's render methods as the `$global` property.\n- **`Marko.RenderResult`**\n  - The [result](./rendering.md#renderresult) of rendering a Marko template\n  - `ReturnType<template.renderSync>`\n  - `Awaited<ReturnType<template.render>>`\n- **`Marko.Emitter`**\n  - `EventEmitter` from `@types/node`\n- **`Marko.NativeTags`**\n  - `Marko.NativeTags`: An object containing all native tags and their types\n- **`Marko.Input<TagName>`** and **`Marko.Return<TagName>`**\n  - Helpers to extract the input and return types native tags (when a string is passed) or a custom tag.\n- **`Marko.BodyParameters<Body>`** and **`Marko.BodyReturnType<Body>`**\n  - Helpers to extract the parameters and return types from the specified `Marko.Body`\n- **`Marko.AttrTag<T>`**\n  - Used to represent types for [attributes tags](./body-content.md#named-body-content)\n  - A single attribute tag, with a `[Symbol.iterator]` to consume any repeated tags.\n\n### Typing `renderBody`\n\nThe most commonly used type from the `Marko` namespace is `Marko.Body` which can be used to type `input.renderBody`:\n\n_child.marko_\n\n```marko\nexport interface Input {\n  renderBody?: Marko.Body;\n}\n```\n\nHere, the following will be acceptable values:\n\n_index.marko_\n\n```marko\n<child/>\n<child>Text in render body</child>\n<child>\n  <div>Any combination of components</div>\n</child>\n```\n\nPassing other values (including components) will cause a type error:\n\n_index.marko_\n\n```marko\nimport OtherTag from \"<other-tag>\";\n<child renderBody=OtherTag/>\n```\n\n### Typing Tag Parameters\n\nTag parameters are passed to the `renderBody` by the child tag. For this reason, `Marko.Body` also allows typing of its parameters:\n\n_for-by-two.marko_\n\n```marko\nexport interface Input {\n  to: number;\n  renderBody: Marko.Body<[number]>\n}\n\n<for|i| from=0 to=input.to step=2>\n  <${input.renderBody}(i)/>\n</for>\n```\n\n_index.marko_\n\n```marko\n<for-by-two|i| to=10>\n  <div>${i}</div>\n</for-by-two>\n```\n\n### Extending native tag types within a Marko tag\n\nThe types for native tags are accessed via the global `Marko.Input` type. Here's an example of a component that extends the `button` html tag:\n\n_color-button.marko_\n\n```marko\nexport interface Input extends Marko.Input<\"button\"> {\n  color: string;\n  renderBody?: Marko.Body;\n}\n\n$ const { color, renderBody, ...restOfInput } = input;\n\n<button style=`color: ${color}` ...restOfInput>\n  <${renderBody}/>\n</button>\n```\n\n### Registering a new native tag (eg for custom elements).\n\n```ts\ninterface MyCustomElementAttributes {\n  // ...\n}\n\ndeclare global {\n  namespace Marko {\n    interface NativeTags {\n      // By adding this entry, you can now use `my-custom-element` as a native html tag.\n      \"my-custom-element\": MyCustomElementAttributes;\n    }\n  }\n}\n```\n\n### Registering new \"global\" HTML Attributes\n\n```ts\ndeclare global {\n  namespace Marko {\n    interface HTMLAttributes {\n      \"my-non-standard-attribute\"?: string; // Adds this attribute as available on all HTML tags.\n    }\n  }\n}\n```\n\n### Registering CSS Properties (eg for custom properties)\n\n```ts\ndeclare global {\n  namespace Marko {\n    namespace CSS {\n      interface Properties {\n        \"--foo\"?: string; // adds a support for a custom `--foo` css property.\n      }\n    }\n  }\n}\n```\n\n## TypeScript Syntax in `.marko`\n\nAny [JavaScript expression in Marko](./syntax.md#inline-javascript) can also be written as a TypeScript expression.\n\n### Tag Type Parameters\n\n```marko\n<child <T>|value: T|>\n  ...\n</child>\n```\n\n### Tag Type Arguments\n\n_components/child.marko_\n\n```marko\nexport interface Input<T> {\n  value: T;\n}\n```\n\n_index.marko_\n\n```marko\n// number would be inferred in this case, but we can be explicit\n<child<number> value=1 />\n```\n\n### Method Shorthand Type Parameters\n\n```marko\n<child process<T>() { /* ... */ } />\n```\n\n### Attribute Type Assertions\n\nThe types of attribute values can _usually_ be inferred. When needed, you can assert values to be more specific with [TypeScript’s `as` keyword](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-assertions):\n\n```marko\n<some-component\n  number=1 as const\n  names=[] as string[]\n/>\n```\n\n# JSDoc Support\n\nFor existing projects that want to incrementally add type safety, adding full TypeScript support is a big leap. This is why Marko also includes full support for [incremental typing via JSDoc](https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html).\n\n## Setup\n\nYou can enable type checking in an existing `.marko` file by adding a `// @ts-check` comment at the top:\n\n```js\n// @ts-check\n```\n\nIf you want to enable type checking for all Marko & JavaScript files in a JavaScript project, you can switch to using a [`jsconfig.json`](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#using-tsconfigjson-or-jsconfigjson). You can skip checking some files by adding a `// @ts-nocheck` comment to files.\n\nOnce that has been enabled, you can start by typing the input with JSDoc. Here's an example component with typed `input`:\n\n```marko\n// @ts-check\n\n/**\n * @typedef {{\n *   firstName: string,\n *   lastName: string,\n * }} Input\n */\n\n<div>${firstName} ${lastName}</div>\n```\n\n## With a separate `component.js` file\n\nMany components in existing projects adhere to the following structure:\n\n<pre>\n📁 components/\n  📁 color-rotate-button/\n    <img src=\"./icons/marko.svg\" width=16> index.marko\n    <img src=\"./icons/js.svg\" width=16> component.js\n</pre>\n\nThe `color-rotate-button` takes a list of colors and moves to the next one each time the button is clicked:\n\n```marko\n<color-rotate-button colors=[\"red\", \"blue\", \"yellow\"]>\n  Next Color\n</color-rotate-button>\n```\n\nHere is an example of how this `color-rotate-button` component could be typed:\n\n_components/color-rotate-button/component.js_\n\n```js\n// @ts-check\n\n/**\n * @typedef {{\n *   colors: string[],\n *   renderBody: Marko.Renderable\n * }} Input\n * @typedef {{\n *   colorIndex: number\n * }} State\n * @extends {Marko.Component<Input, State>}\n */\nexport default class extends Marko.Component {\n  onCreate() {\n    this.state = {\n      colorIndex: 0,\n    };\n  }\n\n  rotateColor() {\n    this.state.colorIndex =\n      (this.state.colorIndex + 1) % this.input.colors.length;\n  }\n}\n```\n\n_components/color-rotate-button/index.marko_\n\n```marko\n// @ts-check\n\n/* Input will be automatically imported from `component.js`! */\n\n<button\n  onClick('rotateColor')\n  style=`color: ${input.colors[state.colorIndex]}`>\n  <${input.renderBody}/>\n</button>\n```\n\n# CI Type Checking\n\nFor type checking Marko files outside of your editor there is the [\"@marko/type-check\" cli](https://github.com/marko-js/language-server/tree/main/packages/type-check).\nCheck out the CLI documentation for more information.\n","packages/runtime-class/docs/vite.md":"# Marko + Vite\n\n# Installation\n\n```console\nnpm install @marko/vite vite\n```\n\n# Example config\n\n```javascript\nimport { defineConfig } from \"vite\";\nimport marko from \"@marko/vite\";\nexport default defineConfig({\n  plugins: [marko()],\n});\n```\n\n# Linked Mode\n\nBy default this plugin operates in `linked` mode (you can disabled this by passing [`linked: false` as an option](#optionslinked)). In `linked` mode the plugin automatically discovers all of the entry `.marko` files while compiling the server, and tells `Vite` which modules to load in the browser.\n\nWith this you _do not_ create `.html` files for `Vite`, it's Marko all the way down!\nScripts, styles and other content that _would have_ been injected into the `.html` files is instead automatically injected into your `.marko` templates.\n\nIn this mode you must use the [Vite SSR API](https://vitejs.dev/guide/ssr.html#setting-up-the-dev-server).\n\nHere's an example using `express`.\n\n```js\nimport { createServer } from \"vite\";\n\nconst app = express();\nlet loadTemplate;\n\nif (process.env.NODE_ENV === \"production\") {\n  // Use Vite's built asset in prod mode.\n  loadTemplate = () => import(\"./dist\");\n} else {\n  // Hookup the vite dev server.\n  const vite = await createServer({\n    server: { middlewareMode: true }\n  });\n\n  app.use(vite.middlewares);\n  loadTemplate = () => vite.ssrLoadModule(\"./template.marko\");\n}\n\napp.get(\"/\", async (req, res) => {\n  const template = (await loadTemplate()).default;\n  // When the template is loaded, it will automatically have `vite` assets inlined.\n  template.render({ hello: \"world\" }, res);\n);\n\napp.listen(3000);\n```\n\n> For a more real world setup check out our [vite express](https://github.com/marko-js/examples/tree/master/examples/vite-express) example app.\n\n# Options\n\n### options.babelConfig\n\nYou can manually override Marko's Babel configuration by passing a `babelConfig` object to the `@marko/vite` plugin. By default Babel's regular [config file resolution](https://babeljs.io/docs/en/config-files) will be used.\n\n```javascript\nmarko({\n  babelConfig: {\n    presets: [\"@babel/preset-env\"],\n  },\n});\n```\n\n### options.runtimeId\n\nIn some cases you may want to embed multiple isolated copies of Marko on the page. Since Marko relies on some `window` properties to initialize this can cause issues. For example, by default Marko will read the server rendered hydration code from `window.$components`. In Marko you can change these `window` properties by rendering with `{ $global: { runtimeId: \"MY_MARKO_RUNTIME_ID\" } }` as input on the server side.\n\nThis plugin exposes a `runtimeId` option produces output that automatically sets `$global.runtimeId` on the server side and initializes properly in the browser.\n\n```js\nmarko({ runtimeId: \"MY_MARKO_RUNTIME_ID\" });\n```\n\n### options.linked\n\nSet this to `false` to opt out of [linked mode](#linked-mode). When this is false, the plugin will only handle resolving and transforming `.marko` files.\n","packages/runtime-class/docs/webpack.md":"# Marko + Webpack\n\n# Installation\n\n> `@marko/webpack` >= 7 Only supports Marko 5+.\n> For Marko 4 support use `@marko/webpack@6`.\n\n```console\nnpm install @marko/webpack\n```\n\n### Loader: `@marko/webpack/loader`\n\nThe loader portion of this module can be used standalone and simply transforms your Marko templates into the appropriate JavaScript depending on your webpack target.\n\nYou can override the output by adding a `target` option to the loader of `target: \"server\" | \"browser\"`.\n\n### Plugin: `@marko/webpack/plugin`\n\nThe plugin actually creates two separate webpack plugins, the `browser` plugin and the `server` plugin.\n\nThese are intended to be used in a isomorphic [webpack multi compiler](https://github.com/webpack/webpack/tree/master/examples/multi-compiler) where you are bundling both the server and the browser. The way it works is that the server plugin is going to analyze the top level Marko components in your server and automatically communicate with the browser compiler to retrieve the assets for that template.\n\nThis plugin also analyzes the top level Marko templates and determines if it is possible for them to rerender (currently the heuristic is simply does the component have an associated `class` or `component.js`). The plugin will automatically skip sending down any unnecessary top level templates to the browser.\n\nThe end result is that you setup a multi compiler (as shown below) and you can simply import Marko templates, and all assets are automatically generated and inlined into an optimized server response. No need to keep track of a webpack manifest yourself!\n\n### Tag: `<webpack-assets>`\n\nThe `<webpack-assets>` tag can be used along with the plugin in a multi-compiler setup. This tag allows you to inject `<script>`/`<style>` tags into a server-rendered template for the assets of an entry in the client compiler.\n\n#### Example Usage\n\n```marko\n<webpack-assets entry=\"tracking\"/>\n```\n\n#### Example Config\n\n```js\n// ...\nexport default [\n  {\n    entry: \"./server.js\",\n    plugins: [markoPlugin.server],\n    // ...\n  },\n  {\n    // ...\n    entry: {\n      tracking: \"./tracking.js\",\n    },\n    plugins: [markoPlugin.browser],\n  },\n];\n```\n\n# Example\n\n```javascript\nimport MarkoPlugin from \"@marko/webpack/plugin\";\n\nconst markoPlugin = new MarkoPlugin();\n\nexport default [\n  {\n    entry: \"./server.js\",\n    module: {\n      rules: [\n        {\n          test: /\\.marko$/,\n          loader: \"@marko/webpack/loader\",\n        },\n      ],\n    },\n    plugins: [markoPlugin.server],\n  },\n  {\n    rules: [\n      {\n        test: /\\.marko$/,\n        loader: \"@marko/webpack/loader\",\n      },\n      // If using `style` blocks with Marko you must use an appropriate loader\n      {\n        test: /\\.css$/,\n        use: [\"style-loader\", \"css-loader\"],\n      },\n    ],\n    plugins: [markoPlugin.browser],\n  },\n];\n```\n\n## Babel options (Marko 5+)\n\nIf you are using Marko 5 with this plugin you can manually override the Babel configuration used by passing a `babelConfig` object along side the `@marko/webpack/loader`. By default Babels regular [config file resolution](https://babeljs.io/docs/en/config-files) will be used.\n\n```javascript\nexport default {\n    module: {\n      rules: [\n        {\n          test: /\\.marko$/,\n          loader: \"@marko/webpack/loader\",\n          options: {\n            babelConfig: {\n              presets: [\n                [\"@babel/preset-env\", { node: \"current\" }]\n              ]\n            }\n          }\n        }\n      ]\n    }\n  },\n```\n\n## Multiple client-side compilers\n\nSometimes you need multiple compilers for your client-side bundles. For example, with [`i18n`](https://github.com/webpack/webpack/tree/master/examples/i18n) or [even shipping dynamic runtime bundles to the browser](https://github.com/eBay/arc/tree/master/packages/arc-webpack).\n\nThe `@marko/webpack` plugin’s `.browser` property can be passed to multiple Webpack compilers. While rendering at runtime, you can provide a `$global.buildName` property to choose which assets from the Webpack compiler are included in the page.\n\nFor example, with the Webpack internationalization plugin, you might have a config like the following:\n\n```js\nimport MarkoPlugin from \"@marko/webpack/plugin\";\nimport I18nPlugin from \"i18n-webpack-plugin\";\nimport germanTranslations from \"./de.json\";\n\nconst languages = {\n  en: null,\n  de: germanTranslations,\n};\n\nconst markoPlugin = new MarkoPlugin();\n\nexport default [\n  {\n    name: \"Server\",\n    entry: \"./server.js\",\n    module: {\n      rules: [\n        {\n          test: /\\.marko$/,\n          loader: \"@marko/webpack/loader\",\n        },\n      ],\n    },\n    plugins: [markoPlugin.server],\n  },\n  ...Object.keys(languages).map((language) => ({\n    name: `Browser-${language}`,\n    rules: [\n      {\n        test: /\\.marko$/,\n        loader: \"@marko/webpack/loader\",\n      },\n      // If using `style` blocks with Marko you must use an appropriate loader\n      {\n        test: /\\.css$/,\n        use: [\"style-loader\", \"css-loader\"],\n      },\n    ],\n    plugins: [new I18nPlugin(languages[language]), markoPlugin.browser],\n  })),\n];\n```\n\nWith the above config, you can render your top-level Marko template server-side with a `$global.buildName` like so:\n\n```javascript\ntemplate.render({ $global: { buildName: \"Browser-de\" } });\n```\n\nThat will automatically send German assets. However, what you _probably_ want instead of always serving German is conditionally sending appropriate assets for a user’s locale. This can be done like so:\n\n```javascript\ntemplate.render({ $global: { buildName: `Browser-${req.language}` } });\n```\n\n**Note:** If a bundle with the provided `buildName` does not exist, an error is thrown.\n\n## Multiple copies of Marko\n\nIn some cases you may want to embed multiple isolated copies of Marko on the page. Since Marko relies on some `window` properties to initialize this can cause issues. For example, by default Marko will read the server rendered hydration code from `window.$components`. In Marko you can change these `window` properties by rendering with `{ $global: { runtimeId: \"MY_MARKO_RUNTIME_ID\" } }` as input on the server side.\n\nThis plugin exposes a `runtimeId` option produces output that automatically sets `$global.runtimeId` on the server side and initializes properly in the browser.\nThe `runtimeId` will default to the [`uniqueName` option](https://webpack.js.org/configuration/output/#outputuniquename) from the server compiler in the webpack config.\n\n```js\nimport MarkoPlugin from \"@marko/webpack/plugin\";\n\nconst markoPlugin = new MarkoPlugin({\n  runtimeId: \"MY_MARKO_RUNTIME_ID\", // default to webpack `output.uniqueName` option.\n});\n```\n\nNote: This option will also override the default values for the `jsonpFunction`, `chunkCallbackName` and `hotUpdateFunction` webpack `output` options, which all use global variables, to be prefixed with the `runtimeId`.\n\n## Dynamic public paths\n\nWhen using the plugin, the server will automatically sync the runtime [`__webpack_public_path__`](https://webpack.js.org/guides/public-path/#on-the-fly) with the browser.\nThis means that you only need to setup the dynamic public path on the server side.\n","packages/runtime-class/docs/why-is-marko-fast.md":"# Why is Marko Fast?\n\n<a href=\"https://medium.com/@psteeleidem/why-is-marko-fast-a20796cb8ae3\">\n  <img src=\"https://user-images.githubusercontent.com/1958812/28104838-d0182f48-6691-11e7-808d-d1ae2d0fed6d.png\" alt=\"Marko logo\" width=\"100%\" />\n</a><br />\n\n> This article was published in May 2017. You can find the original [\"Why is Marko Fast?\" article here](https://medium.com/@psteeleidem/why-is-marko-fast-a20796cb8ae3)!\n\nAt eBay we are using [Marko](https://markojs.com/) to render over a billion\nrequests every day and this has required us to finely tune Marko, our open\nsource UI library. We have heavily optimized Marko for fast rendering, [advanced\nperformance\ntechniques](https://tech.ebayinc.com/engineering/async-fragments-rediscovering-progressive-html-rendering-with-marko/)\nand to achieve a minimal page weight (~10kb gzipped). Performance is only one\nconcern because we have also had to scale Marko to support development across\nhundreds of teams in a way that allows developers to efficiently create\nmaintainable and robust web apps.\n\nWe have created [our own\nbenchmarks](https://github.com/marko-js/isomorphic-ui-benchmarks) and we have\n[added Marko to other\nbenchmarks](https://github.com/raxjs/server-side-rendering-comparison/pull/11),\nbut benchmarks cannot always be trusted. While we make every effort to be fair\nwith our benchmarks, what matters most is performance in real world applications\nas opposed to focusing on micro benchmarks. This is one reason that the V8 team\nhas switched to [a new methodology to measure and understand real-world\nJavaScript\nperformance](https://v8project.blogspot.com/2016/12/how-v8-measures-real-world-performance.html).\n\nSimilarly, we’ve taken a look at how our developers are _actually_ writing their\nMarko components and have found patterns that could be further optimized.\nInstead of focusing on benchmarks in this article, I want to focus on the\ndetails of optimizations that we have applied to Marko.\n\n### Multiple Compilation Outputs\n\nMarko is an isomorphic UI library that runs on both the server and in the\nbrowser. As [Michael Rawlings](https://medium.com/@mlrawlings) mentioned in\n“[Server-side Rendering\nShootout](https://hackernoon.com/server-side-rendering-shootout-with-marko-preact-rax-react-and-vue-25e1ae17800f)”,\nwhen rendering on the server, Marko renders directly to a string representation\nof the document (HTML) that can be sent as the HTTP response.\n\nWhen rendering in the browser, an HTML string would have to be parsed in order\nto update the DOM. For this reason, Marko compiles a view to a program that\nrenders directly to a virtual document (VDOM) tree that can be used to\nefficiently update the real DOM when targeting the browser.\n\nGiven the following template:\n\n```marko\n<div>Hello ${input.name}!</div>\n```\n\n#### Compiled for the server\n\nThe compiled output is optimized for streaming HTML output on the server:\n\n```js\nvar marko_template = require(\"marko/html\").t(__filename),\n  marko_helpers = require(\"marko/runtime/html/helpers\"),\n  marko_escapeXml = marko_helpers.x;\n\nfunction render(input, out) {\n  out.w(\"<div>Hello \" + marko_escapeXml(input.name) + \"!</div>\");\n}\n```\n\n#### Compiled for the browser\n\n<!-- prettier-ignore -->\n```js\nvar marko_template = require(\"marko/vdom\").t(__filename);\n\nfunction render(input, out) {\n  out\n    .e(\"DIV\", null, 3)\n    .t(\"Hello \")\n    .t(input.name)\n    .t(\"!\");\n}\n```\n\nThe compiled output is optimized for virtual DOM rendering in the browser:\n\n### Modular Runtime\n\nThe Marko runtime is not distributed as a single JavaScript file. Instead, the\nMarko compiler generates a JavaScript module that will only import the parts of\nthe runtime that are actually needed. This allows us to add new features to\nMarko without bloating existing applications. For example, given the following\ntemplate:\n\n```marko\n$ var color = 'red';\n<div style={backgroundColor: color}></div>\n```\n\nIn the above example, extra runtime code is needed to render the `style` attribute\nbased on the JavaScript object that is provided. The compiled code that imports\nthe `styleAttr` helper is shown below:\n\n```js\nvar marko_styleAttr = require(\"marko/runtime/vdom/helper-styleAttr\");\n\nfunction render(input, out) {\n  var color = \"red\";\n  out.e(\n    \"DIV\",\n    {\n      style: marko_styleAttr({\n        backgroundColor: color,\n      }),\n    },\n    0,\n    4,\n  );\n}\n```\n\n### High performance server-side rendering\n\nCompared to solutions based on JSX that exclusively do virtual DOM rendering,\nMarko has a huge advantage for server-side rendering. When rendering to a\nvirtual DOM tree on the server it’s a two-step process to render HTML:\n\n- First pass to produce an entire virtual DOM tree in memory\n- Second pass to serialize the virtual DOM tree to an HTML string that can then be\n  sent over the wire (this requires traversing the entire tree structure)\n\nIn contrast, Marko renders directly to an HTML stream in a single pass. There is\nno intermediate tree data structure.\n\n### Compile-time optimization of static sub-trees\n\nGiven the following template:\n\n```marko\n<div>This is a <strong>static</strong> node</div>\n```\n\nMarko will recognize that the template fragment produces the same output every\ntime and it will thus create the virtual DOM node once as shown in the following\ncompiled output:\n\n```js\nvar marko_node0 = marko_createElement(\"DIV\", null, 3, ...)\n  .t(\"This is a \")\n  .e(\"STRONG\", null, 1)\n    .t(\"static\")\n  .t(\" node\");\n\nfunction render(input, out) {\n  out.n(marko_node0);\n}\n```\n\nRendering a static sub-tree has virtually zero cost. In addition, Marko will\nskip diffing/patching static sub-trees.\n\nSimilarly, on the server, Marko will merge static parts of the template into a\nsingle string:\n\n```js\nfunction render(input, out) {\n  out.w(\"<div>This is a <strong>static</strong> node</div>\");\n}\n```\n\n### Compile-time optimization of static attributes\n\nMarko will also optimize static attributes on dynamic elements.\n\nGiven the following template:\n\n```marko\n<div.hello>Hello ${input.name}!</div>\n```\n\nMarko will produce the following compiled output:\n\n<!-- prettier-ignore -->\n```js\nvar marko_attrs0 = {\n  class: \"hello\"\n};\n\nfunction render(input, out) {\n  out\n    .e(\"DIV\", marko_attrs0, 3)\n    .t(\"Hello \")\n    .t(input.name)\n    .t(\"!\");\n}\n```\n\nNotice that the attributes object is only created once and it is used for every\nrender. In addition, no diffing/patching will happen for static attributes.\n\n### Smart compiler\n\nWith Marko we favor doing as much at compile-time as possible. This has made our\ncompiler more complex, but it gives us significant gains at runtime. We have\n~90% code coverage and over 2,000 tests to ensure that the compiler is working\ncorrectly. In addition, in many cases the Marko compiler provides hints to the\nruntime for a given template so that the runtime can optimize for specific\npatterns. For example, Marko recognizes if an HTML element only has `class`/`id`/`style` defined\nand the runtime optimizes for these virtual DOM nodes when doing\ndiffing/patching (the Marko compiler generates code that flags simple virtual\nDOM nodes for targeted diffing/patching logic).\n\n### Event delegation\n\nIf you are building a UI component you will likely need to write code to handle\nvarious DOM events (`click`, `submit`, etc.). It is common for developers to write code that\nadds DOM event listeners using `dom.addEventListener(...)` or using a library such as jQuery. You can still\ndo that when building UI components using Marko, but there is overhead in\nattaching listeners when lots of components are being initialized. Instead,\nMarko recommends using declarative event binding as shown below:\n\n```marko\n<button type=\"button\" on-click(\"handleClick\")>\n  Click Me\n</button>\n```\n\nWhen using declarative event binding, no DOM event listeners are actually\nattached for events that bubble. Instead, Marko attaches a single listener on\nthe root DOM element of the page for each DOM event that bubbles (done at\nstartup). When Marko receives an event at the root it handles delegating the\nevent to the appropriate components that are interested in that event. This is\ndone by looking at the `event.target` property to see where the event originated and then\nwalking up the tree to find components that need to be notified. As a result,\nthere is slightly more work that is done when a DOM event is captured at the\nroot, but this approach uses much less memory and reduces the amount of work\nthat is done during initialization. The extra overhead of delegating events to\ncomponents will not be noticeable so it is a very beneficial optimization.\n\n_Cover image credit: [Superhero by Gan Khoon Lay from the Noun Project](https://thenounproject.com/search/?q=superhero&i=690775)_\n","packages/runtime-class/helpers/README.md":"# Marko Helpers\n\nThis directory contains helpers that were deprecated in Marko v3. Marko v4/5 no longer adds these helpers to every compiled template, but you can still import them if needed.\n","packages/runtime-tags/AGENTS.md":"# Marko 6 (runtime & translator)\n\nPublished as `marko@6` and `@marko/runtime-tags`. Contains both the runtime and the Babel translator that generates code against it; most changes touch both halves plus test fixtures.\n\n## Layout\n\n| Directory         | Purpose                                                                                                                |\n| ----------------- | ---------------------------------------------------------------------------------------------------------------------- |\n| `src/common/`     | Types, accessor enums, helpers shared by both runtimes                                                                 |\n| `src/dom/`        | CSR runtime: scopes, signals, control flow, resume, scheduling                                                         |\n| `src/html/`       | SSR runtime: streaming writer, value serializer, resume boilerplate                                                    |\n| `src/translator/` | Babel translator: `core/` (built-in tags), `visitors/` (per AST node), `util/` (analysis), `interop/` (Marko 5 compat) |\n\nEntries: `src/dom.ts`, `src/html.ts`, `src/translator/index.ts`. Type stubs for core tags: `tags/*.d.marko`.\n\n## Architecture\n\n[CONTEXT.md](CONTEXT.md) is the canonical glossary — use its terms (and respect\nits _Avoid_ lists) in code, comments, and discussion. Read the\n[resume architecture guide](RESUMABILITY.md) before changing reference analysis,\nsignals, serialization, resume, lazy loading, or generated DOM output; it traces\nthe compiler/runtime model end to end and routes each concept to its code.\n\nPrinciples that decide most proposals:\n\n- Client code, serialized data, and registrations ship only where analysis shows they can run or update.\n- Code ships because code that ships references it, never by force. Never keep a call or declaration for its side effect (a registration, a stamp) or to make an optimized build work: a kept value pins its whole reference graph (signals, joins, renders, runtime), which in real apps bundles subgraphs the plain build drops, so a fixture's small size delta proves nothing. Deliver the fact the client needs instead (serialized data or a compiler literal). An unreferenced top-level declaration in an optimized bundle snapshot is this bug.\n- A build contract (an id the compiler registered) is a `MARKO_DEBUG` assert, never a production check, and needs no fixture faking its violation.\n- An optimization may take any shape that idiomatic Marko code cannot observe.\n- HTML output targets what browsers parse, not validators.\n- No API may require `import \"marko\"`.\n\n## Translator\n\nThe compiler phase contract is strict:\n\n| Phase       | Contract                                                                                                                           |\n| ----------- | ---------------------------------------------------------------------------------------------------------------------------------- |\n| Parse       | Create the initial hybrid Marko/Babel AST.                                                                                         |\n| `migrate`   | Apply userland and translator-provided Marko-to-Marko codemods that may be written back to disk.                                   |\n| `transform` | Apply typically userland Marko-to-Marko codemods that affect compilation only and must never be written back.                      |\n| Pre-analyze | Technically part of `transform`; normalize/simplify Marko before analysis when the analyzer or translator needs a canonical shape. |\n| `analyze`   | Annotate the AST, usually via `node.extra`, and compute output-neutral graph data: bindings, signals, ids, reasons.                |\n| `translate` | Convert Marko to JavaScript for the configured `dom` or `html` output.                                                             |\n\nEverything through `analyze` is cached and reused across outputs. Therefore:\n\n- Mutating AST structure during `analyze` is an anti-pattern; perform reshaping in pre-analyze.\n- Analyze records facts about the template, never nodes. Never retain an AST node or `NodePath` across phases, including inside `node.extra` (or program extra/`Section`/`Binding` fields): the analyzed AST is cached and `t.cloneNode`d for each output, so a stored node points at the cache while translate walks a clone — reads go stale and identity checks fail silently. The metadata shell itself (`node.extra` objects, `Section`s, `Binding`s) is shared by reference across clones, so record facts there — flags, ids, `Section`/`Binding` references — and resolve current nodes within the current phase. If the fact concerns a child whose metadata does not exist yet at your visitor, flag it from an analyze `exit` hook (children are analyzed by then) rather than storing the child node for later.\n- Never make output-specific decisions before `translate`. Branch on `dom`/`html` only while translating.\n- Reach the current compilation through `getFile()`/`getProgram()` (from `@marko/compiler/babel-utils`), never `path.hub.file`: the hub chain re-derives what the compile state already tracks and reads inconsistently across contexts. There are currently zero `hub.file` uses in the translator; keep it that way.\n- `file.metadata.marko` is public compiler output (returned from the top-level compile APIs): never route internal channels through it. Internal analyze products belong on the extras shell (program extra, `Section`, `Binding`); metadata carries only deliberately public facts.\n- Naming follows the same contract: analyze metadata (Binding/Section/`node.extra` fields) records **what the template does** — observed facts, in template terms (sources, reads, uses, shapes). Translate names its **conclusions** — decisions, policies, and output mechanisms (ownership, wire channels, masks). A shared field named after a decision (e.g. server/client \"owned\", \"required\") is a smell: name the observation and derive the decision where it is made. Never coin a term the compiler does not already use; a new concept gets a `CONTEXT.md` entry first.\n- Keys on `node.extra` say who may use them: a symbol key is one module's private state and is never exported; a fact any other module reads is a string field declared on its node kind's extra (`MarkoTagExtra`, `FunctionExtra`, or `NodeExtra` for an expression root).\n- The translator has no `MARKO_DEBUG` checks: its published build drops them, so a check guards only local development. Design the invariant out instead: derive the value from what makes it true, type it so a violation does not compile, or leave misuse no path.\n- Gather in analyze, act in translate. There are currently zero Babel `traverse` calls in the translator; keep it that way. Before adding analysis, find the fact in what exists (`Section`, a binding's reads/aliases/sources, `node.extra`, reasons, tag-name and known-tag analysis) and extend it; after adding one, check what else can use it.\n- Analyze facts settle once. `Binding.reads`, `Binding.pruned`, and reasons are complete only once `finalizeReferences` runs at program analyze `exit`, so tag and expression analyze visitors never read them; an expression's resolved references are read through `getReferencedBindings`/`getLazyBindings`, which finalize sets. One exception: a known tag's call site reads its callee's params tree during analyze, which is complete for another template or for a `<define>` called from outside its body; a recursive tag waits for program exit (`analyzeRecursiveTags`) to read it. A fact about the template is a field (`Section`, `Binding`, `node.extra`, the program's extra), written once it is final, never un-set, and never read for a fact it was not built for. `createAnalysisState` holds analyze scratch and caches derived from facts, which every output reads; `createOutputState` holds what one output builds; the `…SectionState` forms key either by section.\n- A tag records its client markup into its section's structure stream (`util/structure.ts`) in render order, passing `structure.node`/`structure.marker` the dom binding that holds each node client code addresses (`structure.controlFlowNode` addresses a control flow tag by its only-child element or a marker). DOM derives the template and walk string from the stream, and the walker stores each node it reaches at the next scope index, so `allocateIds` numbers a section's dom bindings in stream order: creation order never matters.\n- Pruning drops a binding nothing reads, with its value. Translate emits a read only of a binding analysis kept: check `pruned`, and write each read as analysis resolved it (`getReadReplacement`), never by a name the graph does not track.\n- Reference analysis (`util/references.ts`, `finalize-references.ts`, `solve-reasons.ts`) is tag-agnostic: a tag records a generic fact on its expression's `node.extra`, and the analysis reads it without naming the tag. Known tags are the one exception: the solver maps each call site's param reason groups every pass (`addKnownTagReasons`). `solveReasons` repeats its steps until no reason moves, so each step is named for what it adds, merges or ensures (`addClosureReasons`, `mergeSlotReasons`, `ensureSectionReasonGroups`); `finalize*` names work that runs once, on settled facts (`finalizeReferences`).\n- A program-wide effect (`isInteractive`, an imported registration) follows the reason that needs it, never a feature's presence. Only an unconditional reason makes a template a bundle root: a value written only while a caller changes params ships with that caller, which imports the template.\n- Compile-context helpers (`isOptimize`, `isOutputHTML`, `getMarkoOpts`, `callRuntime`) are called where needed, never passed in as overridable parameters. Non-capturing callbacks become named file-level functions here too.\n\nNode visitors live in `visitors/` and are split per phase by `extractVisitors` (`util/visitors.ts`); `visitors/tag/index.ts` dispatches to `native-tag.ts` / `custom-tag.ts` / `dynamic-tag.ts` / `attribute-tag.ts` or a tag definition's own hooks.\n\nCore tags are one file per tag in `core/`, registered in `core/index.ts`:\n\n```ts\nexport default {\n  analyze(tag) { ... },\n  translate: translateByTarget({\n    html(tag) { ... },\n    dom(tag) { ... },\n  }),\n} as Tag;\n```\n\n- `callRuntime(\"_name\", ...args)` (`util/runtime.ts`) references runtime helpers with automatic imports; DOM helpers listed in `pureDOMFunctions` get `/*@__PURE__*/`.\n- Validate early: core tags share their checks and wording from `util/assert.ts` (`assertOnlyValueAttr`, `assertHasBody`, `assertHasVar`, `assertNoSpreadAttrs`, …), while `assertNoArgs` / `assertNoParams` / `assertNoVar` / `assertAllowedAttributes` come from `@marko/compiler/babel-utils`. Compile errors use `path.buildCodeFrameError` with backticked names and a markojs.com docs link — `util/assert.ts` is the canonical style.\n- `util/marko-config.ts` provides `isOutputHTML` / `isOutputDOM` / `isOptimize`.\n- `util/optional.ts` (`Opt`/`Sorted` list algebra) underpins reference tracking; a list a `Sorted` instance builds (`bindingUtil`, `propsUtil`, `sectionUtil`, `sourcesUtil`) is looked up by binary search, so it is typed `SortedOpt` and only that instance can write it (`push`/`concat` results do not type-check into one). Work on these lists with its helpers (`forEach`, `some`, `reduce`, `filter`, the `Sorted` utils): build-then-`reverse` and dedupe-on-add are smells; `util/known-tag.ts` holds the custom/dynamic tag input contracts. Native element work lives in `visitors/tag/native-tag.ts` (with `common/helpers.ts` and `util/tag-facts.ts`).\n\n## Runtime conventions\n\n- **`_name` exports** are runtime API called by generated code — public to codegen, not to app authors. Renames must update `callRuntime` call sites and `pureDOMFunctions`.\n- **`MARKO_DEBUG`** gates all validation, descriptive names, and detailed error messages (`if (MARKO_DEBUG) { ... }`); builds strip these. Write for the optimized build: debug-only code never leaves it a temporary or branch, so return directly. It is `true` for code loaded through the `~ts` register hook; fixture bundles define it per mode (`false` under optimize). Runtime error helpers live in `common/errors.ts`.\n- **`.debug.ts` pairs**: source imports the `.debug` module (e.g. `common/types.ts` imports `./constants/accessor-prop.debug`); the production build remaps `X.debug` → `X.ts`. Both files must export identical member names with unique string values. `src/__tests__/debug-pairs.test.ts` checks every pair because the types cannot — each module's `Value` is `typeof import(\"./<itself>\")` and `translator/util/get-accessor-enums.ts` casts `as any` — so a member added to only one half would otherwise type-check and show up as `undefined` in an optimize build. A runtime record that needs readable debug keys uses a pair, extending the module for the object type that owns the property (repeated short values compress better).\n- **Optional feature enablement** (tree-shakable runtime API) has two patterns:\n  - **`src/{dom,html}/**/*.feat.ts`** are compiler-injected side-effect modules for behavior a referenced import cannot keep alive (catch handling, controllable registration). The build emits them as extra entries of their runtime's bundle — a shared chunk keeps one state instance, so they import runtime internals directly. A feature body is direct registry/property assignments (plus at most one installer call, e.g. `installCatch`); the compiler emits it once per program via `importRuntimeFeature` (typed by `DOMRuntimeFeature`). `lazy.feat` is the exception: `translator/util/entry-builder.ts` › `builder.build` imports it (via `getRuntimeFeatureImport`) into a resuming entry that reaches a lazy import, since resume needs its latch even when no bundled template references lazy runtime.\n  - **Definition-site wrappers** gate behavior on a helper's own retention: `export const _if = /*@__PURE__*/ withBranches(...)`.\n  - Latches are `let`s written only by their enabler (`branchesEnabled`, `catchEnabled`) so bundlers fold latch and guarded code away together; object-property flags defeat that analysis and re-inflate resume bundles.\n  - Never statically import control-flow or a `.feat` module from a main-graph module (queue, resume, load) — it fuses the feature into every bundle.\n  - Base helpers and the writer take no feature-only params, hooks, or flags (a feature-only param goes last). A `.feat` imports the features it always needs.\n- **Size idioms** (client runtime): inline a helper, `const`, or `let` used once, and repeat a short member read rather than binding it (gzip favors repetition). Prefer truthiness with `0`/`1` over `undefined`/booleans, default params, `||=`, `for (let i = n; i--;)`, and `else` over an early `return`. Give every parameterless arrow an unused parameter, consistently, since `e=>` minifies a byte under `()=>`: `(_?: never) =>` where callers pass nothing, else typed as what they pass; generated client code takes `getUnusedParamIdentifier()` (not an IIFE, which the minifier inlines only bare), and the inlined runtimes a free letter. Tell nodes apart with `nodeType >`/`<` against the `NodeType` enum (a marker is `> NodeType.Element`), never the DOM's constants. Settle byte questions by measuring with `build:sizes`, and weigh a byte by how often an app pays it: once (the runtime) counts least, per template (generated code, across an app's thousands of templates) more, and per rendered instance (serialized data, per loop row) most; a fixture's delta shows only the one-time cost.\n- **Hot paths** (SSR writer, serializer, resume): never `delete`, copy with spread/rest, `unshift`/`reverse`, take rest params per tag, or create a promise or closure unconditionally. Never post-process output with string `replace`/`split`/`indexOf`; the serializer appends valid JavaScript. Keep object shapes consistent; put cheap checks first.\n- **Wire bytes**: before serializing a link or field, derive it from what the client already knows (walk and insertion order, id order). Rare tuple slots go last so trailing-empty trimming drops them.\n- Named/top-level functions use `function` declarations; arrows only for closures that must capture or for wrapped feature helpers (smaller output). Extract non-capturing closures into named file-level functions.\n\n## Testing\n\nFixture-based snapshot tests driven by `src/__tests__/main.test.ts`. Fixtures live in `src/__tests__/fixtures/`, plus `fixtures-interop/` (Marko 5 ↔ 6 mixing, suite name `translator-interop`). A dir suffixed `.skip` is ignored.\n\nFrom the repo root:\n\n```sh\npnpm test                                                            # whole suite, fanned across CPU cores\npnpm test -- --grep \"runtime-tags/translator <fixture> \"             # one fixture (note trailing space)\npnpm run test:update -- --grep \"runtime-tags/translator <fixture> \"  # regenerate its snapshots\npnpm test -- --grep \"translator-interop\"                             # interop suite (run after base suite passes)\n```\n\nIterate scoped, then run `pnpm test` for everything; it fans across cores and reports every failure. Repeating a grep as `pnpm run test:serial -- --grep \"...\"` runs it in one process, with `bail: true` and live output, for a debugger or a clean stack trace.\n\n### Fixture anatomy\n\n```\nfixtures/<name>/\n  template.marko    # entry (required); custom tags under tags/\n  test.ts           # optional: export const config: TestConfig = { ... }\n  sizes.json        # generated compiled-size tracking\n  __snapshots__/    # generated + auto-pruned by test:update; never edit or delete by hand\n    dom.bundle[.debug].js       # compiled CSR output\n    html.bundle[.debug].js      # compiled SSR output\n    render[.debug].md           # per-step rendered HTML + granular mutation log + `## Console` output\n    writes[.debug].html         # SSR stream chunks (joined by <!-- FLUSH -->)\n    diagnostics[.debug].md      # debug-only meta.diagnostics (warnings/deprecations)\n    error-compile-{html,dom}[.debug].txt   # expected compile failure (error_compiler)\n    {ssr,csr}.error[.debug].txt            # expected render failure (error_html/error_dom)\n```\n\nAdding or removing a recoverable diagnostic or deprecation therefore fails a `diagnostics.md` snapshot in every fixture that carries one.\n\n`TestConfig` (see `main.test.ts`): `steps` (`[initialInput, ...]` where later steps are input updates, `(container) => {}` interactions, or async `Wait`/`Flush`/`Throws` controls), `error_compiler` (expect compile failure), `error_html` / `error_dom` (expect a render failure), `equivalent: false` (separate `render-ssr`/`render-csr` snapshots), `embedded`, `load_order` / `reject_load` (lazy-chunk ordering and failure), `fix_guide`, `skip_optimize` / `skip_dom` / `skip_html` / `skip_csr` / `skip_ssr`, `skip_parity` (debug intentionally logs a diagnostic optimize cannot), `runtime_id`. Each fixture runs in `debug` and `optimize` modes; CSR only runs in `debug`.\n\nTo add a fixture: create the dir + `template.marko` (+ `test.ts` with steps exercising the behavior), run `test:update` scoped to it, then **read the generated snapshots as part of your change** — the mutation log in `render.md` shows update granularity (an unexpected extra `UPDATE:`/re-render is a regression), and the `.bundle.js` diff shows generated-code cost. Name a fixture for the behavior it pins, not the repro that found it; it fails without the change, uses current syntax (never deprecated features), and gets async values from `__tests__/utils/resolve.ts` (`resolveAfter`, `rejectAfter`). The summary names each changed snapshot family and why it changed.\n\n## Workflows\n\n**New/changed core tag** (see the `<show>` tag commit for a full example):\n\n1. `translator/core/<tag>.ts` + register in `core/index.ts` (and `util/is-core-tag.ts`), and give it an entry in `util/tag-facts.ts`.\n2. Runtime helpers in `src/dom/` / `src/html/`, exported from `src/dom.ts` / `src/html.ts`; add to `util/runtime.ts` lists as needed.\n3. Several small fixtures covering static values, dynamic updates, nesting, and interaction with `<for>`/`<if>`.\n4. `pnpm run change` — user-facing changes need a changeset.\n5. Update `cheatsheet.md` (the LLM syntax reference shipped in the published package) when the change affects user-facing syntax, idioms, or guidance. Keep it dense: a line earns its place only by preventing a real mistake.\n6. Expect broad snapshot/`sizes.json` churn and an update to `packages/runtime-class/test/taglib-lookup/fixtures/getTagsSorted/expected.json` (interop taglib lookup).\n\n**Changing generated output**: iterate with `pnpm run compile -- -o dom -d file.marko` (and `-o html`), then `test:update` and audit snapshot diffs — output shape changes ripple through hundreds of fixtures; verify a sample by hand, don't rubber-stamp.\n\n**Changing runtime behavior**: find the covering fixtures by grepping `__tests__/fixtures` for the runtime helper or syntax; extend `steps` before touching the runtime so the mutation log captures the before/after.\n\n## Gotchas\n\n- `translator/util/bindings.ts` imports `toAccess` from `html/serializer.ts` — serializer key encoding changes affect the translator.\n- Adding an accessor enum member: keep the `src/common/constants/*[.debug].ts` pair in lockstep (same members, char vs. readable string values).\n- Size regressions count as review findings: check the fixture `sizes.json` diffs and root `.sizes.json` (updated by the pre-commit hook).\n- Language semantics questions (what a tag/attribute should do) are answered by the docs, not inferred: <https://markojs.com/llms.txt>.\n","packages/runtime-tags/README.md":"<div align=\"center\">\n\n# [<img alt=\"Marko\" src=\"https://raw.githubusercontent.com/marko-js/website/refs/heads/main/public/assets/logo.svg\" width=\"250\">](https://markojs.com/)\n\n**A declarative, HTML-based language that makes building web apps fun 🔥**\n\n[![NPM](https://img.shields.io/npm/v/marko.svg)](https://www.npmjs.com/package/marko)\n[![Discord Chat](https://img.shields.io/badge/discord-chat-7188da.svg)](https://discord.gg/RFGxYGs)\n[![Continuous Integration status](https://github.com/marko-js/marko/actions/workflows/ci.yml/badge.svg)](https://github.com/marko-js/marko/actions/workflows/ci.yml)\n[![Code coverage %](https://codecov.io/gh/marko-js/marko/branch/master/graph/badge.svg)](https://codecov.io/gh/marko-js/marko)\n[![# of monthly downloads](https://img.shields.io/npm/dm/marko.svg)](https://npm-stat.com/charts.html?package=marko)\n[![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/7029/badge)](https://bestpractices.coreinfrastructure.org/projects/7029)\n\n[Docs](https://markojs.com/docs/introduction/getting-started) ∙ [Try Online](https://markojs.com/playground) ∙ [Contribute](#contributors) ∙ [Get Support](#community--support)\n\n</div>\n\n## Intro\n\nMarko is HTML _reimagined_ as a language for building dynamic and reactive user interfaces. Almost any valid HTML is valid Marko, and Marko extends HTML for building modern applications more declaratively. Among these extensions are [components](https://markojs.com/docs/reference/custom-tag), [conditionals](https://markojs.com/docs/reference/core-tag#if--else) and [loops](https://markojs.com/docs/reference/core-tag#for), and a full [reactivity system](https://markojs.com/docs/reference/reactivity).\n\n### Example Component\n\nThe following renders a button and a counter of how many times the button has been pressed:\n\n**click-count.marko**\n\n```marko\n// HTML + JavaScript = 💜\n<let/count=0>\n<button onClick() { count++ }>\n  Clicked ${count} times\n</button>\n```\n\n## Getting Started\n\n1. `npm init marko`\n2. Read the [docs](https://markojs.com/docs/introduction/getting-started)\n\n## Community & Support\n\n<table>\n<thead><tr>\n  <th><svg viewBox=\"0 0 576 512\"><path d=\"M492.5 69.8c-.2-.3-.4-.6-.8-.7-38.1-17.5-78.4-30-119.7-37.1-.4-.1-.8 0-1.1 .1s-.6 .4-.8 .8c-5.5 9.9-10.5 20.2-14.9 30.6-44.6-6.8-89.9-6.8-134.4 0-4.5-10.5-9.5-20.7-15.1-30.6-.2-.3-.5-.6-.8-.8s-.7-.2-1.1-.2c-41.3 7.1-81.6 19.6-119.7 37.1-.3 .1-.6 .4-.8 .7-76.2 113.8-97.1 224.9-86.9 334.5 0 .3 .1 .5 .2 .8s.3 .4 .5 .6c44.4 32.9 94 58 146.8 74.2 .4 .1 .8 .1 1.1 0s.7-.4 .9-.7c11.3-15.4 21.4-31.8 30-48.8 .1-.2 .2-.5 .2-.8s0-.5-.1-.8-.2-.5-.4-.6-.4-.3-.7-.4c-15.8-6.1-31.2-13.4-45.9-21.9-.3-.2-.5-.4-.7-.6s-.3-.6-.3-.9 0-.6 .2-.9 .3-.5 .6-.7c3.1-2.3 6.2-4.7 9.1-7.1 .3-.2 .6-.4 .9-.4s.7 0 1 .1c96.2 43.9 200.4 43.9 295.5 0 .3-.1 .7-.2 1-.2s.7 .2 .9 .4c2.9 2.4 6 4.9 9.1 7.2 .2 .2 .4 .4 .6 .7s.2 .6 .2 .9-.1 .6-.3 .9-.4 .5-.6 .6c-14.7 8.6-30 15.9-45.9 21.8-.2 .1-.5 .2-.7 .4s-.3 .4-.4 .7-.1 .5-.1 .8 .1 .5 .2 .8c8.8 17 18.8 33.3 30 48.8 .2 .3 .6 .6 .9 .7s.8 .1 1.1 0c52.9-16.2 102.6-41.3 147.1-74.2 .2-.2 .4-.4 .5-.6s.2-.5 .2-.8c12.3-126.8-20.5-236.9-86.9-334.5zm-302 267.7c-29 0-52.8-26.6-52.8-59.2s23.4-59.2 52.8-59.2c29.7 0 53.3 26.8 52.8 59.2 0 32.7-23.4 59.2-52.8 59.2zm195.4 0c-29 0-52.8-26.6-52.8-59.2s23.4-59.2 52.8-59.2c29.7 0 53.3 26.8 52.8 59.2 0 32.7-23.2 59.2-52.8 59.2z\"></path></svg>\n  <th><svg viewBox=\"0 0 576 512\"><path d=\"M407.8 294.7c-3.3-.4-6.7-.8-10-1.3 3.4 .4 6.7 .9 10 1.3zM288 227.1C261.9 176.4 190.9 81.9 124.9 35.3 61.6-9.4 37.5-1.7 21.6 5.5 3.3 13.8 0 41.9 0 58.4S9.1 194 15 213.9c19.5 65.7 89.1 87.9 153.2 80.7 3.3-.5 6.6-.9 10-1.4-3.3 .5-6.6 1-10 1.4-93.9 14-177.3 48.2-67.9 169.9 120.3 124.6 164.8-26.7 187.7-103.4 22.9 76.7 49.2 222.5 185.6 103.4 102.4-103.4 28.1-156-65.8-169.9-3.3-.4-6.7-.8-10-1.3 3.4 .4 6.7 .9 10 1.3 64.1 7.1 133.6-15.1 153.2-80.7 5.9-19.9 15-138.9 15-155.5s-3.3-44.7-21.6-52.9c-15.8-7.1-40-14.9-103.2 29.8-66.1 46.6-137.1 141.1-163.2 191.8z\"></path></svg>\n  <th><svg viewBox=\"0 0 448 512\"><path d=\"M357.2 48L427.8 48 273.6 224.2 455 464 313 464 201.7 318.6 74.5 464 3.8 464 168.7 275.5-5.2 48 140.4 48 240.9 180.9 357.2 48zM332.4 421.8l39.1 0-252.4-333.8-42 0 255.3 333.8z\"></path></svg>\n  <th><svg viewBox=\"0 0 512 512\"><path d=\"M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3 .3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5 .3-6.2 2.3zm44.2-1.7c-2.9 .7-4.9 2.6-4.6 4.9 .3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM252.8 8c-138.7 0-244.8 105.3-244.8 244 0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1 100-33.2 167.8-128.1 167.8-239 0-138.7-112.5-244-251.2-244zM105.2 352.9c-1.3 1-1 3.3 .7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3 .3 2.9 2.3 3.9 1.6 1 3.6 .7 4.3-.7 .7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3 .7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3 .7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z\"></path></svg>\n<tbody><tr><td>\n\nHang out in our [Discord server](https://discord.gg/marko) to ask questions & discuss marko<td>\n\nKeep up with the community on Bluesky at [@markojs.com](https://bsky.app/profile/markojs.com)<td>\n\nTweet to [@MarkoDevTeam](https://twitter.com/MarkoDevTeam) or use the [#markojs](https://twitter.com/search?q=%23markojs%20OR%20%40markodevteam&f=live) hashtag<td>\n\nBrowse the code, open issues, & make pull requests on [GitHub](https://github.com/marko-js/marko)\n\n</table>\n\n### Contributors\n\nMarko would not be what it is without all those who have contributed ✨\n\n[![All marko-js/marko GitHub contributors](https://opencollective.com/marko-js/contributors.svg?width=890&button=false)](https://github.com/marko-js/marko/graphs/contributors)\n\n### Get Involved!\n\n- Pull requests are welcome!\n- Submit [GitHub issues](https://github.com/marko-js/marko/issues) for any feature enhancements, bugs, or documentation problems\n- [Read the Contribution Tips and Guidelines](.github/CONTRIBUTING.md)\n- Participants in this project agree to abide by [its Code of Conduct](https://github.com/eBay/.github/blob/main/CODE_OF_CONDUCT.md)\n","skills/README.md":"# Skills\n\nAgent skills for AI coding assistants working with Marko. Each skill is a folder with a `SKILL.md` entry point (frontmatter `name`/`description` plus instructions); sibling `.md` files are references the agent loads on demand.\n\n| Skill                                                | Use it to                                                                                                                |\n| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |\n| [`marko-best-practices`](./marko-best-practices)     | write idiomatic Marko 6 when creating or editing `.marko` files                                                          |\n| [`marko-5-to-6-migration`](./marko-5-to-6-migration) | migrate Marko 5 (Class API / legacy widgets) apps and libraries to Marko 6, fully or incrementally via the interop layer |\n\n## Installation\n\nSkills run inside your own project, not this repo.\n\nWith the [skills CLI](https://skills.sh) (installs into the current project for Claude Code, Cursor, and other supported agents; pick the skills when prompted):\n\n```sh\nnpx skills add marko-js/marko\n```\n\nOr manually, for Claude Code: copy a skill folder into your project's `.claude/skills/` directory (or `~/.claude/skills/` to enable it globally):\n\n```sh\ncp -r skills/marko-5-to-6-migration YOUR_APP/.claude/skills/\n```\n\nAny agent that supports the `SKILL.md` convention can consume these folders the same way.\n\n## Usage\n\nOnce installed, the agent applies a skill automatically when a request matches its description, or invoke it explicitly (in Claude Code, type `/` plus the skill name). For example, in a Marko 5 project:\n\n```text\n/marko-5-to-6-migration plan an incremental migration of this app\n```\n\n```text\nMigrate this component library to Marko 6 and remove all class components.\n```\n","skills/marko-5-to-6-migration/SKILL.md":"---\nname: marko-5-to-6-migration\ndescription: Migrate Marko 5 (Class API / legacy widget API) applications and component libraries to Marko 6 (Tags API). Use when asked to upgrade Marko, convert class components to tags, remove the Class or widget API, or plan an incremental Marko 6 adoption using the Marko 5 interop layer.\n---\n\n# Marko 5 → Marko 6 Migration\n\nMarko 6 replaces the Class API (`class {}` blocks, `component.js` files, `this.state`, `this.emit`, legacy widgets) with the Tags API (`<let>`, `<const>`, tag variables, function-valued event attributes). `marko@6` is **not** backward compatible: it cannot compile Class API files at all. `marko@5` **is** forward compatible: through the interop layer built into modern `marko@5`, one app compiles Tags API and Class API files side by side, classifying each `.marko` file individually.\n\nThat gives two supported migration strategies. **Confirm with the user which one they want before editing code** (unless they already said):\n\n| Strategy                  | End state                                                                                                                                                              | Choose when                                                                                  |\n| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |\n| **Full migration**        | `marko@6` installed; zero Class/widget API anywhere                                                                                                                    | Small-to-medium codebase, you control all `.marko` sources, one big change is acceptable     |\n| **Incremental migration** | Stays on latest `marko@5`; files convert to Tags API one at a time via interop; app is shippable after every step; ends with the same final flip as the full migration | Large codebase, must keep shipping, third-party Marko 5 tag libraries in use, multiple teams |\n\nHard constraints that force the choice:\n\n- A dependency that ships Class API tags you cannot fork (e.g. `@ebay/ebayui-core`) blocks the final flip to `marko@6`. Use the incremental flow and stay on `marko@5` until every dependency has a Tags API release. For a small straggler module, converting it locally and carrying the diff with [`patch-package`](https://github.com/ds300/patch-package) is often practical — patch, verify, and upstream the conversion.\n- Legacy widget usage (`marko-widgets`, `@marko/compat-v4`, `w-bind`, `defineComponent`) has no interop with Marko 6 and no automated path. Those components must be rewritten to Tags API (or at minimum to the Class API first) in either flow.\n\nThere is **no automatic source-to-source converter** from Class API to Tags API. Every file is converted by hand (by you), using the mapping tables in this skill.\n\n## Reference files\n\nRead these on demand; do not guess at mappings from memory:\n\n- [`api-mapping.md`](./api-mapping.md) — exhaustive Marko 5 → 6 translation tables: template syntax, core tags, the full `Marko.Component` API, legacy widget API, server/template rendering APIs, taglib metadata, TypeScript types. **Read before converting your first file.**\n- [`patterns.md`](./patterns.md) — worked before/after conversions of the common component shapes (stateful, controllable, refs, third-party DOM libraries, attribute tags, `<await>`, split components, legacy widgets).\n- [`interop.md`](./interop.md) — exact file-classification rules, boundary semantics, limitations, and troubleshooting for running both APIs in one app. **Read before any incremental work**, and when debugging \"Cannot mix Tags API and Class API features\" or hydration issues in a mixed app.\n- The Marko 6 cheat sheet (`cheatsheet.md`, shipped with Marko 6) — compact rules for idiomatic Tags API code, including traps the files above don't cover: a top-level `>` in an attribute value silently ends the tag, and native inputs stay uncontrolled until their `*Change` handler is added. **Read before writing Tags API code.** While the app is still on `marko@5` it ships only in its `@marko/runtime-tags` dependency: `node -p \"require.resolve('@marko/runtime-tags/cheatsheet.md', { paths: [require.resolve('marko/package.json')] })\"`. Once on `marko@6` it is `node -p \"require.resolve('marko/cheatsheet.md')\"`, the file compile errors point to.\n\n## Step 1 — Assess\n\nGather facts before proposing anything:\n\n```sh\nnpm ls marko @marko/compiler   # current versions (use the project's package manager: pnpm ls / yarn why)\nfind . -type d \\( -name components -o -name tags \\) -not -path '*/node_modules/*'  # directory conventions in use\n```\n\nInventory the migration surface (run from the project root; counts of affected files). The greps are heuristics for sizing the work, not an exact list — review matches before acting on them, and extend the exclusions to cover this project's build output, docs, and any installed skills:\n\n```sh\ncf() { grep -rlE --exclude-dir={node_modules,.git,dist,build,coverage,.claude} \"$@\" . | wc -l; }  # count files matching\n\n# Class API\ncf '^\\s*class \\{' --include='*.marko'                 # inline class blocks\nfind . -not -path '*/node_modules/*' \\( -name 'component.js' -o -name 'component.ts' \\\n  -o -name 'component-browser.js' -o -name 'component-browser.ts' \\\n  -o -name '*.component.js' -o -name '*.component-browser.js' \\) | wc -l  # external/split components\ncf '^\\$ ' --include='*.marko'                         # $ scriptlets\ncf 'on-[a-zA-Z-]+\\(' --include='*.marko'              # attribute-argument event handlers\ncf 'renderBody' --include='*.marko'\ncf 'this\\.(state|emit|getEl|getComponent|subscribeTo|setState|forceUpdate)'\ncf ':scoped|:no-update|no-update' --include='*.marko'\ncf '<(while|macro|include-text|include-html|module-code|await-reorderer|init-components)' --include='*.marko'\ncf '<await' --include='*.marko'                       # async boundaries (interop-sensitive)\n\n# Legacy widget API (Marko 3/4 era) — must be rewritten in every flow\ncf 'w-bind|w-on-|widget-types|defineComponent|defineWidget|defineRenderer|legacy-components|marko-widgets|@marko/compat-v4'\n\n# Server / rendering API\ncf 'renderSync|renderToString|\\.stream\\(|out\\.global|beginAsync|res\\.marko|marko/node-require|marko/components'\n```\n\nAlso identify: the bundler (lasso / webpack / rollup / vite / `@marko/run` / `browser.json` files), the server integration (`@marko/express`, koa, fastify, raw http), the test setup, and whether TypeScript or `marko.json` `\"script-lang\": \"ts\"` is configured.\n\nReport the inventory to the user together with the recommended strategy, then proceed on the agreed flow.\n\n## Step 2 — Modernize the foundation (both flows, still on Marko 5)\n\nEach of these is an independently shippable change. Verify the app builds and tests pass after each.\n\n1. **Upgrade to the latest `marko@5`** and `@marko/compiler` 5.x. Modern `marko@5` (5.39+) depends on `@marko/runtime-tags` and its `marko/translator` entry _is_ the interop translator, so this alone enables Tags API files — no other configuration.\n2. **Clear existing deprecations** (they become hard errors or dead ends in 6): see \"Already deprecated in Marko 5\" in [`api-mapping.md`](./api-mapping.md). Run the app with `MARKO_DEBUG` / non-production `NODE_ENV` and fix every `complain()` deprecation warning.\n3. **Rewrite legacy widgets** (`defineComponent` / `defineWidget` / `w-bind` / `getInitialState`). Rewrite straight to Tags API when the component is small; otherwise to Class API first so it rides the normal conversion path later. Mapping table: \"Legacy widget API\" in `api-mapping.md`.\n4. **Delete explicit `<init-components/>` and `<await-reorderer/>` tags unconditionally.** Marko 5 injects both implicitly, so explicit usages are already redundant — removing them is safe today and required eventually (both are Class-only signals to the interop classifier).\n5. **Adopt `server` and `client` statements early.** These were backported to Marko 5 (5.38+) and are API-neutral for interop classification, so they work in Class files today. Replace environment guards (`typeof window` checks, browser-only `require`s) and — importantly — any `component-browser.js` that exists only as a glorified bundling trick to keep code out of the server build: `client import \"./browser-only\"` expresses that directly in the template. This shrinks the real migration surface before any API conversion.\n6. **Consider modernizing the bundler.** `@marko/vite`, `@marko/webpack`, `@marko/rollup`, and `@marko/run` all support Marko 5 _and_ 6 (e.g. `@marko/run` declares `\"marko\": \"5 - 6\"`), so this ships while still fully on Marko 5. Lasso also keeps working with Marko 6 — staying on it is viable; you only give up code-splitting of lazy imports (`with { load }` needs the bundler-provided `linkAssets`; without it those imports just load eagerly). `browser.json` component wiring should be retired regardless.\n7. **Baseline**: record SSR output of key pages (curl to files) and make the test suite green. These are your regression oracle.\n\n## Step 3 — Convert files\n\nThe per-file mechanics are identical in both flows; the flows differ in ordering and in when the dependency flips.\n\nFor each `.marko` component (work **leaf-first**, bottom-up):\n\n1. Read _everything_ that makes up the component: `index.marko`, `component.js` / `component-browser.js` (also `.ts` and `*.component[-browser].js` variants), `marko-tag.json`, `browser.json`, adjacent `style.*` files, plus every call site of the tag.\n2. Classify its shape and open the matching worked example in [`patterns.md`](./patterns.md): inert/presentational · stateful · controllable (state initialized from input + change events) · element refs / imperative DOM · third-party library host · attribute tags · async (`<await>`) · split component · legacy widget.\n3. Translate template syntax first, then the component class, using [`api-mapping.md`](./api-mapping.md). Everything from `component.js` / `component-browser.js` folds into the one `.marko` file; delete the JS files, `marko-tag.json` (types move into `export interface Input`), and `browser.json`.\n4. Convert state mutations to **immutable updates** (`items = items.concat(x)`, `obj = { ...obj, k: v }`). Marko 6 reactivity is assignment-driven; `setStateDirty`-style mutation has intentionally no equivalent. Marko 6 serializes to the browser only what client-side code actually references (the compiler computes serialization reasons/intersections per value) — so keep class instances, DOM nodes, and server-only resources out of values that browser code touches.\n5. Update call sites: `on-foo(\"method\")` → `onFoo=fn` function attributes, `renderBody` → `content`, `key=` on loop children → `by=` on `<for>`. In the incremental flow, Class API parents keep working for attributes and body content (the interop bridges `renderBody`/`content` and props automatically), but any `on-foo(\"method\")` bindings on the converted child **must** flip to function attributes in the same change — Class-style event bindings on a Tags API child compile but never fire (see `interop.md`).\n6. Place the file correctly. Incremental flow: converted files should live in a `tags/` directory or contain an unambiguous Tags signal; add a `// use tags` comment to converted route/page files that could be ambiguous. Never leave a file with signals from both APIs — that is a compile error, not a preference.\n7. Verify (Step 4) before moving to the next component.\n\n### Flow A — Full migration finish line\n\nWhen every `.marko` file uses the Tags API and the inventory greps from Step 1 return zero:\n\n1. Rename remaining `components/` directories to `tags/` (Marko 6 discovers relative tags from `tags/` only). For **published tag libraries**, move `marko.json` from `\"tags-dir\"` to `\"exports\"` — `exports` exists only for packages consumed from `node_modules`; `tags-dir` still works in both majors but is discouraged, and apps shouldn't need a `marko.json` at all.\n2. Migrate server entry points and any `template.render(input, cb/stream)` / `renderSync` / `renderToString` / `out.*` usage per \"Template & server API\" in `api-mapping.md`. Remove `marko/components` `init()` calls and `marko/node-require` (→ `@marko/compiler/register`); explicit `<init-components>` / `<await-reorderer>` tags should already be gone from Step 2.\n3. Swap the dependency to `marko@^6` using the project's package manager (npm/pnpm/yarn — detect via the `packageManager` field or the lockfile; e.g. `npm rm marko && npm i marko@^6`). `@marko/compiler` stays 5.x — that is expected; only the `marko` runtime major changes.\n4. Delete now-inert `// use tags` / `// use class` comments, run the full verification suite, and diff SSR output against the Step 2 baseline.\n5. Grep once more for stragglers. Unambiguous Class API tokens must be gone from app code: `renderBody`, `getEl(`, `subscribeTo`, `:scoped`, `no-update`, `<await-reorderer`, `legacy-components`. Broad patterns are review lists, not mandatory zeroes — inspect each match, since they also occur in unrelated code: `key=` (matches `apiKey=` etc.), `\\bout\\.`, `\\bcomponent\\.`, `\\.emit\\(`.\n\n### Flow B — Incremental migration loop\n\nRead [`interop.md`](./interop.md) first. The mechanism that makes per-file adoption safe is the compiler's **Class/Tags feature detection** — each `.marko` file is classified individually, so drive the classification deliberately instead of leaving files ambiguous:\n\n1. Files under a `tags/` directory are seeded **Tags API**.\n2. An exact `// use tags` or `// use class` comment pins a file explicitly.\n3. Class syntax anywhere in the file (a `$ scriptlet`, `class {}`, `style {}` block, attribute arguments like `on-click(\"m\")`, or `<while>`/`<macro>`/`<include-*>`/…) marks it Class; Tags syntax (a tag variable, `:=`, or `<let>`/`<const>`/`<id>`/`<return>`/…) marks it Tags. Signals from **both** APIs in one file are a compile error.\n4. A file with no signals is Tags only when _no_ `components/` directory is discoverable anywhere — otherwise it silently defaults to **Class**.\n\n(Full rules, escape hatches, and troubleshooting: `interop.md`.) In practice: converted and new components go under `tags/`, shells and route files get pinned with a comment when signal-free, and each conversion is completed fully so no file mixes APIs.\n\nThen repeat, in increments sized to one subtree/page per PR:\n\n1. Pick the next subtree (a page or a self-contained component cluster). Prefer converting **whole subtrees** so Tags components mostly reference Tags components — every Class↔Tags boundary costs compat runtime and serialization.\n2. Convert leaf components of that subtree first (inert/presentational ones are nearly free), parents next, using Step 3 mechanics. Route/page/layout files flip last, once their whole subtree is Tags — flipping a shell early maximizes boundary crossings below it.\n3. Do not put an `<await>`/async boundary across the API seam: a pending promise crossing the compat layer throws `Cannot serialize promise across tags/class compat layer`. Resolve async fully on one side.\n4. Ship the increment. Verify SSR + hydration + interactions on the affected pages (Step 4).\n5. When the last Class file is gone, run the Flow A finish line.\n\nNew code during the migration goes in `tags/` directories and uses the Tags API from day one.\n\n## Step 4 — Verify each change\n\n- **Build + typecheck**: run the app build; if TS/jsconfig is set up, run `mtc` (`@marko/type-check`). Format with `prettier` (v3 `prettier-plugin-marko` handles both syntaxes).\n- **Tests**: run the project's suite. `@marko/testing-library` supports both runtimes; update `rerender`-era assertions to reflect that Marko 6 batches updates (await a microtask / use `find*` queries).\n- **SSR parity**: render the affected page server-side and diff against the baseline HTML. Expect attribute-order/comment-marker noise; investigate _content_ differences.\n- **Hydration**: load the page in a browser; check the console for hydration/serialization errors and verify every interaction on the page (clicks, inputs, focus) still works. In mixed apps also confirm Class children inside Tags parents come alive (buttons actually respond, not just render).\n- **Common regressions to hunt**: state that silently stopped updating (mutation instead of assignment), event payload shape changes (`emit(\"change\", a, b)` → single object argument conventions), lost `:scoped` id uniqueness (→ `<id>`), form elements fighting Marko over state (→ change handlers / `:=`), `<select>`/`checked` behavior, and `no-update` regions that relied on Marko _not_ touching third-party DOM (→ `<lifecycle>` owning a container element).\n\n## Renamed / removed quick list\n\nThe ten highest-frequency rewrites (full tables in `api-mapping.md`):\n\n| Marko 5                                                             | Marko 6                                                                           |\n| ------------------------------------------------------------------- | --------------------------------------------------------------------------------- |\n| `$ const x = ...;` scriptlet                                        | `<const/x=...>` (derived) or `<let/x=...>` (mutable)                              |\n| `class { onCreate() { this.state = { n: 0 } } }` + `state.n`        | `<let/n=0>` per state key                                                         |\n| `this.state.n = v` / `setState(\"n\", v)`                             | `n = v` (plain assignment)                                                        |\n| `on-click(\"handleClick\")` / `once-click(...)`                       | `onClick() { ... }` or `onClick=fn`                                               |\n| `this.emit(\"select\", x)`                                            | call `(input.onSelect \\|\\| null)?.(x)` — events become function props             |\n| `<${input.renderBody}/>` / `renderBody`                             | `<${input.content}/>` / `content`                                                 |\n| `key=\"el\"` + `this.getEl(\"el\")`                                     | tag variable `<div/el>` … `el()` (browser getter)                                 |\n| `onMount`/`onUpdate`/`onDestroy`                                    | `<script>` (+ `$signal` for cleanup); `<lifecycle>` only for imperative libraries |\n| `key=` on loop children                                             | `by=` attribute on `<for>`                                                        |\n| `component-browser.js` as a bundling trick / `typeof window` guards | `client import` / `server` statements (backported to Marko 5.38+)                 |\n| `out.global`                                                        | `$global`                                                                         |\n\n## Escalate to the user\n\nStop and ask (with your analysis) when you hit:\n\n- `shouldUpdate`, `update_<state>` handlers, `forceUpdate`-driven flows, or `no-update` regions whose _behavior_ (not just syntax) has no 1:1 equivalent — the replacement is a design decision.\n- Public component APIs consumed by code you can't see (published libraries): event rename (`on-change` → `onChange`) and payload shape changes are breaking for consumers.\n- `out.beginAsync` / manual `out.write` streaming code, custom taglib `transformer`/codegen hooks, or `<module-code>` — these need bespoke redesign.\n- Anything where SSR baseline diffs show content changes you cannot explain.\n","skills/marko-5-to-6-migration/api-mapping.md":"# Marko 5 → Marko 6 API Mapping\n\nExhaustive translation reference. Marko 5 docs: <https://v5.markojs.com/docs/>; Marko 6 docs: <https://markojs.com/docs/> (append `.md` to any page URL for markdown). When unsure about Marko 6 behavior, check the docs — do not guess.\n\n## Template syntax\n\n| Marko 5                                                                                                     | Marko 6                                                                                                   | Notes                                                                                                                                                                                                                        |\n| ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `${expr}`                                                                                                   | `${expr}`                                                                                                 | unchanged (escaped)                                                                                                                                                                                                          |\n| `$!{expr}`                                                                                                  | `$!{expr}`                                                                                                | unchanged (unescaped; same XSS caution)                                                                                                                                                                                      |\n| `$ statement;` / `$ { ... }` scriptlet                                                                      | `<const/x=...>`, `<let/x=...>`, or an IIFE `<const/x=(() => { ... })()>` for multi-statement derivations  | Scriptlets are Class-only. Reassigned-during-render vars usually become a single `<const>` computing the final value                                                                                                         |\n| `static ...` / `static { }`                                                                                 | `static ...` / `static { }`                                                                               | unchanged (module scope, runs once)                                                                                                                                                                                          |\n| env guards (`typeof window` checks, browser-only `require`) and bundling-trick `component-browser.js` files | `server` / `client` statements: `client import \"./browser-only\"`, `server { ... }`                        | backported to Marko 5.38+ and neutral for interop classification — adopt in Class files **before** migrating; a `component-browser.js` that only exists to keep code out of the server bundle is a glorified `client import` |\n| `class { ... }` block                                                                                       | delete; migrate members per \"Component class API\" below                                                   |                                                                                                                                                                                                                              |\n| `style { ... }` / `style.scss { ... }` block                                                                | `<style>` / `<style.scss>` tag                                                                            | Marko 6 `<style>` additionally supports CSS Modules via a tag variable (`<style/styles>` → `styles.foo`) and reactive `${...}` values (compiled to CSS custom properties)                                                    |\n| `import x from \"<my-tag>\"`                                                                                  | unchanged                                                                                                 | Marko 6 adds lazy variant: `import X from \"<my-tag>\" with { load: \"visible#sel\" }`                                                                                                                                           |\n| `export ...`                                                                                                | unchanged                                                                                                 |                                                                                                                                                                                                                              |\n| attribute values `attr=expr`                                                                                | unchanged                                                                                                 | both parse values as JS expressions; in 6 an unparenthesized `>` inside a value is a parse hazard — wrap: `x=(a > b)`                                                                                                        |\n| spread `...expr`                                                                                            | unchanged                                                                                                 |                                                                                                                                                                                                                              |\n| `class=` / `style=` object & array values                                                                   | unchanged                                                                                                 |                                                                                                                                                                                                                              |\n| shorthand `.class` / `#id` (incl. `.icon-${name}`)                                                          | unchanged                                                                                                 |                                                                                                                                                                                                                              |\n| attribute arguments `attr(...)` (e.g. `on-click(\"m\")`, `no-update-if(x)`, `body-only-if(x)`)                | removed — the parenthesized-attribute syntax is Class-only                                                | see rows for each specific attribute                                                                                                                                                                                         |\n| `body-only-if(cond, tagName?)`                                                                              | conditional parent tag: `<${!cond && \"a\"} href=...>content</>`                                            | note the inversion: `body-only-if` drops the wrapper when `cond` is truthy; a falsy dynamic tag name renders content only                                                                                                    |\n| `key=\"name\"` (element/component reference)                                                                  | tag variable: `<div/name>`                                                                                | see \"Refs\" below                                                                                                                                                                                                             |\n| `key=\"name[]\"` (repeated)                                                                                   | tag variable inside `<for>`; iterate the hoisted var (`[...name]`)                                        |                                                                                                                                                                                                                              |\n| `key=expr` on children of `<for>`                                                                           | `by=` attribute on `<for>` itself (`by=\"id\"` or `by=(item) => item.id`)                                   |                                                                                                                                                                                                                              |\n| `on-event(\"method\", ...args)` / `on-event(fn)`                                                              | `onEvent() { ... }` or `onEvent=fn` function attributes                                                   | curried args become closure captures; `on-` dash-case still exists in 6 for case-preserving DOM event names (`on-DblClick`)                                                                                                  |\n| `once-event(...)`                                                                                           | no equivalent attribute                                                                                   | use a conditional handler (`onClick=!done && handler`) or `el().addEventListener(..., { once: true })` in a `<script>`                                                                                                       |\n| `no-update`, `no-update-if(...)`, `no-update-body`, `no-update-body-if(...)`, `attr:no-update`              | removed; updates are granular so most uses are obsolete                                                   | if the intent was \"Marko must not touch third-party-owned DOM\", give the library its own container element managed via `<lifecycle>`; if the intent was \"keep state/DOM alive while hidden\", use `<show>`                    |\n| `attr:scoped` (`id:scoped`, `for:scoped`, ...)                                                              | `<id/name>` tag + plain attributes (`id=name`, `for=name`)                                                |                                                                                                                                                                                                                              |\n| `<tag\\|params\\|>` body parameters                                                                           | unchanged                                                                                                 | Marko 6 adds tag _arguments_: `<${input.content}(a, b)/>` ↔ `<my-tag\\|a, b\\|>`                                                                                                                                               |\n| `<@section>` attribute tags                                                                                 | unchanged syntax; consumed as `input.section.content` (was `.renderBody`); repeated tags iterable in both | Marko 6: attribute tags inside `<if>`/`<for>` apply conditionally/repeatedly; typed with `Marko.AttrTag<T>`                                                                                                                  |\n| `<${dynamic}>` dynamic tags                                                                                 | unchanged                                                                                                 | in 6 a string always renders a _native_ tag; pass the component reference itself for custom tags                                                                                                                             |\n| `<${input.renderBody}/>`                                                                                    | `<${input.content}/>`                                                                                     | `content` also accepts attributes/arguments to pass tag parameters back                                                                                                                                                      |\n| PascalCase variables as tags `<MyTag/>`                                                                     | unchanged                                                                                                 |                                                                                                                                                                                                                              |\n| HTML/JS comments                                                                                            | unchanged (stripped)                                                                                      | literal comment: `<html-comment>` in both                                                                                                                                                                                    |\n| concise mode                                                                                                | unchanged in spirit                                                                                       | see <https://markojs.com/docs/reference/concise-syntax.md> for 6 specifics                                                                                                                                                   |\n| `<!-- use class -->` / `<!-- use tags -->`                                                                  | only meaningful under Marko 5 interop                                                                     | delete after the final flip to `marko@6`                                                                                                                                                                                     |\n\nNew in Marko 6 (no 5 equivalent — reach for these while converting):\n\n- `:=` bound attributes / change handlers (`value:=state`, refining form `value:parseFloat:=num`) — the controllable pattern.\n- Tag variables on custom tags via `<return>`; on native tags they expose a DOM-node getter.\n- `<show>` (toggle visibility, keep state/DOM), `<id>`, `<log>`, `<debug>`, `<define>`, `<try>`, `<lifecycle>`.\n- Controllable native attributes: `<input valueChange= checkedChange= checkedValueChange=>`, `<select value= valueChange=>`, `<textarea value=>`, `<details openChange=>`, `<dialog openChange=>`.\n- `$signal` (an `AbortSignal` for cleanup in any expression) and `$global`.\n- Lazy tag imports `with { load: \"visible|idle|media|on*|render\" }`.\n\n## Core tags\n\n| Marko 5                                     | Marko 6                                                                   | Notes                                                                                                                                              |\n| ------------------------------------------- | ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `<if(cond)>` / `<else-if(cond)>` / `<else>` | `<if=cond>` / `<else if=cond>` / `<else>`                                 | argument syntax → `value` attribute; `else-if` tag name → `else` with `if=` attribute                                                              |\n| `<for\\|item, index, list\\| of=list>`        | `<for\\|item, index\\| of=list>`                                            | third `list` param dropped; add `by=` for keyed diffing                                                                                            |\n| `<for\\|key, value\\| in=obj>`                | unchanged                                                                 |                                                                                                                                                    |\n| `<for\\|i\\| from=x to=y step=z>`             | unchanged; 6 adds exclusive `until=`                                      |                                                                                                                                                    |\n| `<while(cond)>`                             | removed                                                                   | restructure into `<for>` over a computed list/range                                                                                                |\n| `<macro\\|params\\| name=\"foo\">` + `<foo>`    | `<define/Foo\\|input\\|>` + `<Foo>`                                         | params become `input` properties/content                                                                                                           |\n| `<await(promise)>` + `<@then\\|res\\|>`       | `<await\\|res\\|=promise>`                                                  | body is the \"then\"                                                                                                                                 |\n| `<await>` `<@placeholder>`                  | `<try>` ancestor with `<@placeholder>`                                    | placeholder now lives on `<try>`, can wrap several awaits                                                                                          |\n| `<await>` `<@catch\\|err\\|>`                 | `<try>` ancestor with `<@catch\\|err\\|>`                                   |                                                                                                                                                    |\n| `<await client-reorder>`                    | automatic                                                                 | a `<try>` `@placeholder` opts into out-of-order streaming; no flag                                                                                 |\n| `<await timeout= show-after= name=>`        | removed                                                                   | implement timeouts on the promise itself (`AbortSignal.timeout` / `Promise.race`)                                                                  |\n| `<await-reorderer/>`                        | removed                                                                   | already implicitly injected by Marko 5 — explicit usages are redundant; delete unconditionally                                                     |\n| `<include-text('./f.txt')>`                 | bundler raw import (`import text from \"./f.txt?raw\"` in Vite) + `${text}` |                                                                                                                                                    |\n| `<include-html('./f.html')>`                | raw import + `$!{html}`                                                   | audit for XSS while converting                                                                                                                     |\n| `<init-components/>`                        | removed                                                                   | already implicitly injected by Marko 5 — explicit usages are redundant; delete unconditionally (Marko 6 emits hydration boilerplate automatically) |\n| `<module-code>`                             | removed                                                                   | library codegen hook; needs bespoke redesign (compiler hooks)                                                                                      |\n| `<html-comment>`                            | unchanged                                                                 | 6 version also exposes a comment-node tag variable                                                                                                 |\n| `<script>` (plain HTML script)              | `<html-script>`                                                           | in 6, `<script>` is the _effect_ tag (runs in browser, re-runs when referenced state changes)                                                      |\n| `<style>` (plain HTML style)                | `<html-style>`                                                            | in 6, `<style>` extracts to the CSS bundle                                                                                                         |\n| `<context>` (npm package)                   | no equivalent                                                             | pass data through `input` or `$global`                                                                                                             |\n\nIf the app used `@marko/tags-api-preview` (Tags API on Marko 5 before 6 shipped): remove that package; `<let>`/`<const>`/`<return>`/`<define>` carry over, `<effect>` → `<script>`, `<attrs>` → destructuring `<const/{...}=input>` (the Marko 6 compiler auto-fixes these two), and `<get>`/`<set>` context tags must be redesigned onto `input`/`$global`.\n\n## Component class API\n\nThe class (inline `class {}`, `component.js`, `component-browser.js`, or plain-object form) disappears entirely; each member maps to template-level constructs in the one `.marko` file.\n\n### State\n\n| Marko 5                                                     | Marko 6                                                                                                     |\n| ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |\n| `onCreate() { this.state = { a: 1, b: 2 } }`                | `<let/a=1>` `<let/b=2>` — one `<let>` per independently-changing key                                        |\n| read `state.a` / `this.state.a`                             | `a`                                                                                                         |\n| `this.state.a = v` / `setState(\"a\", v)` / `setState({ a })` | `a = v` (assignment is the reactive trigger)                                                                |\n| `setStateDirty(\"list\")` after mutation                      | intentionally no equivalent — make the update immutable: `list = [...list, item]`                           |\n| `replaceState(newState)`                                    | assign each `<let>`                                                                                         |\n| `shouldUpdate(input, state)`                                | none — updates are per-expression; if work must be gated, gate it in the deriving `<const>`/handler         |\n| `update_<name>(new, old)` partial-update handlers           | none — granular updates make them obsolete; side effects on change move to `<script>` reading that variable |\n| `this.forceUpdate()`                                        | none needed; state assignment schedules the update                                                          |\n| `this.update()` (sync flush)                                | none in-template (updates batch after a microtask); tests should await a tick                               |\n\nSerialization in 6 is **need-based, not blanket**: the compiler computes what must cross to the browser from what client-side code references (handlers, `<script>` bodies, reactive expressions, and their intersections) and serializes only that. Values that never reach client code aren't serialized at all. The practical rule while converting: anything browser code touches must be serializable (no class instances, DOM nodes, or server-only resources there) — see <https://markojs.com/docs/explanation/serializable-state.md>.\n\n### Derived data & input\n\n| Marko 5                                                                   | Marko 6                                                  |\n| ------------------------------------------------------------------------- | -------------------------------------------------------- |\n| `$ const full = a + b;`                                                   | `<const/full=a + b>`                                     |\n| `onInput(input) { input.x = normalize(input.x) }` (mutation anti-pattern) | `<const/x=normalize(input.x)>`                           |\n| `onInput` storing input into state (\"controllable\" components)            | `<let/x:=input.x>` — controllable let; see `patterns.md` |\n| `this.input` / template `input`                                           | `input` (unchanged)                                      |\n| template `state` variable                                                 | the individual tag variables                             |\n| template `component` variable                                             | none — every use maps to a specific pattern below        |\n| template `out` variable                                                   | none; `out.global` → `$global`                           |\n\nA Marko 5 getter (`get isFull() { return a + b >= max }`) recomputes on every read, so a handler that assigns `a` then reads `this.isFull` sees the new result. A `<const>` does not: within one handler it still holds its pre-assignment value until the update flushes, while the raw `<let>` reads back the value you just assigned. So after `moves = next`, `moves >= max` is current but a derived `<const/isFull=(moves >= max)>` is not — read the `<let>`s you just assigned (or recompute from them) inside the handler, never the derived `<const>`.\n\n### Lifecycle\n\n| Marko 5                                                                  | Marko 6                                                                                                                    |\n| ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------- |\n| `onMount() { ... }`                                                      | `<script>` (first run = mounted, browser-only) or `<lifecycle onMount() { ... }/>`                                         |\n| `onUpdate()`                                                             | `<script>` re-runs when any referenced tag variable/param changes; or `<lifecycle onUpdate>` (re-runs on its dependencies) |\n| `onDestroy()`                                                            | `$signal.onabort = () => {...}` inside `<script>`; or `<lifecycle onDestroy>`                                              |\n| `onRender(out)`                                                          | usually deleted — it was mostly used for derivations (→ `<const>`)                                                         |\n| `onCreate(input, out)`                                                   | initial values of `<let>` tags                                                                                             |\n| lifecycle _events_ (`this.on(\"update\", fn)`, `this.once(\"destroy\", fn)`) | same replacements as the methods                                                                                           |\n| `on-attach(fn)` on an element                                            | `<script>` or `<lifecycle onMount>` — both run with the element in the DOM                                                 |\n| `on-detach(fn)` on an element                                            | no equivalent — nothing can delay removal (see below)                                                                      |\n\nPrefer plain state and `<script>`; use `<lifecycle>` only to host imperative third-party instances (maps, charts) where a stable `this` across `onMount`/`onUpdate`/`onDestroy` is genuinely needed.\n\nExit animations need rework. Marko 5's `on-detach` handler could hold a node in the DOM (`event.preventDefault()`, then `event.detach()` once the animation finished); nothing in Marko 6 can delay removal — `<lifecycle onDestroy>` only observes teardown, and `<show=false>` parks its nodes in a detached fragment, so a transition never runs. Stage it in state instead: keep the item rendered while marking it exiting (`class={ exiting: id === leavingId }`), then drop it from the list in a `transitionend`/`animationend` handler.\n\n### Events\n\n| Marko 5                                                       | Marko 6                                                                                                                  |\n| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |\n| `this.emit(\"select\", a, b)`                                   | call the function prop: `(input.onSelect \\|\\| null)?.(a, b)` — declare `onSelect?: (a: A, b: B) => void` in `Input`      |\n| parent `<child on-select(\"handleSelect\")>` + class method     | `<child onSelect=handleSelect>` or `<child onSelect(a, b) { ... }>`                                                      |\n| parent `<child on-select(\"emit\", \"select\")>` (re-emit chains) | pass the prop through: `<child onSelect=input.onSelect>`                                                                 |\n| `this.on(...)` / `once` / `removeListener` on a component     | none — components are not emitters; use function props                                                                   |\n| `this.subscribeTo(window).on(\"resize\", fn)`                   | `<script>` + `window.addEventListener(\"resize\", fn, { signal: $signal })`                                                |\n| DOM `on-click(\"method\", extraArg)` on native tags             | `onClick(e) { method(extraArg, e) }` — handler receives the DOM event (and in 6, custom-tag conventions add the element) |\n| state-change notifications via emitted events                 | prefer the controllable pattern (`x` + `xChange`) — <https://markojs.com/docs/explanation/controllable-components.md>    |\n\nThe optional-handler idiom is `(input.onSelect || null)?.(a, b)`: handler attributes may legitimately be _falsy_, not just undefined (conditional handlers like `onClick=!clicked && handler` pass `false`), and `false?.()` still throws — `|| null` coerces any falsy value so the optional call short-circuits.\n\nEvent _naming_: Marko 5 events were dash-case strings (`on-page-change(\"m\")`); Marko 6 props are camelCase functions (`onPageChange=`). For published components this is a breaking API rename — call it out to consumers.\n\n### Refs & DOM access\n\n| Marko 5                                            | Marko 6                                                                                                                                                                                            |\n| -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `key=\"input\"` + `this.getEl(\"input\")`              | `<input/inputEl>` … `inputEl()` (getter; browser-only)                                                                                                                                             |\n| `this.getEls(\"item\")` + `key=\"item[]\"`             | tag variable inside the loop; iterate hoisted: `for (const el of item) ...` / `[...item]`                                                                                                          |\n| `this.el`                                          | tag variable on the root element                                                                                                                                                                   |\n| `this.getElId(...)` / `this.elId(...)` / `this.id` | `<id/myId>` (unique, SSR-stable string)                                                                                                                                                            |\n| `this.getComponent(\"child\")` / `getComponents`     | child exposes an API via `<return={ focus() {...} }>`; parent receives it as a tag variable: `<child/childApi>` … `childApi.focus()`. Often better: controllable props instead of imperative calls |\n| `component.appendTo(el)` etc. (DOM-insert mixins)  | `Template.mount(input, node, position)`                                                                                                                                                            |\n| `this.destroy()`                                   | `instance.destroy()` from `mount()`; inside templates, removal via `<if>`                                                                                                                          |\n| `this.isDestroyed()`                               | none; `$signal.aborted` covers most uses                                                                                                                                                           |\n| `this.rerender(...)` (legacy)                      | input-driven updates / `instance.update(input)`                                                                                                                                                    |\n\n## Legacy widget API (marko-widgets / `@marko/compat-v4`)\n\nNo interop and no automation — rewrite by hand. Mapping for the common members:\n\n| Widget API                                                               | Tags API                                                                                          |\n| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- |\n| `defineComponent({ template, ... })` / `defineWidget` / `defineRenderer` | a single `.marko` file                                                                            |\n| `init(config)` (browser attach)                                          | `<script>` (browser-only by construction)                                                         |\n| `getInitialState(input)`                                                 | `<let>` initial values                                                                            |\n| `getInitialProps(input, out)` / `getTemplateData(state, props)`          | `<const>` derivations from `input`                                                                |\n| `getWidgetConfig()`                                                      | plain values passed via attributes; state that must reach the browser is serialized automatically |\n| `w-bind` / `widget-types`                                                | the component boundary is the file itself                                                         |\n| `w-on-*` handlers                                                        | `onEvent=` function attributes                                                                    |\n| `w-id` / `this.getEl(id)`                                                | tag variables                                                                                     |\n| `widgetBody` / `w-body`                                                  | `content`                                                                                         |\n| `this.setProps(...)` / `this.rerender(...)`                              | input-driven updates from the parent                                                              |\n| `this.state = newState` (replace)                                        | assignments to `<let>` vars                                                                       |\n| jQuery `this.$()` helpers                                                | tag variable + direct DOM APIs (or the library inside `<lifecycle>`)                              |\n\n## Template & server API\n\n| Marko 5                                                                | Marko 6                                                                                                        | Notes                                                                                     |\n| ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |\n| `template.render(input)` (thenable out)                                | `template.render(input)`                                                                                       | 6 result: async-iterable + `.pipe(writable)` + `.toReadable()` + thenable + `.toString()` |\n| `template.render(input, callback)`                                     | `.then()` / `await`                                                                                            | callbacks removed                                                                         |\n| `template.render(input, stream)` / `template.stream(input).pipe(res)`  | `template.render(input).pipe(res)`                                                                             |                                                                                           |\n| `template.renderSync(input)` → `RenderResult`                          | `template.render(input).toString()`                                                                            | throws if anything async — same contract                                                  |\n| `template.renderToString(input)`                                       | `template.render(input).toString()`                                                                            |                                                                                           |\n| `renderResult.appendTo(el)` / `.getComponent()`                        | `template.mount(input, node, position?)` → `{ update(input), destroy(), value }`                               | `value` = the template's `<return>`                                                       |\n| `template.mount(input, el, pos)`                                       | unchanged shape                                                                                                |                                                                                           |\n| `out.global` / `$global`                                               | `$global`                                                                                                      | still passed as `input.$global` at the render call                                        |\n| `$global.serializedGlobals = { key: true }`                            | unchanged                                                                                                      | still the opt-in for serializing globals to the browser                                   |\n| `$global.componentIdPrefix` / `widgetIdPrefix`                         | `$global.renderId`                                                                                             |                                                                                           |\n| `$global.runtimeId` / CSP `cspNonce`                                   | unchanged                                                                                                      |                                                                                           |\n| `out.write(...)`, `out.beginAsync()`, `out.script(...)`, `out.flush()` | removed                                                                                                        | restructure with `<await>`/templates; escalate custom streaming code                      |\n| `require(\"marko/components\").init()` browser bootstrap                 | removed                                                                                                        | bundler plugin emits hydration automatically                                              |\n| `marko/node-require`                                                   | `@marko/compiler/register`                                                                                     | already the guidance in late 5                                                            |\n| `marko/env` (`isDebug`)                                                | none                                                                                                           | use bundler-provided env (`process.env.NODE_ENV`)                                         |\n| express `res.marko(template, input)` (`@marko/express`)                | verify the integration package's Marko 6 support; otherwise `template.render({ ...input, $global }).pipe(res)` | set `content-type` yourself when piping manually                                          |\n\n## Taglib & package metadata\n\n| Marko 5                                                         | Marko 6                                                                                                                                                                                                                                               |\n| --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| relative discovery from `components/`                           | from `tags/` (`tags/NAME.marko`, `tags/NAME/index.marko`, one grouping-folder level allowed)                                                                                                                                                          |\n| `marko.json` `\"tags-dir\": \"./dist/components\"`                  | `marko.json` `\"exports\": \"./dist/tags\"` — for **published `node_modules` tag libraries only**; `tags-dir` still works in both majors but is discouraged, and apps need no `marko.json`                                                                |\n| `marko-tag.json` attribute/nested-tag declarations              | delete; type everything via `export interface Input` (`Marko.AttrTag<T>` for attribute tags)                                                                                                                                                          |\n| `marko-tag.json` compiler hook overrides (`transform`, codegen) | custom compiler work — escalate                                                                                                                                                                                                                       |\n| `browser.json`                                                  | delete; use a modern bundler plugin                                                                                                                                                                                                                   |\n| `marko.json` `\"script-lang\": \"ts\"`                              | unchanged — but it exists for **incremental TS adoption** (opting folders in/out); a project `tsconfig.json` already makes `.marko` files TypeScript, and published packages normally ship compiled `.d.marko` types instead of setting `script-lang` |\n| adjacent `style.css` / `foo.style.css` supporting files         | unchanged                                                                                                                                                                                                                                             |\n\n## TypeScript\n\n| Marko 5                                                   | Marko 6                                                                                       |\n| --------------------------------------------------------- | --------------------------------------------------------------------------------------------- |\n| `export interface Input`                                  | unchanged                                                                                     |\n| `Marko.Component<Input, State>` base class                | removed with the class                                                                        |\n| `State` types                                             | become the inferred/annotated types of `<let>` values                                         |\n| `renderBody?: Marko.Body`                                 | `content?: Marko.Body` (params: `Marko.Body<[Arg1, Arg2]>`)                                   |\n| `Marko.Input<\"button\">`                                   | still exists; `Marko.HTML.Button` etc. is the common spelling for extending native tag inputs |\n| `Marko.AttrTag<T>` / deprecated `Marko.RepeatableAttrTag` | `Marko.AttrTag<T>` (always iterable)                                                          |\n| `Marko.Out`, `Marko.Emitter`, `Marko.RenderResult`        | removed in 6 (available from `marko@5` during interop)                                        |\n| `@marko/type-check` (`mtc`) CLI                           | works for both                                                                                |\n\n## Already deprecated in Marko 5 (clear these first)\n\nThese warn under `MARKO_DEBUG` in Marko 5 and have no future in 6 — fix them while still on 5 (Step 2 of the skill):\n\n- `data` template variable → `input` (auto-fixed by the 5 compiler's migrate stage).\n- `this.els` → `getEls(...)`; `getEl` reaching into child components; `getComponent` with repeated `key[]`; non-string `key` values.\n- `RenderResult.html` → `.toString()`; `RenderResult.context` → `.out`; `getWidget`/`getWidgets` → `getComponent`/`getComponents`.\n- `<await>` with a callback argument → pass a promise.\n- String values for spread/dynamic attributes → objects.\n- `marko/compiler` → `@marko/compiler`; `marko/node-require` → `@marko/compiler/register`.\n- `browser.json` `require:` paths → `marko-dependencies:` (or better: leave `browser.json` behind entirely).\n","skills/marko-5-to-6-migration/interop.md":"# Marko 5 ↔ 6 Interop (Incremental Migration)\n\nHow one Marko 5 app runs Class API and Tags API files together, and how to migrate through that state without regressing. Official doc: <https://markojs.com/docs/guide/marko-5-interop.md>. Source of truth for classification: `packages/runtime-tags/src/translator/interop/feature-detection.ts` in the marko repo.\n\n## Mental model\n\n- The interop is a **coexistence layer, not a converter**. The compiler classifies each `.marko` file as Class or Tags, compiles it with the matching translator, and inserts a runtime compat shim wherever a component of one API is rendered from a file of the other.\n- Classification is **per file** and all-or-nothing. A file cannot mix APIs; conflicting signals are a **compile error** (\"Cannot mix Tags API and Class API features in the same file\", with code frames pointing at both offending features). The heuristics are not a precedence list that picks a winner.\n- Pages that contain both APIs ship **both runtimes** and hydrate twice (a Marko 6 `init` and a Marko 5 `init`). Each Class↔Tags boundary also serializes extra scope-mapping data. This is fine as a transition state and wrong as an end state — keep boundaries few, and prefer converting whole subtrees.\n\n## Enabling\n\nNothing to configure. Modern `marko@5` (5.39+) depends on `@marko/runtime-tags` and its `marko/translator` entry wraps the Class translator with the interop translator. An app whose only Marko runtime dependency is `marko` (v5) gets interop automatically; an app that depends only on `@marko/runtime-tags`/`marko@6` gets **no** Class support.\n\nLazy tag imports (`with { load: ... }`) additionally rely on the `linkAssets` compiler option, which the bundler integrations (`@marko/vite`, `@marko/run`, `@marko/webpack`) provide — not something to set by hand. Lasso works with both APIs but does not provide `linkAssets`, so on it a `with { load }` import compiles as a normal eager import rather than code-splitting.\n\n## File classification rules\n\nEvaluated per file:\n\n1. **`tags/` directory seed.** A file under a `tags/` directory is seeded as Tags API — unless a `components/` directory sits _between_ the `tags/` dir and the file (`tags/components/x.marko` is _not_ seeded; this is the escape hatch for vendored Class code inside a tags tree), or that `tags/` dir is declared as a manual `tagsDir` in a `marko.json`.\n2. **Body scan.** The whole template (including nested tag bodies and attribute tags) is scanned in document order; every signal found is recorded, and signals from both APIs anywhere in one file are the mixing compile error.\n   - **Class signals**: a `// use class` / `<!-- use class -->` comment (exact trimmed match); a non-`static` `$ scriptlet;`; a `class {}` block; a `style { ... }` / `style.ext { ... }` block; any attribute _argument_ (`onClick(\"handler\")`, `no-update-if(x)`); one of these tags: `<await-reorderer>` `<class>` `<include-html>` `<include-text>` `<init-components>` `<macro>` `<module-code>` `<while>`.\n   - **Tags signals**: a `// use tags` / `<!-- use tags -->` comment; any tag variable (`<div/el>`); any bound attribute (`:=`); one of these tags: `<const>` `<debug>` `<define>` `<id>` `<let>` `<lifecycle>` `<log>` `<return>` `<try>`.\n   - `static`, `server`, and `client` statements and plain `<style>` elements are neutral — they force nothing and work in both APIs (`server`/`client` were backported to Marko 5.38+).\n3. **Ambiguous fallback.** A file with no signals (pure markup) is Tags **only if** every tag-discovery directory visible from it is a `tags/` dir; if even one `components/` dir exists anywhere in scope, ambiguous files default to **Class**. In a typical migrating app (which still has `components/` dirs), every ambiguous file is Class — so converted-but-signal-free files silently compile as Class. Pin such files with `// use tags`.\n\nPractical rules that follow:\n\n- Put every new/converted Tags file under a `tags/` directory, or make sure it contains a real Tags signal, or add `// use tags`.\n- When converting a file, convert it **completely** — one leftover `$ scriptlet` or `key=\"x\"` handler argument next to a new `<let>` is a build break, and one leftover neutral file is a silent Class fallback.\n- Route files (`+page.marko`, `+layout.marko`, express-rendered page templates) are frequently ambiguous — pin them explicitly in both directions during the transition.\n\n## Crossing the boundary\n\n### Tags parent → Class child\n\nUse the Class tag like any custom tag. The compat shim translates automatically:\n\n- Attributes pass through as the child's `input`.\n- The Tags body becomes the child's `input.renderBody`.\n- `onFoo=fn` / `onFoo(){}` / `on-foo(){}` attributes are converted to Class custom-event subscriptions: the child's `this.emit(\"foo\", a, b)` invokes the function with `(a, b)`. (`onClick` → event `\"click\"`, `on-Foo` → event `\"Foo\"` preserving case.)\n- Tag parameters work: `<class-layout|a, b|>` receives what the Class child passes via `<${input.renderBody}(a, b)/>`.\n- Split components (`component-browser.js`) hydrate and stay interactive.\n- A Class child with _no_ component (no `class {}`, no state, no handlers — an \"inert\" template) costs almost nothing: it renders on the server and is dropped from client bundles unless a Tags-side update forces re-render (in which case the compat morphs its DOM in place).\n\nYou cannot use Class-only _syntax_ on the call site (it's a Tags file): no `on-foo(\"stringMethod\")`, no `key=`-based `getComponent` into the child. If the parent needs to call into the child imperatively, that child is a good next conversion candidate (then expose `<return>`).\n\n### Class parent → Tags child\n\nAlso plain custom-tag usage, with these rules:\n\n- Attributes pass through as `input`; the Class body becomes the child's `input.content` (renamed from `renderBody` by the shim); attribute tags and tag parameters cross over.\n- Pass event handlers as **function-valued attributes** — the Tags child just calls `input.onSelect(...)`. Both of these compile and work in a Class API file (verified):\n  - `<tags-child onSelect(sel) { component.handleSelect(sel) }/>` (method shorthand — it is not a Class/Tags classification signal)\n  - `<tags-child onSelect=component.handleSelect.bind(component)/>`\n- **Do not use Class-style event bindings on Tags children.** `<tags-child on-select(\"handleSelect\")/>` compiles without error but never fires: it registers a Class custom-event subscription, and Tags components call function props instead of emitting events. This is a silent dead binding — audit for it when converting a child that Class parents consume.\n- Dynamic tags work, including conditional ones: `<${state.show && TagsChild}/>`.\n- Hydration needs no explicit wiring: Marko 5 injects its init/reorderer boilerplate implicitly, and on mixed pages the interop entry emits both hydrate programs. Explicit `<init-components/>` / `<await-reorderer/>` tags in templates are redundant — delete them on sight (they are also Class-only classification signals, so they block converting the file they sit in).\n\n### Hard limitations\n\n- **No async across the seam.** A pending promise (an `<await>` still unresolved) crossing the compat boundary throws `Cannot serialize promise across tags/class compat layer` at render time. Keep each `<await>` and everything it feeds on one side of the boundary.\n- **No shared component registry.** `getComponent`/`getComponents` cannot see Tags children; Tags tag variables cannot point at Class children (no `<return>` there). Communicate across the seam with attributes and function props only.\n- **`$global` / `out.global` is shared** — that part crosses cleanly in both directions.\n- Both runtimes ship while mixed; treat bundle size regressions during migration as expected and temporary, but budget them.\n\n## Incremental order of work\n\n1. **Foundation** (see SKILL.md Step 2): latest `marko@5`, modern bundler, deprecations cleared, legacy widgets rewritten, baseline recorded.\n2. **Create `tags/` directories** next to existing `components/`. This is non-disruptive: ambiguous files still default to Class as long as any `components/` dir exists.\n3. **Convert leaf components first** — inert/presentational ones are nearly free, then stateful leaves. Their Class parents keep consuming them through the shim without changes (though renamed events — `on-select` → `onSelect=` — do require touching call sites; do parent call-site edits in the same increment).\n4. **Work subtree-by-subtree, bottom-up**, so that Tags components mostly reference Tags components. A good increment: one page's component cluster, converted leaves-to-root, parents last.\n5. **Flip pages/layouts last.** Once a page's subtree is all Tags, convert the page file and pin it with `// use tags` if it ends up signal-free.\n6. **Bridge unconverted third-party stragglers with [`patch-package`](https://github.com/ds300/patch-package)** when practical: convert the small blocking module inside `node_modules`, commit the patch, and upstream the change — this keeps the final flip unblocked without forking.\n7. **Track the remaining Class surface** with the Step 1 inventory greps after each increment; the numbers only go down.\n8. When zero Class files remain, run the full-migration finish line (swap to `marko@6`, rename `components/` → `tags/`, remove pin comments and interop-era workarounds).\n\nDuring the whole period: new features are written Tags-first in `tags/`, and no new Class API code gets merged.\n\n## Troubleshooting\n\n| Symptom                                                                         | Cause                                                                                                                                                       | Fix                                                                                                                               |\n| ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |\n| `Cannot mix Tags API and Class API features in the same file` (two code frames) | leftover Class syntax in a converted file (scriptlet, `style {}`, attribute argument, `<macro>`/`<while>`/...) or a Tags construct pasted into a Class file | finish the conversion; the two frames point at the exact conflicting features                                                     |\n| Converted file renders but behaves like Class / new syntax rejected             | file is ambiguous and fell back to Class (a `components/` dir exists somewhere in scope)                                                                    | move under `tags/` or add `// use tags`                                                                                           |\n| File under `tags/` refuses Tags syntax                                          | a `components/` segment between the `tags/` dir and the file, or that dir is a `marko.json` `tagsDir`                                                       | check the full path and `marko.json`s up the tree                                                                                 |\n| `Cannot serialize promise across tags/class compat layer`                       | `<await>`/async content crossing the API boundary                                                                                                           | resolve the promise fully on one side; move the `<await>` into the same API as the content it wraps                               |\n| Class child inside Tags parent renders but is dead (no events)                  | its hydration was skipped — often it looked inert (no serialize reason)                                                                                     | upgrade `marko` — this had fixes in 5.39.x; confirm the child actually has a component; report upstream if reproducible on latest |\n| Tags child inside Class page doesn't hydrate                                    | bundler entry isn't the interop hydrate output (both `init` programs are emitted by the interop entry builder, not by any template-level tag)               | check the bundler integration is current and the page's hydrate entry is generated by it                                          |\n| `with { load }` component loads eagerly instead of code-splitting               | no `linkAssets` (eg `@marko/vite` with `linked: false`, or lasso), so lazy loading degrades to an eager import                                              | use `@marko/vite` (linked)/`@marko/run`/`@marko/webpack` to code-split; the eager fallback is otherwise harmless                  |\n| Duplicate/large client bundles                                                  | both runtimes on the page (expected while mixed); or boundaries scattered across many small islands                                                         | consolidate: convert whole subtrees; finish the migration                                                                         |\n","skills/marko-5-to-6-migration/patterns.md":"# Conversion Patterns\n\nWorked Marko 5 → Marko 6 conversions for the recurring component shapes. Each shows the Class API original, the Tags API result, and the traps. Combine as needed — real components mix several shapes.\n\n## Stateful component\n\n```marko\n/* marko 5 */\nclass {\n  onCreate() {\n    this.state = { count: 0 };\n  }\n  increment() {\n    this.state.count++;\n  }\n}\n\n<button on-click(\"increment\")>\n  Count: ${state.count}\n</button>\n```\n\n```marko\n/* marko 6 */\n<let/count=0>\n\n<button onClick() { count++ }>\n  Count: ${count}\n</button>\n```\n\nOne `<let>` per independently-updating state key. Reads of `state.x` become `x`; writes become plain assignment. Methods that only served as event handlers become inline handlers or `<const/fn() { ... }>` when shared.\n\n**Trap:** mutation. `this.state.list.push(x)` + `setStateDirty(\"list\")` must become `list = [...list, x]` — in Marko 6 only assignment triggers updates, and there is deliberately no dirty-marking escape hatch.\n\n## Derived values\n\n```marko\n/* marko 5 */\n$ const total = input.items.reduce((sum, item) => sum + item.price, 0);\n$ const formatted = total.toFixed(2);\n<div>Total: $${formatted}</div>\n```\n\n```marko\n/* marko 6 */\n<const/total=input.items.reduce((sum, item) => sum + item.price, 0)>\n<const/formatted=total.toFixed(2)>\n<div>Total: $${formatted}</div>\n```\n\nMulti-statement scriptlets that build one value collapse into an IIFE: `<const/list=(() => { ...; return list })()>`. Components that \"normalized\" input by mutating it in `onInput(input)` become `<const>` derivations — never mutate `input`.\n\nDestructuring input is the standard opener of a converted file:\n\n```marko\n<const/{ label, disabled = false, ...restAttrs } = input>\n```\n\n## Controllable state (state initialized from input + change events)\n\nThe Class API pattern of copying input into state and emitting on change:\n\n```marko\n/* marko 5 */\nclass {\n  onCreate(input) {\n    this.state = { open: input.open || false };\n  }\n  onInput(input) {\n    this.state.open = input.open || false;\n  }\n  toggle() {\n    this.setState(\"open\", !this.state.open);\n    this.emit(\"toggle\", { open: this.state.open });\n  }\n}\n\n<button on-click(\"toggle\")>Toggle</button>\n<if(state.open)>\n  <div>Drawer content</div>\n</if>\n```\n\nbecomes a controllable `<let>`:\n\n```marko\n/* marko 6 */\nexport interface Input {\n  open?: boolean;\n  openChange?: (open: boolean) => void;\n}\n\n<let/open=input.open || false valueChange=input.openChange>\n\n<button onClick() { open = !open }>Toggle</button>\n<if=open>\n  <div>Drawer content</div>\n</if>\n```\n\nWhen no default/transform is needed, the shorthand `<let/open:=input.open>` is equivalent. Semantics: with no `openChange` from the parent, the component owns its state (uncontrolled); when the parent passes `openChange`, the parent owns it (controlled) and `open` tracks `input.open`.\n\nCall sites:\n\n```marko\n/* parent.marko (marko 5, via interop) */\n<drawer open=state.drawerOpen openChange(open) { component.handleOpenChange(open) }/>\n```\n\nNote the Class API parent passes `openChange` as a **function attribute** — the converted child reads `input.openChange` and emits no events, so a Class-style `on-open-change(\"handleOpenChange\")` binding would compile but never fire (see `interop.md`).\n\n```marko\n/* parent.marko (marko 6) */\n<let/drawerOpen=false>\n<drawer open:=drawerOpen/>\n```\n\n**Traps:** name the change handler `<prop>Change` (that is what `:=` desugars to — `openChange`, `valueChange`); a differently-named event (`on-toggle`) forfeits the shorthand. Marko 5 events conventionally wrapped payloads (`{ originalEvent, open }`) — Marko 6 passes plain arguments; document the new signature for consumers.\n\n## Element refs and focus\n\n```marko\n/* marko 5 */\nclass {\n  focusName() {\n    this.getEl(\"name\").focus();\n  }\n}\n\n<input key=\"name\" placeholder=\"Name\"/>\n<button on-click(\"focusName\")>Focus</button>\n```\n\n```marko\n/* marko 6 */\n<input/nameInput placeholder=\"Name\">\n<button onClick() { nameInput().focus() }>Focus</button>\n```\n\nThe tag variable is a **getter function** (`nameInput()`), browser-only. For repeated elements (`key=\"opt[]\"` + `getEls(\"opt\")`), the hoisted variable is iterable:\n\n```marko\n<for|opt, i| of=input.options>\n  <input/optEl value=opt>\n</for>\n\n<button onClick() {\n  for (const el of optEl) console.log(el.value);\n  [...optEl][0]?.focus();\n}>Read all</button>\n```\n\n`getElId()` / `id:scoped` uses become the `<id>` tag:\n\n```marko\n<id/inputId>\n<label for=inputId>Name</label>\n<input id=inputId>\n```\n\n## Global listeners, timers, effects\n\n```marko\n/* marko 5 */\nclass {\n  onMount() {\n    this.subscribeTo(window).on(\"resize\", this.onResize.bind(this));\n    this.timer = setInterval(() => this.tick(), 1000);\n  }\n  onDestroy() {\n    clearInterval(this.timer);\n  }\n  onResize() { this.setState(\"width\", window.innerWidth); }\n  tick() { this.setState(\"now\", Date.now()); }\n}\n```\n\n```marko\n/* marko 6 */\n<let/width=0>\n<let/now=Date.now()>\n\n<script>\n  window.addEventListener(\"resize\", () => { width = window.innerWidth }, { signal: $signal });\n\n  const timer = setInterval(() => { now = Date.now() }, 1000);\n  $signal.onabort = () => clearInterval(timer);\n</script>\n```\n\n`<script>` runs in the browser after mount and **re-runs whenever a tag variable it references changes**; `$signal` aborts on cleanup (before re-run and on removal). Keep effect scripts free of incidental state reads or they re-run more than intended — split unrelated effects into separate `<script>` tags.\n\n## Third-party imperative libraries\n\nWhen an instance must persist across updates (charts, maps, editors), `<script>` re-running is the wrong shape — use `<lifecycle>`:\n\n```marko\n/* marko 5 */\nclass {\n  onMount() {\n    this.chart = new Chart(this.getEl(\"canvas\"), { data: this.input.data });\n  }\n  onUpdate() {\n    this.chart.setData(this.input.data);\n  }\n  onDestroy() {\n    this.chart.destroy();\n  }\n}\n\n<canvas key=\"canvas\"/>\n```\n\n```marko\n/* marko 6 */\nclient import { Chart } from \"chart-lib\"\n\n<canvas/canvas/>\n<lifecycle\n  onMount() {\n    return { chart: new Chart(canvas(), { data: input.data }) };\n  }\n  onUpdate() {\n    this.chart.setData(input.data);\n  }\n  onDestroy() {\n    this.chart.destroy();\n  }\n/>\n```\n\n`this` is stable across the three hooks; `onMount`'s returned object merges into it. `onUpdate` re-runs when its own referenced dependencies change. The `client import` keeps the library out of the server bundle (replaces `component-browser.js` tricks).\n\n## Attribute tags (named/nested content)\n\n```marko\n/* marko 5: my-menu.marko + marko-tag.json declaring \"@item\" */\n<ul>\n  <for|item| of=input.item>\n    <li on-click(\"handleSelect\", item.value)>\n      <${item.renderBody}/>\n    </li>\n  </for>\n</ul>\n```\n\n```marko\n/* marko 6: my-menu.marko (marko-tag.json deleted) */\nexport interface Input {\n  item?: Marko.AttrTag<{\n    value: string;\n    content?: Marko.Body;\n  }>;\n  onSelect?: (value: string) => void;\n}\n\n<ul>\n  <for|item| of=input.item>\n    <li onClick() { (input.onSelect || null)?.(item.value) }>\n      <${item.content}/>\n    </li>\n  </for>\n</ul>\n```\n\nCall sites are unchanged (`<my-menu><@item value=\"a\">A</@item>...</my-menu>`). The type declarations from `marko-tag.json` (`\"@item <item>[]\"`, attribute lists) move into `Input` with `Marko.AttrTag<T>`; repeated tags are consumed by iterating the singular property. `(input.onSelect || null)?.(...)` is the standard optional-handler call — handler props may be conditionally _falsy_, and `false?.()` would throw.\n\n## Async content (`<await>`)\n\n```marko\n/* marko 5 */\n<await(getUser()) client-reorder>\n  <@placeholder>Loading…</@placeholder>\n  <@then|user|>Hi ${user.name}</@then>\n  <@catch|err|>${err.message}</@catch>\n</await>\n```\n\n```marko\n/* marko 6 */\n<try>\n  <await|user|=getUser()>\n    Hi ${user.name}\n  </await>\n\n  <@placeholder>Loading…</@placeholder>\n  <@catch|err|>${err.message}</@catch>\n</try>\n```\n\nThe body of `<await>` is the \"then\"; placeholder and error handling move to a wrapping `<try>` (which may cover several awaits). A `@placeholder` opts the section into out-of-order streaming automatically — `client-reorder`, `<await-reorderer>`, `timeout=`, and `show-after=` are removed (implement timeouts on the promise itself, e.g. `AbortSignal.timeout`). Explicit `<await-reorderer/>` (and `<init-components/>`) tags were implicitly injected by Marko 5 anyway — delete them unconditionally, even before migrating.\n\n**Interop trap:** while mixed 5/6, keep an `<await>` and the components it renders on the same side of the Class/Tags boundary — pending promises cannot cross it.\n\n## Split components (`component-browser.js`)\n\nMarko 5 split components separate server-safe rendering from browser behavior:\n\n```text\ncomponents/fancy-toggle/\n  index.marko            # template + component.js lifecycle\n  component-browser.js   # onMount/onUpdate + handlers, browser-only bundle\n```\n\nSplit components exist for two different reasons — treat them differently:\n\n1. **A glorified `client import`.** Many `component-browser.js` files carry no real lifecycle logic; they exist only to keep browser-only code out of the server bundle. Replace these directly with a `client import` in the template — even **before** migrating, since `server`/`client` statements were backported to Marko 5 (5.38+) and are neutral for interop classification:\n\n   ```marko\n   client import \"./browser-only-setup\"\n   ```\n\n2. **Real browser lifecycle** (`onMount`/`onUpdate` + handlers). These collapse into `index.marko` during conversion. There is nothing to preserve about the split itself: targeted compilation already generates separate server/client outputs per template, and only the reactive/handler code ships to the browser.\n\nEither way the end state is one `.marko` file: browser-only imports become `client import`, server-only ones `server import`. Convert the template plus _both_ JS files as one unit using the patterns above, then delete the JS files.\n\n## Parent calls child methods (`getComponent`)\n\n```marko\n/* marko 5 parent */\nclass {\n  reset() {\n    this.getComponent(\"picker\").setColor(\"#ffffff\");\n  }\n}\n<color-picker key=\"picker\"/>\n<button on-click(\"reset\")>Reset</button>\n```\n\nMarko 6 children export an API with `<return>`, received as a tag variable:\n\n```marko\n/* color-picker.marko (marko 6) */\n<let/color=\"#ff8000\">\n<input type=\"color\" value:=color>\n<return={ setColor(c) { color = c } }/>\n```\n\n```marko\n/* parent.marko (marko 6) */\n<color-picker/picker/>\n<button onClick() { picker.setColor(\"#ffffff\") }>Reset</button>\n```\n\nBefore reaching for this, check whether the controllable pattern (`color:=`) removes the need for imperative calls entirely — it usually does.\n\n## Legacy widgets (marko-widgets / `@marko/compat-v4`)\n\n```js\n// marko 5-era legacy widget (widget.js)\nmodule.exports = require(\"marko-widgets\").defineComponent({\n  template: require(\"./template.marko\"),\n  getInitialState(input) {\n    return { expanded: !!input.expanded };\n  },\n  init() {\n    this.el.classList.add(\"ready\");\n  },\n  handleHeaderClick() {\n    this.setState(\"expanded\", !this.state.expanded);\n  },\n});\n```\n\nRewrite directly as one Tags API file — the same shapes apply: `getInitialState` → `<let>` initials, `getTemplateData`/`getInitialProps` → `<const>`, `init()` → `<script>`, `w-on-*`/`w-id` in the template → `onEvent=` handlers and tag variables, `w-body` → `content`. There is no interop for widgets, so this rewrite cannot be deferred in either migration flow. For sprawling widgets, an intermediate rewrite to the Class API (which _does_ interop) is acceptable to unblock the incremental flow, but budget the second pass.\n","skills/marko-best-practices/SKILL.md":"---\nname: marko-best-practices\ndescription: Apply Marko syntax and best practices when editing `.marko` files and building Marko components.\n---\n\n# Marko Best Practices\n\nMarko is a modern UI framework for building web applications. It features a declarative component-based syntax, fine-grained reactivity, and a highly optimized compiler. Marko is designed for both server-rendered and interactive client-side experiences with a focus on streaming, partial hydration, and shipping the smallest possible amount of JavaScript to each page.\n\n## Marko Documentation\n\nThe Marko documentation is the source of truth for all Marko-related information. Always refer to the official docs for information about syntax and behavior. Marko changes over time, so prefer fetching current docs over relying on training data.\n\nThe [docs index](https://markojs.com/llms.txt) lists every available page with its URL and a short description.\n\nAll Marko docs pages can be fetched as markdown by appending `.md` to the URL (<https://markojs.com/docs/introduction/getting-started.md>)\n\n## Marko 6 Syntax\n\nDocumentation and this skill target **Marko 6**. Do not use Marko 5 syntax.\n\n## Checklist for New or Edited .marko Files\n\n- [ ] Uses Marko 6 syntax only (no scriptlets, old event syntax, or Marko 5 blocks).\n- [ ] `<script>` is never used when state (`<let>` or `<const>`) could accomplish the same behavior.\n- [ ] Event handlers use function form: `onClick() { ... }` or a reference, not string names.\n- [ ] `<show=cond>` for toggled content that should keep its state; `<if>` destroys and rebuilds.\n- [ ] Component stays small and readable; consider splitting large templates.\n- [ ] No unnecessary client-side JS; prefer built-in browser APIs and HTML/CSS features over scripts.\n- [ ] Props are declared with an exported `Input` interface, and templates are type checked with `mtc` (`@marko/type-check`) — `tsc` skips `.marko` files and reports nothing.\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Marko Monorepo\n\nMarko compiles `.marko` templates into optimized server (streaming HTML) and client (fine-grained DOM) JavaScript. pnpm workspaces; Node >= 22.18 (native TS type stripping + module.registerHooks). Primary development happens in `packages/runtime-tags`.\n\n## Packages\n\n- [`packages/compiler`](packages/compiler/AGENTS.md) — `@marko/compiler`. Translator-agnostic: parses `.marko` into a (patched) Babel AST, then hands off to a translator for codegen.\n- [`packages/runtime-tags`](packages/runtime-tags/AGENTS.md) — `marko@6` / `@marko/runtime-tags`. The Marko 6 runtime **and** its translator. **Primary development.**\n- [`packages/runtime-class`](packages/runtime-class/AGENTS.md) — `marko@5` (private package, published only as `marko`). Marko 5, in maintenance; its translator wraps the class-API translator with runtime-tags' interop layer.\n\nA \"translator\" is the Babel-plugin half of a runtime package; the compiler loads it as `<pkg>/translator`. \"Marko 6\" is the runtime-tags version — the compiler stays 5.x.\n\n## Commands\n\nAll from repo root. Tests and tooling run directly from TS source (native Node type stripping plus the `~ts` resolve hook for extensionless imports; package `exports` point at `src/` until publish), so no build step is needed to iterate.\n\n```sh\npnpm test                                                 # whole suite fanned across CPU cores (~3x faster than serial)\npnpm test -- --grep \"runtime-tags/translator <fixture> \"  # scoped test run\npnpm run test:serial -- --grep \"...\"                      # same run in one process: bail at first failure, live output, --inspect-brk\npnpm test -- <file.test.ts>                               # only the given spec files (dirs and globs work too)\npnpm run test:update -- --grep \"...\"                      # regenerate snapshots (review the diff!)\npnpm run compile -- -o dom -d foo.marko                   # print compiled output (-o html for SSR; omit -d for optimized)\npnpm run build                                            # all packages -> dist/ + .d.ts\npnpm run build:sizes                                      # bundle-size table; diffs vs .sizes.json\npnpm run lint                                             # oxlint + oxfmt check\npnpm run format                                           # oxlint --fix + oxfmt write\npnpm run change                                           # add a changeset (required for user-facing changes)\n```\n\n`pnpm run compile` is the fastest way to inspect what the translator generates. It writes nothing: each compiled module, and then any module the translator generates for it, prints to stdout under a `// <resolved path>` header. (Pass `-t class` for the Marko 5 translator; `-t` also accepts a full translator module id.)\n\n`pnpm run change` prompts, so write `.changeset/<name>.md` directly, naming the package that owns the changed code: `packages/compiler` is `@marko/compiler`, `packages/runtime-tags` is `@marko/runtime-tags`, `packages/runtime-class` is `marko`. `pnpm exec changeset status` fails on a name that is no workspace package (which would break the release on `main`), but not on the wrong one: `marko` for a runtime-tags fix passes and publishes the wrong package. Restricting behavior that was already broken is a fix (`patch`), never described as a breaking change.\n\n## Repo invariants\n\n- **Dependencies are patched.** `patches/` (applied by pnpm patchedDependencies on install) adds Marko AST node types to `@babel/types`/`traverse`/`generator`, and makes mocha print the `require()` error it otherwise drops when its `import()` fallback rescues a spec. The Babel patches only add Marko AST support; never patch Babel's own behavior. Import Babel only via `@marko/compiler/internal/babel` and helpers via `@marko/compiler/babel-utils`, never `@babel/*` directly. Bumping any patched dependency requires regenerating its patch.\n- **Bundle size is a feature.** The pre-commit hook runs lint-staged, a full build, and `build:sizes`, staging `.sizes.json`/`.sizes/` — that diff is the size impact of the change. Commits are slow by design. The floor is `.sizes/counter.ssr` and `.sizes/comments.ssr` (a resumed page with no async, reorder, lazy, or dynamic html): code for an optional feature, even one `?.`, must fold out of them. Lint rules whose fix rewrites runtime code into larger output stay off in `.oxlintrc.json` (`unicorn/prefer-string-starts-ends-with`, `unicorn/no-new-array`); enabling one means checking `build:sizes` first.\n- **Snapshots and sizes are generated.** Never hand-edit _or delete_ `__snapshots__/**`, fixture `sizes.json`, or `.sizes*`; regenerate with `pnpm run test:update` (which also prunes stale snapshots after a green run) and the commit hook.\n- **CI** (`.github/workflows/ci.yml`): build + lint on Node 26; tests on Node 22/24/26 (zcov coverage). Releases go out via changesets on push to `main`.\n\n## Conventions\n\nOrganize files top-down (progressive disclosure): public API/exports first, then orchestration, helpers, and low-level detail last — use function-declaration hoisting.\n\nComments are a last resort and never exceed two lines: prefer self-describing code, and when one is needed it captures intent — never what the code was or what was removed. Wording is plain and direct, with no invented shorthand.\n\nDerive before adding. Before a new field, flag, helper, state container, parameter, test config, or module, find the existing analysis, helper, or runtime structure that already answers it and extend that. A parallel mechanism for one feature (one the rest of the code never needed) is a smell: say in the summary why nothing existing fits.\n\nEvery line needs a reason you can name. No guards, `?.`, fallbacks, casts (`as never`, `as any`, or one the type already satisfies), or parameters for states the design rules out; lean on the invariant (`!`, or a `MARKO_DEBUG` assert). Name checks, dependency method overrides, and machine heuristics are hacks: find the structural fix. A perf or config knob ships only with a measured win, and never restates a default. Measure performance on the bundled build that ships (`pnpm run build`), not the TS source that tests and tooling run: V8 inlines the bundle's module-level function declarations but not those of an ES module, so source timings can mislead.\n\nDon't bend the code around an edge case. Input the design has no reason to support (a `NaN` loop key, say) gets a compile error or a `MARKO_DEBUG` error that rules it out, not runtime handling that every caller pays for in size or speed. Harden the invariant, then rely on it.\n\nWrite the direct form. No rest or spread to copy, extend, or strip an object: share one record, or key a collection by the field it lacks. Client runtime code, where bundle size comes first, may keep a spread that `build:sizes` shows is smallest, but it is still a red flag to justify. No function that only forwards, and no type named for a single use. A helper every caller guards takes the `undefined` itself, and a flag is set as `flag ||= condition`.\n\nDon't add Babel `NodePath` helper calls (`findParent`, `find`, `getFunctionParent`, …): walk `parentPath` and compare node types directly; existing uses are migrated later.\n\nNames come from the code. Reuse the vocabulary of neighboring code, [`CONTEXT.md`](packages/runtime-tags/CONTEXT.md), and the markojs.com docs; never coin a term the codebase does not already use.\n\nTest through existing fixture families; add a test file only when no fixture can reach the behavior. A fix adds a fixture that fails without it, and so does every branch or statement a change adds: revert each one and confirm a fixture fails. Code no fixture needs is deleted, never kept behind a fixture that passes either way.\n\nMarko language reference: <https://markojs.com/llms.txt> lists every docs page; append `.md` to any docs URL for markdown.\n\n## Agent feedback\n\nAnything actionable but out of scope for the current task (suspected bug, cleanup, perf or size win, tooling friction, confusing code) must be filed in [`agent-feedback/`](agent-feedback/README.md) before finishing. Never drop it silently. Never fix it inside an unrelated diff. In scope, so fixed rather than filed: a defect in code the diff touches or exposes, and anything in the unreleased feature a branch builds (which also takes no changesets). A deliberate limitation gets a site comment, not an item.\n","isInternal":false,"tokens":1938,"sizeBytes":8407},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"AGENTS.md","isInternal":false,"tokens":3,"sizeBytes":9},{"name":"AGENTS.md","path":"packages/compiler/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/compiler/AGENTS.md","title":"Compiler Skill","category":"anthropic-skill","format":"markdown","content":"# `@marko/compiler`\n\nTranslator-agnostic compiler: parses `.marko` into a Babel AST (custom node types like `MarkoTag`, `MarkoAttribute` — added to Babel by the root `patches/`), runs migrate/transform passes, then hands the AST to a **translator** (`@marko/runtime-tags/translator` or `marko/translator`) for codegen. Stays at v5.x; language changes belong in the translators, not here.\n\n## Map\n\n- `src/index.js` — public API: `compile[File][Sync](src, filename, config)` → `{ code, map, meta, ast }`, `configure`, `taglib`, `types`.\n- `src/config.js` — config defaults, and the `globalConfig` that `configure()` sets (both re-exported by `index.js`); an omitted translator in `getRuntimeEntryFiles`, `getRuntimeVersion` and `taglib.buildLookup` reads it. Key options: `output` (`\"html\"` | `\"dom\"` | `\"source\"` | `\"migrate\"`), `optimize`, `translator`, `modules` (`\"esm\"`/`\"cjs\"`), `optimizeKnownTemplates`, `errorRecovery`, `cache`, `fileSystem`.\n- `src/babel-plugin/` — pipeline core. Stages: `parse → migrate → transform → analyze` (cached per template) then `translate` on a clone. Taglib visitors run in `migrate`, `transform` and `translate` — including those from the taglibs a translator registers via `taglibs`/`optionalTaglibs`, which is how a translator contributes migrators. The translator's own hooks are `transform` (optional), `analyze` and `translate`; there is no `translator.migrate` hook, and `analyze` is translator-only — a taglib-level `analyze` prop is a hard load error. Taglib `translate` is skipped for `output: \"hydrate\"`.\n- `src/taglib/` — tag registry/discovery: built-in HTML/SVG/MathML JSON taglibs, `marko.json` / `marko-tag.json` discovery walking up from the template, `buildLookup`.\n- `src/babel-utils/` — the helper API for translator authors (`assert*`, `diagnostic*`, `import*`, `parse*`, `getTagDef`, `isNativeTag`, `resolveTagImport`, ...). Exported as `@marko/compiler/babel-utils`.\n- `internal/babel/index.ts` — the single controlled Babel entry, re-exported as `@marko/compiler/internal/babel`. All Babel access (here and in translators) goes through it, never `@babel/*` directly.\n\n## Translator contract\n\nA translator module exports: `translate` (required visitor), `taglibs` (required, `[[id, props]]`), optional `transform` / `analyze` visitors, `tagDiscoveryDirs`, `optionalTaglibs`, `preferAPI` (`\"tags\"` | `\"class\"`), `getRuntimeEntryFiles(output, optimize)`, and optionally `cheatsheet` (a module-relative path to an LLM syntax reference; `tryLoadTranslator` resolves it to a cwd-relative path and `util/agent-fix-guide.js` points coding agents at it on compile errors). Loading is resolved from `config.translator` or auto-detected from the app's dependencies (`util/try-load-translator.js`, default logic in `config.js`).\n\n## Notes\n\n- `output: \"source\"` / `\"migrate\"` re-print `.marko` source (tooling/codemods) — no translator codegen.\n- Bumping any `@babel/*` version requires regenerating the corresponding patch in root `patches/` (pnpm patchedDependencies); the custom AST types and generated `dist/types.d.ts` (`pnpm --filter @marko/compiler run build-babel-types`) depend on them.\n- Adding a core tag in a translator shows up in taglib-lookup expectations here and in `packages/runtime-class/test/taglib-lookup/`.\n- `util/agent-fix-guide.js` — when a terminal coding agent is detected (env markers; `AI_AGENT=1` is the generic opt-in for harnesses not on the list) and the loaded translator declares a `cheatsheet`, thrown compile errors get a one-line pointer to it (relative to `cwd`) appended at the `compile[Sync]` boundary (to `message`, and to a `CompileError`'s `label`, which bundler plugins like `@marko/vite` print in place of the framed message), and under `errorRecovery` — where nothing throws — the same pointer is appended to the first error in `meta.diagnostics` instead. `MARKO_AGENT_FIX_GUIDE` overrides the sniff in either direction: `0` suppresses the guide, any other value forces it on (e.g. when compiling in a subprocess that drops the inherited marker). No-op for humans, for runtimes without a cheat sheet, and for inline translator objects (so error snapshots, which compile with an inline translator object, are unaffected).\n","isInternal":false,"tokens":1079,"sizeBytes":4249},{"name":"AGENTS.md","path":"packages/runtime-class/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/AGENTS.md","title":"Runtime-class Skill","category":"anthropic-skill","format":"markdown","content":"# Marko 5 (runtime & translator)\n\n## Architecture\n\nThe package is organized into four layers:\n\n| Directory              | Purpose                                                                |\n| ---------------------- | ---------------------------------------------------------------------- |\n| `src/runtime/helpers/` | Shared runtime helpers (class/style values, dynamic tags, attr-tags)   |\n| `src/runtime/html/`    | SSR runtime: streaming HTML output, helpers, hot reload                |\n| `src/runtime/vdom/`    | CSR runtime: virtual DOM, morphdom reconciliation, component lifecycle |\n| `src/translator/`      | Babel-based compiler that transforms `.marko` into SSR/CSR JavaScript  |\n\nThe compiler/translator entry is `src/translator/index.js`, but the package's exported translator (`src/translator.js`) wraps it with `createInteropTranslator` from `@marko/runtime-tags/translator`, so Marko 5 projects can mix in Marko 6 (Tags API) components. Interop behavior changes are usually made in `packages/runtime-tags/src/translator/interop/`, not here.\n\nNote: the package is private (named `marko`); `scripts/publish-alias.mts` publishes it as `marko` under the `m5` dist-tag.\n\nCompiled templates import runtime helpers by string path (`marko/src/runtime/helpers/...`, see `translator/util/load-import.js`), so a source search for importers misses those uses.\n\n`src` mixes ESM and CommonJS `.js` with no `\"type\"`, so Node warns `MODULE_TYPELESS_PACKAGE_JSON` under `-t class`. Accepted: Marko 5 is in maintenance and `src` ships in `files`, so a `{\"type\":\"module\"}` marker would force converting every CJS file.\n\n## Naming Conventions\n\n### Triple-underscore prefix (`___name`)\n\nAll internal properties and methods on runtime objects use a triple-underscore prefix:\n\n```js\nthis.___state;\ncomponent.___queueUpdate();\nexports.___batchUpdate = batchUpdate;\n```\n\nThe build step mangles these names into short single-character identifiers.\n\n### `MARKO_DEBUG` pattern\n\nDebug-only code is wrapped in string-compared conditionals that tree-shake in prod:\n\n```js\n// eslint-disable-next-line no-constant-binary-expression\nvar complain = \"MARKO_DEBUG\" && require(\"complain\");\nif (\"MARKO_DEBUG\") {\n  complain(\"Deprecated: ...\");\n}\n```\n\nThe build step replaces `\"MARKO_DEBUG\"` with `false` and dead-code-eliminates the branches.\n\n## Output Modes\n\n- **HTML (SSR)** — `src/runtime/html/index.js` creates a `Template` produces `AsyncStream`. Output is HTML strings piped to a Node.js stream.\n- **VDOM (browser)** — `src/runtime/vdom/index.js` creates a `Template` produces `AsyncVDOMBuilder`. Output is a virtual DOM tree reconciled via local morphdom .\n\nBoth stacks share `src/runtime/renderable.js`, which mixes `render()`, `renderSync()`, `renderToString()`, and `mount()` into `Template.prototype`.\n\n## Error Handling\n\n- Compile-time errors use Babel's `path.buildCodeFrameError(message)` to include source locations\n- Most validation happens at compile time; runtime errors in production are minimal\n\n## Testing\n\n### Test structure\n\n```\ntest/\n  translator/              # Snapshot tests for compiler output\n  components-pages/        # Full page hydration (ssr + csr) tests\n  components-browser/      # jsdom-based browser component tests\n  components-server/       # SSR rendering tests\n  morphdom/                # morphdom unit tests\n  vdom-create/             # VNode construction unit tests\n  async-stream/            # AsyncStream unit tests\n```\n\n### Translator tests\n\nEach fixture has a `template.marko` input and a `snapshots/` directory:\n\n```\nfixtures/<name>/\n  template.marko\n  snapshots/\n    vdom-expected.js\n    html-expected.js\n    htmlProduction-expected.js\n    hydrate-expected.js\n    cjs-expected.js\n    generated-expected.marko\n```\n\n### Running tests\n\nFrom the repo root:\n\n```sh\npnpm test # all tests\npnpm test -- --grep \"<fixture> \" # specific fixture\npnpm run test:update # update snapshots\n```\n","isInternal":false,"tokens":901,"sizeBytes":3914},{"name":"10-awesome-marko-features.md","path":"packages/runtime-class/docs/10-awesome-marko-features.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/10-awesome-marko-features.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"<a href=\"#\">\n  <img src=\"https://cdn-images-1.medium.com/max/1000/1*Cmy6UutD5-ogL8dr1DySMQ.png\" alt=\"Marko logo\" width=\"100%\" />\n</a><br />\n\n> This article was published in August 2017. You can find the original [\"10 Awesome Marko Features\" article here](https://medium.com/@austinkelleher/10-awesome-marko-features-afba9d094d42)!\n\n# 10 Awesome Marko Features\n\n[Marko](https://markojs.com/) is a friendly and super fast UI library that makes\nbuilding web apps<br> fun! In celebration of rapidly approaching [5,000 stars on\nGitHub](https://github.com/marko-js/marko) (the ultimate open source vanity\nmetric), here are 10 features that will make you more productive in no\nparticular order...\n\n#### 1. Shorthand Attributes\n\nTired of constantly typing out `class` and `id` attributes? No need with Marko.\nSimply utilize the shorthand based on CSS selectors:\n\n```marko\nstyle {\n  .count {\n    color:#09c;\n  }\n}\n\n// Equivalent to <div class=\"count\"/>\n<div.count/>\n\n// Equivalent to <span id=\"my-id\"/>\n<span#my-id/>\n\n// Combined\n<button#submit.primary/>\n```\n\n#### 2. All attribute values are Just JavaScript™\n\nUnlike with HTML, you are not limited to string attribute values when using\nMarko. Attributes can have types, which makes it really easy to pass data to\ncustom tags and it works for standard HTML tags too:\n\n```marko\n<div class=input.myClassName/>\n<input type=\"checkbox\" checked=input.isChecked/>\n<awesome-component myString=\"Hello\"/>\n<awesome-component myNumber=1/>\n<awesome-component myTemplateString=`Hello ${name}`/>\n<awesome-component myBoolean=true/>\n<awesome-component myArray=[1, 2, 3]/>\n<awesome-component myObject={hello: 'world'}/>\n<awesome-component myVariable=name/>\n<awesome-component myFunctionCall=input.foo()/>\n```\n\n#### 3. Isomorphic UI components made easy\n\nTired of boilerplate code and trouble managing component input and state? Marko\nmakes it a breeze to develop self-contained and individually testable\ncomponents. Changing state is completely synchronous, so there won’t be any\nheadaches. You can also use inline styles making it very easy to develop small\ncomponents quickly.\n\n```marko\nclass {\n  onInput(input) {\n    this.state = {\n      count: input.count || 0\n    };\n  }\n  increment() {\n    this.state.count++;\n  }\n}\n\nstyle {\n  .count {\n    color:#09c;\n  }\n}\n\n<div.count>${state.count}</div>\n<button on-click('increment')>\n  Click me!\n</button>\n```\n\nDo you see references to “Marko” in the snippet above? Yeah, me neither.\n\nIs your component becoming too large? Do you prefer separating your CSS,\nJavaScript, and markup code? No problem. You can easily [rip out your code into\nmultiple files](https://markojs.com/docs/class-components/#multi-file-components):\n\n```\ncomponents/\n  click-counter/\n    component.js\n    index.marko\n    style.css\n```\n\n#### 4. Concise syntax\n\nThe DOM is just a tree structure. Indentation is a great way to describe a DOM\ntree without having to worry about matching up beginning and ending tags. Marko\nlets you choose between a concise, indentation-based syntax, and a familiar HTML\nsyntax:\n\n```marko\n<!-- Count our clicks! -->\n<div.count>\n  <p>Count: ${state.count}</p>\n</div>\n<button.example-button on-click('increment')>\n  Click me!\n</button>\n```\n\nHere’s the same thing with the concise syntax:\n\n```marko\n// Count our clicks!\ndiv.count\n  p -- Count: ${state.count}\nbutton.example-button on-click('increment') -- Click me!\n```\n\nCan’t make up your mind or just want to paste in that code snippet from\nStackOverflow? HTML syntax can be used within in the concise syntax. You’ll come\nback and make it consistent…_one day_.\n\n#### 5. Import JavaScript modules\n\nDo you have some helper JavaScript functions that you need to use in your views?\nMarko lets you import any JavaScript module into your template using the same\nsyntax as the JavaScript `import` statement without using Babel or any other\nbuild tool. No need for problematic globals (you could do that too, but please\ndon’t or your coworkers will hate you).\n\n```marko\nimport sum from './utils/sum';\n\n<div>The sum of 2 + 3 is ${sum(2, 3)}</div>\n```\n\n#### 6. No need to import custom tags (it’s a good thing, trust me)\n\nMarko uses your directory structure as a method for automatically registering\ncustom tags. This means that Marko can implicitly import tags based on where the\ntemplate is located on disk. Marko will search up the directory looking for\ncustom tags in `components/`directories similar to how Node.js discovers modules\nin `node_modules/` directories.\n\nGiven the following directory structure:\n\n```\ncomponents/\n  fancy-button/\n    index.marko\n  fancy-container/\n    index.marko\n```\n\nIf `fancy-button` is used inside of `fancy-container`, it will be implicitly<br>\nimported:\n\n```marko\n<!-- No need to use `require` or `import` because it will implicitly import custom tags -->\n<div>\n  <fancy-button color=input.buttonColor/>\n</div>\n```\n\n#### 7. Use JavaScript to set CSS classes and styles\n\nSetting CSS classes and styles is made easy using JavaScript! Marko will happily\naccept simple strings, JavaScript objects and arrays (_falsy values will be\nignored)._\n\n```marko\n$ const fontColor = input.color || 'blue';\n$ const isActive = input.active === true;\n\n<div class=['person', isActive && 'active']\n  style={color: fontColor} />\n```\n\n#### 8. Inline JavaScript Statements\n\nMarko takes HTML and makes it more like JavaScript. You can exit out of HTML\nmode to embed a JavaScript statement by starting the line with a `$`. You can\nuse this feature to embed JavaScript variables, functions, etc. where they are\nneeded (take that, “separation of concerns”).\n\n```marko\n$ const randomNumber = Math.random();\n$ const person = {\n  name: 'Frank',\n  age: 32\n};\n\n<div>Random number: ${randomNumber}</div>\n<div>${person.name} is ${person.age} years old</div>\n```\n\nIf you want to combine multiple JavaScript statements you can do that too:\n\n```marko\n$ {\n  const randomNumber = Math.random();\n  const person = {\n    name: 'Frank',\n    age: 32\n  };\n}\n\n<div>Random number: ${randomNumber}</div>\n<div>${person.name} is ${person.age} years old</div>\n```\n\n#### 9. Async rendering with the `<await>` tag\n\nNode.js is asynchronous. Browsers are asynchronous. Why should rendering be\nsynchronous? Pass your promise along to your template and Marko will\nasynchronously render parts of your view. Turns out, [this is good for\nperformance](https://tech.ebayinc.com/engineering/async-fragments-rediscovering-progressive-html-rendering-with-marko/).\n\n```marko\n$ const searchResultsPromise = searchService.performSearch(keywords);\n\n<await(searchResultsPromise)>\n  <@then|person|>\n    Hello ${person.name}!\n  </@then>\n  <@catch|err|>\n    The error was: ${err.message}.\n  </@catch>\n</await>\n```\n\n#### 10. Server side rendering is easy\n\nCan’t decide if you want to do server-side rendering or client-side rendering?\nWhy are we even talking about this in 2017? It doesn’t matter. Seriously, just\ndo both. Marko makes this a no-brainer since you can render a Marko template\ndirectly to a stream (oh, and Marko will automatically mount UI\ncomponents rendered on the server when the page loads in the browser):\n\n```js\nrequire(\"@marko/compiler/register\"); // require .marko files!\n\nconst http = require(\"http\");\nconst template = require(\"./template\");\n\nhttp\n  .createServer()\n  .on(\"request\", (req, res) => {\n    template.render(\n      {\n        name: \"Frank\",\n        count: 30,\n        colors: [\"red\", \"green\", \"blue\"],\n      },\n      res,\n    );\n  })\n  .listen(8080);\n```\n\n#### Bonus: Friendly compile-time errors\n\nWe all make mistakes _every now and then_. Typo in your custom tag? Forgot an\nending tag? No worries! Marko will give you a friendly error message and point\nyou right to the problematic code.\n\n```marko\n<!-- Ahhhh typo! This should be <fancy-button/> -->\n<fancy-buttn/>\n```\n\nYou may have missed it, but it was obvious to Marko:\n\n```\nUnrecognized tag: fancy-buttn — More details: https://github.com/marko-js/marko/wiki/Error:-Unrecognized-Tag at line 2 col 1\n```\n\nComing soon: auto correction and autonomous coding\n\n---\n\n[_Cover image from Wikipedia_](https://commons.wikimedia.org/wiki/File:Amanhecer_no_Hercules_--.jpg)\n","isInternal":false,"tokens":2015,"sizeBytes":8153},{"name":"body-content.md","path":"packages/runtime-class/docs/body-content.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/body-content.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Body content\n\nWe're used to passing body content to HTML tags. When you do this, the tag has control over where and when this content is rendered. A good example of this is the [HTML `<details>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details):\n\n```html\n<details>\n  <summary>Hello <strong>World</strong></summary>\n  This is some <em>content</em> that can be toggled.\n</details>\n```\n\nThis is what it renders (try clicking it):\n\n---\n\n<details>\n    <summary>Hello <strong>World</strong></summary>\n    This is some <em>content</em> that can be toggled.\n</details>\n\n---\n\nCustom tags can also receive content in the same way. This allows a component to give its user full control over _how_ some section of the content is rendered, but control _where_, _when_, and with _what_ data it is rendered. This feature is necessary to build composable components like overlays, layouts, dropdowns, etc. Imagine a `<table>` that didn't give you control over how its cells were rendered. That would be pretty limited!\n\n## Rendering body content\n\nWhen a custom tag is passed body content, it is received as a special `renderBody` property on the component's `input`. You can include this content anywhere in your component by using the [`<${dynamic}>` syntax](./syntax.md#dynamic-tagname).\n\n_components/fancy-container.marko:_\n\n```marko\n<div class=\"container fancy\">\n    <${input.renderBody}/>\n</div>\n```\n\nIf we were to use this tag like this:\n\n_Marko Source:_\n\n```marko\n<fancy-container>\n    <p>Content goes here...</p>\n</fancy-container>\n```\n\nThe rendered output would be:\n\n_HTML Output:_\n\n```html\n<div class=\"container fancy\"><p>Content goes here...</p></div>\n```\n\nThis is a pretty basic example, but you can imagine how this could be incorporated into a more advanced component to render passed content where/when needed.\n\n> **ProTip:**\n> Body content can be rendered multiple times. Or not at all.\n\n## Passing attributes to body content\n\nWhen rendering body content with `<${dynamic}>`, attributes may also be passed:\n\n_components/random-value.marko:_\n\n```marko\n<!-- heh, it's not actually random -->\n<${input.renderBody} number=1337 />\n```\n\nThese attribute values can be received as a [tag parameter](./syntax.md#parameters):\n\n```marko\n<random-value|{ number }|>\n    The number is ${number}\n</random-value>\n```\n\n> **ProTip:**\n> Some tags (like the above tag) may not render anything except their body content with some data. This can be quite useful, just look at the `<for>` and `<await>` tags!\n\n## Named body content\n\nYou can also pass named content sections to a tag using [attribute tags](./syntax.md#attribute-tag) which are denoted by the `@` prefix.\n\n```marko\n<layout>\n    <@heading>\n        <h1>Hello Marko</h1>\n    </@heading>\n    <@content>\n        <p>...</p>\n    </@content>\n</layout>\n```\n\nLike attributes, these attribute tags are received as `input.heading` and `input.content`, but they each have a `renderBody` property which we can now use:\n\n_components/layout.marko_\n\n```marko\n<!doctype html>\n<html>\n    <body>\n        <${input.heading.renderBody}/>\n        <hr/>\n        <${input.content.renderBody}/>\n    </body>\n</html>\n```\n\n> **ProTip:** The `renderBody` property can be omitted. You could use `<${input.heading}/>`, for example.\n\n### Repeated body content\n\nWhen an attribute tag is repeated, the child component can consume all instances using the [iterable protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol).\n\nThis allows us to, for example, build a custom table component which allows its user to specify any number of columns, while still giving the user control over how each column is rendered.\n\n_Marko Source:_\n\n```marko\n<fancy-table data=people>\n    <@column|person|>\n        Name: ${person.name}\n    </@column>\n    <@column|person|>\n        Age: ${person.age}\n    </@column>\n</fancy-table>\n```\n\n> _Note_\n> For TypeScript the [`Marko.AttrTag` helper](./typescript.md#built-in-marko-types) should be used here.\n\n> _Protip_\n> Since attribute tags are iterable you could pass `input.column` to a `for of` loop, or `[...spread]` it into an array.\n> To `.map`, `.filter` or otherwise work with attribute tags as an array you can use the following pattern:\n>\n> ```marko\n> $ const columns = [...input.column || []];\n> ```\n\nWe can then use the `<for>` tag to render the body content into table, passing the row data to each column's body.\n\n_components/fancy-table/index.marko:_\n\n```marko {4-8}\n<table class=\"fancy\">\n    <for|row| of=input.data>\n        <tr>\n            <for|column| of=input.column>\n                <td>\n                    <${column.renderBody} ...row/>\n                </td>\n            </for>\n        </tr>\n    </for>\n</table>\n```\n\nWe now have a working `<fancy-table>`. Let's see what it renders:\n\n_Example Data:_\n\n```js\n[\n  {\n    name: \"Patrick\",\n    age: 63,\n  },\n  {\n    name: \"Austin\",\n    age: 12,\n  },\n];\n```\n\n_HTML Output:_\n\n```html\n<table class=\"fancy\">\n  <tr>\n    <td>Name: Patrick</td>\n    <td>Age: 63</td>\n  </tr>\n  <tr>\n    <td>Name: Austin</td>\n    <td>Age: 12</td>\n  </tr>\n</table>\n```\n\n### Attributes on attribute tags\n\nIf you look at our previous example, we had to prefix each cell with the column label. It would be better if we could give a name to each column instead and only render that once.\n\n_Marko Source:_\n\n```marko\n<fancy-table>\n    <@column|person| heading=\"Name\">\n        ${person.name}\n    </@column>\n    <@column|person| heading=\"Age\">\n        ${person.age}\n    </@column>\n</fancy-table>\n```\n\nNow, each attribute tag in `input.column` will contain a `heading` property in addition to its `renderBody`. We can use another `<for>` and render the headings in `<th>` tags:\n\n_components/fancy-table/index.marko:_\n\n```marko {3-5}\n<table class=\"fancy\">\n    <tr>\n        <for|column| of=input.column>\n            <th>${column.heading}</th>\n        </for>\n    </tr>\n    <for|row| of=input.data>\n        <tr>\n            <for|column| of=input.column>\n                <td>\n                    <${column.renderBody} ...row/>\n                </td>\n            </for>\n        </tr>\n    </for>\n</table>\n```\n\nWe'll now get a row of headings when we render our `<fancy-table>`\n\n_HTML Output:_\n\n```html\n<table class=\"fancy\">\n  <tr>\n    <th>Name</th>\n    <th>Age</th>\n  </tr>\n  <tr>\n    <td>Patrick</td>\n    <td>63</td>\n  </tr>\n  <tr>\n    <td>Austin</td>\n    <td>12</td>\n  </tr>\n</table>\n```\n\n### Nested attribute tags\n\nContinuing to build on our example, what if we want to add some custom content or even components into the column headings? In this case, we can extend our `<fancy-table>` to use nested attribute tags. We'll now have `<@heading>` and `<@cell>` tags nested under `<@column>`. This gives users of our tag full control over how to render both column headings and the cells within the column!\n\n_Marko Source:_\n\n```marko {3-8}\n<fancy-table>\n    <@column>\n        <@heading>\n            <app-icon type=\"profile\"/> Name\n        </@heading>\n        <@cell|person|>\n            ${person.name}\n        </@cell>\n    </@column>\n    <@column>\n        <@heading>\n            <app-icon type=\"calendar\"/> Age\n        </@heading>\n        <@cell|person|>\n            ${person.age}\n        </@cell>\n    </@column>\n</fancy-table>\n```\n\nNow instead of rendering the heading as text, we'll render the heading's body content.\n\n_components/fancy-table/index.marko:_\n\n```marko {5}\n<table class=\"fancy\">\n    <tr>\n        <for|column| of=input.column>\n            <th>\n                <${column.heading.renderBody}/>\n            </th>\n        </for>\n    </tr>\n    <for|row| of=input.data>\n        <tr>\n            <for|column| of=input.column>\n                <td>\n                    <${column.cell.renderBody} ...row/>\n                </td>\n            </for>\n        </tr>\n    </for>\n</table>\n```\n\nOur headings can now include icons (and anything else)!\n\n_HTML Output:_\n\n```html\n<table class=\"fancy\">\n  <tr>\n    <th><img class=\"icon\" src=\"profile.svg\" /> Name</th>\n    <th><img class=\"icon\" src=\"calendar.svg\" /> Age</th>\n  </tr>\n  <tr>\n    <td>Patrick</td>\n    <td>63</td>\n  </tr>\n  <tr>\n    <td>Austin</td>\n    <td>12</td>\n  </tr>\n</table>\n```\n\n### Dynamic attribute tags\n\nThe flexibility of the `<fancy-table>` is great if you want to render columns differently or have columns that display the data in a special way (such as displaying an age derived from a date of birth). However, if all columns are basically the same, the user might feel they're repeating themselves. As you might expect, you can use `<for>` (and `<if>`) to dynamically render attribute tags.\n\n```marko\n$ const columns = [{\n    property: \"name\",\n    title: \"Name\",\n    icon: \"profile\"\n}, {\n    property: \"age\",\n    title: \"Age\",\n    icon: \"calendar\"\n}]\n\n<fancy-table>\n    <for|{ property, title, icon }|>\n        <@column>\n            <@heading>\n                <app-icon type=icon/> ${title}\n            </@heading>\n            <@cell|person|>\n                ${person[property]}\n            </@cell>\n        </@column>\n    </for>\n</fancy-table>\n```\n","isInternal":false,"tokens":2369,"sizeBytes":9061},{"name":"class-components.md","path":"packages/runtime-class/docs/class-components.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/class-components.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Class Components\n\nMarko makes it easy to create user interface components to use as building blocks for web pages and applications of any complexity.\n\nMarko promotes self-contained components that:\n\n- Are independently testable\n- Encapsulate the view, client-side behavior (like event handling) and styling\n- Can easily be combined to create composite UI components.\n\nMarko components compile into small, efficient JavaScript modules that hide implementation details from consumers. Components can be published to [npm](https://www.npmjs.com) for reuse across applications.\n\n## UI component diagram\n\n![Component diagram](./component-diagram.svg)\n\nIn Marko, the DOM output of a UI component is based on _input properties_ and optional _internal state_ used to control the view.\n\nIf Marko detects changes to `input` or the internal `state`, then the view (that is, the DOM) will automatically update to reflect the new input and state. Internally, Marko uses virtual DOM diffing/patching to update the view, but that’s an implementation detail that could change at any time.\n\n## Component structure\n\nMarko makes it easy to keep your component’s class and styles next to the HTML view that they correspond to. The following are the key parts of any UI component:\n\n- **View** - The HTML template for your UI component. Receives input properties and states, and renders to either server-side HTML or browser-side virtual DOM nodes.\n- **Client-side behavior** - A JavaScript `class` with methods and properties for initialization, event handling (including DOM events, custom events and lifecycle events), and state management.\n- **Styles** - Cascading StyleSheets, including support for CSS preprocessors like [Less](https://lesscss.org/) or [Sass](https://sass-lang.com/).\n\n## Server-side rendering\n\nA UI component can be rendered on the server or in the browser, but stateful component instances will be automatically mounted to the DOM in the browser for both. If a UI component tree is rendered on the server, then Marko will recreate the UI component tree in the browser with no extra code required. For more details, please see [Rendering](/docs/rendering/).\n\n## Single-file components\n\nMarko lets you define a `class` for a component right in the `.marko` file, and call that class’s methods with `on-*` attributes:\n\n```marko\nclass {\n    onCreate() {\n        this.state = {\n            count: 0\n        };\n    }\n    increment() {\n        this.state.count++;\n    }\n}\n\n<label>The current count is <output>${state.count}</output></label>\n<p><button on-click('increment')>+1</button></p>\n```\n\n### Styles\n\nAdding styles in your view is also made easy:\n\n```marko\nstyle {\n    .primary {\n        background: #09c;\n    }\n}\n\n<label>The current count is <output>${state.count}</output></label>\n<p><button.primary on-click('increment')>+1</button></p>\n```\n\nThese styles aren’t output in a `<style>` tag as inline styles usually are, but are externalized to deduplicate them across multiple component instances on a page.\n\nIf you use a CSS preprocessor, you can add its file extension on `style`:\n\n```marko\nstyle.less {\n    .primary {\n        background: @primaryColor;\n    }\n}\n```\n\n> **Note:** The code in the `style` section is processed in a context separate from the rest of the template, so you can’t use JavaScript variables inside it. If you need variables in your CSS, use a CSS preprocessor that supports them.\n\n## Multi-file components\n\nYou might prefer to keep your component’s class and styles in separate files from the view — the classical separation of HTML, CSS, and JavaScript. Marko makes this possible with a filename-based convention.\n\n> **ProTip:** If your’re moving the component’s class and styles to separate files is because the code is getting too large, consider splitting the component into smaller, more manageable components.\n\n### Supporting files\n\nMarko discovers supporting files in the same directory as a Marko view. For example, if you have a view named `counter.marko`, Marko will automatically look for `counter.component.js` and `counter.style.css`.\n\n```\ncounter.marko\ncounter.component.js\ncounter.style.css\n```\n\nMarko also handles views named `index.marko` specially. It will look for `component.js` and `style.css` in addition to `index.component.js` and `index.style.css`. This allows easily grouping component files into a directory:\n\n```\ncounter/\n    index.marko\n    component.js\n    style.css\n```\n\nIn your `component.js` file, export the component’s class:\n\n```js\nexport default class {\n  onCreate() {\n    this.state = {\n      count: 0,\n    };\n  }\n  increment() {\n    this.state.count++;\n  }\n}\n```\n\nIn your `index.marko` file, you can reference methods from that class with `on-*` attributes:\n\n```marko\n<label>The current count is <output>${state.count}</output></label>\n<p><button.primary on-click('increment')>+1</button></p>\n```\n\nAnd in your `style.css`, define the styles:\n\n```css\n.primary {\n  background: #09c;\n}\n```\n\n> **ProTip:** Marko actually looks any filenames with the pattern `[name].style.*`, so it will pick up any CSS preprocessor file extensions you use: `.less`, `.stylus`, `.scss`, etc.\n\n### Components with plain objects\n\nIf you target browsers that does not support classes, a plain object of methods can be exported:\n\n```js\nexport default {\n  onCreate: function () {\n    this.state = {\n      count: 0,\n    };\n  },\n  increment: function () {\n    this.state.count++;\n  },\n};\n```\n\n## Split components\n\nSplit components optimize for when a component renders on the server, and doesn’t need to dynamically rerender in the browser. As a result, its template and logic aren’t sent to the browser, reducing load time and download size.\n\n> **Note:** If a split component is the child of a stateful component, its full rendering logic will still be sent because the parent may pass new input to the split component and rerender it.\n\nAdditionally, if _all_ components rendered on a page are split components, Marko’s VDOM and rendering runtime is unnecessary, and therefore not sent to the browser.\n\n> **ProTip:** Don’t over-optimize. If your component really doesn’t need rerendering, go ahead and split, but don’t forgo stateful rerendering when it would make your code more maintainable.\n\n### Usage\n\nMarko discovers split components similarly to how it discovers an external component class. For example, if you have a view named `button.marko`, it will automatically look for `button.component-browser.js`. If your view is named `index.marko`, it will look for `component-browser.js` in addition to `index.component-browser.js`.\n\n```\ncounter/\n    index.marko\n    component-browser.js\n```\n\nA split component might need to do some setup as part of its initial render. In this case, the component may define a second component class to use the `onCreate`, `onInput`, and `onRender` [lifecycle methods](#lifecycle-events).\n\nThis class can be exported from `component.js`, or defined right in the template as a single-file components. In this case, your component folder may contain a `component.js` file, and must contain a `component-browser.js`. The following [lifecycle methods](#lifecycle-events) can go inside the `component.js` file:\n\n```\nclass {\n  onCreate(input, out) { }\n  onInput(input, out) { }\n  onRender(out) { }\n  onDestroy() { }\n}\n```\n\nAnd the following [lifecycle methods](#lifecycle-events) can go inside the `component-browser.js` file:\n\n```\nclass {\n  onMount() { }\n  onUpdate() { }\n}\n```\n\nAny JavaScript code related to the DOM or browser should also be inside `component-browser.js`.\n\n### Example\n\n`index.marko`\n\n```marko\nclass {\n    onCreate() {\n        this.number = 123;\n    }\n}\n\n<button on-click('shout')>What’s my favorite number?</button>\n```\n\n`component-browser.js`\n\n```js\nexport default {\n  shout() {\n    alert(`My favorite number is ${this.number}!`);\n  },\n};\n```\n\n## Event handling\n\nThe `on-[event](methodName|function, ...args)` attributes allow event listeners to be attached for either:\n\n- A native DOM event, when used on a native DOM element such as a `<button>`\n- Or a UI component event, when used on a custom tag for a UI component such as `<my-component>`\n\nThe `on-*` attributes are used to associate event handler methods with an event name. Event handlers may be specified by `'methodName'` — a string that matches a method on the component instance, or they may be a `function`. Attaching listeners for native DOM events and UI component custom events is explained in more detail in the sections below.\n\nYou may also use the `once-[event](methodName|function, ...args)` syntax, which will listen for only the first event, and then remove the listener.\n\n### Attaching DOM event listeners\n\nThe code below illustrates how to attach an event listener for native DOM events:\n\n```marko\nclass {\n  onButtonClick(name, event, el) {\n    alert(`Hello ${name}!`);\n  }\n}\n\nstatic function fadeIn(event, el) {\n  el.hidden = false;\n  el.style.opacity = 0;\n  el.style.transition = 'opacity 1s';\n  setTimeout(() => el.style.opacity = 1);\n}\n\n<button on-click('onButtonClick', 'Frank')>\n  Say Hello to Frank\n</button>\n\n<button on-click('onButtonClick', 'John')>\n  Say Hello to John\n</button>\n\n<img src='foo.jpg' once-load(fadeIn) hidden />\n```\n\nThe following arguments are passed to the event handler when the event occurs:\n\n1.  `...args` - Any extra bound arguments are _prepended_ to the arguments passed to the component’s handler method.\n    For example: `on-click('onButtonClick', arg1, arg2)` → `onButtonClick(arg1, arg2, event, el)`\n2.  `event` - The native DOM event object.\n3.  `el` - The DOM element that the event listener was attached to.\n\nWhen using the `on-*` or `once-*` attributes to attach event listeners, Marko uses event delegation that is more efficient than direct attachment of `el.addEventListener()`. Please see [Why is Marko Fast? § Event delegation](/docs/why-is-marko-fast/#event-delegation) for more details.\n\n<a id=\"declarative-custom-events\"></a>\n\n### Attaching custom event listeners\n\nThe code below illustrates how to attach an event listener for a UI component’s custom event:\n\n```marko\nclass {\n  onCounterChange(newValue, el) {\n    alert(`New value: ${newValue}!`);\n  }\n  onCounterMax(max) {\n    alert(`It reached the max: ${max}!`);\n  }\n}\n\n<counter on-change('onCounterChange') once-max('onCounterMax') />\n```\n\nThe following arguments are passed to the event handler when the event occurs:\n\n1.  `...args` - Any extra bound arguments are _prepended_ to the arguments passed to the component’s handler method.\n2.  `...eventArgs` - The arguments passed to `this.emit()` by the target UI component.\n3.  `component` - The component instance that the event listener was attached to.\n\nThe following code illustrates how the UI component for `<counter>` might emit its `change` event:\n\n`counter/index.marko`\n\n```marko\nclass {\n  onCreate() {\n    this.max = 50;\n    this.state = { count: 0 };\n  }\n  increment() {\n    if (this.state.count < this.max) {\n        this.emit('change', ++this.state.count);\n    }\n    if (this.state.count === this.max) {\n        this.emit('max', this.state.count);\n    }\n  }\n}\n\n\n<button.example-button on-click('increment')>\n  Increment\n</button>\n```\n\n> **ProTip:** Unlike native DOM events, UI component custom events may be emitted with multiple arguments. For example:\n>\n> ```js\n> this.emit(\"foo\", \"bar\", \"baz\");\n> ```\n\n## Attributes\n\n### `on-[event](methodName|function, ...args)`\n\nThe `on-*` attribute syntax attaches an event listener to either a native DOM event or a UI component event. The `on-*` attribute associates an event handler method with an event name. Please see the [Event handling](#event-handling) section above for details.\n\n### `once-[event](methodName|function, ...args)`\n\nThe same as the `on-*` attribute, except that its listener is only invoked for the first event, and then removed from memory. Please see the [Event handling](#event-handling) section above for more details.\n\n### `key`\n\nThe `key` property does 2 things in Marko:\n\n- Obtains references to nested HTML elements and nested UI components.\n- Matches corresponding elements together when DOM diffing/patching after a rerender. When updating the DOM, keyed elements/components are matched up and reused rather than discarded and recreated.\n\nInternally, Marko assigns a unique key to all HTML elements and UI components in a `.marko` file, based on the order they appear in the file. If you have repeated elements or elements that move between locations in the DOM, then you likely want to assign a custom `key` by adding a `key` attribute. The `key` attribute can be applied to both HTML elements and custom tags.\n\n#### Referencing nested HTML elements and components\n\n```marko\nclass {\n  onMount() {\n    const headerElement = this.getEl('header');\n    const colorListItems = this.getEls('colors');\n    const myFancyButton = this.getComponent('myFancyButton');\n  }\n}\n\n<h1 key=\"header\">Hello</h1>\n\n<ul>\n  <for|color| of=['red', 'green', 'blue']>\n      <li key=\"colors[]\">${color}</li>\n  </for>\n</ul>\n\n<fancy-button key=\"myFancyButton\"/>\n```\n\n> **Note:** The `[]` suffix (e.g. `key=\"colors[]\"`) lets Marko know that the element will be repeated multiple times with the same key.\n\n#### Keyed matching\n\nThe `key` attribute can pair an HTML element or UI component that moves to a new location in the DOM. For example:\n\n```marko\nclass {\n  onCreate() {\n    this.state = {\n      swapped: false\n    }\n  }\n}\n\n<if(state.swapped)>\n  <p key=\"b\">B</p>\n  <p key=\"a\">A</p>\n</if>\n<else>\n  <p key=\"a\">A</p>\n  <p key=\"b\">B</p>\n</else>\n```\n\nThe `key` attribute can be used to pair HTML elements or UI components that are repeated:\n\n```marko\n<ul>\n  <for|user| of=input.users>\n      <li key=user.id>${user.name}</li>\n  </for>\n</ul>\n```\n\nThis way, if the order of `input.users` changes, the DOM will be rerendered more efficiently.\n\n#### `*:scoped`\n\nThe `:scoped` attribute modifier results in the attribute value getting prefixed with a unique ID associated with the current UI component. `:scoped` attribute modifiers can be used to assign a globally unique attribute value from a value that only needs to be unique to the current UI component.\n\nHere’s a use-case: certain HTML attributes reference the `id` of other elements on the page. For example, the [HTML `<label>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label) `for` attribute takes an `id` as its value. Many `ARIA` attributes like [`aria-describedby`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-describedby_attribute) also take an `id` as their value.\n\nThe `:scoped` modifier on an attribute allows you to reference another element without fear of duplicate `id`s, as shown in the following examples:\n\n**`for:scoped`**\n\n```marko\n<label for:scoped=\"name\">Name</label>\n<input id:scoped=\"name\" value=\"Frank\"/>\n```\n\nThe above code will output HTML similar to the following:\n\n```html\n<label for=\"c0-name\">Name</label> <input id=\"c0-name\" value=\"Frank\" />\n```\n\n**`aria-describedby:scoped`**\n\n```marko\n<button\n   aria-describedby:scoped=\"closeDisclaimer\"\n   on-click('closeDialog')>Close</button>\n\n<p id:scoped=\"closeDisclaimer\">\n   Closing this window will discard any entered information and return you to the main page.\n</p>\n```\n\n```html\n<button aria-describedby=\"c0-closeDisclaimer\">Close</button>\n\n<p id=\"c0-closeDisclaimer\">\n  Closing this window will discard any entered information and return you to the\n  main page.\n</p>\n```\n\n**`href:scoped`**\n\n```marko\n<a href:scoped=\"#anchor\">Jump to section</a>\n<section id:scoped=\"anchor\"></section>\n```\n\n```html\n<a href=\"#c0-anchor\">Jump to section</a>\n<section id=\"c0-anchor\"></section>\n```\n\n### `no-update`\n\nPreserves the DOM subtree associated with the element or component, so it won’t be modified when rerendering.\n\n```marko\n<!-- Never rerender this table -->\n<table no-update>\n  …\n</table>\n```\n\n```marko\n<!-- N ever rerender this UI component -->\n<app-map no-update/>\n```\n\nThis is most useful when other JavaScript modifies the DOM tree of an element, like for embeds.\n\n### `no-update-if`\n\nSimilar to [no-update](#no-update), except that the DOM subtree is _conditionally_ preserved:\n\n```marko\n<!-- Don’t re-render this table without table data -->\n<table no-update-if(input.tableData == null)>\n  …\n</table>\n```\n\n### `no-update-body`\n\nSimilar to [no-update](#no-update), except that only the descendant DOM nodes are preserved:\n\n```marko\n<!-- Never rerender any nested DOM elements -->\n<div no-update-body>\n  …\n</div>\n```\n\n### `no-update-body-if`\n\nSimilar to [no-update-body](#no-update-body), except that its descendant DOM nodes are _conditionally_ preserved:\n\n```marko\n<!-- Never rerender any nested DOM elements without table data -->\n<table no-update-body-if(input.tableData == null)>\n  …\n</table>\n```\n\n### `:no-update`\n\nPrevents certain attributes from being modified during a rerender. The attribute(s) that should not be modified should have a `:no-update` modifier:\n\n```marko\n<!-- Never modify the `class` attribute -->\n<div class:no-update=input.className>\n  …\n</div>\n```\n\n## Properties\n\n### `this.id`\n\nA string identifier for the root HTML element that the component is bound to. (Not the `id` attribute.)\n\n### `this.state`\n\nThe current state for the component. Changing `this.state` or its direct properties will cause the component to rerender.\n\nOnly properties that exist when `this.state` is first defined will be watched for changes. If you don’t need a property initially, you can set its value to `null`:\n\n```marko\nclass {\n    onCreate() {\n        this.state = {\n            data: null,\n            error: null\n        }\n    }\n    getData() {\n        fetch('/endpoint')\n            .then(data => this.state.data = data)\n            .catch(error => this.state.error = error);\n    }\n}\n```\n\nBeware: setting a `state` property only _nominates_ the component for a possible rerender, and properties are only watched one level deep. Thus, the component is only rerendered if at least one of the component state properties changed (`oldValue !== newValue`).\n\nIf none of the properties changed (because the new value is identical, or no difference is detected by a shallow comparison), the assignment is considered a no-operation (great for performance).\n\nWe recommend using [immutable data structures](https://wecodetheweb.com/2016/02/12/immutable-javascript-using-es6-and-beyond/), but if you want to mutate a state property (perhaps push a new item into an array), you can mark it as dirty with `setStateDirty`:\n\n```js\nthis.state.numbers.push(num);\n\n// Mark numbers as dirty, because a `push`\n// won’t be automatically detected by Marko\nthis.setStateDirty(\"numbers\");\n```\n\n### `this.input`\n\nThe current input for the component. Setting `this.input` will rerender the component which can be useful for testing, but generally avoided (prefer `state` instead).\n\n## Variables\n\nWhen a Marko component is compiled, some additional variables are available to the rendering function. These variables are described below.\n\n### `component`\n\nThe `component` variable refers to the instance of the currently rendering UI component. This variable can be used to call methods on the UI component instance:\n\n```marko\nclass {\n    getFullName() {\n        const { person } = this.input;\n        return `${person.firstName} ${person.lastName}`;\n    }\n}\n\n<h1>Hello, ${component.getFullName()}</h1>\n```\n\n### `input`\n\nThe `input` variable refers to the `input` object, and is equivalent to `component.input`|`this.input`.\n\n```marko\n<h1>Hello, ${input.name}</h1>\n```\n\n### `state`\n\nThe `state` variable refers to the UI component’s `state` object, and is the _unwatched_ equivalent of `component.state`|`this.state`.\n\n```marko\n<h1>Hello ${state.name}</h1>\n```\n\n## Methods\n\n### `destroy([options])`\n\n| Option       | Type      | Default | Description                                                                       |\n| ------------ | --------- | ------- | --------------------------------------------------------------------------------- |\n| `removeNode` | `Boolean` | `true`  | `false` will keep the component in the DOM while unsubscribing all events from it |\n| `recursive`  | `Boolean` | `true`  | `false` will prevent child components from being destroyed                        |\n\nDestroys the component by unsubscribing from all listeners made using the `subscribeTo` method, and then detaching the component’s root element from the DOM. All nested components (discovered by querying the DOM) are also destroyed.\n\n```js\ncomponent.destroy({\n  removeNode: false, // true by default\n  recursive: false, // true by default\n});\n```\n\n### `forceUpdate()`\n\nQueue the component to re-render and skip all checks to see if it actually needs it.\n\n> When using `forceUpdate()` the updating of the DOM will be queued up. If you want to immediately update the DOM\n> then call `this.update()` after calling `this.forceUpdate()`.\n\n### `getEl([key, index])`\n\n| Signature    | Type          | Description                                                                       |\n| ------------ | ------------- | --------------------------------------------------------------------------------- |\n| `key`        | `String`      | _optional_ — the scoped identifier for the element                                |\n| `index`      | `Number`      | _optional_ — the index of the component, if `key` references a repeated component |\n| return value | `HTMLElement` | The element matching the key, or `this.el` if no key is provided                  |\n\nReturns a nested DOM element by prefixing the provided `key` with the component’s ID. For Marko, nested DOM elements should be assigned an ID with the `key` attribute.\n\n### `getEls(key)`\n\n| Signature    | Type                 | Description                                           |\n| ------------ | -------------------- | ----------------------------------------------------- |\n| `key`        | `String`             | The scoped identifier for the element                 |\n| return value | `Array<HTMLElement>` | An array of _repeated_ DOM elements for the given key |\n\nRepeated DOM elements must have a value for the `key` attribute that ends with `[]`. For example, `key=\"items[]\"`.\n\n### `getElId([key, index])`\n\n| Signature    | Type     | Description                                                                       |\n| ------------ | -------- | --------------------------------------------------------------------------------- |\n| `key`        | `String` | _optional_ — The scoped identifier for the element                                |\n| `index`      | `Number` | _optional_ — The index of the component, if `key` references a repeated component |\n| return value | `String` | The element ID matching the key, or `this.el.id` if `key` is undefined            |\n\nSimilar to `getEl`, but only returns the String ID of the nested DOM element instead of the actual DOM element.\n\n### `getComponent(key[, index])`\n\n| Signature    | Type        | Description                                                                                                                                                                                                       |\n| ------------ | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `key`        | `String`    | The scoped identifier for the element                                                                                                                                                                             |\n| `index`      | `Number`    | _optional_ — The index of the component, if `key` references a repeated component                                                                                                                                 |\n| return value | `Component` | A reference to a nested `Component` for the given key. If an `index` is provided and the target component is a repeated component (i.e. `key=\"items[]\"`), then the component at the given index will be returned. |\n\nFor example, given the following component,\n\n```marko\n<app-main>\n  <app-child key=\"child\"/>\n</app-main>\n```\n\nThe following code can be used to get the `<app-child/>` component:\n\n```js\nconst childComponent = this.getComponent(\"child\");\n```\n\n### `getComponents(key, [, index])`\n\n| Signature    | Type               | Description                                                                       |\n| ------------ | ------------------ | --------------------------------------------------------------------------------- |\n| `key`        | `String`           | The scoped identifier for the element                                             |\n| `index`      | `Number`           | _optional_ — The index of the component, if `key` references a repeated component |\n| return value | `Array<Component>` | An array of _repeated_ `Component` instances for the given key                    |\n\nRepeated components must have a value for the `key` attribute that ends with `[]`, like `key=\"items[]\"`.\n\n### `isDestroyed()`\n\nReturns `true` if a component has been destroyed using [`component.destroy()`](#ondestroy), otherwise `false`.\n\n### `isDirty()`\n\nReturns `true` if the component needs a bath.\n\n### `replaceState(newState)`\n\n| Signature  | Type     | Description                                      |\n| ---------- | -------- | ------------------------------------------------ |\n| `newState` | `Object` | A new state object to replace the previous state |\n\nReplaces the state with an entirely new state. Equivalent to `this.state = newState`.\n\n> **Note:** While `setState()` is additive and will not remove properties that are in the old state but not in the new state, `replaceState()` _will_ add the new state and remove the old state properties that are not found in the new state. Thus, if `replaceState()` is used, consider possible side effects if the new state contains less or other properties than the replaced state.\n\n### `rerender([input])`\n\n| Signature | Type     | Description                                         |\n| --------- | -------- | --------------------------------------------------- |\n| `input`   | `Object` | _optional_ — New input data to use when rerendering |\n\nRerenders the component using its `renderer`, and either supplied `input` or internal `input` and `state`.\n\n### `setState(name, value)`\n\n| Signature | Type     | Description                                |\n| --------- | -------- | ------------------------------------------ |\n| `name`    | `String` | The name of the `state` property to update |\n| `value`   | `Any`    | The new value for the `state` property     |\n\nChanges the value of a single `state` property. Equivalent to `this.state[name] = value`, except it will also work for adding new properties to the component state.\n\n```js\nthis.setState(\"disabled\", true);\n```\n\n### `setState(newState)`\n\n| Signature  | Type     | Description                                         |\n| ---------- | -------- | --------------------------------------------------- |\n| `newState` | `Object` | A new state object to merge into the previous state |\n\nChanges the value of multiple state properties:\n\n```js\nthis.setState({\n  disabled: true,\n  size: \"large\",\n});\n```\n\n### `setStateDirty(name[, value])`\n\n| Signature | Type     | Description                                       |\n| --------- | -------- | ------------------------------------------------- |\n| `name`    | `String` | The name of the `state` property to mark as dirty |\n| `value`   | `Any`    | _optional_ — A new value for the `state` property |\n\nForces a state property change, even if the value is equal to the old value. This is helpful in cases where a change occurs to a complex object that would not be detected by a shallow compare. Invoking this function completely circumvents all property equality checks (shallow compares) and always rerenders the component.\n\n#### More details\n\nThe first parameter, `name`, is used to allow update handlers (e.g. `update_foo(newValue)`) to handle the state transition for the specific state property that was marked dirty.\n\nThe second parameter, `value`, is used as the new value that is given to update handlers. Because `setStateDirty()` always bypasses all property equality checks, this parameter is optional. If not given or equal to the old value, the old value will be used for the update handler.\n\nImportant: the given parameters do not affect how or if `setStateDirty()` rerenders a component; they are only considered as additional information to update handlers.\n\n```js\n// Because this does not create a new array, the change\n// would not be detected by a shallow property comparison\nthis.state.colors.push(\"red\");\n\n// Force that particular state property to be considered dirty so\n// that it will trigger the component's view to be updated\nthis.setStateDirty(\"colors\");\n```\n\n### `subscribeTo(emitter)`\n\n| Signature    | Description                                                                                                                                           |\n| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `emitter`    | A [Node.js `EventEmitter`](https://nodejs.org/api/events.html#events_class_eventemitter) or DOM object that emits events (`window`, `document`, etc.) |\n| return value | A tracked subscription                                                                                                                                |\n\nWhen a component is destroyed, it is necessary to remove any listeners that were attached by the component to prevent memory leaks. By using `subscribeTo`, Marko will automatically track and remove any listeners you attach when the component is destroyed.\n\nMarko uses [`listener-tracker`](https://github.com/patrick-steele-idem/listener-tracker) to provide this feature.\n\n```js\nthis.subscribeTo(window).on(\"scroll\", () =>\n  console.log(\"The user scrolled the window!\"),\n);\n```\n\n### `update()`\n\nImmediately executes any pending updates to the DOM, rather than following the normal queued update mechanism for rendering.\n\n```js\nthis.setState(\"foo\", \"bar\");\nthis.update(); // Force the DOM to update\nthis.setState(\"hello\", \"world\");\nthis.update(); // Force the DOM to update\n```\n\n## Event methods\n\nMarko components inherit from [`EventEmitter`](https://nodejs.org/api/events.html#events_class_eventemitter). Below are a few commonly used methods — view the Node.js docs for the full list.\n\n### `emit(eventName, ...args)`\n\n| Signature   | Type     | Description                                           |\n| ----------- | -------- | ----------------------------------------------------- |\n| `eventName` | `String` | Name of the event                                     |\n| `...args`   | `Any`    | All subsequent parameters are passed to the listeners |\n\nEmits a UI component custom event. If a UI component attached a listener with the matching `eventName`, then the corresponding event listener method will be invoked. Event listeners can be attached using either the [`on-[event](methodName|function, ...args)`](#declarative-custom-events) attribute syntax, or `targetComponent.on()`.\n\n### `on(eventName, handler)`\n\n| Signature   | Type       | Description                               |\n| ----------- | ---------- | ----------------------------------------- |\n| `eventName` | `String`   | Name of the event to listen for           |\n| `handler`   | `Function` | The function to call when the event fires |\n\nAdds the listener function to the end of the listeners array for the `eventName` event. Does not check to see if the listener has already been added. Multiple calls passing the same combination of `eventName` and `handler` will result in the listener being added and called multiple times.\n\n### `once(eventName, handler)`\n\n| Signature   | Type       | Description                               |\n| ----------- | ---------- | ----------------------------------------- |\n| `eventName` | `String`   | Name of the event to listen for           |\n| `handler`   | `Function` | The function to call when the event fires |\n\nAdds a one-time listener function for the `eventName` event. The next time `eventName` triggers, this listener is removed and then invoked.\n\n## Lifecycle events\n\nMarko defines six lifecycle events:\n\n- `create`\n- `input`\n- `render`\n- `mount`\n- `update`\n- `destroy`\n\nThese events are emitted at specific points over the lifecycle of a component, as shown below:\n\n**First render**\n\n```js\nemit('create') → emit('input') → emit('render') → emit('mount')\n```\n\n**New input**\n\n```js\nemit('input') → emit('render') → emit('update')\n```\n\n**Internal state change**\n\n```js\nemit('render') → emit('update')\n```\n\n**Destroy**\n\n```js\nemit(\"destroy\");\n```\n\n### Lifecycle event methods\n\nEach lifecycle event has a corresponding component lifecycle method that can listen for the event:\n\n```js\nclass {\n  onCreate(input, out) { }\n  onInput(input, out) { }\n  onRender(out) { }\n  onMount() { }\n  onUpdate() { }\n  onDestroy() { }\n}\n```\n\n> **ProTip:** When a lifecycle event occurs in the browser, the corresponding event is emitted on the component instance. A parent component, or other code that has access to the component instance, can listen for these events. For example:\n>\n> ```js\n> component.on(\"input\", function (input, out) {\n>   // The component received an input\n> });\n> ```\n\n### `onCreate(input, out)`\n\n| Signature | Description                                                     |\n| --------- | --------------------------------------------------------------- |\n| `input`   | The input data used to render the component for the first time  |\n| `out`     | The async `out` used to render the component for the first time |\n\nThe `create` event is emitted (and `onCreate` is called) when the component is first created.\n\n`onCreate` is typically used to set the initial state for stateful components:\n\n```marko\nclass {\n    onCreate(input) {\n        this.state = { count: input.initialCount };\n    }\n}\n```\n\n### `onInput(input, out)`\n\n| Signature | Description        |\n| --------- | ------------------ |\n| `input`   | The new input data |\n\nThe `input` event is emitted (and `onInput` is called) when the component receives input: both the initial input, and for any subsequent updates to its input.\n\n### `onRender(out)`\n\n| Signature | Description                            |\n| --------- | -------------------------------------- |\n| `out`     | The async `out` for the current render |\n\nThe `render` event is emitted (and `onRender` is called) when the component is about to render or rerender.\n\n### `onMount()`\n\nThe `mount` event is emitted (and `onMount` is called) when the component is first mounted to the DOM. For server-rendered components, this is the first event that is emitted only in the browser.\n\nThis is the first point at which `this.el` and `this.els` are defined. `onMount` is commonly used to attach third-party JavaScript to the newly-mounted DOM.\n\nFor example, attaching a library that monitors if the component is in the viewport:\n\n```marko\nimport scrollmonitor from 'scrollmonitor';\n\nclass {\n    onMount() {\n        this.watcher = scrollmonitor.create(this.el);\n        this.watcher.enterViewport(() => console.log('I have entered the viewport'));\n        this.watcher.exitViewport(() => console.log('I have left the viewport'));\n    }\n}\n```\n\n### `onUpdate()`\n\nThe `update` event is emitted (and `onUpdate` is called) when the component is called after a component rerenders and the DOM has been updated. If a rerender does not update the DOM (nothing changed), this event will not fire.\n\n### `onDestroy()`\n\nThe `destroy` event is emitted (and `onDestroy` is called) when the component is about to unmount from the DOM and cleaned up. `onDestroy` should be used to do any additional cleanup beyond what Marko handles itself.\n\nFor example, cleaning up from our `scrollmonitor` example in [`onMount`](#onmount):\n\n```marko\nimport scrollmonitor from 'scrollmonitor';\n\nclass {\n    onMount() {\n        this.watcher = scrollmonitor.create(this.el);\n        this.watcher.enterViewport(() => console.log('Entered the viewport'));\n        this.watcher.exitViewport(() => console.log('Left the viewport'));\n    }\n    onDestroy() {\n        this.watcher.destroy();\n    }\n}\n```\n\n## DOM manipulation methods\n\nThe following methods move the component’s root DOM node(s) from the current parent element to a new parent element (or out of the DOM in the case of `detach`).\n\n### `appendTo(targetEl)`\n\nMoves the UI component’s DOM elements into the position after the target element’s last child.\n\n```js\nthis.appendTo(document.body);\n```\n\n### `insertAfter(targetEl)`\n\nMoves the UI component’s DOM elements into the position after the target DOM element.\n\n### `insertBefore(targetEl)`\n\nMoves the UI component’s DOM elements into the position before the target DOM element.\n\n### `prependTo(targetEl)`\n\nMoves the UI component’s DOM elements into the position before the target element’s first child.\n\n### `replace(targetEl)`\n\nReplaces the target element with the UI component’s DOM elements.\n\n### `replaceChildrenOf(targetEl)`\n\nReplaces the target element’s children with the UI component’s DOM elements.\n","isInternal":false,"tokens":8173,"sizeBytes":37517},{"name":"cloudflare-workers.md","path":"packages/runtime-class/docs/cloudflare-workers.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/cloudflare-workers.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Marko + Cloudflare Workers\n\nSee the [the cloudflare sample](https://github.com/marko-js/examples/tree/master/examples/vite-cloudflare)\nproject for a working example.\n\n## Usage\n\nWhen using Marko with [Cloudflare Workers](https://workers.cloudflare.com/), make sure that Marko is loaded with a `worker` [export condition](https://nodejs.org/api/packages.html#conditional-exports). Most bundlers support defining export conditions.\n\nAfter that point, imported `.marko` files will export a `.stream` method that returns a worker compatible [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream). You can then respond with that returned stream:\n\n```js\nimport Template from \"./index.marko\";\n\naddEventListener(\"fetch\", (event) => {\n  event.respondWith(handleRequest(event.request));\n});\n\nasync function handleRequest(request) {\n  return new Response(Template.stream(), {\n    headers: {\n      status: 200,\n      headers: { \"content-type\": \"text/html;charset=UTF-8\" },\n    },\n  });\n}\n```\n\n### BYOB (Bring your own bundler)\n\nFor the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.\nMarko supports a number of bundlers, [take a look through our supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) and pick what works best for you.\n","isInternal":false,"tokens":307,"sizeBytes":1366},{"name":"compiler.md","path":"packages/runtime-class/docs/compiler.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/compiler.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Compiler\n\n> **Note**:\n> This page documents the compiler for Marko 5. The [Compiler API reference](https://markojs.com/docs/reference/compiler) covers the current compiler, including the options Marko 6 adds.\n\n> **Warning**:\n> The compiler API and hooks are not terribly stable. They’re intended for advanced integrations or userland experimentation with new language features.\n>\n> Prefer existing official plugins and the standard tag library when possible.\n\n## Compile API\n\n> **Warning**:\n> The Compile API is intended for advanced integration with build tools, like Webpack and Rollup. Unless you’re doing that, you probably instead want [`build`/`serve` in the Marko CLI](https://github.com/marko-js/cli#readme), or one of [Marko’s bundler integrations](https://markojs.com/docs/bundler-integrations-overview/).\n\n### Compile Functions\n\nCompile functions take two arguments:\n\n1. A source Marko template\n2. [`CompileOptions`](#options)\n\nThen, they return a `CompileResult`:\n\n```ts\ntype CompileResult = {\n  code: string;\n  map?: SourceMap;\n  meta: Record<string, unknown>;\n};\n```\n\n- `code`: The compiled output of executable JavaScript code.\n- `map`: [A source map, used for debugging.](https://firefox-source-docs.mozilla.org/devtools-user/debugger/how_to/use_a_source_map/index.html)\n- `meta`: Metadata gathered while compiling — nothing terribly useful, probably going to get deprecated.\n  - Data about child dependencies. Was useful back when it was primarily the bundlers that handled tree-shaking out server components. Now that happens in the compiler, so we don’t use this anymore and therefore might become inaccurate in the future.\n  - A list of `watchFiles`: files that were used to compile the template (e.g. `marko.json`). Used to tell bundlers which files should be watched in dev mode.\n\n#### `compileFile()` and `compileFileSync`\n\n```ts\ncompiler.compileFile(filename: string, options?: CompileOptions): Promise<CompileResult>\ncompiler.compileFileSync(filename: string, options?: CompileOptions): CompileResult\n```\n\n`compileFile` and `compileFileSync` load `filename` from disk to use as a source template, then translate it into JavaScript.\n\n```js\nimport * as compiler from \"@marko/compiler\";\n\nconst asyncResult = await compiler.compileFile(\"./src/index.marko\", {\n  modules: \"cjs\",\n});\nconst syncResult = compiler.compileFileSync(\"./src/index.marko\", {\n  modules: \"cjs\",\n});\n```\n\n#### `compile()` and `compileSync()`\n\n```ts\ncompiler.compile(src: string, filename: string, options?: CompileOptions): Promise<CompileResult>\ncompiler.compileSync(src: string, filename: string, options?: CompileOptions): CompileResult\n```\n\n`compile` and `compileSync` accept source templates as a string, rather than loading from disk.\n\nThe `filename` location is used for resolving taglibs and imports, but does not have to be an actually existing file. <!-- TODO: should it be renamed to baseFile or importBase or something? -->\n\n```js\nimport * as compiler from \"@marko/compiler\";\n\nconst asyncResult = await compiler.compile(\n  \"<h1>Hello!</>\",\n  \"./src/index.marko\",\n  { modules: \"cjs\" },\n);\nconst syncResult = compiler.compileSync(\"<h1>Hello!</>\", \"./src/index.marko\", {\n  modules: \"cjs\",\n});\n```\n\n### Options\n\nThe compiler may be configured globally to change its default options:\n\n```js\nimport * as compiler from \"@marko/compiler\";\ncompiler.configure({ output: \"dom\" });\n```\n\nOr you can pass options objects when calling compile functions. Each property will override individual properties set by `configure()`:\n\n```js\nimport * as compiler from \"@marko/compiler\";\ncompiler.configure({\n  output: \"dom\",\n  sourceMaps: true,\n});\nconst result = compiler.compileFileSync(\"./example.marko\", {\n  output: \"html\",\n});\n```\n\nIn the above example, `result` would be compiled with the options of `{ output: \"html\", sourceMaps: true }`.\n\n#### `output`\n\nType: `string`<br>\nDefault: `\"html\"`\n\n- `\"html\"`: compiles templates to JavaScript that generates HTML strings for server HTTP responses, writing `.html` files, or maybe even constructing `Response`s in Web Workers.\n- `\"dom\"`: compiles templates to JavaScript that generates DOM nodes for client-side rendering in browsers.\n- `\"hydrate\"`: like `\"dom\"`, but only includes assets & components needed in-browser, assuming the page was rendered on the server.\n- `\"migrate\"`: only runs migrations (no transforms or translation) and returns the migrated template code.\n- `\"source\"`: parses templates without running any migrations or transforms. (Useful with `ast: true`)\n\n> **Note**:\n> For `dom` or `hydrate` outputs, you should also specify a [`resolveVirtualDependency`](#resolvevirtualdependency) function.\n\n#### `code`\n\nType: `boolean`<br>\nDefault: `true`\n\nIf `false`, will not generate or return the compiled `code` string.\n\n#### `ast`\n\nType: `boolean`<br>\nDefault: `false`\n\nIf `true`, the compiler will provide the `ast` in its output.\n\n#### `stripTypes`\n\nType: `boolean|undefined`<br>\nDefault: `undefined`\n\nIf `true`, removes all TypeScript types from the output.\nIf the value is `undefined` (the default), the compiler will remove types if the `output` option is not `source` or `migrate`.\n\nFor example, to run migrations _and_ strip types, you can set both `output: \"migrate\"` and `stripTypes: true`.\n\n#### `runtimeId`\n\nType: `string`<br>\nDefault: `undefined`\n\nOptionally use to override the runtime ID used to differentiate multiple copies of Marko on the same page, which is passed to `marko/components.init(runtimeId)` when compiling in the `hydrate` output.\n\n#### `writeVersionComment`\n\nType: `boolean`<br>\nDefault: `true`\n\nWhether the Marko version should be written to the template in a comment, like so:\n\n```js\n// Compiled using marko@x.x.x - DO NOT EDIT\n```\n\n#### `ignoreUnrecognizedTags`\n\nType: `boolean`<br>\nDefault: `false`\n\nWhether unrecognized tags should be silently ignored or throw a compile error. Ignored tags will be output as native elements.\n\n> **ProTip**:\n> Some test setups use this alongside `taglib.excludeDir` and `taglib.excludePackage` from `@marko/compiler` to simulate \"shallow\" rendering.\n\n#### `sourceMaps`\n\nType: `boolean` or `string`<br>\nDefault: `false`\n\nWhether source maps should be output with the compiled templates.\n\n- When `true` a `map` property will be available on the compile result.\n- When `\"inline\"` the sourcemap will be inlined as a comment in the output code.\n- When `\"both\"` both of the above will be used.\n\n#### `meta`\n\nType: `boolean`<br>\nDefault: `false`\n\n_Deprecated_. This option inlines the metadata in the output Javascript code. Metadata should be accessed instead from the `CompileResult`.\n\n#### `fileSystem`\n\nType: typeof [`fs`](https://nodejs.org/api/fs.html) (specifically read APIs)<br>\nDefault: Cached `fs`\n\nUse a different file system object (eg. webpack's [CachedInputFileSystem](https://github.com/webpack/enhanced-resolve/blob/f08fe3f1a22c90c722eca14b38a9300ad00c62e8/lib/CachedInputFileSystem.js) or [`arc-fs`](https://github.com/eBay/arc/tree/master/packages/arc-fs))\n\n#### `modules`\n\nType: `string` (`\"esm\"` or `\"cjs\"`)<br>\nDefault: `\"esm\"`\n\nBy default Marko outputs ES Modules. You can optionally specify `\"cjs\"` for CommonJS/`require()`.\n\n#### `optimize`\n\nType: `boolean`<br>\nDefault: [environment based](https://github.com/marko-js/marko/blob/0f212897d2d3ec30b12c2f18ba950818bccb83b4/packages/compiler/src/babel-plugin/index.js#L277-L284) (`false` in development, `true` in production)\n\nEnables production mode optimizations.\n\n#### `optimizeKnownTemplates`\n\nType: `string[]`<br>\nDefault: `undefined`\n\nIf `optimize` is enabled you can provide an array of template paths which the compiler will use to generate shorter registry/template ids using incrementing ids. This can only be used if the same `optimizeKnownTemplates` are used for both server and client compilations.\n\n#### `resolveVirtualDependency`\n\nType:\n\n```ts\n(\n  filename: string,\n  dep: {\n    code: string;\n    virtualPath: string;\n    map?: SourceMap;\n  },\n) => string;\n```\n\nDefault: `undefined`\n\nThis option should be set for `dom` or `hydrate` outputs. Since Marko templates can represent multiple output files (eg. JS renderer and CSS styles), a single source `.marko` file must be treated as potentially multiple virtual files.\n\nDifferent build tools have different mechanisms for handling virtual files. You should pass a function that returns a virtual path that can be handled by your build tool.\n\n##### Example based on `@marko/webpack/loader`:\n\n```js\n// lookup is shared between resolveVirtualDependency and markoLoader\nconst virtualSources = new Map();\n\nfunction resolveVirtualDependency(filename, { virtualPath, code, map }) {\n  const virtualFilename = `${filename}?virtual=${virtualPath}`;\n\n  // Add virtual source to the lookup to be later accessed by the loader\n  virtualSources.set(virtualFilename, { code, map });\n\n  // Generate the webpack path, from right to left...\n  // 1. Pass the virtualFilename so webpack can find the real file\n  //    located at sourceFilename, but the virtualPath is also present\n  //    (eg. \"./index.marko?virtual=./index.marko.css\")\n  // 2. Use an inline loader to run this file through @marko/webpack/loader\n  //    https://webpack.js.org/concepts/loaders/#inline\n  // 3. Use an inline matchResource to redefine this as the virtualPath\n  //    which allows the appropriate loaders to match the virtual dependency\n  //    https://webpack.js.org/api/loaders/#inline-matchresource\n  return `${virtualPath}!=!@marko/webpack/loader!${virtualFilename}`;\n}\n\nexport default function markoLoader(source) {\n  let code, map;\n\n  if (virtualSources.has(this.resource)) {\n    // If the resource has a ?virtual query param, we should\n    // find it in the lookup and then return the virtual code\n    // rather than performing the normal compilation\n    ({ code, map } = virtualSources.get(this.resource));\n    virtualSources.delete(this.resource);\n  } else {\n    // The default behavior is to compile the template in dom output mode\n    ({ code, map } = markoCompiler.compileSync(source, this.resourcePath, {\n      output: \"dom\",\n      resolveVirtualDependency,\n    }));\n  }\n\n  return this.callback(null, code, map);\n}\n```\n\n#### `hydrateIncludeImports`\n\nThis option is only used for `output: \"hydrate\"`. By default, `import`s in server-only files are not included in the hydrate output. However, for some assets, like stylesheets, it is useful to have them included in hydrate mode.\n\nThe `hydrateIncludeImports` option allows you to provide a function which receives an import path, or a regexp to match against that path which tells Marko to include that import in the hydrate mode output.\n\nThe default regexp includes a list of common known asset file extensions, and is as follows:\n\n```js\n/\\.(css(\\.[cm]?[jt]s)?|less|s[ac]ss|styl(us)?|p(ost)?css|sss|png|jpe?g|gif|svg|ico|webp|avif|mp4|webm|ogg|mp3|wav|flac|aac|woff2?|eot|ttf|otf)$/;\n```\n\nLooking at a partial Marko file such as:\n\n```marko\nimport \"./bar\"\nimport \"./foo.css\";\nimport \"./baz.wasm\";\n\n<div/>\n```\n\nFor `hydrate` output, with the default `hydrateIncludeImports`, would only cause `./foo.css` to be loaded in the browser.\n\n#### `hydrateInit`\n\nThis option is only used for `output: \"hydrate\"`. It defaults to `true` and causes the hydrate output to include code which tells the Marko runtime to begin hydrating any registered components.\n\nSetting to false will disable that `init` call and allow you to generate code which _just_ imports any hydrate dependencies for a template.\n\n#### `cache`\n\nType: typeof [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) (specifically, `.get()` is required)<br>\nDefault: `new Map()`\n\nCompiling a Marko template may require other (used) Marko templates to compile. To prevent compiling templates more than once, most of the compilation is cached.\n\nThe default cache strategy is to clear the cache each macrotask. If the default cache is overwritten, it is up to the user to determine when the cache is cleared.\n\n#### `babelConfig`\n\nType: see [babel options](https://babeljs.io/docs/en/options)<br>\nDefault: babel defaults, plus\n\n```js\n{\n  filename,\n  sourceType: \"module\",\n  sourceMaps: config.sourceMaps\n}\n```\n\n#### `translator`\n\nType: `{ analyze: Visitor, transform:Visitor }`<br>\nDefault: [autodiscovers](https://github.com/marko-js/marko/blob/0f212897d2d3ec30b12c2f18ba950818bccb83b4/packages/compiler/src/config.js#L46-L89) a translator package starting with `@marko/translator-` or `marko-translator-`\n\nThe translator is a collection of transforms that translates the Marko AST into a valid JavaScript AST based on the `output` option. There is a default translator in Marko, but this option may be used to switch to experimental translators for alternate runtimes.\n\nThe translator is an object with `analyze` and `transform` [Babel Visitors](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#visitors):\n\n- The result of the `analyze` visitor is cached and may be requested by other templates.\n- The `transform` visitor transforms the AST to its final JavaScript AST.\n\nSee [`@marko/translator-default`](https://github.com/marko-js/marko/blob/11a10f82cdb5389880e6deca5f77d17727acb831/packages/translator-default/src/index.js) for a reference implementation.\n\n## Hooks\n\n> **Note**:\n> These compiler hooks aren’t terribly stable either. Using hooks for one-time migrations, like a codemod, is the best-supported way to use the compiler hooks, since you won’t have to worry about the code changing underneath you in the future.\n\n![1. Parse (angle bracket source code) 2. Migrate (old Marko to new Marko) 3. Transform (objects to different objects) 4. Translate (Marko to JavaScript.)](./compiler-hooks.png)\n\nThe Marko compiler runs a series of stages to produce its final JavaScript output. These stages handle different steps of template processing, and can be tweaked, extended, and hooked into with [`marko.json` configuration files](./marko-json.md).\n\n- All compiler hooks must have a default export of a [Babel-style visitor function](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#toc-visitors), which will receive a [babel `NodePath`](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#paths) with a `MarkoTag` node.\n\n- Hooks will also receive a `types` object that matches the [`@babel/types`](https://babeljs.io/docs/en/babel-types) API extended with the [Marko AST types](#marko-ast). (You may also reference the types by importing `{ types } from \"@marko/compiler\"`.)\n\n- Hooks may alternatively export an `enter` function (alias of `default`), and optionally an `exit` function. These map to [`@babel/traverse`’s `enter` and `exit` methods](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#babel-traverse).\n\nHere is an example hook:\n\n```js\nexport default (tag, types) => {\n  if (types.isStringLiteral(tag.node.name)) {\n    console.log(`Found a tag called ${tag.node.name.value}`);\n    tag.remove();\n  }\n};\n```\n\n### Parse\n\nMarko compilation starts by converting the raw text of your Marko template into an [AST (Abstract Syntax Tree)](https://en.wikipedia.org/wiki/Abstract_syntax_tree) — an object representation of your code.\n\n```marko\n<h1>Hello!</h1>\n```\n\n…will roughly become:\n\n```json\n{\n  \"type\": \"MarkoTag\",\n  \"name\": {\n    \"type\": \"StringLiteral\",\n    \"value\": \"h1\"\n  },\n  \"body\": {\n    \"type\": \"MarkoTagBody\",\n    \"body\": [\n      {\n        \"type\": \"MarkoText\",\n        \"value\": \"Hello!\"\n      }\n    ]\n  }\n}\n```\n\nThis might look a bit verbose, but ASTs aim for completeness, not terseness.\n\nMarko parses in two steps to stay flexible with the ever-changing syntax of JavaScript:\n\n1. The first parsing pass happens in our [`htmljs-parser`](https://github.com/marko-js/htmljs-parser), which understands the HTML and HTML-like parts of your template.\n\n2. For JavaScript expressions, Marko defers to [`@babel/parser`](https://babeljs.io/docs/en/babel-parser). The resulting [Marko AST](#marko-ast) is a superset of what `@babel/parser` would return.\n\nTo hook into the `parse` stage, use [the `parse` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n> **Note**: The `parse` hook deviates from the other compiler hooks:\n>\n> - It does not support the `enter` & `exit` API.\n> - You _must return_ a replacement AST node.\n\n### Migrate\n\nThat’s right, Marko has _first-class_ support for migrations. The **migration stage** can translate outdated APIs into modern counterparts, leaving the rest of the compilation none the wiser.\n\nMigrations run automatically in the background, and can be written to disk when users are ready by running the [`@marko/migrate` CLI command](https://github.com/marko-js/cli/blob/master/packages/migrate/README.md).\n\nTo hook into the `migrate` stage, [use the `migrate` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n> **Note:**\n> To make the compiler stop at this point and output the migrated template, rather than continuing to produce the JavaScript output, [set `output: \"migrate\"`](#output) in the [compilation options](#options).\n\n### Transform\n\nThe **transform stage** is meant for userland transformations of Marko code into different Marko code. Think of it like [`babel.transform`](https://babeljs.io/docs/en/babel-core#transform) for Marko templates.\nAt this stage, you are given a fully parsed and migrated AST to do what you will with.\n\nTo hook into the `transform` stage, [use the `transform` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n### Analyze\n\nNext is the **analyze stage**, intended for non-mutative analysis of the entire AST in a way that can be cached in RAM.\n\n> **Note**:\n> “Non-mutative analysis” means that if you modify the AST during this stage, _you’ll probably regret it_ someday.\n\nMetadata should be stored on nodes’ `.extra` property. These `.extra` properties are typically read in [the translate stage](#translate), or when using the child template analysis helpers.\n\nTo hook into the `analyze` stage, [use the `analyze` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n### Translate\n\nFinally, we have the **translation stage**. This stage is Marko’s “Rosetta Stone”, and is responsible for turning your beautiful `.marko` code into different versions of optimized JavaScript you’d rather not write yourself.\n\nTo hook into the `translate` stage, [use the `translate` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n## Utilities\n\n[The `@marko/babel-utils` package](https://github.com/marko-js/marko/tree/master/packages/babel-utils/index.d.ts) exposes a handful of utilities for various tasks on [Marko ASTs](#marko-ast).\n\n### Marko AST\n\nMarko extends Babel’s AST types to add nodes for `MarkoTag`, `MarkoAttribute`, etc.\n\nFor AST creation and assertion utilities, you can import Marko’s `@babel/types` superset from the compiler package:\n\n```js\nimport { types } from \"@marko/compiler\";\n```\n\nThe [`@babel/types` documentation](https://babeljs.io/docs/en/babel-types) shows all utility methods available for Babel AST nodes. When importing `types` from `@marko/compiler`, you also get the same types of utilities for Marko nodes: `types.markoTag`, `types.isMarkoTag`, `types.assertMarkoTag`, and so on.\n\nFor full definitions, view the source code for Babel and Marko:\n\n- [Babel’s Core Definitions](https://github.com/babel/babel/blob/master/packages/babel-types/src/definitions/core.js)\n- [Babel’s Extended Definitions](https://github.com/babel/babel/tree/master/packages/babel-types/src/definitions)\n- [Marko’s Definitions](https://github.com/marko-js/marko/blob/main/packages/compiler/src/babel-types/types/definitions.js)\n","isInternal":false,"tokens":4823,"sizeBytes":19834},{"name":"concise.md","path":"packages/runtime-class/docs/concise.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/concise.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Concise syntax\n\nMarko's concise syntax is very similar to the HTML syntax, except it's more... concise. Essentially, you take an HTML tag, remove the angle brackets (`<>`) and use indentation rather than a closing tag:\n\n_input.marko_\n\n```marko\ndiv class=\"thumbnail\"\n    img src=\"https://example.com/thumb.png\"\n```\n\n_output.html_\n\n```html\n<div class=\"thumbnail\"><img src=\"https://example.com/thumb.png\" /></div>\n```\n\n## Shorthand attributes\n\nMarko provides a shorthand for declaring classes and ids on an element:\n\n_input.marko_\n\n```marko\ndiv.my-class\nspan#my-id\nbutton#submit.primary.large\n```\n\nYields this HTML:\n\n_output.html_\n\n```html\n<div class=\"my-class\"></div>\n<span id=\"my-id\"></span> <button id=\"submit\" class=\"primary large\"></button>\n```\n\n> **ProTip:** These shorthand attributes are available within the HTML syntax as well\n\n## Attributes on multiple lines\n\nIf a component has lots of attributes, you can spread them across multiple lines by surrounding them with square brackets\n\n_input.marko_\n\n```marko\ndiv [\n    id=\"hello\"\n    class=[\"class1\", \"class2\", \"class3\"]\n    style={ border: \"1px solid red\" }\n] -- hello\n```\n\n_output.html_\n\n```html\n<div id=\"hello\" class=\"class1 class2 class3\" style=\"border:1px solid red\">\n  hello\n</div>\n```\n\n## Text\n\nText in concise mode is denoted by two or more dashes (`--`).\n\nIf there is text on the same line following `--`, it is single-line text:\n\n_single-line-text.marko_\n\n```marko\n-- Hello world\n```\n\nThe dashes can also follow an element to give it a single text node as a child\n\n_single-line-text.marko_\n\n```marko\ndiv -- Hello world\n```\n\nIf there is a line break immediately following `--`, everything following the `--` at the current indentation is parsed as multi-line line text.\n\n_multi-line-text.marko_\n\n```marko\ndiv\n    --\n    Hello world\n    this text\n    is multi-line\n\ndiv\n    --\n    this is more\n    text\n```\n\nA multi-line text block can be ended by the same number of dashes that opened it. This allows it to have siblings:\n\n_multi-line-text.marko_\n\n```marko\ndiv\n    img src=\"https://example.com/photo.png\"\n    --\n    Hello world\n    this text\n    is multi-line\n    --\n    span -- text after\n```\n\n### Root level text\n\nThere is one \"gotcha\" that you need to be aware of. The Marko parser starts out in the concise mode. Therefore, given the following template:\n\n_input.marko_\n\n```marko\nHello World\nWelcome to Marko\n```\n\nThe output would be the following:\n\n_output.html_\n\n```html\n<Hello World></Hello> <Welcome to Marko></Welcome>\n```\n\nInstead, prefix the lines with `--` so they are parsed as text:\n\n_input.marko_\n\n```marko\n-- Hello World\n-- Welcome to Marko\n```\n","isInternal":false,"tokens":668,"sizeBytes":2627},{"name":"conditionals-and-lists.md","path":"packages/runtime-class/docs/conditionals-and-lists.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/conditionals-and-lists.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Conditionals and Lists\n\nWhile HTML itself does not support conditionally displaying elements or repeating elements, it is a critical part of building any web application. In Marko, this functionality is provided by the `<if>` and `<for>` tags.\n\n## Conditionals\n\nThe `<if>` tag receives an [argument](./syntax.md#arguments) which is used to determine if its body content should be present.\n\n```marko\n<if(user.loggedOut)>\n    <a href=\"/login\">Log in</a>\n</if>\n```\n\nAs you might expect, there are also `<else>` and `<else-if>` tags as well:\n\n```marko\n<if(user.loggedOut)>\n    <a href=\"/login\">Log in</a>\n</if>\n<else-if(!user.trappedForever)>\n    <a href=\"/logout\">Log out</a>\n</else-if>\n<else>\n    Hey ${user.name}!\n</else>\n```\n\n## Lists\n\nIf you have a list of data and need to represent it in the UI, the `<for>` tag is probably what you're looking for. The `<for>` tag passes each item and its index to its body as [parameters](./syntax.md#parameters).\n\n```marko\n<ul>\n    <for|color, index| of=colors>\n        <li>${index}: ${color}</li>\n    </for>\n</ul>\n```\n\nThe `<for>` tag actually support 3 different flavors:\n\n- [`<for|item, index, array| of=array>`](./core-tags.md#iterating-over-a-list) renders its body for each item of an array. It's similar to the JavaScript [`for...of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) loop.\n- [`<for|key, value| in=object>`](./core-tags.md#iterating-over-an-objects-properties) renders its body for each property in an object. It's similar to the JavaScript [`for...in`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in) loop.\n- [`<for|value| from=first to=last step=increment>`](./core-tags.md#iterating-between-a-range-of-numbers) renders its body for each value in between and including `from` and `to`.\n\n### Always set a `key`\n\nMarko automatically keeps your UI in sync with the state behind it, but one place where it needs a little extra help is repeated content. Specifying keys gives Marko a way to identify items in a list and keep track of which items have been changed, added, or removed.\n\nA key should be a string or number that uniquely identifies an item in the list and differentiates it from its siblings. The same key value should never be used twice! Often, you will use something like an `id` property.\n\n```marko\n<for|user| of=users>\n    <user-card key=user.id data=user/>\n</for>\n```\n\n> **ProTip:** If you have multiple tags underneath `<for>`, you can key only the first tag and that is enough to properly identify its siblings as well\n>\n> ```marko\n> <dl>\n>     <for|entry| of=entries>\n>         <!-- only the first tag needs a key -->\n>         <dt key=entry.id>${entry.word}</dt>\n>         <!-- This key can be omitted -->\n>         <dd>${entry.definition}</dd>\n>     </for>\n> </dl>\n> ```\n\n> **Note:** If a key is not set, Marko will use the index of an item as its key. However this only works perfectly if items are only ever added or removed at the end of a list. Here's an example where things break down: if we have a list of `[\"A\", \"B\", \"C\"]` and reverse the order, index keys would cause \"A\" to be transformed into \"C\" (and \"C\" into \"A\"), rather than just swapping them. Additionally if these components contained state, the new \"C\" would contain the state from the old \"A\" (and vice-versa). Be aware, stateful components include tags like the native `<input>` element. For this reason **it is always recommended to set a `key` on tags in a `<for>`.**\n","isInternal":false,"tokens":910,"sizeBytes":3503},{"name":"core-tags.md","path":"packages/runtime-class/docs/core-tags.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/core-tags.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Core tags and attributes\n\nMuch like [HTML has its own native tags](https://developer.mozilla.org/en-US/docs/Web/HTML/Element), Marko includes **core tags** and **global attributes** for declaratively building modern applications.\n\n## `<if>`, `<else-if>`, `<else>`\n\nLike the [equivalent JavaScript statements](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else), these tags render [conditional content](./conditionals-and-lists.md#conditionals):\n\n```marko\n<if(arriving)>\n  Hey there\n</if>\n<else-if(leaving)>\n  Bye now\n</else-if>\n<else>\n  What’s up?\n</else>\n```\n\nThey support any JavaScript expression in their [tag arguments](./syntax.md#arguments):\n\n```marko\n<if(Math.random() > 0.5)>\n  <p>50% chance to see this</p>\n</if>\n```\n\n## `<for>`\n\nThe `<for>` tag iterates over [arrays/array-likes](#iterating-over-a-list), [object properties](#iterating-over-an-objects-properties), and [ranges of numbers](#iterating-between-a-range-of-numbers).\n\n### Iterating over a list\n\nLike the [JavaScript `for...of` loop statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of), giving `<for>`’s `of` attribute a value will loop over that value as an array or iterable.\n\nThe current **item**, **index**, and the **iterating list** are provided as [tag parameters](./syntax.md#parameters):\n\n```marko\n$ const colors = [\"red\", \"green\", \"blue\"];\n<ol>\n  <for|color, index, colorList| of=colors>\n    <li value=index>${color}</li>\n  </for>\n</ol>\n```\n\nThe output HTML would be:\n\n```html\n<ol>\n  <li value=\"0\">red</li>\n  <li value=\"1\">green</li>\n  <li value=\"2\">blue</li>\n</ol>\n```\n\n> **Pro Tip**: `<for>`’s `of` attribute can loop over any iterable, just like JavaScript’s [`for...of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of). This includes strings, `NodeList`s, `Set`s… any object with zero-indexed numeric properties and a `.length`, basically.\n\n### Iterating over an object’s properties\n\nLike [JavaScript’s `for...in` loop statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in), giving `<for>` an object as its `in` attribute will loop over that object’s properties.\n\nThe current **property name** and **property value** are provided as [tag parameters](./syntax.md#parameters):\n\n```marko\n$ const settings = {\n  \"Dark Mode\": false,\n  \"Fullscreen\": true\n};\n\n<dl>\n  <for|name, enabled| in=settings>\n    <dt>${name}:</dt>\n    <dd>${enabled ? \"on\" : \"off\"}</dd>\n  </for>\n</dl>\n```\n\nThe output HTML would be:\n\n```html\n<dl>\n  <dt>Dark Mode:</dt>\n  <dd>off</dd>\n  <dt>Fullscreen:</dt>\n  <dd>on</dd>\n</dl>\n```\n\n### Iterating between a range of numbers\n\nThe final `<for>` variant loops between two numbers, by providing `from` and `to` attributes. The current number in the range will be provided as a [tag parameter](./syntax.md#parameters):\n\n```marko\n<ol type=\"I\">\n  <for|i| from=0 to=10>\n    <li value=i>${i}</li>\n  </for>\n</ol>\n```\n\nYou can also pass an optional `step` attribute, which defaults to 1 otherwise. `step` lets you increment by a specific amount:\n\n```marko\n<ol type=\"I\">\n  <for|i| from=0 to=10 step=2>\n    <li value=i>${i}</li>\n  </for>\n</ol>\n```\n\n…becomes:\n\n```marko\n<ol type=\"I\">\n  <li value=\"0\">0</li>\n  <li value=\"2\">2</li>\n  <li value=\"4\">4</li>\n  <li value=\"6\">6</li>\n  <li value=\"8\">8</li>\n  <li value=\"10\">10</li>\n</ol>\n```\n\n> **ProTip:** This syntax is for generating numbers from nothing. Don’t use it to iterate over an object, like so:\n>\n> ```marko\n> <!-- Inefficient code, do not copy -->\n> <ul>\n>   <for|i| from=0 to=(myArray.length - 1)>\n>     <li>${myArray[i]}</li>\n>   </for>\n> </ul>\n> ```\n>\n> Use [`<for of>`](#iterating-over-a-list) instead.\n\n## `<while>`\n\n> **Warning:** Using `<while>` is not recommended. Instead, replicate it with [an iterable and `<for>`](#iterating-over-a-list).\n>\n> In the future, Marko may restrict value mutation during rendering, for runtime optimizations.\n\nYou can repeat a chunk of markup _until a condition is met_ with the `while` tag:\n\n```marko\n$ let n = 0;\n\n<while(n < 4)>\n  <p>${n++}</p>\n</while>\n```\n\n…becomes:\n\n```html\n<p>0</p>\n<p>1</p>\n<p>2</p>\n<p>3</p>\n```\n\n## `<macro>`\n\nMacros create reusable markup fragments for later use in the same template they were defined in.\n\nThe `<macro>` tag defines a macro as a tag via the `name` attribute. For example, the following macro is registered as the `<greeting>` tag:\n\n```marko\n<macro name=\"greeting\">\n  <p>Welcome!</p>\n</macro>\n\n<greeting/>\n<greeting/>\n```\n\n…the output HTML would be:\n\n```html\n<p>Welcome!</p>\n<p>Welcome!</p>\n```\n\nMacros become more useful with [tag parameters](./syntax.md#parameters), allowing complex templates. In this next example, `<greeting>` can now receive `firstName` and `count` parameters from its parent:\n\n```marko\n<macro|{ firstName, count }| name=\"greeting\">\n  <p>Hello ${firstName}!\n    <output>You have ${count} new messages.</output>\n  </p>\n</macro>\n\n<greeting firstName=\"Frank\" count=20/>\n```\n\n…the output HTML would be:\n\n```html\n<p>\n  Hello Frank!\n  <output>You have 20 new messages.</output>\n</p>\n```\n\nMacros receive input like components do, including [a `renderBody` for provided body content](./body-content.md):\n\n```marko\n<macro|{ renderBody }| name=\"special-heading\">\n  <h1>\n    <${renderBody}/>!\n  </h1>\n</macro>\n\n<special-heading>\n  Hello\n</special-heading>\n```\n\n…the output HTML would be:\n\n```html\n<h1>Hello!</h1>\n```\n\n> **ProTip:** You can use a macro inside itself for recursive layouts, like displaying directory contents.\n\n## `<await>`\n\nThe `<await>` tag **renders markup asynchronously using a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)**.\n\n- Its `<@then>` [attribute tag](./syntax.md#attribute-tag) displays when the Promise _resolves_, optionally receiving the resolved value as a [tag parameter](./syntax.md#parameters).\n- Its `<@catch>` attribute tag displays when the Promise _rejects_, optionally receiving the rejected value as a tag parameter.\n- Its optional `<@placeholder>` attribute tag displays while the Promise is pending.\n\n```marko\n$ const personPromise = new Promise((resolve, reject) => {\n  setTimeout(() => resolve({ name: 'Frank' }), 1000);\n});\n\n<await(personPromise) client-reorder=true>\n  <@placeholder>\n    <!-- Displays while promise is pending -->\n    <label>Loading…\n      <progress></progress>\n    </label>\n  </@placeholder>\n\n  <@then|person|>\n    <!-- Displays if promise resolves -->\n    <p>Hello ${person.name}!</p>\n  </@then>\n\n  <@catch|err|>\n    <!-- Displays if promise rejects -->\n    ${err.name} error: ${err.message}\n  </@catch>\n</await>\n```\n\nOptional attributes for `<await>`:\n\n|        Attribute | Type    | Description                                                                                                                                                                   |\n| ---------------: | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n|        `timeout` | integer | An optional timeout. If reached, rejects the promise with a `TimeoutError`.                                                                                                   |\n|           `name` | string  | Improves debugging and ensures ordering with the `show-after` attribute.                                                                                                      |\n|     `show-after` | string  | Another `<await>` tag’s `name`. Use with `client-reorder` to ensure that the current `<await>` will always render alongside or after the named `<await>`.                     |\n| `client-reorder` | boolean | If true, anything after this `<await>` will be server-rendered before the Promise completes, then the fulfilled Promise’s result will be updated with client-side JavaScript. |\n\nRegardless of these attributes, the promise is executed as eagerly as possible. The attributes control how to coordinate rendering with the rest of the page:\n\n- `client-reorder` prevents `<await>` blocks from delaying the HTTP stream, at the expense of making their rendering rely on client-side JS. Useful for making non-critical page sections not block HTML streaming of important content.\n\n- Using `show-after` with `client-reorder` ensures that the current `<await>` block will always render simultaneously with or after the named `<await>`. Useful for cutting down on [layout shift](https://web.dev/debug-layout-shifts/). `<@placeholder>`s can help fine-tune the user experience while loading.\n\n- `timeout` is useful for limiting non-critical content from slowing down the rest of the page too much.\n\n> **Pro Tip**: When using `timeout`, you can distinguish between `TimeoutError`s and promise rejections by checking the error’s `name`:\n>\n> ```marko\n> <await(slowPromise) timeout=5000>\n>   <@then>Done</@then>\n>   <@catch|err|>\n>     <if(err.name === \"TimeoutError\")>\n>       Took too long to fetch the data!\n>     </if>\n>     <else>\n>       Promise failed with ${err.message}.\n>     </else>\n>   </@catch>\n> </await>\n> ```\n\n## `<include-text>`\n\n`<include-text>` inlines text files into a template, escaping HTML syntax characters (`<`, `\"`, etc.).\n\n```marko\n<include-text('./foo.txt')/>\n```\n\nIf you do not want escaping, use [`<include-html>`](#include-html) instead.\n\n## `<include-html>`\n\nLike `<include-text>`, `<include-html>` inlines the contents of a file. However, this tag **does _not_ escape** special HTML characters.\n\n```marko\n<include-html('./foo.html')/>\n```\n\n## `<html-comment>`\n\nMarko removes HTML comment tags from its output. But if you need comments in the output, that’s what `<html-comment>` is for:\n\n```marko\n<html-comment>[if IE]><script src=\"html-shiv.js\"></script><![endif]</html-comment>\n```\n\n…becomes:\n\n```html\n<!--[if IE]><script src=\"html-shiv.js\"></script><![endif]-->\n```\n","isInternal":false,"tokens":2527,"sizeBytes":9967},{"name":"custom-tags.md","path":"packages/runtime-class/docs/custom-tags.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/custom-tags.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Custom tags\n\nCustom tags allow you to break up your application UI into encapsulated, reusable components.\n\n## Your first custom tag\n\nLet's say we have a page with the following content:\n\n_page.marko_\n\n```marko\n<!doctype html>\n<html>\n<body>\n    <h1>Hello World!</h1>\n</body>\n</html>\n```\n\nHowever, this page is getting pretty complex and unmaintainable. Let's split out the content into a separate component. To do this, we'll create a `components/` folder and inside it a `hello.marko` file:\n\n_components/hello.marko_\n\n```marko\n<h1>Hello World!</h1>\n```\n\nMarko [automatically discovers](#how-tags-are-discovered) `.marko` files under a `components/` directory, so we can now use the `<hello>` tag in our page:\n\n_page.marko_\n\n```marko\n<!doctype html>\n<html>\n<body>\n    <hello/>\n</body>\n</html>\n```\n\nNow this `<hello>` tag can be used multiple times, and even on multiple pages. But what if we don't only want to say hello to the world? Let's pass some attributes.\n\n_page.marko_\n\n```marko\n<!doctype html>\n<html>\n<body>\n    <hello name=\"World\"/>\n</body>\n</html>\n```\n\nThe component will receive these attributes as `input`:\n\n_components/hello.marko_\n\n```marko\n<h1>Hello ${input.name}!</h1>\n```\n\nNice.\n\n## How tags are discovered\n\nMarko discovers components relative to the `.marko` file where a custom tag is used. From this file, Marko walks up directories until it finds a `components/` folder which contains a component matching the name of the custom tag. If it reaches the project root without finding anything, it will then check installed packages for the component.\n\nLet's take a look at an example directory structure to better understand this:\n\n```dir\ncomponents/\n    app-header.marko\n    app-footer.marko\npages/\n    about/\n        components/\n            team-members.marko\n        page.marko\n    home/\n        components/\n            home-banner.marko\n        page.marko\n```\n\nThe file `pages/home/page.marko` can use the following tags:\n\n- `<app-header>`\n- `<app-footer>`\n- `<home-banner>`\n\nAnd the file `pages/about/page.marko` can use the following tags:\n\n- `<app-header>`\n- `<app-footer>`\n- `<team-members>`\n\nThe home page can't see `<team-members>` and the about page can't see `<home-banner>`. By using nested `component/` directories, we've scoped our page-specific components to their respective pages.\n\n## Tag directories\n\nIn addition to a Marko template, the children of `components/` can be a directory with an `index.marko` template:\n\n```dir\ncomponents/\n    app-header/\n        index.marko\n        logo.png\n        style.css\n    app-footer/\n        index.marko\n```\n\nOr a directory with a template whose name matches its parent directory:\n\n```dir\ncomponents/\n    app-header/\n        app-header.marko\n        app-header.style.css\n        logo.png\n    app-footer/\n        app-footer.marko\n```\n\nThis allows you to create components that have other files associated with them and keep those files together in the directory structure.\n\n> **ProTip:**\n> You can take advantage of nested `components/` directories to create \"subcomponents\" that are only available to the component that contains them.\n>\n> ```dir\n> components/\n>     app-header/\n>         components/\n>             navigation.marko\n>             user-info.marko\n>         app-header.marko\n>     app-footer/\n>         app-footer.marko\n> ```\n\n## Using tags from npm\n\nTo use [tags from npm](https://www.npmjs.com/search?q=keywords%3Amarko%20components), ensure that the package is installed and listed in your `package.json` dependencies:\n\n```\nnpm install --save @marko-tags/match-media\n```\n\nMarko discovers tags from packages defined in your `package.json`, so you can start using them right away:\n\n```marko\n<div>\n    <match-media|{ mobile }| mobile=\"max-width:30em\">\n        <!-- nice -->\n    </match-media>\n</div>\n```\n\n## Publishing tags to npm\n\nWe saw above that tags from npm are automatically discovered. In order to make this work, your package must include a [`marko.json`](./marko-json.md) at the root.\n\n_marko.json_\n\n```json\n{\n  \"tags-dir\": \"./dist/components\"\n}\n```\n\nThis example file tells Marko to expose all components directly under the `dist/components/` directory to the application using your package.\n\nIf your components are written in TypeScript, publish the output of [`mtc`](https://github.com/marko-js/language-server/tree/main/packages/type-check). Editors and type checkers read components under `node_modules` as JavaScript, so consumers get their types from the `.d.marko` files it emits. See [TypeScript in Marko](./typescript.md).\n\nWe recommend adding the `marko` and `components` keywords to your `package.json` so others can find your components. Then `npm publish`!\n\n# Macros\n\nThe [`<macro>`](./core-tags.md#macro) tag allows you to create custom tags in the same file that they are used in.\n\n```marko\n<macro|{ name }| name=\"welcome-message\">\n    <h1>Hello ${name}!</h1>\n</macro>\n\n<welcome-message name=\"Patrick\"/>\n<welcome-message name=\"Austin\"/>\n```\n\n# From Variables\n\nIf no other tag would be discovered Marko will check for an in scope variable that matches the tag name.\n\n```marko\nimport SomeTag from \"./somewhere.marko\"\n\n$ const { renderBody } = input;\n$ const MyTag = input.href ? \"a\" : \"button\";\n\n<SomeTag/>\n<MyTag/>\n<renderBody/>\n```\n","isInternal":false,"tokens":1271,"sizeBytes":5249},{"name":"editor-plugins.md","path":"packages/runtime-class/docs/editor-plugins.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/editor-plugins.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Editor Plugins\n\n## Visual Studio Code\n\n[Documentation](https://marketplace.visualstudio.com/items?itemName=Marko-JS.marko-vscode)\n\n- Syntax highlighting\n- Tag matching\n- Tag, attribute and css autocompletion\n- Hyperclick (clickable tags and attributes)\n- Surfaces errors within the templates.\n- Prettyprinting ([marko-prettyprint](https://github.com/marko-js/marko-prettyprint) is used internally)\n\n## Atom\n\n[Documentation](https://atom.io/packages/language-marko)\n\n- Syntax highlighting\n- Tag matching\n- Tag and attribute autocompletion\n- Code snippets\n- Hyperclick (clickable tags and attributes)\n- Prettyprinting ([marko-prettyprint](https://github.com/marko-js/marko-prettyprint) is used internally)\n\n## Sublime\n\n[Documentation](https://github.com/merwan7/sublime-marko)\n\n- Syntax highlighting\n\n## WebStorm\n\n[Documentation](https://github.com/marko-js/marko-tmbundle)\n\n- Syntax highlighting\n\n## TextMate\n\n[Documentation](https://github.com/marko-js/marko-tmbundle)\n\n- Syntax highlighting\n\n## CodeMirror\n\n[codemirror-atom-modes](https://github.com/patrick-steele-idem/codemirror-atom-modes) + [atom-language-marko](https://github.com/marko-js/atom-language-marko)\n","isInternal":false,"tokens":291,"sizeBytes":1169},{"name":"events.md","path":"packages/runtime-class/docs/events.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/events.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Events\n\nMarko’s event API supports:\n\n- [Browser events](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Events) on native tags\n- Custom events from [custom tags](./custom-tags.md)\n\nNote that **you can’t mix event targets and event types**: custom tags can only listen for custom events, and native tags can only listen for native events.\n\n## Listening to events\n\nBoth kinds of events are received with an `on-*` attribute and the [attribute arguments syntax](./syntax.md#arguments):\n\n```marko\n<input type=\"checkbox\"\n  on-change(event => console.info(`Checked? ${event.target.checked}`))\n/>\n```\n\nThe [first argument for the attribute can be a function](#function-handler), or [a string matching a method name](#method-handler) on the [component’s `class` declaration](./class-components.md).\n\n### Function handler\n\nIf you provide a function as the first argument of the `on-*` attribute, the function is called whenever the event fires, like standard event listeners.\n\nBelow we use the [`static` prefix](./syntax.md#static-javascript) to define a function, then use it as a `click` handler:\n\n```marko\nstatic function handleClick(event) {\n  event.preventDefault();\n  console.log(\"Clicked!\");\n}\n\n<button on-click(handleClick)>\n  Log click\n</button>\n```\n\nIn the above example, any time the `<button>` is clicked the `handleClick` function is called.\n\nYou can also use an inline arrow function:\n\n```marko\n<button on-click(() => alert(\"Clicked! 🎉\"))>\n  Celebrate click\n</button>\n```\n\n…or anything that evaluates to a function:\n\n```marko\n$ const handler = (\n  input.dontBreakMyApp ?\n    () => console.error(\"Clicked!\") :\n    () => { throw Error(\"Clicked!\") }\n);\n\n<button on-click(handler)>\n  Do not click\n</button>\n```\n\n### Method handler\n\nWhen a string is the first argument, Marko calls a matching method on the component's `class`.\n\n```marko\nclass {\n  logChange(newTab) {\n    console.log(`changed to: ${newTab}`);\n  }\n}\n\n<my-tabs on-switch-tab(\"logChange\")>\n  …\n</my-tabs>\n```\n\nWhen `<my-tabs>` emits the `switch-tab` event, it will call its `logChange` method.\n\nWithin the handler you can access the current component instance, read data, emit events, update state, etc.\n\n### Binding additional arguments\n\nArguments after the handler are prepended when the handler is called:\n\n```marko\nstatic function removeFriend(friendId, event) {\n  event.preventDefault();\n  window.myAPI.unfriend(friendId);\n}\n\n<for|friend| of=input.friends>\n  <button on-click(removeFriend, friend.id)>\n    Unfriend ${friend.name}\n  </button>\n</for>\n```\n\nHere we share the logic for `removeFriend()` with each `friend` in the `friends` array. When the `<button>` is clicked, the `id` of the removed `friend` is passed to the `removeFriend()`, handler followed by the DOM `click` event.\n\n## Emitting custom events\n\nThe recommended way for a [custom tag](./custom-tags.md) to communicate with its parent is through **custom events**.\n\nAll components implement a [Node.js-style event emitter](https://nodejs.org/api/events.html#events_class_eventemitter) to send events to parent components.\n\n_email-input.marko_\n\n```marko\nclass {\n  handleChange(event) {\n    if (event.target.validity.valid) {\n      // Only emit email-changes if they are valid.\n      this.emit(\"email-change\", { email: event.target.value });\n    }\n  }\n}\n\n<input type=\"email\" name=input.name on-change(\"handleChange\")/>\n```\n\nThe above code listens to native `change` events from the `<input>` element, and then emits its own `email-change` event if the change was valid.\n\n```marko\n<form>\n  <email-input name=\"email\" on-email-change(\"...\")/>\n</form>\n```\n\n> **Note:** Events are not received as `input`; you cannot access `input.onEmailChange`. Instead, they set up subscriptions.\n","isInternal":false,"tokens":892,"sizeBytes":3749},{"name":"express.md","path":"packages/runtime-class/docs/express.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/express.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Marko + Express\n\n## Quick Start\n\n```sh\nnpm init marko -- --template vite-express\n# Or `npx create-marko --template vite-express`\n```\n\nSee [Marko’s example projects](https://github.com/marko-js/examples) for working [Express](https://expressjs.com/) integration code, such as:\n\n- [`examples/vite-express`](https://github.com/marko-js/examples/tree/master/examples/vite-express)\n- [`examples/rollup-express`](https://github.com/marko-js/examples/tree/master/examples/rollup-express)\n- [`examples/webpack-express`](https://github.com/marko-js/examples/tree/master/examples/webpack-express)\n\nBut if you want to do things the hard way…\n\n## Doing things the hard way\n\nFirst, install Marko, Express, and the glue to hold them together:\n\n```sh\nnpm install marko express @marko/express --save\n```\n\n### Skip the view engine\n\nExpress’s builtin view engine may be asynchronous, but it doesn’t support streaming — see [Rediscovering Progressive HTML Rendering](https://tech.ebayinc.com/engineering/async-fragments-rediscovering-progressive-html-rendering-with-marko/) for why that’s important. So instead, we [bypass Express’s view engine](https://strongloop.com/strongblog/bypassing-express-view-rendering-for-speed-and-modularity/) to use `@marko/express` instead.\n\n[The `@marko/express` package](https://www.npmjs.com/package/@marko/express) adds a `res.marko()` method to [Express’s response object](https://expressjs.com/en/api.html#res). This method works like [`res.render()`](https://expressjs.com/en/api.html#res.render), but without the restrictions of Express’s view engine, letting you take full advantage of Marko’s streaming and modular template organization.\n\n> **ProTip**: By using `res.marko()`, properties from [`app.locals`](https://expressjs.com/en/api.html#app.locals) and [`res.locals`](https://expressjs.com/en/api.html#res.locals) are automatically [available on `$global`](https://markojs.com/docs/rendering/#global-data).\n\n```js\nimport express from \"express\";\nimport markoPlugin from \"@marko/express\";\nimport template from \"./template.marko\";\n\nconst app = express();\napp.use(markoPlugin()); // Enables `res.marko(template, input)`\n\napp.get(\"/\", function (req, res) {\n  res.marko(template, {\n    name: \"Frank\",\n    count: 30,\n    colors: [\"red\", \"green\", \"blue\"],\n  });\n});\n\napp.listen(8080);\n```\n\n> **Note**: Older versions of `@marko/express` used to also attach Express’s `app`, `req`, and `res` objects onto `$global`. This meant uncontrolled network data could cause new and exciting surprises in your app code. Nowadays we recommend explicitly accessing the specific pieces of the HTTP exchange you’re interested in, like this:\n>\n> ```js\n> app.get(\"/\", function (req, res) {\n>   res.marko(template, {\n>     params: req.params,\n>     submitted: req.method === \"POST\" && req.body,\n>   });\n> });\n> ```\n\n### BYOB (Bring Your Own Bundler)\n\nMost of Marko’s API requires a bundler: the example code above assumes that `.marko` files can be `import`ed in your environment. [Check out Marko’s supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) to see what works best for you.\n","isInternal":false,"tokens":775,"sizeBytes":3141},{"name":"fastify.md","path":"packages/runtime-class/docs/fastify.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/fastify.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Marko + Fastify\n\n## Quick Start\n\n```terminal\nnpm init marko -- --template vite-fastify\n```\n\nSee the [the fastify sample](https://github.com/marko-js/examples/tree/master/examples/vite-fastify)\nproject for a working example.\n\n## From Scratch\n\nFirst install Marko and the fastify related dependencies:\n\n```terminal\nnpm install marko @marko/fastify fastify --save\n```\n\n### Usage\n\nThe [`@marko/fastify`](https://github.com/marko-js/fastify/) adds a `reply.marko` decorator to the `reply` object. This function allows us to pass in a Marko template and supports Marko's streaming and modular approach to templates.\n\nBy using `reply.marko` you'll automatically have access to `app.locals`, and `reply.locals` from within your Marko template and custom tags. These values are added to `$global`.\n\n```javascript\nimport fastify from \"fastify\";\nimport markoPlugin from \"@marko/fastify\";\nimport Template from \"./template.marko\";\n\nconst app = fastify();\n\napp.register(markoPlugin);\n\napp.get(\"/\", (request, reply) => {\n  // Streams Marko template into the response.\n  // Forwards errors into fa error handler.\n  reply.marko(Template, { hello: \"world\" });\n});\n\nawait fastify.listen(3000);\n```\n\n### Global Outputs\n\nWe can add global outputs from the server side using the reply object or fastify instance.\n\n```javascript\nreply.locals.newProperty = \"Your value\";\n```\n\nTo use this in marko components we just need to refer out.global\n\n```marko\n$ const { newProperty } = $global;\n```\n\nTo know more about sending the data to the browser checkout:\n\n### [Sending global data to browsers](https://markojs.com/docs/rendering/#sending-global-data-to-browsers)\n\n### BYOB (Bring your own bundler)\n\nFor the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.\nMarko supports a number of bundlers, [take a look through our supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) and pick what works best for you.\n","isInternal":false,"tokens":474,"sizeBytes":1994},{"name":"getting-started.md","path":"packages/runtime-class/docs/getting-started.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/getting-started.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Getting started\n\n## Setup\n\n### Marko Run (Recommended)\n\n[Marko Run](https://github.com/marko-js/run) makes it easy to get started with little to no config and is the recommended starting point for a new Marko project.\n\nTo set up your project:\n\n1. `npm init marko -- -t basic`\n2. `cd ./<PROJECT_NAME>`\n3. `npm run dev`\n\nOpen `src/routes/_index/+page.marko` in your editor to change the index page. See the [routing documentation](https://github.com/marko-js/run#file-based-routing) to learn how to add additional pages to your project.\n\n### Other setups\n\nIf you just want to test out Marko in your browser, use the [Try Online](https://markojs.com/try-online) feature. You can open it in another tab and follow along. For other setups, check out the [Installation](./installing.md) page.\n\n## Hello world\n\nMarko makes it easy to represent your UI using a [syntax](./syntax.md) that is like HTML:\n\n_hello.marko_\n\n```marko\n<h1>Hello World</h1>\n```\n\nIn fact, Marko is so much like HTML, that you can use it as a replacement for a templating language like handlebars, mustache, or pug:\n\n_template.marko_\n\n```marko\n<!doctype html>\n<html>\n<head>\n    <title>Hello World</title>\n</head>\n<body>\n    <h1>Hello World</h1>\n</body>\n</html>\n```\n\nHowever, Marko is much more than a templating language. It's a language that allows you to declaratively build an application by describing how the application view changes over time and in response to user actions.\n\nIn the browser, when the data representing your UI changes, Marko will automatically and efficiently update the DOM to reflect the changes.\n\n## A simple component\n\nLet's say we want to perform an action once a `<button>` is clicked:\n\n_button.marko_\n\n```marko\n<button>Click me!</button>\n```\n\nMarko makes this really easy, allowing you to define a `class` for a component right in the `.marko` view and call methods of that class with `on-` attributes:\n\n_button.marko_\n\n```marko\nclass {\n    sayHi() {\n        alert(\"Hi!\");\n    }\n}\n\n<button on-click(\"sayHi\")>Click me!</button>\n```\n\n### Adding state\n\nAlerting when a button is clicked is great, but what about updating your UI in response to an action? Marko's stateful components make this easy. All you need to do is set `this.state` from inside your component's class. This makes a new `state` variable available to your view. When a value in `this.state` is changed, the view will automatically re-render and only update the part of the DOM that changed.\n\n_counter.marko_\n\n```marko\nclass {\n    onCreate() {\n        this.state = {\n            count: 0\n        };\n    }\n    increment() {\n        this.state.count++;\n    }\n}\n\n<div>The current count is ${state.count}</div>\n<button on-click(\"increment\")>Click me!</button>\n```\n","isInternal":false,"tokens":671,"sizeBytes":2723},{"name":"http.md","path":"packages/runtime-class/docs/http.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/http.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Marko + HTTP Server\n\nSee the [the http sample](https://github.com/marko-js/examples/tree/master/examples/vite-http)\nproject for a working example.\n\n## Usage\n\n```js\nimport http from \"http\";\nimport Template from \"./index.marko\";\n\nconst port = 8080;\nconst server = http.createServer();\n\nserver.on(\"request\", (req, res) => {\n  Template.render(\n    {\n      name: \"Frank\",\n      count: 30,\n      colors: [\"red\", \"green\", \"blue\"],\n    },\n    res,\n  ).on(\"error\", (err) => {\n    // Without a listener, a render error crashes the process.\n    console.error(err);\n  });\n});\n\nserver.listen(port, () => {\n  console.log(`Successfully started server on port ${port}`);\n});\n```\n\n### BYOB (Bring your own bundler)\n\nFor the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.\nMarko supports a number of bundlers, [take a look through our supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) and pick what works best for you.\n","isInternal":false,"tokens":252,"sizeBytes":1021},{"name":"installing.md","path":"packages/runtime-class/docs/installing.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/installing.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Installation\n\n## Trying out Marko\n\nIf you just want to play around with Marko in the browser, head on over to our [Try Online](https://markojs.com/try-online) feature. You'll be able to develop a Marko application right in your browser.\n\n## Creating new apps (Recommended)\n\nIf you're starting from scratch, you can use Marko's [CLI](https://github.com/marko-js/cli) commands to quickly create a starter app:\n\n```bash\nnpm init marko\n```\n\nThis will use an interactive [CLI](https://github.com/marko-js/cli) to automatically create a project for you using the pre-made starter template of your choosing. The `basic` template is the most minimal and the easiest way to get started. It uses our recommended app framework [Marko Run](https://github.com/marko-js/run) that handles building, bundling, and serving your web application. These projects are config-free with built-in file based routing and automatic code reloading.\n\n## Custom Bundling\n\nMarko relies on JavaScript bundlers to package your code on both the client and the server. This is because Marko's client and server bundling works closely together to optimize the smallest client bundles and handle shared assets properly.\n\nUsing the CLI is still the easiest way to get started even when you want to get your hands dirty tweaking every last part of your config files. Marko currently supports Webpack, Lasso, and Rollup.\n\n### Webpack\n\n[Webpack Integration Docs](https://markojs.com/docs/webpack/)\n\n[Marko Webpack Plugin](https://github.com/marko-js/webpack)\n\n[Webpack Example](https://github.com/marko-js/examples/tree/master/examples/webpack-express)\n\nCLI Command: `npx @marko/create --template webpack-express`\n\n### Lasso\n\n[Lasso Integration Docs](https://markojs.com/docs/lasso/)\n\n[Marko Lasso Plugin](https://github.com/lasso-js/lasso-marko)\n\n[Lasso Example](https://github.com/marko-js/examples/tree/master/examples/lasso-express)\n\nCLI Command: `npx @marko/create --template lasso-express`\n\n### Rollup\n\n[Rollup Integration Docs](https://markojs.com/docs/rollup/)\n\n[Marko Rollup Plugin](https://github.com/marko-js/rollup)\n\n<!-- [Rollup Example](https://github.com/marko-js/examples/tree/master/examples/rollup)\n\nCLI Command: `npx @marko/create --template rollup` -->\n","isInternal":false,"tokens":532,"sizeBytes":2235},{"name":"koa.md","path":"packages/runtime-class/docs/koa.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/koa.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Marko + Koa\n\nSee the [the koa sample](https://github.com/marko-js/examples/tree/master/examples/vite-koa)\nproject for a working example.\n\n## Installation\n\n```terminal\nnpm install koa marko --save\n```\n\n## Usage\n\n```javascript\nimport Koa from \"koa\";\nimport Template from \"./index.marko\";\n\nconst app = new Koa();\n\napp.use((ctx, next) => {\n  ctx.type = \"html\";\n  ctx.body = Template.stream({\n    name: \"Frank\",\n    count: 30,\n    colors: [\"red\", \"green\", \"blue\"],\n  });\n});\n\napp.listen(8080);\n```\n\n### BYOB (Bring your own bundler)\n\nFor the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.\nMarko supports a number of bundlers, [take a look through our supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) and pick what works best for you.\n","isInternal":false,"tokens":223,"sizeBytes":851},{"name":"lasso.md","path":"packages/runtime-class/docs/lasso.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/lasso.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Marko + Lasso\n\nThe [lasso-marko](https://github.com/lasso-js/lasso-marko) plugin for [Lasso.js](https://github.com/lasso-js/lasso) will automatically compile all imported Marko templates during bundling. In addition, the `lasso-marko` plugin will automatically bundle any template dependencies (including required CSS).\n\nLasso.js provides Marko custom tags for injecting JavaScript and CSS bundles, images and other resources.\n\nThe sample [lasso-express](https://github.com/marko-js/examples/tree/master/examples/lasso-express) app demonstrates how to build a production-ready web application using Marko and Lasso. Run `npx @marko/create --template lasso-express` to use this sample as a starting point for a new app.\n\n## Installation\n\n```\nnpm install lasso-marko --save\n```\n\n## Registering the plugin\n\n```js\nrequire('lasso').configure({\n    \"plugins\": [\n        ...\n        \"lasso-marko\"\n    ]\n    ...\n});\n```\n\n## Lasso custom tags\n\nTo inject the required JavaScript and CSS into the page you will want to use the `<lasso-page>`, `<lasso-head>` and `<lasso-body>` tags.\n\nIf you are using lasso@^3 (latest), make sure to install the [lasso-marko-taglib](https://github.com/lasso-js/lasso-marko-taglib), so that you can use the lasso custom tags.\n\n```\nnpm install lasso-marko\nnpm install @lasso/marko-taglib\n```\n\nAfter installing, the lasso custom tags can be used in your templates:\n\n```html\n<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>Marko + Lasso</title>\n    <lasso-head />\n  </head>\n  <body>\n    <lasso-body />\n  </body>\n</html>\n```\n\nLasso.js will automatically bundle up transitive dependencies by building and walking a dependency graph.\n\n## Client-side rendering\n\nMarko templates can be imported and rendered by any JavaScript module. The code below shows how to render a top-level UI component and have it be mounted to the DOM as a child `document.body`:\n\n_client.js_\n\n<!-- prettier-ignore -->\n```js\nrequire(\"./components/app/index.marko\")\n  .renderSync({})\n  .appendTo(document.body);\n```\n\nWhen Lasso.js bundles up the code above it will automatically bundle up the required `./components/app/index.marko` file.\n\n## Server-side rendering\n\nIf you are rendering the initial UI on the server then it is necessary to make sure that all UI components are bundled and sent to the browser so that UI components can be mounted in the browser. For example:\n\n_about-me/index.marko_\n\n```marko\n<!DOCTYPE html>\n<html lang=\"en\">\n    <head>\n        <meta charset=\"UTF-8\">\n        <title>Marko + Lasso</title>\n\n        <!-- CSS will be inserted here -->\n        <lasso-head/>\n    </head>\n    <body>\n        <!-- Top-level UI component: -->\n        <app/>\n\n        <!-- JS will be inserted here -->\n        <lasso-body/>\n    </body>\n</html>\n```\n\n## Browser refresh\n\n[browser-refresh](https://github.com/patrick-steele-idem/browser-refresh) is recommended in development for instant page refreshes and hot reloading of Marko templates, styles and other resources. `browser-refresh` works well with Lasso and Marko and is very easy to use as a drop-in replacement for `node`:\n\n```bash\nbrowser-refresh server.js\n```\n\n## Lasso package types commonly used with Marko\n\nFor many use cases, the combination of `lasso-marko` and `@lasso/marko-taglib` is sufficient to render and bundle components without the need for explicit `browser.json` files. For more advanced use cases, the following bundle types may be defined in a `browser.json` for Lasso.\n\n#### `marko-dependencies` _(provided by `lasso-marko`)_\n\nIncludes all the dependencies needed by template and the code to register all components that would be rendered by the template. It does not automatically initialize the component, so is most useful if you need to initialize components manually.\n\n```json\n{\n  \"type\": \"marko-dependencies\",\n  \"path\": \"src/ui-modules/outdated-browser-banner/index.marko\"\n}\n```\n\n**Note:** To initialize the server rendered components, there are 2 steps:\n\n**Step 1:** Manually _retrieve_ server rendered components, shipped via `marko-dependencies`.\n\nTo retrieve the list of server rendered components, do:\n\n```javascript\ntemplate.render(data, (err, output) => {\n  const renderedComponentsList =\n    require(\"marko/components\").getRenderedComponents(output.out);\n  const html = output.getOutput();\n});\nres.json({\n  renderedComponentsList,\n  html,\n});\n```\n\n**Step 2:** Manually _initialize_ server rendered components, shipped via `marko-dependencies`.\n\nTo initialize the list of server rendered components, do:\n\n```javascript\n// from the response received, retrieve as\nrequire(\"marko/components\").init(response.renderedComponentsList);\n```\n\n**Note:** Ensure Step 2 is inside a DOM-ready wrapper, for the legacy widgets layer to load (if there are widgets built out of Marko 3, that is being used inside a Marko 4 component.)\n\n#### `marko-hydrate` _(provided by `lasso-marko`)_\n\nIncludes all the dependencies needed by template and the code to register all components that would be rendered by the template. This also includes the code to initialize the rendered components. Including this bundle on the page will automatically hydrate server rendered components.\n\n```json\n{\n  \"type\": \"marko-hydrate\",\n  \"path\": \"src/ui-modules/outdated-browser-banner/index.marko\"\n}\n```\n\n**Note:** `marko-hydrate` will initialize the component if its defined on the global `window.$components` which is inserted by `Marko` when it sees a `<body>` tag. Else, if you are just rendering out and lasso-ing the a portion of a page with a set of components, include `<init-components/>` at the end of the associated `template.marko` file that builds out the page fragment.\n\n#### `package`\n\nA collection of dependencies. `browser.json` is the most common package type.\nIt could be used to point to another `browser.json` from within one component's `browser.json`.\nTypically also used when the dependencies of the referred `browser.json` have to be packaged inline.\n\n```json\n{\n  \"type\": \"package\",\n  \"path\": \"src/ui-modules/show-diag/browser.json\"\n}\n```\n\n#### `require`\n\nIf a javascript file has to be wrapped over for its common JS syntax, to a browser understandable format.\n\n```json\n{\n  \"type\": \"require\",\n  \"path\": \"src/ui-modules/dynamic-module-loader/dynamic-init-client.js\"\n}\n```\n\n#### `require` and `run`\n\nIf a javascript file has to be wrapped over for its common JS syntax, to a browser understandable format and be executed immediately.\n\n```json\n{\n  \"run\": true,\n  \"type\": \"require\",\n  \"path\": \"src/ui-modules/my-module/init.js\"\n}\n```\n","isInternal":false,"tokens":1558,"sizeBytes":6535},{"name":"marko-5-upgrade.md","path":"packages/runtime-class/docs/marko-5-upgrade.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/marko-5-upgrade.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Upgrading to Marko 5\n\n## Step 0 - Ensure you're in a working state on the latest version of Marko 4\n\nBefore we start, you'll want to make sure that you are already on the latest `4.x` release of `marko`.\n\n```bash\n# Upgrade using yarn\nyarn upgrade marko@^4\n```\n\n```bash\n# Upgrade using npm\nnpm install marko@^4\n```\n\n> [!Warning]\n> Do _not_ run `npm install marko` (without the `@^4`). This will put you on Marko 5 and we're not quite there yet.\n\n> [!Tip]\n> If upgrading from Marko 3 you may want to reference [this guide](https://marko-v4.github.io/docs/marko-4-upgrade/).\n\nRun your application and tests to ensure your project is in a working state. There's little worse than finding an issue after you've started the upgrade process only to figure out the issue existed beforehand.\n\n## Step 1 - Upgrade Marko & Dependencies\n\n**TL;DR**: Paste & run this random shell script. It's safe. Trust us.\n\n```bash\n# Update Marko, and related ecosystem dependencies\nnpx -y npm-check-updates -u \\\n  marko \\\n  `# for webpack projects` \\\n  @marko/webpack \\\n  `# for lasso projects` \\\n  lasso lasso-marko @lasso/marko-taglib \\\n  `# for jest test runner` \\\n  @marko/jest \\\n  `# for projects with v3 widgets` \\\n  marko-widgets\n\n# Install @marko/compat-v4 unless `marko-widgets` is already installed\ngrep -q \"marko-widgets\" package.json || { [[ -f yarn.lock ]] && yarn add @marko/compat-v4 || npm install @marko/compat-v4; }\n[[ -f yarn.lock ]] && npx -y yarn-deduplicate && yarn\n[[ -f yarn.lock ]] || npm i\n```\n\nThis script automates the following steps for you:\n\n- Install the compat package\n  - `marko-widgets` if using Marko 3's Widgets\n  - `@marko/compat-v4` if not using Widgets\n- Update `marko` to 5.x\n- Update any ecosystem packages used by your app (lasso, webpack, jest, etc)\n\n> [!Note]\n> Check your `package.json`. If you have other third-party Marko packages not covered by the script, you may need to update them as well.\n\nYour application should continue to work. Run your tests to ensure everything is working. Congratulations! You've upgraded to Marko 5.\n","isInternal":false,"tokens":575,"sizeBytes":2055},{"name":"marko-json.md","path":"packages/runtime-class/docs/marko-json.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/marko-json.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# `marko.json` & `marko-tag.json`\n\nMarko supports configuration files for validation, enabling experimental features, and custom paths for component files.\n\nThese configuration files are automatically found with [the same discovery mechanism as custom tags](./custom-tags.md#how-tags-are-discovered).\n\nThere are 2 types of configuration files:\n\n1. `marko.json` describes an entire suite of components.\n2. `marko-tag.json` describes a single component.\n\n## Single component definition\n\n`marko-tag.json` configures a single component. It’s automatically discovered if placed inside a [tag directory](./custom-tags.md#tag-directories).\n\n### Options\n\n```js\n{\n  \"html\": true, // Treat as a native HTML tag, not a custom tag.\n  \"htmlType\": \"svg\", // Optimizes for specific types of native tags (currently only `svg` and `html`).\n  \"open-tag-only\": true, // Forbids passing body content to this tag.\n  \"featureFlags\": [ \"feature-a\" ], // Enable beta features by passing feature flags.\n  \"nested-tags\": { // This section configures attribute tags.\n    \"tab\": {\n      \"target-property\": \"tabs\", // Puts `<@tab>` tags into `input.tabs`.\n      \"is-repeated\": true,  // Allow more than one nested `<@tab>`.\n      \"attributes\": {\n        // Same as the “Attributes” section below.\n      }\n    }\n  }\n}\n```\n\n### Attributes\n\nOne commonly-used feature of this config file is compile-time checks for attributes.\n\n```js\n{\n  \"attributes\": {\n    \"heading\": \"string\"\n  }\n}\n```\n\nThe above code ensures that the `heading` attribute is the _only_ attribute supplied to this tag.\n\nThe `string` value is used as documentation for the custom tag. It may be picked up by tooling, like Marko’s editor plugins, to provide hints to the user.\n\nThe recommended list of attribute types are as follows:\n\n- `expression` (any JavaScript expression)\n- `string`\n- `number`\n- `boolean`\n- `regexp`\n- `date`\n- `object`\n- `array`\n- `function`\n\nYou can also provide an object for an attribute definition’s value for additional options:\n\n```js\n{\n  \"attributes\": {\n    \"heading\": {\n      \"type\": \"string\", // Same as setting \"string\" above.\n      \"default-value\": 0, // The attribute will default to this value.\n      \"required\": true, // Error during compilation if this attribute is undefined. (Mutually exclusive with \"default-value\"\n      \"preserve-name\": true, // By default component attributes are camelCased; this disables that feature.\n      \"remove-dashes\": true, // By default native tag attributes are dash-cased; this disables that feature.\n\n      // The following attributes do nothing, but are picked up by tooling.\n      \"deprecated\": true,\n      \"description\": \"The component’s heading text\" // Describes the attribute’s purpose.\n    }\n  }\n}\n```\n\nWe can also describe a _pattern_ of attributes to match a definition:\n\n```js\n{\n    \"attributes\": {\n        \"data-*\": {\n          \"type\": \"string\",\n          \"pattern\": true\n        }\n    }\n}\n```\n\nIn the above, all attributes prefixed with `data-` are configured to be a `string`.\n\n> **Note:** Future Marko versions will describe these definitions/types in the component itself, reducing the need for this configuration file.\n\n### Paths\n\nThere are several options that override the default discovery of component files, such as the template.\n\nTypically, you should let Marko find these files automatically, but here is a reference in case you encounter these settings in the wild.\n\n```javascript\n{\n  \"template\": \"./template.marko\", // Custom path to the `.marko` template.\n  \"renderer\": \"./renderer.js\", // Custom path to the `renderer.js` file.\n\n  // Compiler file hooks\n  \"parse\": \"./parse.js\", // Used to augment parsing.\n  \"migrate\": \"./migrate.js\", // Used for migrating deprecated features.\n  \"transform\": \"./transform.js\", // Used to modify the AST before generating it.\n  \"analyze\": \"./analyze.js\" // Used to analyze metadata the entire ast before beginning to translate it.\n  \"translate\": \"./translate.js\" // Used to generate custom JS.\n}\n```\n\nFor more information about the compiler hooks [jump over here](./compiler.md#hooks).\n\n## Tag library definition\n\nAlong with configuring a single component, you can use a `marko.json` file to configure an _entire library of components_.\n\nSimilar to [`marko-tag.json`](#single-component-definition), this file is discovered if placed within a [tag directory](./custom-tags.md#tag-directories). It will also be discovered at the root directory of a project, or [in a `node_module` package](./custom-tags.md#publishing-tags-to-npm).\n\n### Options\n\n```js\n{\n  \"taglib-id\": \"my-custom-tag-library\", // Names the component library, for better errors.\n  \"exports\": \"./dist\", // Where to export the compiled components.\n  \"tags-dir\": \"./ui-modules\", // What directory to crawl to autodiscover components. Default:`./components/`\n  \"taglib-imports\": [\"./some-folder/marko.json\", \"./other-folder/marko.json\"], // Creates a _combined_ tag library by referencing others.\n  \"script-lang\": \"ts\", // Overrides the default script language, \"js\" or \"ts\", for mixed code such as an incremental TypeScript migration.\n\n  \"tags\": { // Definitions for individual tags.\n    \"my-tag\": {\n      // Same options as “marko-tag.json”.\n    }\n  },\n\n  \"attributes\": {\n    // Defines attributes on all tags.\n    // Options are the same as the “attributes” section in “marko-tag.json”.\n  },\n\n  // Compiler file hooks (run on all templates)\n  \"migrator\": \"./migrator.js\", // Hooks into the migration stage for migrating deprecated features.\n  \"transformer\": \"./transformer.js\", // Used to modify the AST before generating it.\n  \"text-transformer\": \"./text-transformer.js\", // Used to transform all static text in the template.\n}\n```\n\n> **⚠️ Note:** Compiler hooks are currently undocumented: avoid using them. The compiler API is overhauled in Marko 5, and will be documented once that transition is complete.\n\n## Shorthands\n\nBoth configuration files support _shorthands_ for defining `tags` and `attributes`. For example, take this `marko.json` file:\n\n_marko.json_\n\n```js\n{\n  \"taglib-id\": \"my-custom-tag-library\",\n  \"tags\": {\n    \"my-layout\": {\n      \"attributes\": {\n        \"name\": \"string\",\n        \"age\": \"number\"\n      },\n      \"nested-tags\": {\n        \"heading\": {\n          \"attributes\": {\n            \"color\": \"string\"\n          }\n        },\n        \"body\": {\n          \"attributes\": {\n            \"color\": \"string\"\n          }\n        }\n      }\n    }\n  }\n}\n```\n\nAs a shorthand, anywhere `tags` or `nested-tags` is used, you can remove the outer object and wrap the individual tags in `<angle-brackets>`.\n\nFor `attributes`, you can remove the outer object and prefix the attributes with an `@`.\n\nThe above example using the shorthand syntax would become:\n\n_marko.json_\n\n```js\n{\n  \"taglib-id\": \"my-custom-tag-library\",\n  \"<my-layout>\": {\n    \"@name\": \"string\",\n    \"@age\": \"number\",\n    \"<heading>\": {\n      \"@color\": \"string\"\n    },\n    \"<body>\": {\n      \"@color\": \"string\"\n    }\n  }\n}\n```\n\nFor `nested-tags`, there is also a shorthand for `is-repeated` (a postfix of `[]`) and `target-property` (a prefix of `@newName`):\n\n_marko.json_\n\n```javascript\n{\n  \"<my-layout>\": {\n    \"@sections <section>[]\": {\n      \"@color\": \"string\"\n    }\n  }\n}\n```\n\nIs equivalent to:\n\n_marko.json_\n\n```javascript\n{\n  \"tags\": {\n    \"my-layout\": {\n      \"nested-tags\": {\n        \"section\": {\n          \"target-property\": \"sections\",\n          \"is-repeated\": true,\n          \"attributes\": {\n            \"color\": \"string\"\n          }\n        }\n      }\n    }\n  }\n}\n```\n","isInternal":false,"tokens":1804,"sizeBytes":7512},{"name":"marko-vs-react.md","path":"packages/runtime-class/docs/marko-vs-react.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/marko-vs-react.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Marko vs React: An In-depth Look\n\n<a href=\"https://hackernoon.com/marko-vs-react-an-in-depth-look-767de0a5f9a6\">\n  <img src=\"https://cdn-images-1.medium.com/max/2000/1*4BP6tPQtwImj6_QseeybwQ.png\" alt=\"Marko logo\" width=\"100%\" />\n</a><br />\n\n> This article was published March 2017. Both frameworks have gone through several updates since. You can find the original [\"Marko vs React: An In-depth Look\" article here](https://hackernoon.com/marko-vs-react-an-in-depth-look-767de0a5f9a6)!\n\nIn this article we will take an in-depth look at the differences and\nsimilarities between [Marko](https://markojs.com/) and React from the perspective\nof the maintainers of Marko.\n\nOn the surface, Marko and React have a lot in common and both are trying to\nsolve very similar problems. Specifically, both Marko and React allow developers\nto build web applications based on UI components and both free developers from\nhaving to write code to manually update the DOM. While many of the features in\nMarko were inspired by React, Marko and React offer very different usability and\nperformance characteristics. Marko was designed to avoid almost all boilerplate\nand is more closely aligned with HTML. In almost all cases, a Marko UI component\nwill require less lines of code than its React JSX equivalent while maintaining\nreadability and allowing the same expressiveness as JSX. In addition, Marko is\nhighly optimized for use on the server and in the browser and has a much smaller\nweight:\n\n<img src=\"https://cdn-images-1.medium.com/max/1600/1*a9hL_pfNrRq1UU3Mxkf3Jg.png\" alt=\"Marko logo\" width=\"100%\" /><br />\n\nBecause the Marko JavaScript library is much smaller than React, it will require\nless time to load and parse and this will drastically improve page load times on\nslow connections or on older devices. Based on [our\nbenchmarks](https://markojs.com/#benchmarks), Marko consistently outperforms\nReact by a significant margin on both the server and in the browser.\n\n### Example\n\nThe following code highlights some of the differences between Marko and React\nJSX using a somewhat contrived UI component as an example:\n\n#### React JSX\n\n```jsx\nclass Counter extends React.Component {\n  constructor(props) {\n    super(props);\n\n    this.state = { count: 0 };\n  }\n\n  increment(delta) {\n    this.setState({ count: this.state.count + delta });\n  }\n\n  render() {\n    const count = this.state.count;\n    let countClassName = \"count\";\n\n    if (count > 0) {\n      countClassName += \" positive\";\n    } else if (count < 0) {\n      countClassName += \" negative\";\n    }\n\n    return (\n      <div className=\"click-count\">\n        <div className={countClassName}>{count}</div>\n        <button\n          onClick={() => {\n            this.increment(-1);\n          }}\n        >\n          -1\n        </button>\n        <button\n          onClick={() => {\n            this.increment(1);\n          }}\n        >\n          +1\n        </button>\n      </div>\n    );\n  }\n}\n```\n\n<span class=\"figcaption_hack\">[▶ Try Online](https://codepen.io/mlrawlings/pen/wJXOWR?editors=0010)</span>\n\n#### Marko\n\n```marko\nclass {\n  onCreate() {\n    this.state = { count: 0 };\n  }\n  increment(delta) {\n    this.state.count += delta;\n  }\n}\n\n$ var count = state.count;\n\n<div.click-count>\n  <div.count class={\n      positive: count > 0,\n      negative: count < 0\n    }>\n    ${count}\n  </div>\n  <button on-click('increment', -1)>\n    -1\n  </button>\n  <button on-click('increment', 1)>\n    +1\n  </button>\n</div>\n```\n\n<span class=\"figcaption_hack\">[▶ Try\nOnline](https://markojs.com/try-online/?gist=8fe46bc5866605aca0dfeec202604011)</span>\n\n### Similarities\n\nMarko and React have the following in common:\n\n- UI component-based\n- JavaScript and HTML markup can be intertwined\n- No restrictions on JavaScript (use ES5 or ES2015+, your choice)\n- Virtual DOM rendering in the browser\n- DOM diffing/patching is used to reconcile views\n- Both support keyed element matching\n- UI components can have input properties\n- UI components can have internal state\n- Changes to state trigger an asynchronous update to the DOM\n- Updates to the DOM are batched\n- Compatible with central application state stores such as Redux and MobX\n- UI components can be embedded using custom tags\n- Declarative event binding (no `domEl.addEventListener()` needed)\n- Support for all DOM events\n- Event delegation utilized internally for DOM events that bubble\n- IE9+ support\n- Similar lifecycle events for UI components\n- JSX and Marko both compile to JavaScript\n\n### Differences\n\nAt a high level here are some differences:\n\n#### Differences in rendering\n\n- **Improved performance:** Marko renders to a virtual DOM in the browser and\n  directly to an HTML stream on the server (Marko supports multiple compilation\n  targets).\n- **Improved performance:** Marko supports asynchronous rendering with [early\n  flushing of\n  HTML](https://tech.ebayinc.com/engineering/async-fragments-rediscovering-progressive-html-rendering-with-marko/)\n  for improvements in actual and perceived page load times.\n- **Improved performance:** React requires an additional client-side re-render if\n  a page is initially rendered on the server while Marko does not.\n- **Improved ease of use:** Marko automatically serializes UI component state and\n  input down to the browser so that the browser can pick up right where the server\n  left off.\n- **Improved ease of use:** Marko is suitable for rendering an entire HTML page on\n  the server with support for tags such as `<doctype>` and `<html>`\n\n#### Differences in syntax\n\n- **Improved ease of use:** Marko uses the\n  [HTML-JS](https://markojs.com/docs/syntax/) syntax and the\n  [JSX](https://facebook.github.io/react/docs/jsx-in-depth.html) syntax is offered\n  for React.\n- **Improved ease of use:** Marko supports both a concise syntax and a familiar\n  HTML syntax.\n- **Improved ease of use:** JSX requires strict XML while Marko aligns with less\n  strict HTML that web developers are used to.\n- **Improved ease of use:** With Marko, _all_ HTML attribute values are parsed as\n  JavaScript expressions.\n- **Improved ease of use:** Marko supports simple directives for conditionals,\n  looping, etc.\n- **JSX limitation:** JSX is “just JavaScript” but requires expressions that\n  preclude the usage of JavaScript statements such as in certain places.\n\n#### Differences in compilation\n\n- **Improved performance:** Marko supports multiple compilation outputs (Marko\n  VDOM and HTML streaming are currently supported).\n- **Improved ease of use:** Marko compiles UI components to JavaScript modules\n  that export a rendering API.\n- **Expanded capabilities:** Marko supports a robust API for controlling how\n  custom tags and custom attributes get compiled and it supports compile-time\n  transforms based on a friendly Abstract Syntax Tree (AST).\n- **Improved performance:** JSX is just syntactic sugar that translates elements\n  to `createElement()` function calls while the Marko compiler has full control over how things are\n  compiled and optimized.\n- **Improved ease of use:** React requires all UI components to be explicitly\n  imported before they can be used as custom tags while Marko supports both\n  explicit importing and implicit importing.\n- **Improved performance:** Marko has a modular runtime and the compiler generates\n  code that only imports the parts of the Marko runtime that are needed for much\n  smaller builds.\n- **Improved ease of use:** Marko supports optional compile-time checks to ensure\n  that only allowed attributes are passed to custom tags. (React `PropTypes` only provide\n  validation at render-time)\n- **Improved ease of use:** Marko validates _all_ tag names at compile-time.\n- **Improved ease of use:** Marko provides its own compiler that integrates with\n  Node.js and JavaScript module bundlers while React JSX requires babel and custom\n  babel transforms.\n\n#### Differences in UI components\n\n- **Reduced boilerplate:** No explicit extending of JavaScript classes in Marko\n  (in contrast to `class Counter extends React.Component` in React).\n- **Improved ease of use:** Modifications to UI component state are synchronous\n  with Marko while [the rules for React are more\n  complicated](https://facebook.github.io/react/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous).\n- **Improved ease of use:** Marko watches UI component state objects to allow\n  state to be modified directly (e.g., `this.state.count++`).\n- **Improved ease of use:** Marko supports single-file UI components combining\n  JavaScript behavior, CSS styling (with support for CSS preprocessors) and HTML\n  markup. (React requires using one of the many [CSS in JS\n  solutions](https://github.com/MicheleBertoli/css-in-js) if you want styles in\n  the same file as your component and there is no standard in the community)\n- **Improved maintainability:** Marko supports a seamless transition from a\n  single-file UI component to a multi-file UI component.\n- **Improved performance:** Marko assumes UI components are pure by default and\n  skips re-rendering when input properties and state are unchanged (React requires\n  extending\n  [React.PureComponent](https://facebook.github.io/react/docs/react-api.html#react.purecomponent)).\n\n#### Differences in event systems\n\n- **Reduced complexity:** React utilizes [synthetic\n  events](https://facebook.github.io/react/docs/events.html) while Marko utilizes\n  real DOM events.\n- **Improved ease of use:** Custom events are emitted using the [EventEmitter\n  API](https://nodejs.org/api/events.html) in Marko (e.g., `this.emit('myCustomEvent', arg1, arg2)`).\n- **Improved ease of use:** Marko has a consistent approach for listening to both\n  native DOM events and custom events.\n- **Improved ease of use:** React requires passing around `Function` references for custom\n  events while Marko automatically delegates emitted custom events to event\n  handler methods on components.\n- **Improved ease of use:** Marko provides a simple mechanism for binding\n  additional arguments to event handler methods and `this` will be the component\n  instance.\n\n#### Differences in compatibility\n\n- **Marko limitation:** Marko has no support for native mobile similar to React\n  Native (although with Marko VDOM rendering, this is possible).\n- **Marko limitation:** Marko requires a JavaScript module bundler (such as\n  [Lasso](https://markojs.com/docs/lasso/),\n  [Webpack](https://markojs.com/docs/webpack/),\n  [Rollup](https://markojs.com/docs/rollup/)\n  since Marko UI components compile down to JavaScript modules. (we consider using\n  a JavaScript module bundler a best practice)\n\n---\n\nIn the sections below we will take a closer look at some of the differences\nbetween Marko and React.\n\n### Syntax\n\nBoth Marko and React JSX allow HTML markup and JavaScript to be combined into a\nsingle file and both support building web applications based on UI components.\nMarko utilizes an [HTML-JS syntax](https://markojs.com/docs/syntax/) while most\nReact apps use the JSX syntax.\n\n> React JSX makes JavaScript more like HTML and Marko makes HTML more like\n> JavaScript.\n\nIn the end, both Marko and React allow JavaScript and HTML to be intertwined.\n\n### Syntax: attributes\n\n#### React JSX\n\nIn React JSX, all attribute values are parsed as string values unless `{}` is used.\n\n```jsx\n<MyComponent\n  name=\"Frank\"\n  messageCount={30}\n  visible={true}\n  person={{ firstName: 'John', lastName: 'Doe' }}\n  colors={['red', 'green', 'blue']} />\n\n<div id=\"content\" className=\"foo\">Hello</div>\n```\n\n#### Marko\n\nWith Marko, _all_ attribute values are parsed as JavaScript expressions. The\nfollowing Marko code is equivalent to the React JSX code above:\n\n```marko\n<my-component\n  name=\"Frank\"\n  message-count=30\n  visible=true\n  person={ firstName: 'John', lastName: 'Doe' }\n  colors=['red', 'green', 'blue'] />\n\n<div id=\"content\" class=\"foo\">Hello</div>\n```\n\n### Syntax: inline JavaScript\n\n#### React JSX\n\nReact JSX starts with JavaScript and allows XML elements to be inlined as shown\nbelow:\n\n```jsx\nimport { formatDate } from \"./util\";\n\nfunction formatName(person) {\n  return person.firstName + \" \" + person.lastName.charAt(0) + \".\";\n}\n\nexport default function HelloMessage(props) {\n  var person = props.person;\n\n  return (\n    <div>\n      Hello {formatName(person)}!\n      <span>You were born on {formatDate(person.birthday)}.</span>\n    </div>\n  );\n}\n```\n\n#### Marko\n\nMarko starts out in HTML, but it allows JavaScript to be inlined in a clean and\nmaintainable way. Unlike other template languages, Marko aims to allow the full\npower of JavaScript. The following Marko code is equivalent to the React JSX\ncode above:\n\n```marko\nimport { formatDate } from './util';\n\nstatic function formatName(person) {\n    return person.firstName + ' ' + person.lastName.charAt(0) + '.';\n}\n\n$ var person = input.person;\n\n<div>\n    Hello ${formatName(person)}!\n    <span>\n      You were born on ${formatDate(person.birthday)}.\n    </span>\n</div>\n```\n\nLines prefixed with `$` are directly added to the compiled JavaScript output inside\nthe compiled `render()` function (for JavaScript code that should run for every render).\nLines prefixed with `static` are directly added to the compiled JavaScript output\noutside the `render()` function (for code that should only run _once_ when the template is\nloaded).\n\n### Syntax: HTML support\n\nWith Marko any valid HTML markup can be used inside a Marko template. This is\nnot the case with React. The following quote is from the [React\ndocumentation](https://facebook.github.io/react/docs/introducing-jsx.html#specifying-children-with-jsx):\n\n> **Caveat:**\n\n> Since JSX is closer to JavaScript than HTML, React DOM uses `camelCase` property naming\n> convention instead of HTML attribute names.\n\n> For example, `class` becomes `className` in JSX, and `tabindex` becomes `tabIndex`.\n\nAs a result of this caveat for React, [tools for converting HTML to JSX\nexist](https://magic.reactjs.net/htmltojsx.htm).\n\n#### React JSX\n\n```jsx\n<div id=\"content\" className=\"my-component\">Hello</div>\n\n<input type=\"text\" name=\"firstName\" value=\"John\" />\n```\n\n#### Marko\n\n```marko\n<div id=\"content\" class=\"my-component\">Hello</div>\n\n<input type=\"text\" name=\"firstName\" value=\"John\">\n```\n\n### Syntax: conditionals\n\nJSX is syntactic sugar on top of JavaScript, but it requires expressions, so\nsimple things like an `if/else/for` statement don’t work on their own within a JSX element. As\na result, you must either use a ternary expression, an immediately invoked\nfunction expression, function call expression, or the experimental `do {}` expression\n(stage 0 at the time of writing). This is not an issue for Marko, and tags\nsuch as `if()` and `for` can be used anywhere as shown below:\n\n#### React JSX\n\n```jsx\nfunction counterMessage(count) {\n  return (\n    <div className=\"counter-message\">\n      (function() {\n        if (count < 0) {\n          return <div>Count is negative</div>\n        } else if (count === 0) {\n          return <div>Count is zero</div>\n        } else {\n          return <div>Count is positive</div>\n        }\n      }())\n    </div>\n  )\n}\n```\n\n#### Marko\n\n```marko\n<div.counter-message>\n  <if(count < 0)>\n    <div>Count is negative</div>\n  </if>\n  <else if(count === 0)>\n    <div>Count is zero</div>\n  </else>\n  <else>\n    <div>Count is positive</div>\n  </else>\n</div>\n```\n\nMarko also allows directives to be used as attributes for a more condensed\ntemplate:\n\n```marko\n<div.counter-message>\n  <div if(count < 0)>Count is negative</div>\n  <div if(count === 0)>Count is zero</div>\n  <div else>Count is positive</div>\n</div>\n```\n\n### Syntax: looping\n\n#### React JSX\n\n```jsx\nfunction renderColors(colors) {\n  return (\n    <ul>\n      {colors.map((color) => (\n        <li\n          className=\"color\"\n          style={{\n            backgroundColor: color,\n          }}\n        >\n          {color}\n        </li>\n      ))}\n    </ul>\n  );\n}\n```\n\n#### Marko\n\n```marko\n<ul>\n  <for|color| of=colors>\n    <li.color style={ backgroundColor: color }>\n        ${color}\n    </li>\n  </for>\n</ul>\n```\n\n### Syntax: HTML shorthand\n\n```marko\n<div id=\"content\"/>\n<h1 class=\"subheader\"/>\n<h1 id=\"pageTitle\" class=\"foo bar\"/>\n\n<!-- Shorthand equivalent: -->\n<div#content/>\n<h1.subheader/>\n<h1#pageTitle.foo.bar/>\n```\n\nMarko supports a shorthand based on CSS selectors for less code.\n\nReact does not support these helpful shorthands.\n\n### Syntax: concise\n\nMarko supports a concise syntax that drops angled brackets and ending tags in\nfavor of indentation. Here’s how the Marko syntax options compare:\n\n#### Marko HTML syntax\n\n```marko\n<ul>\n  <for|color| of=colors>\n    <li>${color}</li>\n  </for>\n</ul>\n```\n\n#### Marko concise syntax\n\n```marko\nul\n  for|color| of=colors\n    li -- ${color}\n```\n\n#### Marko mixed syntax\n\n```marko\nul\n  for|color| of=colors\n    <li>${color}</li>\n```\n\nThe HTML syntax and the concise syntax can be used together:\n\n#### React JSX\n\nReact does not offer a concise syntax.\n\n### Components\n\nMarko starts with simple HTML and allows UI component logic to easily be layered\non top.\n\n#### React JSX\n\nA React UI component is typically implemented as a class that extends `ReactComponent`:\n\n```jsx\nclass HelloMessage extends React.Component {\n  render() {\n    return <div>Hello {this.props.name.toUpperCase()}</div>;\n  }\n}\n```\n\nReact also supports a more concise functional component:\n\n```jsx\nfunction HelloMessage(props) {\n  return <div>Hello {props.name.toUpperCase()}</div>;\n}\n```\n\nHowever, if state or lifecycle events are needed then a functional UI component\nmust be converted to a class component:\n\n```jsx\nclass HelloMessage extends React.Component {\n  componentDidMount() {\n    // ...\n  }\n  render() {\n    return <div>Hello {this.props.name.toUpperCase()}</div>;\n  }\n}\n```\n\n#### Marko\n\nHere is the same component in Marko:\n\n```marko\n<div>Hello ${input.name.toUpperCase()}</div>\n```\n\nBehavior can easily be added to any Marko UI component:\n\n```marko\nclass {\n  onMount() {\n    // ...\n  }\n}\n\n<div>Hello ${input.name.toUpperCase()}</div>\n```\n\nMarko also allows JavaScript behavior, CSS styling and HTML markup to be\nembedded in the Marko template as a single file UI component:\n\n```marko\nclass {\n  onMount() {\n    // ...\n  }\n}\n\nstyle.less {\n  .hello {\n    color: red;\n  }\n}\n\n<div.hello>\n  Hello ${input.name.toUpperCase()}\n</div>\n```\n\n### API\n\nMarko compiles components to JavaScript modules that export their rendering APIs,\nas shown below:\n\n```js\nimport Greeting from \"./components/greeting.marko\";\nGreeting.renderSync({ name: \"Frank\" }).appendTo(document.body);\n```\n\nThe same UI component can render to streams, such as a writable HTTP\nresponse stream:\n\n```js\nimport Greeting from \"./components/greeting.marko\";\nGreeting.render({ name: \"John\" }, res);\n```\n\n> The users of a Marko UI component do not need to know that the component was\n> implemented using Marko.\n\nContrast this with React as an example:\n\n```jsx\nimport ReactDOM from \"react-dom\";\n\nReactDOM.render(\n  <HelloMessage name=\"John\" />,\n  document.getElementById(\"container\"),\n);\n```\n\nOn top of that, React requires that a different module be imported to render the\nexact same UI component on the server:\n\n```jsx\nimport ReactDOMServer from \"react-dom/server\";\n\nvar html = ReactDOMServer.renderToString(<HelloMessage name=\"John\" />);\n```\n\n### Custom tags\n\n#### React JSX\n\nWith React, all custom tags for UI components must be explicitly imported:\n\n```jsx\nimport Hello from \"./components/Hello\";\nimport GoodBye from \"./components/GoodBye\";\n\nexport default function HelloGoodBye(props) {\n  return (\n    <div>\n      <Hello name={props.name} />\n      <GoodBye name={props.name} />\n    </div>\n  );\n}\n```\n\n#### Marko\n\nMarko supports a mechanism for [automatically discovering custom\ntags](https://markojs.com/docs/custom-tags/#discovering-tags) for UI components\nbased on the project directory structure. Marko walks up the directory tree to\ndiscover all directories and it will also automatically discover custom tags\nexported by installed packages. This approach negates the need for explicitly\nimporting a custom tag to reduce the amount of code needed in a Marko template.\nFor example given the following directory structure:\n\n```\n    .\n    ├── components/\n    │   ├── hello.marko\n    │   └── good-bye.marko\n    └── index.marko\n```\n\nThe `<hello>` tag and the `<good-bye>` tag nested below the `components/`\ndirectory will automatically be made available to the `index.marko` at the root:\n\n```marko\n<div>\n  <hello name=input.name />\n  <good-bye name=input.name />\n</div>\n```\n\nThis approach also allows editors and IDEs to offer autocompletion for custom\ntags.\n\n### Async\n\nEven after rendering has started, Marko allows parts of the view to be rendered\nasynchronously using the [`<await>`](https://markojs.com/docs/core-tags#await)\ntag as shown in the following Marko template:\n\n```marko\nimport fsp from 'fs-promise';\n\n$ var filePath = __dirname + '/hello.txt';\n$ var readPromise = fsp.readFile(filePath, {encoding: 'utf8'});\n\n<await(readPromise)>\n  <@then|helloText|>\n    <p>${helloText}</p>\n  </@then>\n</await>\n```\n\n### Compiler\n\nMarko compiles a template differently based on whether or not it will be used on\nthe server or in the browser. For example, given the following template:\n\n```marko\n<div>Hello ${input.name}!</div>\n```\n\n#### Compiled for the server:\n\n```js\nvar marko_template = require(\"marko/html\").t(__filename),\n  marko_helpers = require(\"marko/runtime/html/helpers\"),\n  marko_escapeXml = marko_helpers.x;\n\nfunction render(input, out) {\n  out.w(\"<div>Hello \" + marko_escapeXml(input.name) + \"!</div>\");\n}\n```\n\n#### Compiled for the browser:\n\n```js\nvar marko_template = require(\"marko/vdom\").t(__filename);\n\nfunction render(input, out) {\n  out.e(\"DIV\", null, 3).t(\"Hello \").t(input.name).t(\"!\");\n}\n```\n\n### Compile-time code transforms\n\nThe Marko compiler was built to support compile-time code generators for custom\ntags and it also provides support for compile-time transforms. While Babel\nallows code transformations of JavaScript, the Marko compiler provides support\nfor resolving custom tags declaratively and the Marko AST provides for very\npowerful and simple transformations as shown in the following code for rendering\nMarkdown to HTML at _compile-time_:\n\n**components/markdown/code-generator.js:**\n\n```js\nimport marked from \"marked\";\nimport { removeIndentation } from \"./util\";\n\nexport default function generateCode(el, codegen) {\n  var bodyText = removeIndentation(el.bodyText);\n  var html = marked(bodyText);\n  var builder = codegen.builder;\n  return builder.html(builder.literal(html));\n}\n```\n\nThe `<markdown>` tag can then be used as shown below:\n\n```marko\n<markdown>\n\n> This section demonstrates Markdown in Marko\n\n# Marko is awesome!\n\n- High performance\n- Small\n- Intuitive\n\n</markdown>\n```\n\nIn this example, after the template is compiled, the\n[marked](https://github.com/chjj/marked) library is no longer needed at\nrender-time.\n\n### Tools\n\nMarko and React offer a variety of developer tools. The [Marko developer\ntools](https://github.com/marko-js/marko-devtools) are constantly evolving, but\nMarko currently provides tools for unit testing UI components, precompiling `.marko`\nfiles and generating configuration-less apps (similar to\n[create-react-app](https://github.com/facebookincubator/create-react-app)).\nCurrently, there are no Marko developer tools that integrate with the browser,\nbut this is something we would like to see in the future. We will go into more\ndetail on the Marko developer tools in a future post.\n\n#### IDE and editor support\n\nMarko offers syntax highlighting across all major IDEs and editors, as well as\non GitHub. Marko provides first-class support for the Atom editor with syntax\nhighlighting,\n[Autocomplete](https://github.com/marko-js/atom-language-marko#autocomplete) for\nboth HTML and custom tags,\n[Hyperclick](https://github.com/marko-js/atom-language-marko#hyperclick) to\nquickly jump to referenced files and methods, and [Pretty\nprinting](https://github.com/marko-js/atom-language-marko#prettyprint) to keep\nyour code readable.\n\n---\n\n### Why Marko?\n\nHere are just a few reasons you should consider using\n[Marko](https://markojs.com/) over React:\n\n- Marko requires much less boilerplate.\n- Marko has much better performance based on our benchmarks.\n- Marko offers a clean and powerful syntax that aligns with HTML while also\n  allowing the full power of JavaScript.\n- Marko has much less complexity and a very small runtime.\n- Marko has a much lower page weight for faster page loads.\n- Marko has strong integrations with Node.js.\n- Marko allows for extremely powerful IDE and editor plugins (see the [Marko\n  plugin for Atom](https://github.com/marko-js/atom-language-marko) as an\n  example).\n- Marko has a powerful compiler that allows new features to be added without\n  introducing bloat.\n- eBay relies heavily on Marko and it is being used to build ebay.com (including\n  the mobile web).\n- Marko has a strong and growing community on\n  [GitHub](https://github.com/marko-js/marko) and in\n  [Discord](https://discord.gg/RFGxYGs).\n\nInterested in learning more about Marko? If so, you can get additional\ninformation on the [Marko website](https://markojs.com/). Join the conversation\nand contribute on [GitHub](https://github.com/marko-js/marko) and follow us on\n[Twitter](https://twitter.com/MarkoDevTeam).\n","isInternal":false,"tokens":6038,"sizeBytes":25246},{"name":"redux.md","path":"packages/runtime-class/docs/redux.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/redux.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Redux + Marko\n\nSee the [`marko-redux` sample project](https://github.com/marko-js/examples/tree/master/examples/redux) for a fully-working example.\n\n## Installation\n\nFirst, save the [`marko`](https://www.npmjs.com/package/marko) and [`redux`](https://www.npmjs.com/package/redux) packages to your project’s dependencies:\n\n```bash\nnpm i marko redux\n```\n\n## Usage\n\nThe partial code below shows how a Marko UI component can connect to a Redux store, using Redux’s `store.subscribe()` method and Marko’s `forceUpdate()` method:\n\n### `counter.marko`\n\n```marko\nimport store from './store.js';\n\nclass {\n  onMount () {\n    store.subscribe(() => {\n      // Force this UI component to rerender\n      this.forceUpdate();\n\n      // The UI component will rerender with the new\n      // state returned by `store.getState()`\n      //\n      // You could also force an update like this:\n      // this.input = store.getState();\n    });\n  }\n}\n\n<counter(store.getState()) />\n```\n\n### `reducer.js`\n\n```js\nexport default function (state, action) {\n  state = state || { value: 0 };\n\n  // Additional reducer logic here…\n\n  return state;\n}\n```\n\n### `store.js`\n\nIn `counter.marko`, the imported store module exports a Redux store created with the following code:\n\n```js\nimport redux from \"redux\";\nimport counter from \"./reducer.js\";\n\nexport default redux.createStore(counter);\n```\n","isInternal":false,"tokens":325,"sizeBytes":1365},{"name":"rendering.md","path":"packages/runtime-class/docs/rendering.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/rendering.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Rendering\n\nTo render a Marko view, you need to `import` it.\n\n_example.js_\n\n```js\nimport FancyButton from \"./components/fancy-button.marko\";\n```\n\n> **Note:** If you are targeting node.js, you will need to enable the [require extension](./installing.md#require-marko-views) in order to require `.marko` files or you will need to precompile all of your templates using [Marko CLI](https://github.com/marko-js/cli). If you are targeting the browser, you will need to use a bundler like [`lasso`](./lasso.md), [`webpack`](./webpack.md) or [`rollup`](./rollup.md).\n\nOnce you have a view, you can pass input data and render it:\n\n_example.js_\n\n```js\nimport FancyButton from \"./components/fancy-button.marko\";\nconst html = FancyButton.renderToString({ label: \"Click me!\" });\n\nconsole.log(html);\n```\n\nThe data passed to `renderToString` becomes available as `input` in the component, so if `fancy-button.marko` looked like this:\n\n_./components/fancy-button.marko_\n\n```marko\n<button>${input.label}</button>\n```\n\nThe output HTML would be:\n\n```html\n<button>Click me!</button>\n```\n\n## Rendering methods\n\nWe used the `renderToString` method above to render the view, but there are a number of different method signatures that can be used to render.\n\nMany of these methods return a [`RenderResult`](#renderresult) which is an object with helper methods for working with the rendered output.\n\n### `renderSync(input)`\n\n| params       | type                            | description                            |\n| ------------ | ------------------------------- | -------------------------------------- |\n| `input`      | `Object`                        | the input data used to render the view |\n| return value | [`RenderResult`](#renderresult) | The result of the render               |\n\nUsing `renderSync` forces the render to complete synchronously. If a tag attempts to run asynchronously, an error will be thrown.\n\n```js\nimport View from \"./view.marko\";\nvar result = View.renderSync({});\n\nresult.appendTo(document.body);\n```\n\n### `render(input)`\n\n| params       | type                             | description                            |\n| ------------ | -------------------------------- | -------------------------------------- |\n| `input`      | `Object`                         | the input data used to render the view |\n| return value | `AsyncStream`/`AsyncVDOMBuilder` | the async `out` render target          |\n\nThe `render` method returns an async `out` which is used to generate HTML on the server or a virtual DOM in the browser. In either case, the async `out` has a `then` method that follows the Promises/A+ spec, so it can be used as if it were a Promise. This promise resolves to a [`RenderResult`](#renderresult).\n\n```js\nimport View from \"./view.marko\";\nvar resultPromise = View.render({});\n\nresultPromise.then((result) => {\n  result.appendTo(document.body);\n});\n```\n\n### `render(input, callback)`\n\n| params         | type                             | description                                    |\n| -------------- | -------------------------------- | ---------------------------------------------- |\n| `input`        | `Object`                         | the input data used to render the view         |\n| `callback`     | `Function`                       | a function to call when the render is complete |\n| callback value | [`RenderResult`](#renderresult)  | The result of the render                       |\n| return value   | `AsyncStream`/`AsyncVDOMBuilder` | the async `out` render target                  |\n\n```js\nimport View from \"./view.marko\";\n\nView.render({}, (err, result) => {\n  result.appendTo(document.body);\n});\n```\n\n### `render(input, stream)`\n\n| params       | type                             | description                            |\n| ------------ | -------------------------------- | -------------------------------------- |\n| `input`      | `Object`                         | the input data used to render the view |\n| `stream`     | `WritableStream`                 | a writeable stream                     |\n| return value | `AsyncStream`/`AsyncVDOMBuilder` | the async `out` render target          |\n\nThe HTML output is written to the passed `stream`. Render errors are emitted as `\"error\"` events on the stream, and like any unhandled stream `\"error\"` event, one without a listener crashes the process, so always attach one:\n\n```js\nimport http from \"http\";\nimport View from \"./view.marko\";\n\nhttp.createServer((req, res) => {\n  res.setHeader(\"content-type\", \"text/html\");\n  View.render({}, res).on(\"error\", (err) => {\n    console.error(err);\n  });\n});\n```\n\n### `render(input, out)`\n\n| params       | type                             | description                            |\n| ------------ | -------------------------------- | -------------------------------------- |\n| `input`      | `Object`                         | the input data used to render the view |\n| `out`        | `AsyncStream`/`AsyncVDOMBuilder` | The async `out` to render to           |\n| return value | `AsyncStream`/`AsyncVDOMBuilder` | The `out` that was passed              |\n\nThe `render` method also allows passing an existing async `out`. If you do this, `render` will not automatically end the async `out` (this allows rendering a view in the middle of another view). If the async `out` won't be ended by other means, you are responsible for ending it.\n\n```js\nimport View from \"./view.marko\";\nvar out = View.createOut();\n\nView.render({}, out);\n\nout.on(\"finish\", () => {\n  console.log(out.getOutput());\n});\n\nout.end();\n```\n\n### `renderToString(input)`\n\n| params       | type     | description                            |\n| ------------ | -------- | -------------------------------------- |\n| `input`      | `Object` | the input data used to render the view |\n| return value | `String` | The HTML string produced by the render |\n\nReturns an HTML string and forces the render to complete synchronously. If a tag attempts to run asynchronously, an error will be thrown.\n\n```js\nimport View from \"./view.marko\";\nvar html = View.renderToString({});\n\ndocument.body.innerHTML = html;\n```\n\n### `renderToString(input, callback)`\n\n| params         | type        | description                            |\n| -------------- | ----------- | -------------------------------------- |\n| `input`        | `Object`    | the input data used to render the view |\n| callback value | `String`    | The HTML string produced by the render |\n| return value   | `undefined` | N/A                                    |\n\nAn HTML string is passed to the callback.\n\n```js\nimport View from \"./view.marko\";\n\nView.renderToString({}, (err, html) => {\n  document.body.innerHTML = html;\n});\n```\n\n### `stream(input)`\n\nThe `stream` method returns a Node.js-style stream of the output HTML.\n\n```js\nimport fs from \"fs\";\nimport View from \"./view.marko\";\nconst writeStream = fs.createWriteStream(\"output.html\");\n\nView.stream({}).pipe(writeStream);\n```\n\nThis method is available on the server, but not available by default in the browser. If you need to use streams in the browser, you may `import 'marko/stream'` as part of your client-side bundle.\n\n## RenderResult\n\n### `getComponent()`\n\n### `getComponents(selector)`\n\n### `afterInsert(doc)`\n\n### `getNode(doc)`\n\n### `getOutput()`\n\n### `appendTo(targetEl)`\n\n### `insertAfter(targetEl)`\n\n### `insertBefore(targetEl)`\n\n### `prependTo(targetEl)`\n\n### `replace(targetEl)`\n\n### `replaceChildrenOf(targetEl)`\n\n## Global data\n\nIf you need to make data available to all rendered views, use the `$global` property on the input data object. This property will be removed from `input` and provided to the template through a variable called `$global`. It is also made available on the `out.global` property.\n\nGlobal values persist across renders.\n\n```js\nView.render({\n  $global: {\n    flags: [\"mobile\"],\n  },\n});\n```\n\nWithin the template you can access `$global` similar to accessing `input`.\n\n```marko\n<div>\n  You are on ${$global.flags.includes(\"mobile\") ? \"mobile\" : \"desktop\"}\n</div>\n```\n\n> **Note:** `$global` is not available within [`static`](./syntax.md#static-javascript) parts of the template. In order to reference `$global` within the component class you must use `out.global` from one of the lifecycle methods that provide it.\n\n> **Warning:** Use `$global` with caution; it is visible in any component.\n\n### Sending global data to browsers\n\n⚠️ To prevent accidentally exposing sensitive data, by default **no keys** in `$global` are sent to browsers. To serialize data to the frontend, name the desired properties in `$global.serializedGlobals`.\n\nValues must be serializable by [the `warp10` module](https://www.npmjs.com/package/warp10).\n\n```js\nimport Page from \"./index.marko\";\n\napp.get(\"/\", (req, res) => {\n  const ua = req.get(\"User-Agent\");\n\n  Page.render(\n    {\n      $global: {\n        isIos: /iPad|iPhone/.test(ua), // Serialized and available on the server and browser as `$global.isIos`\n        isAndroid: /Android/.test(ua), // Serialized and available on the server and browser as `$global.isAndroid`\n        req, // Only available server-side and not serialized, because it’s not in `serializedGlobals`\n\n        serializedGlobals: {\n          isIos: true, // Tell Marko to serialize `isIos`\n          isAndroid: true, // Tell Marko to serialize `isAndroid`\n        },\n      },\n    },\n    res,\n  );\n});\n```\n\n> **Warning:** Ensure that you serialize only data which is necessary for the browser. Serialization is expensive for both server rendering performance and HTML output size.\n\nFor details, check [#672: “Serialize only input and state on top-level server-rendered UI components”](https://github.com/marko-js/marko/pull/672).\n","isInternal":false,"tokens":2136,"sizeBytes":9672},{"name":"rollup.md","path":"packages/runtime-class/docs/rollup.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/rollup.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Marko + Rollup\n\nThis is Marko’s official integration plugin for [the Rollup bundler](https://rollupjs.org/).\n\n## Installation\n\n```sh\nnpm install --save-dev \\\n  @marko/rollup \\\n  rollup \\\n  @rollup/plugin-node-resolve \\\n  @rollup/plugin-commonjs\n```\n\n> **Note**: The Marko runtime is CommonJS, so don’t forget the `@rollup/plugin-commonjs` package!\n\n## Configuration\n\n`@marko/rollup` exports two methods for use in [Rollup configuration files](https://rollupjs.org/guide/en/#configuration-files): `.browser()` and `.server()`.\n\nYou _probably_ want to use both, since that’ll get you…\n\n- Automatic [`input` entrypoint configuration](https://rollupjs.org/guide/en/#input) for route-based bundle splitting\n- Complete control over asset loading with [the `<rollup>` tag](#rollup-tag)\n- The strengths behind why Marko exists in the first place: cooperation between servers and browsers for high performance in both\n\n> **ProTip**: You _could_ use only `.browser()` or only `.server()` to build a completely client-side-rendered or server-side-rendered app. That would be a little odd, but you could.\n\n### Config example\n\n```js\nimport nodeResolve from \"@rollup/plugin-node-resolve\";\nimport commonjs from \"@rollup/plugin-commonjs\";\nimport marko from \"@marko/rollup\";\n\nconst sharedPlugins = [\n  commonjs({\n    extensions: [\".js\", \".marko\"]\n  }),\n  // If using Marko’s `style {}` blocks, you’ll need an appropriate plugin, like npmjs.com/rollup-plugin-postcss\n  postcss({ external: true })\n]\n\nconst serverAssetsConfig = {\n  input: \"src/start-server.js\",\n  plugins: [\n    marko.server(),\n    nodeResolve({ preferBuiltins: true })\n    ...sharedPlugins\n  ]\n};\nconst browsersAssetsConfig = {\n  plugins: [\n    marko.browser(),\n    nodeResolve({ browser: true })\n    ...sharedPlugins\n  ]\n};\n\nexport default [serverAssetsConfig, browsersAssetsConfig];\n```\n\n### Advanced config example\n\nThe following configuration file is long and hairy, which may be upsetting to some viewers. However, it does show how to accomplish the following:\n\n- Support for Rollup’s watch mode\n- A bundle analyzer\n- The ability to `import` JSON files to use their data\n- The ability to `import` image files to use their asset URLs for `img[src]` and such\n- Dead-code elimination for development-only code\n- Static compression of assets for something like [NGiNX’s `gzip_static`](https://nginx.org/en/docs/http/ngx_http_gzip_static_module.html)\n- A CSS preprocessor (Sass, in this case)\n- Browserslist to automatically configure:\n  - Babel for JS transpilation\n  - Autoprefixer for CSS transpilation\n\n<details><summary>Big ugly production-esque Rollup config</summary>\n\n```js\nimport { builtinModules } from \"module\";\nimport path from \"path\";\nimport autoprefixer from \"autoprefixer\";\nimport babelPlugin from \"@rollup/plugin-babel\";\nimport commonjsPlugin from \"@rollup/plugin-commonjs\";\nimport jsonPlugin from \"@rollup/plugin-json\";\nimport markoPlugin from \"@marko/rollup\";\nimport nodeResolvePlugin from \"@rollup/plugin-node-resolve\";\nimport replacePlugin from \"@rollup/plugin-replace\";\nimport runPlugin from \"@rollup/plugin-run\";\nimport stylesPlugin from \"rollup-plugin-styles\";\nimport urlPlugin from \"@rollup/plugin-url\";\nimport pkg from \"./package.json\";\n\nconst __DEV__ = process.env.NODE_ENV === \"development\";\nconst __PROD__ = !__DEV__;\n\nconst isWatch = Boolean(process.env.ROLLUP_WATCH);\n\nconst publicPath = \"/s/\"; // Guess what character is only 5 bits under HPACK\nconst assetFileNames = \"[name]-[hash][extname]\";\n\nconst externalDependencies = [\n  ...Object.keys(pkg.dependencies),\n  ...builtinModules,\n];\n\nprocess.env.SASS_PATH = \"./:./node_modules\";\n\nexport default (async () => [\n  compiler(\"server\", {\n    input: \"index.js\",\n    output: {\n      dir: \"built/server/\",\n      assetFileNames: `../browser/${assetFileNames}`,\n      format: \"cjs\",\n      sourcemap: true,\n    },\n    external: (id) =>\n      externalDependencies.some(\n        (dependency) => id === dependency || id.startsWith(dependency + \"/\"),\n      ),\n    plugins: [isWatch && runPlugin({ execArgv: [\"--enable-source-maps\"] })],\n  }),\n\n  compiler(\"browser\", {\n    output: {\n      dir: \"built/browser/\",\n      chunkFileNames: __PROD__ ? \"[name]-[hash].js\" : null,\n      entryFileNames: __PROD__ ? \"[name]-[hash].js\" : null,\n      assetFileNames,\n      sourcemap: true,\n      sourcemapExcludeSources: __PROD__,\n    },\n    plugins: [\n      stylesPlugin({\n        mode: \"extract\",\n        sourceMap: true,\n        config: {\n          target: \"browserslist:css\",\n          plugins: [autoprefixer({ env: \"css\" })],\n        },\n        minimize: __PROD__,\n        url: {\n          publicPath,\n          hash: assetFileNames,\n        },\n      }),\n      __PROD__ && (await import(\"rollup-plugin-terser\")).terser(),\n      __PROD__ &&\n        (await import(\"rollup-plugin-gzip\")).default({\n          filter: /\\.(?:js|css|svg|json|xml|txt)$/,\n          minSize: 1024,\n          gzipOptions: {\n            level: 9,\n            memLevel: 9,\n          },\n        }),\n      __PROD__ &&\n        !isWatch &&\n        (await import(\"rollup-plugin-visualizer\")).default(),\n      __PROD__ &&\n        !isWatch && {\n          name: \"bundle-visualizer-location\",\n          writeBundle() {\n            console.info(\n              `📊 Bundle visualizer at \\x1b[4;36mfile://${path.join(\n                __dirname,\n                \"../../\",\n                bundleAnalyzerFilename,\n              )}\\x1b[0m`,\n            );\n          },\n        },\n    ],\n  }),\n])();\n\nfunction compiler(target, config) {\n  const isBrowser = target === \"browser\";\n  const browserslistEnv = isBrowser ? \"js\" : \"server\";\n  const babelConfig = {\n    comments: false,\n    browserslistEnv,\n    compact: false,\n    babelrc: false,\n    caller: { target },\n  };\n  if (isBrowser) {\n    babelConfig.presets = [\n      [\n        \"@babel/preset-env\",\n        {\n          browserslistEnv,\n          bugfixes: true,\n        },\n      ],\n    ];\n  }\n\n  return {\n    ...config,\n    preserveEntrySignatures: false,\n    plugins: [\n      markoPlugin[target]({ babelConfig }),\n      nodeResolvePlugin({\n        browser: isBrowser,\n        preferBuiltins: !isBrowser,\n      }),\n      commonjsPlugin(),\n      replacePlugin({\n        preventAssignment: true,\n        values: { __DEV__, __PROD__ },\n      }),\n      babelPlugin({\n        babelHelpers: \"bundled\",\n        ...babelConfig,\n      }),\n      jsonPlugin(),\n      urlPlugin({\n        publicPath,\n        destDir: \"built/browser/\",\n        fileName: assetFileNames,\n        include: \"**/*.{svg,png,jpg,jpeg}\",\n        limit: 0, // Never Base64 & inline\n        emitFiles: !isBrowser,\n      }),\n      ...config.plugins,\n    ],\n  };\n}\n```\n\n</details>\n\n## `<rollup>` tag\n\nUsing both `.server()` and `.browser()` enables **the `<rollup>` tag**, which gives you complete control over how your app loads assets. That lets you do things like:\n\n- [Critical CSS](https://web.dev/extract-critical-css/) for components as they write out within a kB budget, or [as components first appear on the page](https://jakearchibald.com/2016/link-in-body/#a-simpler-better-way), or any other style-loading mad science\n- [`module`/`nomodule` scripts](https://philipwalton.com/articles/using-native-javascript-modules-in-production-today/) for smaller bundles in modern browsers\n- [Content-Security Policy `nonce`s](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce) or [Subresource `integrity` hashes](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)\n- Anything a web page can do, really. You can even combine `<rollup>` with [the `serialize` option](#options.serialize) to be as fancy as you wanna be.\n\nThe `<rollup>` tag provides two [tag parameters](https://markojs.com/docs/syntax/#parameters):\n\n1. `entry` is the generated `input` string that the `server` plugin gave to the `browser` plugin. You can use it to find the corresponding entry chunk from Rollup’s `output` (the next parameter).\n\n2. `output` is an array of `AssetInfo | ChunkInfo` objects with most of [the data returned from Rollup's `generateBundle` hook](https://rollupjs.org/guide/en/#generatebundle). Some properties are omitted, like `code` and `map`, since they’re often too large to inline directly. However, each chunk also has a `size` property, to let you filter out empty chunks, inline code yourself below a certain size, or other delightful devilishness.\n\nFor example, using the `entry` name and properties of `output` items to load scripts:\n\n```marko\n<head>\n  <rollup|entry, output|>\n    $ const entryChunk = output.find(chunk => chunk.name === entry);\n\n    <if(entryChunk.size /* only load non-empty JS entry points */)>\n      <for|fileName| of=entryChunk.imports>\n        <link rel=\"modulepreload\" href=fileName />\n      </for>\n\n      <script async type=\"module\" src=entryChunk.fileName></script>\n    </if>\n  </rollup>\n</head>\n```\n\n> **Note**: It’s up to you to transform the chunk data (also called the **manifest**) into `<link>`s, `<script>`s, and other HTML to load assets. Opting into complete control means we can’t do any of it for you.\n\nIf your Rollup `browser` config contains multiple `output` options, or you have multiple `browser` configs, every `output`’s chunk is passed to the `<rollup>` tag.\n\nFor example, if you have both `esm` and `iife` build outputs configured:\n\n```js\n{\n  output: [\n    { dir: \"dist/iife\", format: \"iife\" },\n    { dir: \"dist/esm\", format: \"esm\" },\n  ];\n}\n```\n\n…you could cross-reference assets from both…\n\n```marko\n<rollup|entry, iifeOutput, esmOutput|>\n  $ const iifeEntryChunk = iifeOutput.find(chunk => chunk.name === entry);\n  $ const esmEntryChunk = esmOutput.find(chunk => chunk.name === entry);\n\n  <script src=esmEntryChunk.fileName type=\"module\" async></script>\n  <script src=iifeEntryChunk.fileName nomodule async></script>\n</rollup>\n```\n\n…and _boom:_ you now have [a `module`/`nomodule` setup](https://philipwalton.com/articles/using-native-javascript-modules-in-production-today/).\n\n## Options\n\n### `options.babelConfig`\n\nBoth the `.server()` and `.browser()` plugins accept this option.\n\nYou can manually override the builtin Babel configuration by passing a `babelConfig` object. By default, [Babel’s regular config file resolution](https://babeljs.io/docs/en/config-files) will be used.\n\n```js\nmarko.browser({\n  babelConfig: {\n    presets: [\"@babel/preset-env\"],\n  },\n});\n```\n\n### `options.runtimeId`\n\nBoth the `.server()` and `.browser()` plugins accept this option. In fact, you _really_ want to use it with both simultaneously.\n\nIn some cases, you may want to embed multiple isolated copies of Marko on the page. (If you can’t think of why, then don’t worry about this option.)\n\nSince Marko uses some `window` properties to initialize, multiple instances can cause issues. For example, by default Marko checks `window.$components` for server-rendered hydration. Usually you can change these `window` properties by [rendering with `{ $global: { runtimeId: \"MY_MARKO_RUNTIME_ID\" } }` as input](https://markojs.com/docs/rendering/#global-data) on the server, but since `@marko/rollup` usually writes the autoinitialization code for you, instead this plugin exposes a `runtimeId` option to automatically set `$global.runtimeId` to initialize properly in the browser:\n\n```js\nconst runtimeId = \"MY_MARKO_RUNTIME_ID\";\n// Make the `runtimeId` the same across `server` and `browser`, or it’ll error!\nmarko.server({ runtimeId });\nmarko.browser({ runtimeId });\n```\n\n### `options.serialize`\n\nThis option is only available for the `.browser()` plugin. It lets you inspect and transform the `output` chunks before they’re passed to [the `<rollup>` tag](#rollup-tag).\n\nFor example, if you _did_ want to include the `code` property from the Rollup chunk — say, to inline code small enough that it’s not worth the overhead of an HTTP request, you’d try something like the following:\n\n```js\nmarko.browser({\n  serialize(output) {\n    return output.map(({ type, fileName, isEntry, code }) =>\n      type === \"asset\"\n        ? { type, fileName }\n        : {\n            type,\n            name,\n            isEntry,\n            fileName,\n            // only inline code chunks below 1kB\n            inline: code.trim().length < 1024 && code,\n          },\n    );\n  },\n});\n```\n","isInternal":false,"tokens":3035,"sizeBytes":12280},{"name":"state.md","path":"packages/runtime-class/docs/state.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/state.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# State\n\nThe output of a component is based on input properties passed from its parent as attributes. However, a component may also maintain internal state that it uses to control its view. If Marko detects a change to either input or to the internal state, the view will automatically be updated.\n\n> **ProTip:**\n> Only data that is owned and modified by the component should go into its `state`. State should be exclusively used for data that triggers rerenders. Parents control `input`, and the component controls its own `state`.\n\n## Initializing state\n\nTo use `state` in Marko, you must first create a [class component](./class-components.md) and initialize the state within the [`onCreate`](./class-components.md#oncreateinput-out) method. In class methods, `this.state` may be used and within the template section, a `state` variable is available.\n\n```marko\nclass {\n    onCreate() {\n        this.state = { count: 0 };\n    }\n}\n\n<div>The count is ${state.count}</div>\n```\n\n> **Note:** Only properties that exist when `this.state` is first defined will be watched for changes. If you don't need a property initially, you can set it to `null`.\n\n## Updating state\n\nYou can update `state` in response to DOM events, browser events, ajax calls, etc. When a property on the state changes, the view will be updated to match.\n\n```marko\nclass {\n    onCreate() {\n        this.state = { count: 0 };\n    }\n    increment() {\n        this.state.count++;\n    }\n}\n\n<div>The count is ${state.count}</div>\n<button on-click('increment')>Increment</button>\n```\n\nWe've extended our example above to add a button with an [event handler](./events.md), so that, when clicked, the `state.count` value is incremented.\n\n> **Note:**\n> When browsing existing code, you may see `this.setState('name', value)` being used. This is equivalent to `this.state.name = value`.\n\n### How updates work\n\nWhen a property on `state` is set, the component will be scheduled for an update if the property has changed. All updates are batched together for performance. This means you can update multiple state properties at the same time without causing multiple updates.\n\n> **ProTip:** If you need to know when the update has been applied, you can use `this.once('update', fn)` within a component method.\n\n> **Note:** The state object only watches its properties one level deep. This means updates to nested properties on the state (e.g. `this.state.object.something = newValue`) will not be detected.\n>\n> Using [immutable](https://wecodetheweb.com/2016/02/12/immutable-javascript-using-es6-and-beyond/) data structures is recommended, but if you want to mutate a state property (perhaps push a new item into an array) you can let Marko know it changed using `setStateDirty`.\n>\n> ```js\n> this.state.numbers.push(num);\n>\n> // mark numbers as dirty, because a `push`\n> // won't be automatically detected by Marko\n> this.setStateDirty(\"numbers\");\n> ```\n\n## Cross component state management\n\nThere are various tools available to manage state outside of a single component. Here are some basic guidelines.\n\nTypically we recommend using `attributes` to pass data in to a child component, and children can [emit events](./events.md#emitting-custom-events) to communicate back up to their parents. In some cases this can become cumbersome with deeply nested data dependencies or global state.\n\n### Global/Subtree\n\nFor passing state throughout a component tree without explicit attribute setting throughout the entire app, you can leverage the [`<context>`](https://github.com/marko-js/tags/tree/master/tags/context) tag. This tag can be [installed from npm](./custom-tags.md#using-tags-from-npm).\n\nThis tag allows you to pull state from any level above in the tree and can also be used to pass global state throughout your app.\nContext providers can register event handlers that any child in the tree can trigger similar to the [events API](./events.md).\n\n_fancy-form.marko_\n\n```marko\n<context coupon=input.coupon on-buy(handleBuy)>\n    <!-- Somewhere nested in the container will be the buy button -->\n    <fancy-container/>\n</context>\n```\n\n_fancy-save-button.marko_\n\n```marko\n<context|{ coupon }, emit| from=\"fancy-form\">\n    Coupon: ${coupon}.\n    <button on-click(emit, \"buy\")>Buy</button>\n</context>\n```\n\n> **Note:** Context _couples_ tags together and can limit reuse of components.\n\n### When to use a Redux like pattern\n\nOften the above two approaches are enough, and many people [jump to this part far too quickly](https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367). Like `<context>`, often anything stored in redux is `global`. This means that it can (if abused) create components that are hard to reuse, reason about and test. However it is important to understand when a tool like `redux` is useful in any UI library.\n\nRedux provides indirection to updating any state that it controls. This is useful if you need the following:\n\n- Single state update, multiple actions (eg: logging, computed data, etc).\n- Time travel debugging and other [redux-specific tooling](https://redux.js.org/introduction/ecosystem).\n","isInternal":false,"tokens":1155,"sizeBytes":5091},{"name":"structure.json","path":"packages/runtime-class/docs/structure.json","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/structure.json","title":"Docs Skill","category":"anthropic-skill","format":"json","content":"[\n  {\n    \"title\": \"Guides\",\n    \"docs\": [\n      \"Installing\",\n      \"Getting started\",\n      \"Conditionals and lists\",\n      \"Custom tags\",\n      \"State\",\n      \"Styles\",\n      \"Events\",\n      \"Body content\",\n      \"TypeScript\",\n      \"Marko 5 upgrade\",\n      \"Troubleshooting Streaming\"\n    ]\n  },\n  {\n    \"title\": \"Tutorials\",\n    \"docs\": [\"Color Picker\"]\n  },\n  {\n    \"title\": \"Reference\",\n    \"docs\": [\n      \"Rendering\",\n      \"Syntax\",\n      \"Core tags\",\n      \"Class components\",\n      \"marko.json\",\n      \"Compiler\"\n    ]\n  },\n  {\n    \"title\": \"Bundler Integrations\",\n    \"docs\": [\"Vite\", \"Webpack\", \"Rollup\", \"Lasso\"]\n  },\n  {\n    \"title\": \"Server Integrations\",\n    \"docs\": [\"Cloudflare Workers\", \"Express\", \"Fastify\", \"Koa\", \"HTTP\"]\n  },\n  {\n    \"title\": \"Tooling\",\n    \"docs\": [\"Editor plugins\"]\n  },\n  {\n    \"title\": \"Articles\",\n    \"docs\": [\"Marko vs React\", \"Why is Marko Fast\", \"10 Awesome Marko Features\"]\n  }\n]\n","isInternal":false,"tokens":269,"sizeBytes":930},{"name":"styles.md","path":"packages/runtime-class/docs/styles.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/styles.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Styles\n\nBoth HTML and Marko provide support for `<style>` tags. However, Marko also provides a special syntax (called a style _block_) which adds support for CSS preprocessors and acts as a hint to bundlers to extract this static css from your templates into a common bundle.\n\n```marko\nstyle {\n    div {\n        color: green;\n    }\n}\n\n<div>Hello World</div>\n```\n\nThese blocks add global css to the page. The above example will not style just the `<div>` in the component, but all divs on the page. Because of this we recommend following a naming convention such as [BEM](https://getbem.com/introduction/). Marko will likely provide a way to automatically scope these styles to the current component [in the future](https://github.com/marko-js/marko/issues/666).\n\n> **Note:** Style blocks (unlike `<style>` tags) do not support `${placeholders}` and must be static.\n\n## Preprocessors\n\nIf you use a css preprocessor, you can add the extension right on `style`. This will cause your bundler of choice to run the contents of the style block through the appropriate processor.\n\n```marko\nstyle.less {\n    button.primary {\n        background-color: @primaryColor;\n    }\n}\n```\n","isInternal":false,"tokens":268,"sizeBytes":1171},{"name":"syntax.md","path":"packages/runtime-class/docs/syntax.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/syntax.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Syntax\n\nMarko is HTML _re-imagined_ as a language for building dynamic and reactive user interfaces.\nJust about any valid HTML is valid Marko, but Marko extends the HTML language to allow building modern applications in a declarative way.\n\n> **ProTip:** Marko also supports a [beautiful concise syntax](./concise.md). If you'd prefer to see the documentation using this syntax, just click the `switch syntax` button in the corner of any Marko code sample.\n\n> **Note:** Text at the root of a template (outside any tags) must be prefixed with the [concise syntax's `--`](./concise.md#text) to denote it is text. The parser starts in concise mode and would otherwise try to parse what you meant to be text as a concise tag declaration.\n>\n> ```marko\n> -- Root level text\n> ```\n\n## Tags\n\nAs you might expect, Marko supports all native HTML/SVG/whatever tags and attributes. In addition to these, it also comes with a set of useful [core tags](./core-tags.md). Beyond this, you can also build your own [custom tags](./custom-tags.md) and [install third-party tags](./custom-tags.md#using-tags-from-npm) from `npm`.\n\nAll of these types of tags use the same syntax:\n\n```marko\n<my-tag-name/>\n```\n\nYou don't need to import tags. Marko discovers them based on the folder structure—similar to how you don't specify a full path when referencing a module in `node_modules/`. Marko looks in [`components/`](./custom-tags.md#how-tags-are-discovered) by default and this directory can be configured in [`marko.json`](./marko-json.md).\n\n## Dynamic text\n\nYou can use placeholders (`${}`) to insert a value into the template:\nPlaceholders accept any JavaScript expression and the result of the expression will be inserted into the HTML output:\n\n```marko\n<div>\n    Hello ${\"world\".toUpperCase()}\n</div>\n```\n\nThese values are automatically escaped so you don't accidentally insert malicious code. If you do need to pass unescaped HTML, you can use `$!{}`:\n\n```marko\n<div>\n    Hello $!{\"<b>World</b>\"}\n</div>\n```\n\n> **ProTip:** If necessary, you can escape `$` using a backslash to have it be treated as text instead of a placeholder token:\n>\n> ```marko\n> <div>\n>     Placeholder example: <code>\\${someValue}</code>\n> </div>\n> ```\n\n## Attributes\n\nIn marko attributes are parsed as JavaScript expressions (instead of just strings).\n\n```marko\n<div class=myClassName/>\n<input type=\"checkbox\" checked=isChecked/>\n\n<custom-tag string=\"Hello\"/>\n<custom-tag number=1/>\n<custom-tag template-string=`Hello ${name}`/>\n<custom-tag boolean=true/>\n<custom-tag array=[1, 2, 3]/>\n<custom-tag object={ hello: \"world\" }/>\n<custom-tag variable=name/>\n<custom-tag function-call=user.getName()/>\n```\n\nAttributes that are passed to a custom tag are received as it's [`input`](https://markojs.com/docs/class-components/#input).\n\n> **Note:** Although in most cases you won't see a difference, strings are parsed as JavaScript strings, not HTML strings. Where this comes up most often is using the `pattern` attribute with the `<input>` tag: you need to \"double escape\" your regex escape sequences much like you were passing a string to the [`RegExp` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) (or you can use a literal `/regex/`).\n>\n> _Marko Source:_\n>\n> ```marko\n> <input pattern=\"\\\\w+\" type=\"text\"/>\n> <input pattern=/\\w+/ type=\"text\"/>\n> ```\n>\n> _HTML Output:_\n>\n> ```html\n> <input pattern=\"\\w+\" type=\"text\" />\n> ```\n\n### Complex expressions\n\nAny JavaScript expression is a valid attribute value, provided it meets the following criteria:\n\n_It does not contain any spaces_\n\n_It does not contain any right angle brackets (`>`)_\n\n```marko\n<custom-tag sum=1+2 difference=3-4/>\n```\n\n```marko\ncustom-tag sum=1+2 difference=3-4\n```\n\n_Spaces and `>` are contained within matching `()`, `[]`, `{}`, strings and regexps_\n\n```marko\n<custom-tag sum=(1 + 2) difference=(3 - 4) greater=(1 > 2)/>\n```\n\n```marko\ncustom-tag sum=(1 + 2) difference=(3 - 4) greater=(1 > 2)\n```\n\n### Boolean attributes\n\nHTML defines the following rules for [boolean attributes](https://www.w3.org/TR/2008/WD-html5-20080610/semantics.html#boolean):\n\n> The presence of a boolean attribute on an element represents the true value, and the absence of the attribute represents the false value.\n\nIn Marko when an attribute value evaluates to `false`, `null`, or `undefined`, the attribute is not included in the output. If an attribute value is `true`, only the attribute name is included in the output.\n\n_Marko Source:_\n\n```marko\n<input type=\"checkbox\" checked=true>\n<input type=\"checkbox\" checked=false>\n```\n\nRenders the following HTML:\n\n_HTML Output:_\n\n```html\n<input type=\"checkbox\" checked /> <input type=\"checkbox\" />\n```\n\nSimilarly, when only an attribute name is defined, it is equivalent to specifying the attribute with a value of `true`:\n\n```marko\n<!-- These are equivalent -->\n<custom-menu expanded/>\n<custom-menu expanded=true/>\n```\n\n> **ProTip:**\n> You can take advantage of the way Marko handles boolean attributes to conditionally render attributes:\n>\n> _Marko Source:_\n>\n> ```marko\n> <div class=(active && \"tab-active\")>Hello</div>\n> ```\n>\n> With a value of `true` for `active`, the output would be the following:\n>\n> _HTML Output:_\n>\n> ```html\n> <div class=\"tab-active\">Hello</div>\n> ```\n>\n> With a value of `false` for `active`, the output would be the following:\n>\n> _HTML Output:_\n>\n> ```html\n> <div>Hello</div>\n> ```\n\n### Dynamic attributes\n\nThe spread syntax (`...`) can be used to merge in an object as attributes to a tag:\n\n_Marko Source:_\n\n```marko\n<a ...attrs target=\"_blank\">eBay</a>\n```\n\nWith `attrs` as the following value:\n\n```js\n{\n    class: \"active\",\n    href: \"https://ebay.com/\"\n}\n```\n\nwould output the following HTML:\n\n_HTML Output:_\n\n```html\n<a class=\"active\" href=\"https://ebay.com/\" target=\"_blank\">eBay</a>\n```\n\n> **ProTip:**\n> With spread attributes order matters.\n> You can take advantage of this to implement both default attributes, and enforced attributes.\n>\n> ```marko\n> <custom-tag ...defaults ...userSupplied class=\"overridden\"/>\n> ```\n\n> **ProTip:**\n> You can provide `undefined` to a spread attribute which will output nothing.\n\n### Style attribute\n\nYou can pass a string as the value of `style` just as you would in HTML, in addition Marko supports passing an object or array as the value of the `style` attribute:\n\n_Marko Source:_\n\n```marko\n<!-- string: -->\n<div style=\"display:block;margin-right:16px\"/>\n\n<!-- object: -->\n<div style={ display: \"block\", color: false, marginRight: 16 }/>\n\n<!-- array: -->\n<div style=[\"display:block\", null, { marginRight: 16 }]/>\n```\n\nIn all cases, the output will be the same:\n\n_HTML Output:_\n\n```html\n<div style=\"display:block;margin-right:16px;\"></div>\n```\n\n### Class attribute\n\nThe `class` attribute also supports receiving an object or array (in addition to a string) as shown below:\n\n_Marko Source:_\n\n```marko\n<!-- string: -->\n<div class=\"a c\"/>\n\n<!-- object: -->\n<div class={ a:true, b:false, c:true }/>\n\n<!-- array: -->\n<div class=[\"a\", null, { c:true }]/>\n```\n\nIn all cases, the output will be the same:\n\n_HTML Output:_\n\n```html\n<div class=\"a c\"></div>\n```\n\n### Shorthand attributes\n\nMarko provides a shorthand for declaring classes and ids on an element, including interpolation. Given `size` is the string `small`:\n\n_Marko Source:_\n\n```marko\n<div.my-class/>\n<span#my-id/>\n<button#submit.primary.large/>\n<button.button--${size}></button>\n```\n\nRenders the following HTML:\n\n_HTML Output:_\n\n<!-- prettier-ignore -->\n```html\n<div class=\"my-class\"></div>\n<span id=\"my-id\"></span>\n<button id=\"submit\" class=\"primary large\"></button>\n<button class=\"button--small\"></button>\n```\n\n## Parameters\n\nWhen a tag renders its body content, it may provide data which can be received by defining parameters after the tagname. Parameters are available to the tag's body content.\n\nThis is a powerful feature that allows components to provide functionality and data while giving you full control over what gets rendered.\n\nIn the following example, `<mouse>` provides a parameter which we have named `position`:\n\n```marko\n<mouse|position|>\n   The mouse is at ${position.x}, ${position.y}!\n</mouse>\n```\n\n> `<mouse>` would [render its body](./body-content.md) and provide the position similar to this: `<${input.renderBody} x=0 y=0/>`.\n\n> **ProTip:** Tag `|parameters|` are treated as regular JavaScript function parameters. This means you can destructure, set default values, etc.\n>\n> ```marko\n> <mouse|{ x, y }|>\n>   The mouse is at ${x}, ${y}!\n> </mouse>\n> ```\n\n> **Note:** Parameters are not available to attributes, only to the tag body.\n>\n> ```marko\n> <mouse|position| something=position>\n>   ReferenceError when setting the \"something\" attribute\n> </mouse>\n> ```\n\nParameters are used by some of Marko's [core tags](./core-tags.md) like the [`<for>`](./core-tags.md#for) and [`<await>`](./core-tags.md#await) tags.\n\n## Arguments\n\nSome tags and attributes accept javascript style `arguments`. Arguments are denoted by parenthesis following the tag or attribute name. Arguments provide a way to pass unnamed data to a tag.\n\n```marko\n<if(true)>\n    <strong>Marko is awesome</strong>\n</if>\n\n<h1 body-only-if(skipHeading)>\n    Conditional display heading, but always show content!\n</h1>\n```\n\nArguments are used by some of Marko's [core tags](./core-tags.md) like the [`<if>`](./core-tags.md#if-else-if-else) tag and [`body-only-if`](./core-tags.md#body-only-if) attribute displayed above.\n\nPreviously you could also use them in your own [custom tags](./custom-tags.md) however it is now recommended to use [dynamic attributes](#dynamic-attributes).\n\n## Dynamic tagname\n\nThe `<${dynamic}>` syntax is used to render a tag or component that isn't determined until runtime. It can also be used within a [custom tag](./custom-tags.md) to render body content that was passed to that tag.\n\n_Marko Source:_\n\n```marko\n<${href ? 'a' : 'button'} href=href>\n    Click me!\n</>\n```\n\nWith `href` as `https://ebay.com` would output the following HTML:\n\n_HTML Output:_\n\n```html\n<a href=\"https://ebay.com\">Click me!</a>\n```\n\nAnd with `href` as `undefined` would output the following HTML:\n\n_HTML Output:_\n\n```html\n<button>Click me!</button>\n```\n\nAs a shorthand if there is a variable in scope and [no other matching tag is discovered](#how-tags-are-discovered) the wrapping `${}` is unnecessary.\n\nFor example the following are equivalent:\n\n```marko\n$ const MyTag = href ? 'a' : 'button';\n<${MyTag}/>\n<MyTag/>\n```\n\n> **ProTip:**\n> If you find that you have a wrapper element that is conditional, but whose body should always be rendered then you can use a null dynamic tag. For example, to only render a wrapping `<a>` tag if there is a valid URL then you could do the following:\n>\n> _Marko Source:_\n>\n> ```marko\n> <${input.linkUrl ? \"a\" : null} href=input.linkUrl >\n>    Some body content\n> </>\n> ```\n>\n> Given a value of `\"http://localhost/\"` for the `input.linkUrl` variable: , the output would be the following:\n>\n> _HTML Output:_\n>\n> ```html\n> <a href=\"http://localhost/\"> Some body content </a>\n> ```\n>\n> Given a value of `undefined` for the `input.linkUrl` variable: , the output would be the following:\n>\n> _HTML Output:_\n>\n> ```html\n> Some body content\n> ```\n\n### Dynamic components\n\nInstead of just strings, the dynamic tagname can also be a component:\n\n```marko\nimport componentA from \"<component-a>\";\nimport componentB from \"<component-b>\";\n\n<${useA ? componentA : componentB}/>\n```\n\n> **ProTip:**\n> You can also switch between a normal HTML tag and a component:\n>\n> ```marko\n> import FancyButton from \"<fancy-button>\";\n>\n> <${isFancy ? FancyButton : 'button'}>\n>     Button text\n> </>\n> ```\n\n> **Note:** You **cannot** reference a Marko custom tag or macro using a name string:\n>\n> _Marko Source:_\n>\n> ```marko\n> <${isFancy ? 'fancy-button' : 'button'}>\n>     Button text\n> </>\n> ```\n>\n> With `isFancy` as `true` would output the following HTML:\n>\n> _HTML Output:_\n>\n> ```html\n> <fancy-button>Button text</fancy-button>\n> ```\n\n### Dynamic body content\n\nWhen a custom tag receives [body content](./body-content.md), it is passed as a `renderBody` property. To render this content you can pass the `renderBody` as the dynamic tagname.\n\n```marko\n<div class=\"container\">\n    <${input.renderBody}/>\n</div>\n```\n\n## Attribute Tag\n\nAs the name implies, `<@attribute-tags>` are special attributes that take the form of tags. They allow you to pass named body sections to a [custom tag](./custom-tags.md).\n\nThe core `<await>` tag allows you to pass multiple body sections that it will conditionally render based on the state of the promise.\n\n```marko\n<await(somePromise)>\n    <@then|result|>\n        The promise resolved: ${result}\n    </@then>\n    <@catch|error|>\n        The promise rejected: ${error.message}\n    </@catch>\n</await>\n```\n\nThese body sections are also commonly used to create layouts:\n\n```marko\n<page-layout>\n    <@heading>\n        <h1>Hello</h1>\n    </@heading>\n    <@body>\n        <p>Lorem ipsum....</p>\n    </@body>\n</page-layout>\n```\n\nThese tags are passed to the custom tag as objects with a `renderBody`, it can then [render its body content](./body-content.md).\n\n> **Note:**\n> Attribute tags can have their own parameters, but like attributes, they cannot access the parameters of their parent tag:\n>\n> ```marko\n> <list|item|>\n>   ${item.name}\n>   <@separator>${item} (oops, ReferenceError)</@separator>\n> </list>\n> ```\n\n## Inline JavaScript\n\nTo execute JavaScript in your template you can insert a Javascript statement using the `$ <code>` syntax.\n\nA line that starts with a `$` followed by a space will execute the code that follows.\n\n```marko\n$ const name = \"World\";\n\n<div>\n    Hello, ${name}\n    $ console.log(\"The value rendered was\", name);\n</div>\n```\n\nA statement may continue onto subsequent lines if new lines are bounded by `{}`, `[]`, `()`, ` `` `, or `/**/`:\n\n```marko\n$ const person = {\n    name: \"Frank\",\n    age: 32\n};\n```\n\nMultiple statements or an unbounded statement may be used by wrapping the statement(s) in a block:\n\n```marko\n$ {\n    const bgColor = getRandomColor();\n    const textColor = isLight(bgColor)\n        ? \"black\"\n        : \"white\";\n}\n```\n\n> **ProTip:** Any JavaScript statement can be used here, even `debugger`:\n>\n> ```marko\n> <div>\n>     ${textColor}\n>     $ debugger; // Quickly debug `textColor`\n> </div>\n> ```\n\n> **ProTip:** If necessary, you can escape `$` using a backslash to have it be treated as text instead of a placeholder token:\n>\n> ```marko\n> <p>You can run JS in a Marko template like this:</p>\n> <code>\n>     \\$ var num = 123;\n> </code>\n> ```\n\n> **ProTip:** If you find yourself writing a lot of inline JS, consider moving it out to an external file and then [`import`](#importing-external-files) it.\n\n### Static JavaScript\n\nInline JavaScript will run each time your template is rendered, but the JavaScript code that follows `static` will only run once when the template is loaded. It must be declared at the top level and does not have access to values passed in at render time.\n\n```marko\nstatic var count = 0;\nstatic var formatter = new Formatter();\n\nstatic function sum(a, b) {\n    return a + b;\n};\n\n<div>${formatter.format(sum(2, 3))}</div>\n```\n\nLike inline Javascript, multiple statements or an unbounded statement may be used by wrapping the statement(s) in a block:\n\n```marko\nstatic {\n    var base = 2;\n    function sum(a, b) {\n        return base + a + b;\n    };\n}\n```\n\n### Importing external files\n\nThe `import` statement is used to access data and functions from external files. It follows the same syntax as the [JavaScript `import` statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import).\n\n```marko\nimport sum from './utils/sum';\n<div>The sum of 2 + 3 is ${sum(2, 3)}</div>\n```\n\nAs a shorthand you can also import components by providing it's html tag name wrapped in angle brackets, eg:\n\n```marko\nimport MyComponent from \"<my-component>\"\n```\n\nThis is especially useful with the [dynamic tag name syntax](./syntax.md#dynamic-tagname) and uses the same [component discovery](./custom-tags.md#how-tags-are-discovered) as if the tag was used in the template.\n\n## Comments\n\nStandard HTML comments can be used and will be stripped out of the rendered output.\nAt the top level of the template JavaScript comments (`// comment` and `/** comment */`) can also be used.\n\n```marko\n<!-- This is a comment that will not be rendered -->\n\n<h1>Hello</h1>\n```\n\nIf you would like for your HTML comment to show up in the final output then you can use the [`html-comment` core tag](./core-tags.md#html-comment).\n","isInternal":false,"tokens":4237,"sizeBytes":16555},{"name":"troubleshooting-streaming.md","path":"packages/runtime-class/docs/troubleshooting-streaming.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/troubleshooting-streaming.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Troubleshooting HTTP Streams\n\n[The way Marko streams HTML](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding) is old and well-supported, but default configurations and assumptions by other software can foil it. This page describes some known culprits that may buffer your Node server’s output HTTP streams.\n\n## Reverse proxies/load balancers\n\n- Turn off proxy buffering, or if you can’t, set the proxy buffer sizes to be reasonably small.\n\n- Make sure the “upstream” HTTP version is 1.1 or higher; HTTP/1.0 and lower do not support streaming.\n\n- Some software doesn’t support HTTP/2 or higher “upstream” connections at all or very well — if your Node server uses HTTP/2, you may need to downgrade.\n\n- Check if “upstream” connections are `keep-alive`: overhead from closing and reopening connections may delay responses.\n\n- For typical modern webpage file sizes, the following bullet points probably won’t matter. But if you want to stream **small chunks of data with the lowest latency**, investigate these sources of buffering:\n  - Automatic gzip/brotli compression may have their buffer sizes set too high; you can tune their buffers to be smaller for faster streaming in exchange for slightly worse compression.\n\n  - You can [tune HTTPS record sizes for lower latency, as described in High Performance Browser Networking](https://hpbn.co/transport-layer-security-tls/#optimize-tls-record-size).\n\n  - Turning off MIME sniffing with [the `X-Content-Type-Options`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options) header eliminates browser buffering at the very beginning of HTTP responses\n\n### NGiNX\n\nMost of NGiNX’s relevant parameters are inside [its builtin `http_proxy` module](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering):\n\n```nginx\nproxy_http_version 1.1; # 1.0 by default\nproxy_buffering off; # on by default\n```\n\n### Apache\n\nApache’s default configuration works fine with streaming, but your host may have it configured differently. The relevant Apache configuration is inside [its `mod_proxy` and `mod_proxy_*` modules](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html) and their [associated environment variables](https://httpd.apache.org/docs/2.4/env.html).\n\n## CDNs\n\nContent Delivery Networks (CDNs) consider efficient streaming one of their best features, but it may be off by default or if certain features are enabled.\n\n- For Fastly or another provider that uses VCL configuration, check [if backend responses have `beresp.do_stream = true` set](https://developer.fastly.com/reference/vcl/variables/backend-response/beresp-do-stream/).\n\n- Some [Akamai features designed to mitigate slow backends can ironically slow down fast chunked responses](https://community.akamai.com/customers/s/question/0D50f00006n975d/enabling-chunked-transfer-encoding-responses). Try toggling off Adaptive Acceleration, Ion, mPulse, Prefetch, and/or similar performance features. Also check for the following in the configuration:\n\n  ```xml\n  <network:http.buffer-response-v2>off</network:http.buffer-response-v2>\n  ```\n\n## Node.js itself\n\nFor extreme cases where [Node streams very small HTML chunks with its built-in compression modules](https://github.com/marko-js/marko/pull/1641), you may need to tweak the compressor stream settings. Here’s an example with `createGzip` and its `Z_PARTIAL_FLUSH` flag:\n\n```js\nimport http from \"http\";\nimport zlib from \"zlib\";\n\nimport MarkoTemplate from \"./something.marko\";\n\nhttp\n  .createServer(function (request, response) {\n    response.writeHead(200, { \"content-type\": \"text/html;charset=utf-8\" });\n    const templateStream = MarkoTemplate.stream({});\n    const gzipStream = zlib.createGzip({\n      flush: zlib.constants.Z_PARTIAL_FLUSH,\n    });\n    templateStream.pipe(outputStream).pipe(response);\n  })\n  .listen(80);\n```\n","isInternal":false,"tokens":877,"sizeBytes":3884},{"name":"typescript.md","path":"packages/runtime-class/docs/typescript.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/typescript.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# TypeScript in Marko\n\n> **Note:** Types are supported in Marko v5.22.7+ and Marko v4.24.6+\n\nMarko’s TypeScript support offers in-editor error checking, makes refactoring less scary, verifies that data matches expectations, and even helps with API design.\n\nOr maybe you just want more autocomplete in VSCode. That works too.\n\n## Enabling TypeScript in your Marko project\n\nThere are two (non-exclusive) ways to add TypeScript to a Marko project:\n\n- **For sites and web apps**, you can place [a `tsconfig.json` file](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) at the project root:\n  <pre>\n  📁 components/\n  📁 node_modules/\n  <img src=\"./icons/marko.svg\" width=16> index.marko\n  📦 package.json\n  <mark><img src=\"./icons/ts.svg\" width=16> tsconfig.json</mark>\n  </pre>\n- **If you’re [publishing packages of Marko tags](./custom-tags.md#publishing-tags-to-npm)**, publish the output of [`mtc`](#ci-type-checking). Each component gets a `.d.marko` file with its types, which editors and type checkers read in place of the `.marko` file. This exposes type-checking and autocomplete for the published tags.\n\n> **ProTip**: For mixed JavaScript and TypeScript code, such as an incremental migration, set `\"script-lang\": \"ts\"` or `\"js\"` in [a `marko.json`](./marko-json.md) to override these defaults. The nearest `marko.json` up the directory tree applies, so folders can opt in or out.\n\n## Typing a tag's `input`\n\nA `.marko` file will use any exported `Input` type for [that file’s `input` object](./class-components.md#input).\n\nThis can be `export type Input` or `export interface Input`.\n\n### Example\n\n_PriceField.marko_\n\n```marko\nexport interface Input {\n  currency: string;\n  amount: number;\n}\n\n<label>\n  Price in ${input.currency}:\n  <input type=\"number\" value=input.amount min=0 step=0.01>\n</label>\n```\n\nYou can also import, reuse, and extend `Input` interfaces from other `.marko` or `.ts` files:\n\n```marko\nimport { Input as PriceInput } from \"<PriceField>\";\nimport { ExtraTypes } from \"lib/utils.ts\";\nexport type Input = PriceInput & ExtraTypes;\n```\n\n```marko\nimport { Input as PriceInput } from \"<PriceField>\";\nexport interface Input extends PriceInput {\n  discounted: boolean;\n  expiresAt: Date;\n};\n```\n\n### Generic `Input`s\n\n[Generic Types and Type Parameters](https://www.typescriptlang.org/docs/handbook/2/generics.html) on `Input` are recognized throughout the entire `.marko` template (excluding [static statements](./syntax.md#static-javascript)).\n\nFor example, if you set up a component like this:\n\n_components/my-select.marko_\n\n```marko\nexport interface Input<T> {\n  options: T[];\n  onSelect: (newVal: T) => unknown;\n}\n\nstatic function staticFn() {\n  // can NOT use `T` here\n}\n\n$ const instanceFn = (val: T) => {\n  // can use `T` here\n}\n\n// can use `as T` here\n<select on-input(evt => input.onSelect(options[evt.target.value] as T))>\n  <for|value, i| of=input.options>\n    <option value=i>${value}</option>\n  </for>\n</select>\n```\n\n…then your editor will figure out the types of inputs to that component:\n\n```marko\n<my-select options=[1,2,3] onSelect=val => {}/>\n                                 // ^^^ number\n\n<my-select options=[\"M\",\"K\",\"O\"] onSelect=val => {}/>\n                                       // ^^^ string\n```\n\n## Built-in Marko Types\n\nMarko exposes [type definitions](https://github.com/marko-js/marko/blob/main/packages/runtime-class/index.d.ts) you can reuse in [a TypeScript namespace](https://www.typescriptlang.org/docs/handbook/namespaces.html) called `Marko`:\n\n- **`Marko.Template<Input, Return>`**\n  - The type of a `.marko` file\n  - `typeof import(\"./template.marko\")`\n- **`Marko.TemplateInput<Input>`**\n  - The object accepted by the render methods of a template. It includes the template's `Input` as well as `$global` values.\n- **`Marko.Body<Params, Return>`**\n  - The type of the [body content](./body-content.md) of a tag (`renderBody`)\n- **`Marko.Component<Input, State>`**\n  - The base class for a [class component](./class-components.md)\n- **`Marko.Renderable`**\n  - Values accepted by the [`<${dynamic}/>` tag](./syntax.md#dynamic-tagname)\n  - `string | Marko.Template | Marko.Body | { renderBody: Marko.Body}`\n- **`Marko.Out`**\n  - The render context with methods like `write`, `beginAsync`, etc.\n  - `ReturnType<template.render>`\n- **`Marko.Global`**\n  - The type of the object in `$global` and `out.global` that can be passed to a template's render methods as the `$global` property.\n- **`Marko.RenderResult`**\n  - The [result](./rendering.md#renderresult) of rendering a Marko template\n  - `ReturnType<template.renderSync>`\n  - `Awaited<ReturnType<template.render>>`\n- **`Marko.Emitter`**\n  - `EventEmitter` from `@types/node`\n- **`Marko.NativeTags`**\n  - `Marko.NativeTags`: An object containing all native tags and their types\n- **`Marko.Input<TagName>`** and **`Marko.Return<TagName>`**\n  - Helpers to extract the input and return types native tags (when a string is passed) or a custom tag.\n- **`Marko.BodyParameters<Body>`** and **`Marko.BodyReturnType<Body>`**\n  - Helpers to extract the parameters and return types from the specified `Marko.Body`\n- **`Marko.AttrTag<T>`**\n  - Used to represent types for [attributes tags](./body-content.md#named-body-content)\n  - A single attribute tag, with a `[Symbol.iterator]` to consume any repeated tags.\n\n### Typing `renderBody`\n\nThe most commonly used type from the `Marko` namespace is `Marko.Body` which can be used to type `input.renderBody`:\n\n_child.marko_\n\n```marko\nexport interface Input {\n  renderBody?: Marko.Body;\n}\n```\n\nHere, the following will be acceptable values:\n\n_index.marko_\n\n```marko\n<child/>\n<child>Text in render body</child>\n<child>\n  <div>Any combination of components</div>\n</child>\n```\n\nPassing other values (including components) will cause a type error:\n\n_index.marko_\n\n```marko\nimport OtherTag from \"<other-tag>\";\n<child renderBody=OtherTag/>\n```\n\n### Typing Tag Parameters\n\nTag parameters are passed to the `renderBody` by the child tag. For this reason, `Marko.Body` also allows typing of its parameters:\n\n_for-by-two.marko_\n\n```marko\nexport interface Input {\n  to: number;\n  renderBody: Marko.Body<[number]>\n}\n\n<for|i| from=0 to=input.to step=2>\n  <${input.renderBody}(i)/>\n</for>\n```\n\n_index.marko_\n\n```marko\n<for-by-two|i| to=10>\n  <div>${i}</div>\n</for-by-two>\n```\n\n### Extending native tag types within a Marko tag\n\nThe types for native tags are accessed via the global `Marko.Input` type. Here's an example of a component that extends the `button` html tag:\n\n_color-button.marko_\n\n```marko\nexport interface Input extends Marko.Input<\"button\"> {\n  color: string;\n  renderBody?: Marko.Body;\n}\n\n$ const { color, renderBody, ...restOfInput } = input;\n\n<button style=`color: ${color}` ...restOfInput>\n  <${renderBody}/>\n</button>\n```\n\n### Registering a new native tag (eg for custom elements).\n\n```ts\ninterface MyCustomElementAttributes {\n  // ...\n}\n\ndeclare global {\n  namespace Marko {\n    interface NativeTags {\n      // By adding this entry, you can now use `my-custom-element` as a native html tag.\n      \"my-custom-element\": MyCustomElementAttributes;\n    }\n  }\n}\n```\n\n### Registering new \"global\" HTML Attributes\n\n```ts\ndeclare global {\n  namespace Marko {\n    interface HTMLAttributes {\n      \"my-non-standard-attribute\"?: string; // Adds this attribute as available on all HTML tags.\n    }\n  }\n}\n```\n\n### Registering CSS Properties (eg for custom properties)\n\n```ts\ndeclare global {\n  namespace Marko {\n    namespace CSS {\n      interface Properties {\n        \"--foo\"?: string; // adds a support for a custom `--foo` css property.\n      }\n    }\n  }\n}\n```\n\n## TypeScript Syntax in `.marko`\n\nAny [JavaScript expression in Marko](./syntax.md#inline-javascript) can also be written as a TypeScript expression.\n\n### Tag Type Parameters\n\n```marko\n<child <T>|value: T|>\n  ...\n</child>\n```\n\n### Tag Type Arguments\n\n_components/child.marko_\n\n```marko\nexport interface Input<T> {\n  value: T;\n}\n```\n\n_index.marko_\n\n```marko\n// number would be inferred in this case, but we can be explicit\n<child<number> value=1 />\n```\n\n### Method Shorthand Type Parameters\n\n```marko\n<child process<T>() { /* ... */ } />\n```\n\n### Attribute Type Assertions\n\nThe types of attribute values can _usually_ be inferred. When needed, you can assert values to be more specific with [TypeScript’s `as` keyword](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-assertions):\n\n```marko\n<some-component\n  number=1 as const\n  names=[] as string[]\n/>\n```\n\n# JSDoc Support\n\nFor existing projects that want to incrementally add type safety, adding full TypeScript support is a big leap. This is why Marko also includes full support for [incremental typing via JSDoc](https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html).\n\n## Setup\n\nYou can enable type checking in an existing `.marko` file by adding a `// @ts-check` comment at the top:\n\n```js\n// @ts-check\n```\n\nIf you want to enable type checking for all Marko & JavaScript files in a JavaScript project, you can switch to using a [`jsconfig.json`](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#using-tsconfigjson-or-jsconfigjson). You can skip checking some files by adding a `// @ts-nocheck` comment to files.\n\nOnce that has been enabled, you can start by typing the input with JSDoc. Here's an example component with typed `input`:\n\n```marko\n// @ts-check\n\n/**\n * @typedef {{\n *   firstName: string,\n *   lastName: string,\n * }} Input\n */\n\n<div>${firstName} ${lastName}</div>\n```\n\n## With a separate `component.js` file\n\nMany components in existing projects adhere to the following structure:\n\n<pre>\n📁 components/\n  📁 color-rotate-button/\n    <img src=\"./icons/marko.svg\" width=16> index.marko\n    <img src=\"./icons/js.svg\" width=16> component.js\n</pre>\n\nThe `color-rotate-button` takes a list of colors and moves to the next one each time the button is clicked:\n\n```marko\n<color-rotate-button colors=[\"red\", \"blue\", \"yellow\"]>\n  Next Color\n</color-rotate-button>\n```\n\nHere is an example of how this `color-rotate-button` component could be typed:\n\n_components/color-rotate-button/component.js_\n\n```js\n// @ts-check\n\n/**\n * @typedef {{\n *   colors: string[],\n *   renderBody: Marko.Renderable\n * }} Input\n * @typedef {{\n *   colorIndex: number\n * }} State\n * @extends {Marko.Component<Input, State>}\n */\nexport default class extends Marko.Component {\n  onCreate() {\n    this.state = {\n      colorIndex: 0,\n    };\n  }\n\n  rotateColor() {\n    this.state.colorIndex =\n      (this.state.colorIndex + 1) % this.input.colors.length;\n  }\n}\n```\n\n_components/color-rotate-button/index.marko_\n\n```marko\n// @ts-check\n\n/* Input will be automatically imported from `component.js`! */\n\n<button\n  onClick('rotateColor')\n  style=`color: ${input.colors[state.colorIndex]}`>\n  <${input.renderBody}/>\n</button>\n```\n\n# CI Type Checking\n\nFor type checking Marko files outside of your editor there is the [\"@marko/type-check\" cli](https://github.com/marko-js/language-server/tree/main/packages/type-check).\nCheck out the CLI documentation for more information.\n","isInternal":false,"tokens":2873,"sizeBytes":11077},{"name":"vite.md","path":"packages/runtime-class/docs/vite.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/vite.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Marko + Vite\n\n# Installation\n\n```console\nnpm install @marko/vite vite\n```\n\n# Example config\n\n```javascript\nimport { defineConfig } from \"vite\";\nimport marko from \"@marko/vite\";\nexport default defineConfig({\n  plugins: [marko()],\n});\n```\n\n# Linked Mode\n\nBy default this plugin operates in `linked` mode (you can disabled this by passing [`linked: false` as an option](#optionslinked)). In `linked` mode the plugin automatically discovers all of the entry `.marko` files while compiling the server, and tells `Vite` which modules to load in the browser.\n\nWith this you _do not_ create `.html` files for `Vite`, it's Marko all the way down!\nScripts, styles and other content that _would have_ been injected into the `.html` files is instead automatically injected into your `.marko` templates.\n\nIn this mode you must use the [Vite SSR API](https://vitejs.dev/guide/ssr.html#setting-up-the-dev-server).\n\nHere's an example using `express`.\n\n```js\nimport { createServer } from \"vite\";\n\nconst app = express();\nlet loadTemplate;\n\nif (process.env.NODE_ENV === \"production\") {\n  // Use Vite's built asset in prod mode.\n  loadTemplate = () => import(\"./dist\");\n} else {\n  // Hookup the vite dev server.\n  const vite = await createServer({\n    server: { middlewareMode: true }\n  });\n\n  app.use(vite.middlewares);\n  loadTemplate = () => vite.ssrLoadModule(\"./template.marko\");\n}\n\napp.get(\"/\", async (req, res) => {\n  const template = (await loadTemplate()).default;\n  // When the template is loaded, it will automatically have `vite` assets inlined.\n  template.render({ hello: \"world\" }, res);\n);\n\napp.listen(3000);\n```\n\n> For a more real world setup check out our [vite express](https://github.com/marko-js/examples/tree/master/examples/vite-express) example app.\n\n# Options\n\n### options.babelConfig\n\nYou can manually override Marko's Babel configuration by passing a `babelConfig` object to the `@marko/vite` plugin. By default Babel's regular [config file resolution](https://babeljs.io/docs/en/config-files) will be used.\n\n```javascript\nmarko({\n  babelConfig: {\n    presets: [\"@babel/preset-env\"],\n  },\n});\n```\n\n### options.runtimeId\n\nIn some cases you may want to embed multiple isolated copies of Marko on the page. Since Marko relies on some `window` properties to initialize this can cause issues. For example, by default Marko will read the server rendered hydration code from `window.$components`. In Marko you can change these `window` properties by rendering with `{ $global: { runtimeId: \"MY_MARKO_RUNTIME_ID\" } }` as input on the server side.\n\nThis plugin exposes a `runtimeId` option produces output that automatically sets `$global.runtimeId` on the server side and initializes properly in the browser.\n\n```js\nmarko({ runtimeId: \"MY_MARKO_RUNTIME_ID\" });\n```\n\n### options.linked\n\nSet this to `false` to opt out of [linked mode](#linked-mode). When this is false, the plugin will only handle resolving and transforming `.marko` files.\n","isInternal":false,"tokens":720,"sizeBytes":2939},{"name":"webpack.md","path":"packages/runtime-class/docs/webpack.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/webpack.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Marko + Webpack\n\n# Installation\n\n> `@marko/webpack` >= 7 Only supports Marko 5+.\n> For Marko 4 support use `@marko/webpack@6`.\n\n```console\nnpm install @marko/webpack\n```\n\n### Loader: `@marko/webpack/loader`\n\nThe loader portion of this module can be used standalone and simply transforms your Marko templates into the appropriate JavaScript depending on your webpack target.\n\nYou can override the output by adding a `target` option to the loader of `target: \"server\" | \"browser\"`.\n\n### Plugin: `@marko/webpack/plugin`\n\nThe plugin actually creates two separate webpack plugins, the `browser` plugin and the `server` plugin.\n\nThese are intended to be used in a isomorphic [webpack multi compiler](https://github.com/webpack/webpack/tree/master/examples/multi-compiler) where you are bundling both the server and the browser. The way it works is that the server plugin is going to analyze the top level Marko components in your server and automatically communicate with the browser compiler to retrieve the assets for that template.\n\nThis plugin also analyzes the top level Marko templates and determines if it is possible for them to rerender (currently the heuristic is simply does the component have an associated `class` or `component.js`). The plugin will automatically skip sending down any unnecessary top level templates to the browser.\n\nThe end result is that you setup a multi compiler (as shown below) and you can simply import Marko templates, and all assets are automatically generated and inlined into an optimized server response. No need to keep track of a webpack manifest yourself!\n\n### Tag: `<webpack-assets>`\n\nThe `<webpack-assets>` tag can be used along with the plugin in a multi-compiler setup. This tag allows you to inject `<script>`/`<style>` tags into a server-rendered template for the assets of an entry in the client compiler.\n\n#### Example Usage\n\n```marko\n<webpack-assets entry=\"tracking\"/>\n```\n\n#### Example Config\n\n```js\n// ...\nexport default [\n  {\n    entry: \"./server.js\",\n    plugins: [markoPlugin.server],\n    // ...\n  },\n  {\n    // ...\n    entry: {\n      tracking: \"./tracking.js\",\n    },\n    plugins: [markoPlugin.browser],\n  },\n];\n```\n\n# Example\n\n```javascript\nimport MarkoPlugin from \"@marko/webpack/plugin\";\n\nconst markoPlugin = new MarkoPlugin();\n\nexport default [\n  {\n    entry: \"./server.js\",\n    module: {\n      rules: [\n        {\n          test: /\\.marko$/,\n          loader: \"@marko/webpack/loader\",\n        },\n      ],\n    },\n    plugins: [markoPlugin.server],\n  },\n  {\n    rules: [\n      {\n        test: /\\.marko$/,\n        loader: \"@marko/webpack/loader\",\n      },\n      // If using `style` blocks with Marko you must use an appropriate loader\n      {\n        test: /\\.css$/,\n        use: [\"style-loader\", \"css-loader\"],\n      },\n    ],\n    plugins: [markoPlugin.browser],\n  },\n];\n```\n\n## Babel options (Marko 5+)\n\nIf you are using Marko 5 with this plugin you can manually override the Babel configuration used by passing a `babelConfig` object along side the `@marko/webpack/loader`. By default Babels regular [config file resolution](https://babeljs.io/docs/en/config-files) will be used.\n\n```javascript\nexport default {\n    module: {\n      rules: [\n        {\n          test: /\\.marko$/,\n          loader: \"@marko/webpack/loader\",\n          options: {\n            babelConfig: {\n              presets: [\n                [\"@babel/preset-env\", { node: \"current\" }]\n              ]\n            }\n          }\n        }\n      ]\n    }\n  },\n```\n\n## Multiple client-side compilers\n\nSometimes you need multiple compilers for your client-side bundles. For example, with [`i18n`](https://github.com/webpack/webpack/tree/master/examples/i18n) or [even shipping dynamic runtime bundles to the browser](https://github.com/eBay/arc/tree/master/packages/arc-webpack).\n\nThe `@marko/webpack` plugin’s `.browser` property can be passed to multiple Webpack compilers. While rendering at runtime, you can provide a `$global.buildName` property to choose which assets from the Webpack compiler are included in the page.\n\nFor example, with the Webpack internationalization plugin, you might have a config like the following:\n\n```js\nimport MarkoPlugin from \"@marko/webpack/plugin\";\nimport I18nPlugin from \"i18n-webpack-plugin\";\nimport germanTranslations from \"./de.json\";\n\nconst languages = {\n  en: null,\n  de: germanTranslations,\n};\n\nconst markoPlugin = new MarkoPlugin();\n\nexport default [\n  {\n    name: \"Server\",\n    entry: \"./server.js\",\n    module: {\n      rules: [\n        {\n          test: /\\.marko$/,\n          loader: \"@marko/webpack/loader\",\n        },\n      ],\n    },\n    plugins: [markoPlugin.server],\n  },\n  ...Object.keys(languages).map((language) => ({\n    name: `Browser-${language}`,\n    rules: [\n      {\n        test: /\\.marko$/,\n        loader: \"@marko/webpack/loader\",\n      },\n      // If using `style` blocks with Marko you must use an appropriate loader\n      {\n        test: /\\.css$/,\n        use: [\"style-loader\", \"css-loader\"],\n      },\n    ],\n    plugins: [new I18nPlugin(languages[language]), markoPlugin.browser],\n  })),\n];\n```\n\nWith the above config, you can render your top-level Marko template server-side with a `$global.buildName` like so:\n\n```javascript\ntemplate.render({ $global: { buildName: \"Browser-de\" } });\n```\n\nThat will automatically send German assets. However, what you _probably_ want instead of always serving German is conditionally sending appropriate assets for a user’s locale. This can be done like so:\n\n```javascript\ntemplate.render({ $global: { buildName: `Browser-${req.language}` } });\n```\n\n**Note:** If a bundle with the provided `buildName` does not exist, an error is thrown.\n\n## Multiple copies of Marko\n\nIn some cases you may want to embed multiple isolated copies of Marko on the page. Since Marko relies on some `window` properties to initialize this can cause issues. For example, by default Marko will read the server rendered hydration code from `window.$components`. In Marko you can change these `window` properties by rendering with `{ $global: { runtimeId: \"MY_MARKO_RUNTIME_ID\" } }` as input on the server side.\n\nThis plugin exposes a `runtimeId` option produces output that automatically sets `$global.runtimeId` on the server side and initializes properly in the browser.\nThe `runtimeId` will default to the [`uniqueName` option](https://webpack.js.org/configuration/output/#outputuniquename) from the server compiler in the webpack config.\n\n```js\nimport MarkoPlugin from \"@marko/webpack/plugin\";\n\nconst markoPlugin = new MarkoPlugin({\n  runtimeId: \"MY_MARKO_RUNTIME_ID\", // default to webpack `output.uniqueName` option.\n});\n```\n\nNote: This option will also override the default values for the `jsonpFunction`, `chunkCallbackName` and `hotUpdateFunction` webpack `output` options, which all use global variables, to be prefixed with the `runtimeId`.\n\n## Dynamic public paths\n\nWhen using the plugin, the server will automatically sync the runtime [`__webpack_public_path__`](https://webpack.js.org/guides/public-path/#on-the-fly) with the browser.\nThis means that you only need to setup the dynamic public path on the server side.\n","isInternal":false,"tokens":1637,"sizeBytes":7136},{"name":"why-is-marko-fast.md","path":"packages/runtime-class/docs/why-is-marko-fast.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/docs/why-is-marko-fast.md","title":"Docs Skill","category":"anthropic-skill","format":"markdown","content":"# Why is Marko Fast?\n\n<a href=\"https://medium.com/@psteeleidem/why-is-marko-fast-a20796cb8ae3\">\n  <img src=\"https://user-images.githubusercontent.com/1958812/28104838-d0182f48-6691-11e7-808d-d1ae2d0fed6d.png\" alt=\"Marko logo\" width=\"100%\" />\n</a><br />\n\n> This article was published in May 2017. You can find the original [\"Why is Marko Fast?\" article here](https://medium.com/@psteeleidem/why-is-marko-fast-a20796cb8ae3)!\n\nAt eBay we are using [Marko](https://markojs.com/) to render over a billion\nrequests every day and this has required us to finely tune Marko, our open\nsource UI library. We have heavily optimized Marko for fast rendering, [advanced\nperformance\ntechniques](https://tech.ebayinc.com/engineering/async-fragments-rediscovering-progressive-html-rendering-with-marko/)\nand to achieve a minimal page weight (~10kb gzipped). Performance is only one\nconcern because we have also had to scale Marko to support development across\nhundreds of teams in a way that allows developers to efficiently create\nmaintainable and robust web apps.\n\nWe have created [our own\nbenchmarks](https://github.com/marko-js/isomorphic-ui-benchmarks) and we have\n[added Marko to other\nbenchmarks](https://github.com/raxjs/server-side-rendering-comparison/pull/11),\nbut benchmarks cannot always be trusted. While we make every effort to be fair\nwith our benchmarks, what matters most is performance in real world applications\nas opposed to focusing on micro benchmarks. This is one reason that the V8 team\nhas switched to [a new methodology to measure and understand real-world\nJavaScript\nperformance](https://v8project.blogspot.com/2016/12/how-v8-measures-real-world-performance.html).\n\nSimilarly, we’ve taken a look at how our developers are _actually_ writing their\nMarko components and have found patterns that could be further optimized.\nInstead of focusing on benchmarks in this article, I want to focus on the\ndetails of optimizations that we have applied to Marko.\n\n### Multiple Compilation Outputs\n\nMarko is an isomorphic UI library that runs on both the server and in the\nbrowser. As [Michael Rawlings](https://medium.com/@mlrawlings) mentioned in\n“[Server-side Rendering\nShootout](https://hackernoon.com/server-side-rendering-shootout-with-marko-preact-rax-react-and-vue-25e1ae17800f)”,\nwhen rendering on the server, Marko renders directly to a string representation\nof the document (HTML) that can be sent as the HTTP response.\n\nWhen rendering in the browser, an HTML string would have to be parsed in order\nto update the DOM. For this reason, Marko compiles a view to a program that\nrenders directly to a virtual document (VDOM) tree that can be used to\nefficiently update the real DOM when targeting the browser.\n\nGiven the following template:\n\n```marko\n<div>Hello ${input.name}!</div>\n```\n\n#### Compiled for the server\n\nThe compiled output is optimized for streaming HTML output on the server:\n\n```js\nvar marko_template = require(\"marko/html\").t(__filename),\n  marko_helpers = require(\"marko/runtime/html/helpers\"),\n  marko_escapeXml = marko_helpers.x;\n\nfunction render(input, out) {\n  out.w(\"<div>Hello \" + marko_escapeXml(input.name) + \"!</div>\");\n}\n```\n\n#### Compiled for the browser\n\n<!-- prettier-ignore -->\n```js\nvar marko_template = require(\"marko/vdom\").t(__filename);\n\nfunction render(input, out) {\n  out\n    .e(\"DIV\", null, 3)\n    .t(\"Hello \")\n    .t(input.name)\n    .t(\"!\");\n}\n```\n\nThe compiled output is optimized for virtual DOM rendering in the browser:\n\n### Modular Runtime\n\nThe Marko runtime is not distributed as a single JavaScript file. Instead, the\nMarko compiler generates a JavaScript module that will only import the parts of\nthe runtime that are actually needed. This allows us to add new features to\nMarko without bloating existing applications. For example, given the following\ntemplate:\n\n```marko\n$ var color = 'red';\n<div style={backgroundColor: color}></div>\n```\n\nIn the above example, extra runtime code is needed to render the `style` attribute\nbased on the JavaScript object that is provided. The compiled code that imports\nthe `styleAttr` helper is shown below:\n\n```js\nvar marko_styleAttr = require(\"marko/runtime/vdom/helper-styleAttr\");\n\nfunction render(input, out) {\n  var color = \"red\";\n  out.e(\n    \"DIV\",\n    {\n      style: marko_styleAttr({\n        backgroundColor: color,\n      }),\n    },\n    0,\n    4,\n  );\n}\n```\n\n### High performance server-side rendering\n\nCompared to solutions based on JSX that exclusively do virtual DOM rendering,\nMarko has a huge advantage for server-side rendering. When rendering to a\nvirtual DOM tree on the server it’s a two-step process to render HTML:\n\n- First pass to produce an entire virtual DOM tree in memory\n- Second pass to serialize the virtual DOM tree to an HTML string that can then be\n  sent over the wire (this requires traversing the entire tree structure)\n\nIn contrast, Marko renders directly to an HTML stream in a single pass. There is\nno intermediate tree data structure.\n\n### Compile-time optimization of static sub-trees\n\nGiven the following template:\n\n```marko\n<div>This is a <strong>static</strong> node</div>\n```\n\nMarko will recognize that the template fragment produces the same output every\ntime and it will thus create the virtual DOM node once as shown in the following\ncompiled output:\n\n```js\nvar marko_node0 = marko_createElement(\"DIV\", null, 3, ...)\n  .t(\"This is a \")\n  .e(\"STRONG\", null, 1)\n    .t(\"static\")\n  .t(\" node\");\n\nfunction render(input, out) {\n  out.n(marko_node0);\n}\n```\n\nRendering a static sub-tree has virtually zero cost. In addition, Marko will\nskip diffing/patching static sub-trees.\n\nSimilarly, on the server, Marko will merge static parts of the template into a\nsingle string:\n\n```js\nfunction render(input, out) {\n  out.w(\"<div>This is a <strong>static</strong> node</div>\");\n}\n```\n\n### Compile-time optimization of static attributes\n\nMarko will also optimize static attributes on dynamic elements.\n\nGiven the following template:\n\n```marko\n<div.hello>Hello ${input.name}!</div>\n```\n\nMarko will produce the following compiled output:\n\n<!-- prettier-ignore -->\n```js\nvar marko_attrs0 = {\n  class: \"hello\"\n};\n\nfunction render(input, out) {\n  out\n    .e(\"DIV\", marko_attrs0, 3)\n    .t(\"Hello \")\n    .t(input.name)\n    .t(\"!\");\n}\n```\n\nNotice that the attributes object is only created once and it is used for every\nrender. In addition, no diffing/patching will happen for static attributes.\n\n### Smart compiler\n\nWith Marko we favor doing as much at compile-time as possible. This has made our\ncompiler more complex, but it gives us significant gains at runtime. We have\n~90% code coverage and over 2,000 tests to ensure that the compiler is working\ncorrectly. In addition, in many cases the Marko compiler provides hints to the\nruntime for a given template so that the runtime can optimize for specific\npatterns. For example, Marko recognizes if an HTML element only has `class`/`id`/`style` defined\nand the runtime optimizes for these virtual DOM nodes when doing\ndiffing/patching (the Marko compiler generates code that flags simple virtual\nDOM nodes for targeted diffing/patching logic).\n\n### Event delegation\n\nIf you are building a UI component you will likely need to write code to handle\nvarious DOM events (`click`, `submit`, etc.). It is common for developers to write code that\nadds DOM event listeners using `dom.addEventListener(...)` or using a library such as jQuery. You can still\ndo that when building UI components using Marko, but there is overhead in\nattaching listeners when lots of components are being initialized. Instead,\nMarko recommends using declarative event binding as shown below:\n\n```marko\n<button type=\"button\" on-click(\"handleClick\")>\n  Click Me\n</button>\n```\n\nWhen using declarative event binding, no DOM event listeners are actually\nattached for events that bubble. Instead, Marko attaches a single listener on\nthe root DOM element of the page for each DOM event that bubbles (done at\nstartup). When Marko receives an event at the root it handles delegating the\nevent to the appropriate components that are interested in that event. This is\ndone by looking at the `event.target` property to see where the event originated and then\nwalking up the tree to find components that need to be notified. As a result,\nthere is slightly more work that is done when a DOM event is captured at the\nroot, but this approach uses much less memory and reduces the amount of work\nthat is done during initialization. The extra overhead of delegating events to\ncomponents will not be noticeable so it is a very beneficial optimization.\n\n_Cover image credit: [Superhero by Gan Khoon Lay from the Noun Project](https://thenounproject.com/search/?q=superhero&i=690775)_\n","isInternal":false,"tokens":2076,"sizeBytes":8710},{"name":"AGENTS.md","path":"packages/runtime-tags/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-tags/AGENTS.md","title":"Runtime-tags Skill","category":"anthropic-skill","format":"markdown","content":"# Marko 6 (runtime & translator)\n\nPublished as `marko@6` and `@marko/runtime-tags`. Contains both the runtime and the Babel translator that generates code against it; most changes touch both halves plus test fixtures.\n\n## Layout\n\n| Directory         | Purpose                                                                                                                |\n| ----------------- | ---------------------------------------------------------------------------------------------------------------------- |\n| `src/common/`     | Types, accessor enums, helpers shared by both runtimes                                                                 |\n| `src/dom/`        | CSR runtime: scopes, signals, control flow, resume, scheduling                                                         |\n| `src/html/`       | SSR runtime: streaming writer, value serializer, resume boilerplate                                                    |\n| `src/translator/` | Babel translator: `core/` (built-in tags), `visitors/` (per AST node), `util/` (analysis), `interop/` (Marko 5 compat) |\n\nEntries: `src/dom.ts`, `src/html.ts`, `src/translator/index.ts`. Type stubs for core tags: `tags/*.d.marko`.\n\n## Architecture\n\n[CONTEXT.md](CONTEXT.md) is the canonical glossary — use its terms (and respect\nits _Avoid_ lists) in code, comments, and discussion. Read the\n[resume architecture guide](RESUMABILITY.md) before changing reference analysis,\nsignals, serialization, resume, lazy loading, or generated DOM output; it traces\nthe compiler/runtime model end to end and routes each concept to its code.\n\nPrinciples that decide most proposals:\n\n- Client code, serialized data, and registrations ship only where analysis shows they can run or update.\n- Code ships because code that ships references it, never by force. Never keep a call or declaration for its side effect (a registration, a stamp) or to make an optimized build work: a kept value pins its whole reference graph (signals, joins, renders, runtime), which in real apps bundles subgraphs the plain build drops, so a fixture's small size delta proves nothing. Deliver the fact the client needs instead (serialized data or a compiler literal). An unreferenced top-level declaration in an optimized bundle snapshot is this bug.\n- A build contract (an id the compiler registered) is a `MARKO_DEBUG` assert, never a production check, and needs no fixture faking its violation.\n- An optimization may take any shape that idiomatic Marko code cannot observe.\n- HTML output targets what browsers parse, not validators.\n- No API may require `import \"marko\"`.\n\n## Translator\n\nThe compiler phase contract is strict:\n\n| Phase       | Contract                                                                                                                           |\n| ----------- | ---------------------------------------------------------------------------------------------------------------------------------- |\n| Parse       | Create the initial hybrid Marko/Babel AST.                                                                                         |\n| `migrate`   | Apply userland and translator-provided Marko-to-Marko codemods that may be written back to disk.                                   |\n| `transform` | Apply typically userland Marko-to-Marko codemods that affect compilation only and must never be written back.                      |\n| Pre-analyze | Technically part of `transform`; normalize/simplify Marko before analysis when the analyzer or translator needs a canonical shape. |\n| `analyze`   | Annotate the AST, usually via `node.extra`, and compute output-neutral graph data: bindings, signals, ids, reasons.                |\n| `translate` | Convert Marko to JavaScript for the configured `dom` or `html` output.                                                             |\n\nEverything through `analyze` is cached and reused across outputs. Therefore:\n\n- Mutating AST structure during `analyze` is an anti-pattern; perform reshaping in pre-analyze.\n- Analyze records facts about the template, never nodes. Never retain an AST node or `NodePath` across phases, including inside `node.extra` (or program extra/`Section`/`Binding` fields): the analyzed AST is cached and `t.cloneNode`d for each output, so a stored node points at the cache while translate walks a clone — reads go stale and identity checks fail silently. The metadata shell itself (`node.extra` objects, `Section`s, `Binding`s) is shared by reference across clones, so record facts there — flags, ids, `Section`/`Binding` references — and resolve current nodes within the current phase. If the fact concerns a child whose metadata does not exist yet at your visitor, flag it from an analyze `exit` hook (children are analyzed by then) rather than storing the child node for later.\n- Never make output-specific decisions before `translate`. Branch on `dom`/`html` only while translating.\n- Reach the current compilation through `getFile()`/`getProgram()` (from `@marko/compiler/babel-utils`), never `path.hub.file`: the hub chain re-derives what the compile state already tracks and reads inconsistently across contexts. There are currently zero `hub.file` uses in the translator; keep it that way.\n- `file.metadata.marko` is public compiler output (returned from the top-level compile APIs): never route internal channels through it. Internal analyze products belong on the extras shell (program extra, `Section`, `Binding`); metadata carries only deliberately public facts.\n- Naming follows the same contract: analyze metadata (Binding/Section/`node.extra` fields) records **what the template does** — observed facts, in template terms (sources, reads, uses, shapes). Translate names its **conclusions** — decisions, policies, and output mechanisms (ownership, wire channels, masks). A shared field named after a decision (e.g. server/client \"owned\", \"required\") is a smell: name the observation and derive the decision where it is made. Never coin a term the compiler does not already use; a new concept gets a `CONTEXT.md` entry first.\n- Keys on `node.extra` say who may use them: a symbol key is one module's private state and is never exported; a fact any other module reads is a string field declared on its node kind's extra (`MarkoTagExtra`, `FunctionExtra`, or `NodeExtra` for an expression root).\n- The translator has no `MARKO_DEBUG` checks: its published build drops them, so a check guards only local development. Design the invariant out instead: derive the value from what makes it true, type it so a violation does not compile, or leave misuse no path.\n- Gather in analyze, act in translate. There are currently zero Babel `traverse` calls in the translator; keep it that way. Before adding analysis, find the fact in what exists (`Section`, a binding's reads/aliases/sources, `node.extra`, reasons, tag-name and known-tag analysis) and extend it; after adding one, check what else can use it.\n- Analyze facts settle once. `Binding.reads`, `Binding.pruned`, and reasons are complete only once `finalizeReferences` runs at program analyze `exit`, so tag and expression analyze visitors never read them; an expression's resolved references are read through `getReferencedBindings`/`getLazyBindings`, which finalize sets. One exception: a known tag's call site reads its callee's params tree during analyze, which is complete for another template or for a `<define>` called from outside its body; a recursive tag waits for program exit (`analyzeRecursiveTags`) to read it. A fact about the template is a field (`Section`, `Binding`, `node.extra`, the program's extra), written once it is final, never un-set, and never read for a fact it was not built for. `createAnalysisState` holds analyze scratch and caches derived from facts, which every output reads; `createOutputState` holds what one output builds; the `…SectionState` forms key either by section.\n- A tag records its client markup into its section's structure stream (`util/structure.ts`) in render order, passing `structure.node`/`structure.marker` the dom binding that holds each node client code addresses (`structure.controlFlowNode` addresses a control flow tag by its only-child element or a marker). DOM derives the template and walk string from the stream, and the walker stores each node it reaches at the next scope index, so `allocateIds` numbers a section's dom bindings in stream order: creation order never matters.\n- Pruning drops a binding nothing reads, with its value. Translate emits a read only of a binding analysis kept: check `pruned`, and write each read as analysis resolved it (`getReadReplacement`), never by a name the graph does not track.\n- Reference analysis (`util/references.ts`, `finalize-references.ts`, `solve-reasons.ts`) is tag-agnostic: a tag records a generic fact on its expression's `node.extra`, and the analysis reads it without naming the tag. Known tags are the one exception: the solver maps each call site's param reason groups every pass (`addKnownTagReasons`). `solveReasons` repeats its steps until no reason moves, so each step is named for what it adds, merges or ensures (`addClosureReasons`, `mergeSlotReasons`, `ensureSectionReasonGroups`); `finalize*` names work that runs once, on settled facts (`finalizeReferences`).\n- A program-wide effect (`isInteractive`, an imported registration) follows the reason that needs it, never a feature's presence. Only an unconditional reason makes a template a bundle root: a value written only while a caller changes params ships with that caller, which imports the template.\n- Compile-context helpers (`isOptimize`, `isOutputHTML`, `getMarkoOpts`, `callRuntime`) are called where needed, never passed in as overridable parameters. Non-capturing callbacks become named file-level functions here too.\n\nNode visitors live in `visitors/` and are split per phase by `extractVisitors` (`util/visitors.ts`); `visitors/tag/index.ts` dispatches to `native-tag.ts` / `custom-tag.ts` / `dynamic-tag.ts` / `attribute-tag.ts` or a tag definition's own hooks.\n\nCore tags are one file per tag in `core/`, registered in `core/index.ts`:\n\n```ts\nexport default {\n  analyze(tag) { ... },\n  translate: translateByTarget({\n    html(tag) { ... },\n    dom(tag) { ... },\n  }),\n} as Tag;\n```\n\n- `callRuntime(\"_name\", ...args)` (`util/runtime.ts`) references runtime helpers with automatic imports; DOM helpers listed in `pureDOMFunctions` get `/*@__PURE__*/`.\n- Validate early: core tags share their checks and wording from `util/assert.ts` (`assertOnlyValueAttr`, `assertHasBody`, `assertHasVar`, `assertNoSpreadAttrs`, …), while `assertNoArgs` / `assertNoParams` / `assertNoVar` / `assertAllowedAttributes` come from `@marko/compiler/babel-utils`. Compile errors use `path.buildCodeFrameError` with backticked names and a markojs.com docs link — `util/assert.ts` is the canonical style.\n- `util/marko-config.ts` provides `isOutputHTML` / `isOutputDOM` / `isOptimize`.\n- `util/optional.ts` (`Opt`/`Sorted` list algebra) underpins reference tracking; a list a `Sorted` instance builds (`bindingUtil`, `propsUtil`, `sectionUtil`, `sourcesUtil`) is looked up by binary search, so it is typed `SortedOpt` and only that instance can write it (`push`/`concat` results do not type-check into one). Work on these lists with its helpers (`forEach`, `some`, `reduce`, `filter`, the `Sorted` utils): build-then-`reverse` and dedupe-on-add are smells; `util/known-tag.ts` holds the custom/dynamic tag input contracts. Native element work lives in `visitors/tag/native-tag.ts` (with `common/helpers.ts` and `util/tag-facts.ts`).\n\n## Runtime conventions\n\n- **`_name` exports** are runtime API called by generated code — public to codegen, not to app authors. Renames must update `callRuntime` call sites and `pureDOMFunctions`.\n- **`MARKO_DEBUG`** gates all validation, descriptive names, and detailed error messages (`if (MARKO_DEBUG) { ... }`); builds strip these. Write for the optimized build: debug-only code never leaves it a temporary or branch, so return directly. It is `true` for code loaded through the `~ts` register hook; fixture bundles define it per mode (`false` under optimize). Runtime error helpers live in `common/errors.ts`.\n- **`.debug.ts` pairs**: source imports the `.debug` module (e.g. `common/types.ts` imports `./constants/accessor-prop.debug`); the production build remaps `X.debug` → `X.ts`. Both files must export identical member names with unique string values. `src/__tests__/debug-pairs.test.ts` checks every pair because the types cannot — each module's `Value` is `typeof import(\"./<itself>\")` and `translator/util/get-accessor-enums.ts` casts `as any` — so a member added to only one half would otherwise type-check and show up as `undefined` in an optimize build. A runtime record that needs readable debug keys uses a pair, extending the module for the object type that owns the property (repeated short values compress better).\n- **Optional feature enablement** (tree-shakable runtime API) has two patterns:\n  - **`src/{dom,html}/**/*.feat.ts`** are compiler-injected side-effect modules for behavior a referenced import cannot keep alive (catch handling, controllable registration). The build emits them as extra entries of their runtime's bundle — a shared chunk keeps one state instance, so they import runtime internals directly. A feature body is direct registry/property assignments (plus at most one installer call, e.g. `installCatch`); the compiler emits it once per program via `importRuntimeFeature` (typed by `DOMRuntimeFeature`). `lazy.feat` is the exception: `translator/util/entry-builder.ts` › `builder.build` imports it (via `getRuntimeFeatureImport`) into a resuming entry that reaches a lazy import, since resume needs its latch even when no bundled template references lazy runtime.\n  - **Definition-site wrappers** gate behavior on a helper's own retention: `export const _if = /*@__PURE__*/ withBranches(...)`.\n  - Latches are `let`s written only by their enabler (`branchesEnabled`, `catchEnabled`) so bundlers fold latch and guarded code away together; object-property flags defeat that analysis and re-inflate resume bundles.\n  - Never statically import control-flow or a `.feat` module from a main-graph module (queue, resume, load) — it fuses the feature into every bundle.\n  - Base helpers and the writer take no feature-only params, hooks, or flags (a feature-only param goes last). A `.feat` imports the features it always needs.\n- **Size idioms** (client runtime): inline a helper, `const`, or `let` used once, and repeat a short member read rather than binding it (gzip favors repetition). Prefer truthiness with `0`/`1` over `undefined`/booleans, default params, `||=`, `for (let i = n; i--;)`, and `else` over an early `return`. Give every parameterless arrow an unused parameter, consistently, since `e=>` minifies a byte under `()=>`: `(_?: never) =>` where callers pass nothing, else typed as what they pass; generated client code takes `getUnusedParamIdentifier()` (not an IIFE, which the minifier inlines only bare), and the inlined runtimes a free letter. Tell nodes apart with `nodeType >`/`<` against the `NodeType` enum (a marker is `> NodeType.Element`), never the DOM's constants. Settle byte questions by measuring with `build:sizes`, and weigh a byte by how often an app pays it: once (the runtime) counts least, per template (generated code, across an app's thousands of templates) more, and per rendered instance (serialized data, per loop row) most; a fixture's delta shows only the one-time cost.\n- **Hot paths** (SSR writer, serializer, resume): never `delete`, copy with spread/rest, `unshift`/`reverse`, take rest params per tag, or create a promise or closure unconditionally. Never post-process output with string `replace`/`split`/`indexOf`; the serializer appends valid JavaScript. Keep object shapes consistent; put cheap checks first.\n- **Wire bytes**: before serializing a link or field, derive it from what the client already knows (walk and insertion order, id order). Rare tuple slots go last so trailing-empty trimming drops them.\n- Named/top-level functions use `function` declarations; arrows only for closures that must capture or for wrapped feature helpers (smaller output). Extract non-capturing closures into named file-level functions.\n\n## Testing\n\nFixture-based snapshot tests driven by `src/__tests__/main.test.ts`. Fixtures live in `src/__tests__/fixtures/`, plus `fixtures-interop/` (Marko 5 ↔ 6 mixing, suite name `translator-interop`). A dir suffixed `.skip` is ignored.\n\nFrom the repo root:\n\n```sh\npnpm test                                                            # whole suite, fanned across CPU cores\npnpm test -- --grep \"runtime-tags/translator <fixture> \"             # one fixture (note trailing space)\npnpm run test:update -- --grep \"runtime-tags/translator <fixture> \"  # regenerate its snapshots\npnpm test -- --grep \"translator-interop\"                             # interop suite (run after base suite passes)\n```\n\nIterate scoped, then run `pnpm test` for everything; it fans across cores and reports every failure. Repeating a grep as `pnpm run test:serial -- --grep \"...\"` runs it in one process, with `bail: true` and live output, for a debugger or a clean stack trace.\n\n### Fixture anatomy\n\n```\nfixtures/<name>/\n  template.marko    # entry (required); custom tags under tags/\n  test.ts           # optional: export const config: TestConfig = { ... }\n  sizes.json        # generated compiled-size tracking\n  __snapshots__/    # generated + auto-pruned by test:update; never edit or delete by hand\n    dom.bundle[.debug].js       # compiled CSR output\n    html.bundle[.debug].js      # compiled SSR output\n    render[.debug].md           # per-step rendered HTML + granular mutation log + `## Console` output\n    writes[.debug].html         # SSR stream chunks (joined by <!-- FLUSH -->)\n    diagnostics[.debug].md      # debug-only meta.diagnostics (warnings/deprecations)\n    error-compile-{html,dom}[.debug].txt   # expected compile failure (error_compiler)\n    {ssr,csr}.error[.debug].txt            # expected render failure (error_html/error_dom)\n```\n\nAdding or removing a recoverable diagnostic or deprecation therefore fails a `diagnostics.md` snapshot in every fixture that carries one.\n\n`TestConfig` (see `main.test.ts`): `steps` (`[initialInput, ...]` where later steps are input updates, `(container) => {}` interactions, or async `Wait`/`Flush`/`Throws` controls), `error_compiler` (expect compile failure), `error_html` / `error_dom` (expect a render failure), `equivalent: false` (separate `render-ssr`/`render-csr` snapshots), `embedded`, `load_order` / `reject_load` (lazy-chunk ordering and failure), `fix_guide`, `skip_optimize` / `skip_dom` / `skip_html` / `skip_csr` / `skip_ssr`, `skip_parity` (debug intentionally logs a diagnostic optimize cannot), `runtime_id`. Each fixture runs in `debug` and `optimize` modes; CSR only runs in `debug`.\n\nTo add a fixture: create the dir + `template.marko` (+ `test.ts` with steps exercising the behavior), run `test:update` scoped to it, then **read the generated snapshots as part of your change** — the mutation log in `render.md` shows update granularity (an unexpected extra `UPDATE:`/re-render is a regression), and the `.bundle.js` diff shows generated-code cost. Name a fixture for the behavior it pins, not the repro that found it; it fails without the change, uses current syntax (never deprecated features), and gets async values from `__tests__/utils/resolve.ts` (`resolveAfter`, `rejectAfter`). The summary names each changed snapshot family and why it changed.\n\n## Workflows\n\n**New/changed core tag** (see the `<show>` tag commit for a full example):\n\n1. `translator/core/<tag>.ts` + register in `core/index.ts` (and `util/is-core-tag.ts`), and give it an entry in `util/tag-facts.ts`.\n2. Runtime helpers in `src/dom/` / `src/html/`, exported from `src/dom.ts` / `src/html.ts`; add to `util/runtime.ts` lists as needed.\n3. Several small fixtures covering static values, dynamic updates, nesting, and interaction with `<for>`/`<if>`.\n4. `pnpm run change` — user-facing changes need a changeset.\n5. Update `cheatsheet.md` (the LLM syntax reference shipped in the published package) when the change affects user-facing syntax, idioms, or guidance. Keep it dense: a line earns its place only by preventing a real mistake.\n6. Expect broad snapshot/`sizes.json` churn and an update to `packages/runtime-class/test/taglib-lookup/fixtures/getTagsSorted/expected.json` (interop taglib lookup).\n\n**Changing generated output**: iterate with `pnpm run compile -- -o dom -d file.marko` (and `-o html`), then `test:update` and audit snapshot diffs — output shape changes ripple through hundreds of fixtures; verify a sample by hand, don't rubber-stamp.\n\n**Changing runtime behavior**: find the covering fixtures by grepping `__tests__/fixtures` for the runtime helper or syntax; extend `steps` before touching the runtime so the mutation log captures the before/after.\n\n## Gotchas\n\n- `translator/util/bindings.ts` imports `toAccess` from `html/serializer.ts` — serializer key encoding changes affect the translator.\n- Adding an accessor enum member: keep the `src/common/constants/*[.debug].ts` pair in lockstep (same members, char vs. readable string values).\n- Size regressions count as review findings: check the fixture `sizes.json` diffs and root `.sizes.json` (updated by the pre-commit hook).\n- Language semantics questions (what a tag/attribute should do) are answered by the docs, not inferred: <https://markojs.com/llms.txt>.\n","isInternal":false,"tokens":4837,"sizeBytes":21645},{"name":"api-mapping.md","path":"skills/marko-5-to-6-migration/api-mapping.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/skills/marko-5-to-6-migration/api-mapping.md","title":"Marko-5-to-6-migration Skill","category":"anthropic-skill","format":"markdown","content":"# Marko 5 → Marko 6 API Mapping\n\nExhaustive translation reference. Marko 5 docs: <https://v5.markojs.com/docs/>; Marko 6 docs: <https://markojs.com/docs/> (append `.md` to any page URL for markdown). When unsure about Marko 6 behavior, check the docs — do not guess.\n\n## Template syntax\n\n| Marko 5                                                                                                     | Marko 6                                                                                                   | Notes                                                                                                                                                                                                                        |\n| ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `${expr}`                                                                                                   | `${expr}`                                                                                                 | unchanged (escaped)                                                                                                                                                                                                          |\n| `$!{expr}`                                                                                                  | `$!{expr}`                                                                                                | unchanged (unescaped; same XSS caution)                                                                                                                                                                                      |\n| `$ statement;` / `$ { ... }` scriptlet                                                                      | `<const/x=...>`, `<let/x=...>`, or an IIFE `<const/x=(() => { ... })()>` for multi-statement derivations  | Scriptlets are Class-only. Reassigned-during-render vars usually become a single `<const>` computing the final value                                                                                                         |\n| `static ...` / `static { }`                                                                                 | `static ...` / `static { }`                                                                               | unchanged (module scope, runs once)                                                                                                                                                                                          |\n| env guards (`typeof window` checks, browser-only `require`) and bundling-trick `component-browser.js` files | `server` / `client` statements: `client import \"./browser-only\"`, `server { ... }`                        | backported to Marko 5.38+ and neutral for interop classification — adopt in Class files **before** migrating; a `component-browser.js` that only exists to keep code out of the server bundle is a glorified `client import` |\n| `class { ... }` block                                                                                       | delete; migrate members per \"Component class API\" below                                                   |                                                                                                                                                                                                                              |\n| `style { ... }` / `style.scss { ... }` block                                                                | `<style>` / `<style.scss>` tag                                                                            | Marko 6 `<style>` additionally supports CSS Modules via a tag variable (`<style/styles>` → `styles.foo`) and reactive `${...}` values (compiled to CSS custom properties)                                                    |\n| `import x from \"<my-tag>\"`                                                                                  | unchanged                                                                                                 | Marko 6 adds lazy variant: `import X from \"<my-tag>\" with { load: \"visible#sel\" }`                                                                                                                                           |\n| `export ...`                                                                                                | unchanged                                                                                                 |                                                                                                                                                                                                                              |\n| attribute values `attr=expr`                                                                                | unchanged                                                                                                 | both parse values as JS expressions; in 6 an unparenthesized `>` inside a value is a parse hazard — wrap: `x=(a > b)`                                                                                                        |\n| spread `...expr`                                                                                            | unchanged                                                                                                 |                                                                                                                                                                                                                              |\n| `class=` / `style=` object & array values                                                                   | unchanged                                                                                                 |                                                                                                                                                                                                                              |\n| shorthand `.class` / `#id` (incl. `.icon-${name}`)                                                          | unchanged                                                                                                 |                                                                                                                                                                                                                              |\n| attribute arguments `attr(...)` (e.g. `on-click(\"m\")`, `no-update-if(x)`, `body-only-if(x)`)                | removed — the parenthesized-attribute syntax is Class-only                                                | see rows for each specific attribute                                                                                                                                                                                         |\n| `body-only-if(cond, tagName?)`                                                                              | conditional parent tag: `<${!cond && \"a\"} href=...>content</>`                                            | note the inversion: `body-only-if` drops the wrapper when `cond` is truthy; a falsy dynamic tag name renders content only                                                                                                    |\n| `key=\"name\"` (element/component reference)                                                                  | tag variable: `<div/name>`                                                                                | see \"Refs\" below                                                                                                                                                                                                             |\n| `key=\"name[]\"` (repeated)                                                                                   | tag variable inside `<for>`; iterate the hoisted var (`[...name]`)                                        |                                                                                                                                                                                                                              |\n| `key=expr` on children of `<for>`                                                                           | `by=` attribute on `<for>` itself (`by=\"id\"` or `by=(item) => item.id`)                                   |                                                                                                                                                                                                                              |\n| `on-event(\"method\", ...args)` / `on-event(fn)`                                                              | `onEvent() { ... }` or `onEvent=fn` function attributes                                                   | curried args become closure captures; `on-` dash-case still exists in 6 for case-preserving DOM event names (`on-DblClick`)                                                                                                  |\n| `once-event(...)`                                                                                           | no equivalent attribute                                                                                   | use a conditional handler (`onClick=!done && handler`) or `el().addEventListener(..., { once: true })` in a `<script>`                                                                                                       |\n| `no-update`, `no-update-if(...)`, `no-update-body`, `no-update-body-if(...)`, `attr:no-update`              | removed; updates are granular so most uses are obsolete                                                   | if the intent was \"Marko must not touch third-party-owned DOM\", give the library its own container element managed via `<lifecycle>`; if the intent was \"keep state/DOM alive while hidden\", use `<show>`                    |\n| `attr:scoped` (`id:scoped`, `for:scoped`, ...)                                                              | `<id/name>` tag + plain attributes (`id=name`, `for=name`)                                                |                                                                                                                                                                                                                              |\n| `<tag\\|params\\|>` body parameters                                                                           | unchanged                                                                                                 | Marko 6 adds tag _arguments_: `<${input.content}(a, b)/>` ↔ `<my-tag\\|a, b\\|>`                                                                                                                                               |\n| `<@section>` attribute tags                                                                                 | unchanged syntax; consumed as `input.section.content` (was `.renderBody`); repeated tags iterable in both | Marko 6: attribute tags inside `<if>`/`<for>` apply conditionally/repeatedly; typed with `Marko.AttrTag<T>`                                                                                                                  |\n| `<${dynamic}>` dynamic tags                                                                                 | unchanged                                                                                                 | in 6 a string always renders a _native_ tag; pass the component reference itself for custom tags                                                                                                                             |\n| `<${input.renderBody}/>`                                                                                    | `<${input.content}/>`                                                                                     | `content` also accepts attributes/arguments to pass tag parameters back                                                                                                                                                      |\n| PascalCase variables as tags `<MyTag/>`                                                                     | unchanged                                                                                                 |                                                                                                                                                                                                                              |\n| HTML/JS comments                                                                                            | unchanged (stripped)                                                                                      | literal comment: `<html-comment>` in both                                                                                                                                                                                    |\n| concise mode                                                                                                | unchanged in spirit                                                                                       | see <https://markojs.com/docs/reference/concise-syntax.md> for 6 specifics                                                                                                                                                   |\n| `<!-- use class -->` / `<!-- use tags -->`                                                                  | only meaningful under Marko 5 interop                                                                     | delete after the final flip to `marko@6`                                                                                                                                                                                     |\n\nNew in Marko 6 (no 5 equivalent — reach for these while converting):\n\n- `:=` bound attributes / change handlers (`value:=state`, refining form `value:parseFloat:=num`) — the controllable pattern.\n- Tag variables on custom tags via `<return>`; on native tags they expose a DOM-node getter.\n- `<show>` (toggle visibility, keep state/DOM), `<id>`, `<log>`, `<debug>`, `<define>`, `<try>`, `<lifecycle>`.\n- Controllable native attributes: `<input valueChange= checkedChange= checkedValueChange=>`, `<select value= valueChange=>`, `<textarea value=>`, `<details openChange=>`, `<dialog openChange=>`.\n- `$signal` (an `AbortSignal` for cleanup in any expression) and `$global`.\n- Lazy tag imports `with { load: \"visible|idle|media|on*|render\" }`.\n\n## Core tags\n\n| Marko 5                                     | Marko 6                                                                   | Notes                                                                                                                                              |\n| ------------------------------------------- | ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `<if(cond)>` / `<else-if(cond)>` / `<else>` | `<if=cond>` / `<else if=cond>` / `<else>`                                 | argument syntax → `value` attribute; `else-if` tag name → `else` with `if=` attribute                                                              |\n| `<for\\|item, index, list\\| of=list>`        | `<for\\|item, index\\| of=list>`                                            | third `list` param dropped; add `by=` for keyed diffing                                                                                            |\n| `<for\\|key, value\\| in=obj>`                | unchanged                                                                 |                                                                                                                                                    |\n| `<for\\|i\\| from=x to=y step=z>`             | unchanged; 6 adds exclusive `until=`                                      |                                                                                                                                                    |\n| `<while(cond)>`                             | removed                                                                   | restructure into `<for>` over a computed list/range                                                                                                |\n| `<macro\\|params\\| name=\"foo\">` + `<foo>`    | `<define/Foo\\|input\\|>` + `<Foo>`                                         | params become `input` properties/content                                                                                                           |\n| `<await(promise)>` + `<@then\\|res\\|>`       | `<await\\|res\\|=promise>`                                                  | body is the \"then\"                                                                                                                                 |\n| `<await>` `<@placeholder>`                  | `<try>` ancestor with `<@placeholder>`                                    | placeholder now lives on `<try>`, can wrap several awaits                                                                                          |\n| `<await>` `<@catch\\|err\\|>`                 | `<try>` ancestor with `<@catch\\|err\\|>`                                   |                                                                                                                                                    |\n| `<await client-reorder>`                    | automatic                                                                 | a `<try>` `@placeholder` opts into out-of-order streaming; no flag                                                                                 |\n| `<await timeout= show-after= name=>`        | removed                                                                   | implement timeouts on the promise itself (`AbortSignal.timeout` / `Promise.race`)                                                                  |\n| `<await-reorderer/>`                        | removed                                                                   | already implicitly injected by Marko 5 — explicit usages are redundant; delete unconditionally                                                     |\n| `<include-text('./f.txt')>`                 | bundler raw import (`import text from \"./f.txt?raw\"` in Vite) + `${text}` |                                                                                                                                                    |\n| `<include-html('./f.html')>`                | raw import + `$!{html}`                                                   | audit for XSS while converting                                                                                                                     |\n| `<init-components/>`                        | removed                                                                   | already implicitly injected by Marko 5 — explicit usages are redundant; delete unconditionally (Marko 6 emits hydration boilerplate automatically) |\n| `<module-code>`                             | removed                                                                   | library codegen hook; needs bespoke redesign (compiler hooks)                                                                                      |\n| `<html-comment>`                            | unchanged                                                                 | 6 version also exposes a comment-node tag variable                                                                                                 |\n| `<script>` (plain HTML script)              | `<html-script>`                                                           | in 6, `<script>` is the _effect_ tag (runs in browser, re-runs when referenced state changes)                                                      |\n| `<style>` (plain HTML style)                | `<html-style>`                                                            | in 6, `<style>` extracts to the CSS bundle                                                                                                         |\n| `<context>` (npm package)                   | no equivalent                                                             | pass data through `input` or `$global`                                                                                                             |\n\nIf the app used `@marko/tags-api-preview` (Tags API on Marko 5 before 6 shipped): remove that package; `<let>`/`<const>`/`<return>`/`<define>` carry over, `<effect>` → `<script>`, `<attrs>` → destructuring `<const/{...}=input>` (the Marko 6 compiler auto-fixes these two), and `<get>`/`<set>` context tags must be redesigned onto `input`/`$global`.\n\n## Component class API\n\nThe class (inline `class {}`, `component.js`, `component-browser.js`, or plain-object form) disappears entirely; each member maps to template-level constructs in the one `.marko` file.\n\n### State\n\n| Marko 5                                                     | Marko 6                                                                                                     |\n| ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |\n| `onCreate() { this.state = { a: 1, b: 2 } }`                | `<let/a=1>` `<let/b=2>` — one `<let>` per independently-changing key                                        |\n| read `state.a` / `this.state.a`                             | `a`                                                                                                         |\n| `this.state.a = v` / `setState(\"a\", v)` / `setState({ a })` | `a = v` (assignment is the reactive trigger)                                                                |\n| `setStateDirty(\"list\")` after mutation                      | intentionally no equivalent — make the update immutable: `list = [...list, item]`                           |\n| `replaceState(newState)`                                    | assign each `<let>`                                                                                         |\n| `shouldUpdate(input, state)`                                | none — updates are per-expression; if work must be gated, gate it in the deriving `<const>`/handler         |\n| `update_<name>(new, old)` partial-update handlers           | none — granular updates make them obsolete; side effects on change move to `<script>` reading that variable |\n| `this.forceUpdate()`                                        | none needed; state assignment schedules the update                                                          |\n| `this.update()` (sync flush)                                | none in-template (updates batch after a microtask); tests should await a tick                               |\n\nSerialization in 6 is **need-based, not blanket**: the compiler computes what must cross to the browser from what client-side code references (handlers, `<script>` bodies, reactive expressions, and their intersections) and serializes only that. Values that never reach client code aren't serialized at all. The practical rule while converting: anything browser code touches must be serializable (no class instances, DOM nodes, or server-only resources there) — see <https://markojs.com/docs/explanation/serializable-state.md>.\n\n### Derived data & input\n\n| Marko 5                                                                   | Marko 6                                                  |\n| ------------------------------------------------------------------------- | -------------------------------------------------------- |\n| `$ const full = a + b;`                                                   | `<const/full=a + b>`                                     |\n| `onInput(input) { input.x = normalize(input.x) }` (mutation anti-pattern) | `<const/x=normalize(input.x)>`                           |\n| `onInput` storing input into state (\"controllable\" components)            | `<let/x:=input.x>` — controllable let; see `patterns.md` |\n| `this.input` / template `input`                                           | `input` (unchanged)                                      |\n| template `state` variable                                                 | the individual tag variables                             |\n| template `component` variable                                             | none — every use maps to a specific pattern below        |\n| template `out` variable                                                   | none; `out.global` → `$global`                           |\n\nA Marko 5 getter (`get isFull() { return a + b >= max }`) recomputes on every read, so a handler that assigns `a` then reads `this.isFull` sees the new result. A `<const>` does not: within one handler it still holds its pre-assignment value until the update flushes, while the raw `<let>` reads back the value you just assigned. So after `moves = next`, `moves >= max` is current but a derived `<const/isFull=(moves >= max)>` is not — read the `<let>`s you just assigned (or recompute from them) inside the handler, never the derived `<const>`.\n\n### Lifecycle\n\n| Marko 5                                                                  | Marko 6                                                                                                                    |\n| ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------- |\n| `onMount() { ... }`                                                      | `<script>` (first run = mounted, browser-only) or `<lifecycle onMount() { ... }/>`                                         |\n| `onUpdate()`                                                             | `<script>` re-runs when any referenced tag variable/param changes; or `<lifecycle onUpdate>` (re-runs on its dependencies) |\n| `onDestroy()`                                                            | `$signal.onabort = () => {...}` inside `<script>`; or `<lifecycle onDestroy>`                                              |\n| `onRender(out)`                                                          | usually deleted — it was mostly used for derivations (→ `<const>`)                                                         |\n| `onCreate(input, out)`                                                   | initial values of `<let>` tags                                                                                             |\n| lifecycle _events_ (`this.on(\"update\", fn)`, `this.once(\"destroy\", fn)`) | same replacements as the methods                                                                                           |\n| `on-attach(fn)` on an element                                            | `<script>` or `<lifecycle onMount>` — both run with the element in the DOM                                                 |\n| `on-detach(fn)` on an element                                            | no equivalent — nothing can delay removal (see below)                                                                      |\n\nPrefer plain state and `<script>`; use `<lifecycle>` only to host imperative third-party instances (maps, charts) where a stable `this` across `onMount`/`onUpdate`/`onDestroy` is genuinely needed.\n\nExit animations need rework. Marko 5's `on-detach` handler could hold a node in the DOM (`event.preventDefault()`, then `event.detach()` once the animation finished); nothing in Marko 6 can delay removal — `<lifecycle onDestroy>` only observes teardown, and `<show=false>` parks its nodes in a detached fragment, so a transition never runs. Stage it in state instead: keep the item rendered while marking it exiting (`class={ exiting: id === leavingId }`), then drop it from the list in a `transitionend`/`animationend` handler.\n\n### Events\n\n| Marko 5                                                       | Marko 6                                                                                                                  |\n| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |\n| `this.emit(\"select\", a, b)`                                   | call the function prop: `(input.onSelect \\|\\| null)?.(a, b)` — declare `onSelect?: (a: A, b: B) => void` in `Input`      |\n| parent `<child on-select(\"handleSelect\")>` + class method     | `<child onSelect=handleSelect>` or `<child onSelect(a, b) { ... }>`                                                      |\n| parent `<child on-select(\"emit\", \"select\")>` (re-emit chains) | pass the prop through: `<child onSelect=input.onSelect>`                                                                 |\n| `this.on(...)` / `once` / `removeListener` on a component     | none — components are not emitters; use function props                                                                   |\n| `this.subscribeTo(window).on(\"resize\", fn)`                   | `<script>` + `window.addEventListener(\"resize\", fn, { signal: $signal })`                                                |\n| DOM `on-click(\"method\", extraArg)` on native tags             | `onClick(e) { method(extraArg, e) }` — handler receives the DOM event (and in 6, custom-tag conventions add the element) |\n| state-change notifications via emitted events                 | prefer the controllable pattern (`x` + `xChange`) — <https://markojs.com/docs/explanation/controllable-components.md>    |\n\nThe optional-handler idiom is `(input.onSelect || null)?.(a, b)`: handler attributes may legitimately be _falsy_, not just undefined (conditional handlers like `onClick=!clicked && handler` pass `false`), and `false?.()` still throws — `|| null` coerces any falsy value so the optional call short-circuits.\n\nEvent _naming_: Marko 5 events were dash-case strings (`on-page-change(\"m\")`); Marko 6 props are camelCase functions (`onPageChange=`). For published components this is a breaking API rename — call it out to consumers.\n\n### Refs & DOM access\n\n| Marko 5                                            | Marko 6                                                                                                                                                                                            |\n| -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `key=\"input\"` + `this.getEl(\"input\")`              | `<input/inputEl>` … `inputEl()` (getter; browser-only)                                                                                                                                             |\n| `this.getEls(\"item\")` + `key=\"item[]\"`             | tag variable inside the loop; iterate hoisted: `for (const el of item) ...` / `[...item]`                                                                                                          |\n| `this.el`                                          | tag variable on the root element                                                                                                                                                                   |\n| `this.getElId(...)` / `this.elId(...)` / `this.id` | `<id/myId>` (unique, SSR-stable string)                                                                                                                                                            |\n| `this.getComponent(\"child\")` / `getComponents`     | child exposes an API via `<return={ focus() {...} }>`; parent receives it as a tag variable: `<child/childApi>` … `childApi.focus()`. Often better: controllable props instead of imperative calls |\n| `component.appendTo(el)` etc. (DOM-insert mixins)  | `Template.mount(input, node, position)`                                                                                                                                                            |\n| `this.destroy()`                                   | `instance.destroy()` from `mount()`; inside templates, removal via `<if>`                                                                                                                          |\n| `this.isDestroyed()`                               | none; `$signal.aborted` covers most uses                                                                                                                                                           |\n| `this.rerender(...)` (legacy)                      | input-driven updates / `instance.update(input)`                                                                                                                                                    |\n\n## Legacy widget API (marko-widgets / `@marko/compat-v4`)\n\nNo interop and no automation — rewrite by hand. Mapping for the common members:\n\n| Widget API                                                               | Tags API                                                                                          |\n| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- |\n| `defineComponent({ template, ... })` / `defineWidget` / `defineRenderer` | a single `.marko` file                                                                            |\n| `init(config)` (browser attach)                                          | `<script>` (browser-only by construction)                                                         |\n| `getInitialState(input)`                                                 | `<let>` initial values                                                                            |\n| `getInitialProps(input, out)` / `getTemplateData(state, props)`          | `<const>` derivations from `input`                                                                |\n| `getWidgetConfig()`                                                      | plain values passed via attributes; state that must reach the browser is serialized automatically |\n| `w-bind` / `widget-types`                                                | the component boundary is the file itself                                                         |\n| `w-on-*` handlers                                                        | `onEvent=` function attributes                                                                    |\n| `w-id` / `this.getEl(id)`                                                | tag variables                                                                                     |\n| `widgetBody` / `w-body`                                                  | `content`                                                                                         |\n| `this.setProps(...)` / `this.rerender(...)`                              | input-driven updates from the parent                                                              |\n| `this.state = newState` (replace)                                        | assignments to `<let>` vars                                                                       |\n| jQuery `this.$()` helpers                                                | tag variable + direct DOM APIs (or the library inside `<lifecycle>`)                              |\n\n## Template & server API\n\n| Marko 5                                                                | Marko 6                                                                                                        | Notes                                                                                     |\n| ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |\n| `template.render(input)` (thenable out)                                | `template.render(input)`                                                                                       | 6 result: async-iterable + `.pipe(writable)` + `.toReadable()` + thenable + `.toString()` |\n| `template.render(input, callback)`                                     | `.then()` / `await`                                                                                            | callbacks removed                                                                         |\n| `template.render(input, stream)` / `template.stream(input).pipe(res)`  | `template.render(input).pipe(res)`                                                                             |                                                                                           |\n| `template.renderSync(input)` → `RenderResult`                          | `template.render(input).toString()`                                                                            | throws if anything async — same contract                                                  |\n| `template.renderToString(input)`                                       | `template.render(input).toString()`                                                                            |                                                                                           |\n| `renderResult.appendTo(el)` / `.getComponent()`                        | `template.mount(input, node, position?)` → `{ update(input), destroy(), value }`                               | `value` = the template's `<return>`                                                       |\n| `template.mount(input, el, pos)`                                       | unchanged shape                                                                                                |                                                                                           |\n| `out.global` / `$global`                                               | `$global`                                                                                                      | still passed as `input.$global` at the render call                                        |\n| `$global.serializedGlobals = { key: true }`                            | unchanged                                                                                                      | still the opt-in for serializing globals to the browser                                   |\n| `$global.componentIdPrefix` / `widgetIdPrefix`                         | `$global.renderId`                                                                                             |                                                                                           |\n| `$global.runtimeId` / CSP `cspNonce`                                   | unchanged                                                                                                      |                                                                                           |\n| `out.write(...)`, `out.beginAsync()`, `out.script(...)`, `out.flush()` | removed                                                                                                        | restructure with `<await>`/templates; escalate custom streaming code                      |\n| `require(\"marko/components\").init()` browser bootstrap                 | removed                                                                                                        | bundler plugin emits hydration automatically                                              |\n| `marko/node-require`                                                   | `@marko/compiler/register`                                                                                     | already the guidance in late 5                                                            |\n| `marko/env` (`isDebug`)                                                | none                                                                                                           | use bundler-provided env (`process.env.NODE_ENV`)                                         |\n| express `res.marko(template, input)` (`@marko/express`)                | verify the integration package's Marko 6 support; otherwise `template.render({ ...input, $global }).pipe(res)` | set `content-type` yourself when piping manually                                          |\n\n## Taglib & package metadata\n\n| Marko 5                                                         | Marko 6                                                                                                                                                                                                                                               |\n| --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| relative discovery from `components/`                           | from `tags/` (`tags/NAME.marko`, `tags/NAME/index.marko`, one grouping-folder level allowed)                                                                                                                                                          |\n| `marko.json` `\"tags-dir\": \"./dist/components\"`                  | `marko.json` `\"exports\": \"./dist/tags\"` — for **published `node_modules` tag libraries only**; `tags-dir` still works in both majors but is discouraged, and apps need no `marko.json`                                                                |\n| `marko-tag.json` attribute/nested-tag declarations              | delete; type everything via `export interface Input` (`Marko.AttrTag<T>` for attribute tags)                                                                                                                                                          |\n| `marko-tag.json` compiler hook overrides (`transform`, codegen) | custom compiler work — escalate                                                                                                                                                                                                                       |\n| `browser.json`                                                  | delete; use a modern bundler plugin                                                                                                                                                                                                                   |\n| `marko.json` `\"script-lang\": \"ts\"`                              | unchanged — but it exists for **incremental TS adoption** (opting folders in/out); a project `tsconfig.json` already makes `.marko` files TypeScript, and published packages normally ship compiled `.d.marko` types instead of setting `script-lang` |\n| adjacent `style.css` / `foo.style.css` supporting files         | unchanged                                                                                                                                                                                                                                             |\n\n## TypeScript\n\n| Marko 5                                                   | Marko 6                                                                                       |\n| --------------------------------------------------------- | --------------------------------------------------------------------------------------------- |\n| `export interface Input`                                  | unchanged                                                                                     |\n| `Marko.Component<Input, State>` base class                | removed with the class                                                                        |\n| `State` types                                             | become the inferred/annotated types of `<let>` values                                         |\n| `renderBody?: Marko.Body`                                 | `content?: Marko.Body` (params: `Marko.Body<[Arg1, Arg2]>`)                                   |\n| `Marko.Input<\"button\">`                                   | still exists; `Marko.HTML.Button` etc. is the common spelling for extending native tag inputs |\n| `Marko.AttrTag<T>` / deprecated `Marko.RepeatableAttrTag` | `Marko.AttrTag<T>` (always iterable)                                                          |\n| `Marko.Out`, `Marko.Emitter`, `Marko.RenderResult`        | removed in 6 (available from `marko@5` during interop)                                        |\n| `@marko/type-check` (`mtc`) CLI                           | works for both                                                                                |\n\n## Already deprecated in Marko 5 (clear these first)\n\nThese warn under `MARKO_DEBUG` in Marko 5 and have no future in 6 — fix them while still on 5 (Step 2 of the skill):\n\n- `data` template variable → `input` (auto-fixed by the 5 compiler's migrate stage).\n- `this.els` → `getEls(...)`; `getEl` reaching into child components; `getComponent` with repeated `key[]`; non-string `key` values.\n- `RenderResult.html` → `.toString()`; `RenderResult.context` → `.out`; `getWidget`/`getWidgets` → `getComponent`/`getComponents`.\n- `<await>` with a callback argument → pass a promise.\n- String values for spread/dynamic attributes → objects.\n- `marko/compiler` → `@marko/compiler`; `marko/node-require` → `@marko/compiler/register`.\n- `browser.json` `require:` paths → `marko-dependencies:` (or better: leave `browser.json` behind entirely).\n","isInternal":false,"tokens":6115,"sizeBytes":46950},{"name":"interop.md","path":"skills/marko-5-to-6-migration/interop.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/skills/marko-5-to-6-migration/interop.md","title":"Marko-5-to-6-migration Skill","category":"anthropic-skill","format":"markdown","content":"# Marko 5 ↔ 6 Interop (Incremental Migration)\n\nHow one Marko 5 app runs Class API and Tags API files together, and how to migrate through that state without regressing. Official doc: <https://markojs.com/docs/guide/marko-5-interop.md>. Source of truth for classification: `packages/runtime-tags/src/translator/interop/feature-detection.ts` in the marko repo.\n\n## Mental model\n\n- The interop is a **coexistence layer, not a converter**. The compiler classifies each `.marko` file as Class or Tags, compiles it with the matching translator, and inserts a runtime compat shim wherever a component of one API is rendered from a file of the other.\n- Classification is **per file** and all-or-nothing. A file cannot mix APIs; conflicting signals are a **compile error** (\"Cannot mix Tags API and Class API features in the same file\", with code frames pointing at both offending features). The heuristics are not a precedence list that picks a winner.\n- Pages that contain both APIs ship **both runtimes** and hydrate twice (a Marko 6 `init` and a Marko 5 `init`). Each Class↔Tags boundary also serializes extra scope-mapping data. This is fine as a transition state and wrong as an end state — keep boundaries few, and prefer converting whole subtrees.\n\n## Enabling\n\nNothing to configure. Modern `marko@5` (5.39+) depends on `@marko/runtime-tags` and its `marko/translator` entry wraps the Class translator with the interop translator. An app whose only Marko runtime dependency is `marko` (v5) gets interop automatically; an app that depends only on `@marko/runtime-tags`/`marko@6` gets **no** Class support.\n\nLazy tag imports (`with { load: ... }`) additionally rely on the `linkAssets` compiler option, which the bundler integrations (`@marko/vite`, `@marko/run`, `@marko/webpack`) provide — not something to set by hand. Lasso works with both APIs but does not provide `linkAssets`, so on it a `with { load }` import compiles as a normal eager import rather than code-splitting.\n\n## File classification rules\n\nEvaluated per file:\n\n1. **`tags/` directory seed.** A file under a `tags/` directory is seeded as Tags API — unless a `components/` directory sits _between_ the `tags/` dir and the file (`tags/components/x.marko` is _not_ seeded; this is the escape hatch for vendored Class code inside a tags tree), or that `tags/` dir is declared as a manual `tagsDir` in a `marko.json`.\n2. **Body scan.** The whole template (including nested tag bodies and attribute tags) is scanned in document order; every signal found is recorded, and signals from both APIs anywhere in one file are the mixing compile error.\n   - **Class signals**: a `// use class` / `<!-- use class -->` comment (exact trimmed match); a non-`static` `$ scriptlet;`; a `class {}` block; a `style { ... }` / `style.ext { ... }` block; any attribute _argument_ (`onClick(\"handler\")`, `no-update-if(x)`); one of these tags: `<await-reorderer>` `<class>` `<include-html>` `<include-text>` `<init-components>` `<macro>` `<module-code>` `<while>`.\n   - **Tags signals**: a `// use tags` / `<!-- use tags -->` comment; any tag variable (`<div/el>`); any bound attribute (`:=`); one of these tags: `<const>` `<debug>` `<define>` `<id>` `<let>` `<lifecycle>` `<log>` `<return>` `<try>`.\n   - `static`, `server`, and `client` statements and plain `<style>` elements are neutral — they force nothing and work in both APIs (`server`/`client` were backported to Marko 5.38+).\n3. **Ambiguous fallback.** A file with no signals (pure markup) is Tags **only if** every tag-discovery directory visible from it is a `tags/` dir; if even one `components/` dir exists anywhere in scope, ambiguous files default to **Class**. In a typical migrating app (which still has `components/` dirs), every ambiguous file is Class — so converted-but-signal-free files silently compile as Class. Pin such files with `// use tags`.\n\nPractical rules that follow:\n\n- Put every new/converted Tags file under a `tags/` directory, or make sure it contains a real Tags signal, or add `// use tags`.\n- When converting a file, convert it **completely** — one leftover `$ scriptlet` or `key=\"x\"` handler argument next to a new `<let>` is a build break, and one leftover neutral file is a silent Class fallback.\n- Route files (`+page.marko`, `+layout.marko`, express-rendered page templates) are frequently ambiguous — pin them explicitly in both directions during the transition.\n\n## Crossing the boundary\n\n### Tags parent → Class child\n\nUse the Class tag like any custom tag. The compat shim translates automatically:\n\n- Attributes pass through as the child's `input`.\n- The Tags body becomes the child's `input.renderBody`.\n- `onFoo=fn` / `onFoo(){}` / `on-foo(){}` attributes are converted to Class custom-event subscriptions: the child's `this.emit(\"foo\", a, b)` invokes the function with `(a, b)`. (`onClick` → event `\"click\"`, `on-Foo` → event `\"Foo\"` preserving case.)\n- Tag parameters work: `<class-layout|a, b|>` receives what the Class child passes via `<${input.renderBody}(a, b)/>`.\n- Split components (`component-browser.js`) hydrate and stay interactive.\n- A Class child with _no_ component (no `class {}`, no state, no handlers — an \"inert\" template) costs almost nothing: it renders on the server and is dropped from client bundles unless a Tags-side update forces re-render (in which case the compat morphs its DOM in place).\n\nYou cannot use Class-only _syntax_ on the call site (it's a Tags file): no `on-foo(\"stringMethod\")`, no `key=`-based `getComponent` into the child. If the parent needs to call into the child imperatively, that child is a good next conversion candidate (then expose `<return>`).\n\n### Class parent → Tags child\n\nAlso plain custom-tag usage, with these rules:\n\n- Attributes pass through as `input`; the Class body becomes the child's `input.content` (renamed from `renderBody` by the shim); attribute tags and tag parameters cross over.\n- Pass event handlers as **function-valued attributes** — the Tags child just calls `input.onSelect(...)`. Both of these compile and work in a Class API file (verified):\n  - `<tags-child onSelect(sel) { component.handleSelect(sel) }/>` (method shorthand — it is not a Class/Tags classification signal)\n  - `<tags-child onSelect=component.handleSelect.bind(component)/>`\n- **Do not use Class-style event bindings on Tags children.** `<tags-child on-select(\"handleSelect\")/>` compiles without error but never fires: it registers a Class custom-event subscription, and Tags components call function props instead of emitting events. This is a silent dead binding — audit for it when converting a child that Class parents consume.\n- Dynamic tags work, including conditional ones: `<${state.show && TagsChild}/>`.\n- Hydration needs no explicit wiring: Marko 5 injects its init/reorderer boilerplate implicitly, and on mixed pages the interop entry emits both hydrate programs. Explicit `<init-components/>` / `<await-reorderer/>` tags in templates are redundant — delete them on sight (they are also Class-only classification signals, so they block converting the file they sit in).\n\n### Hard limitations\n\n- **No async across the seam.** A pending promise (an `<await>` still unresolved) crossing the compat boundary throws `Cannot serialize promise across tags/class compat layer` at render time. Keep each `<await>` and everything it feeds on one side of the boundary.\n- **No shared component registry.** `getComponent`/`getComponents` cannot see Tags children; Tags tag variables cannot point at Class children (no `<return>` there). Communicate across the seam with attributes and function props only.\n- **`$global` / `out.global` is shared** — that part crosses cleanly in both directions.\n- Both runtimes ship while mixed; treat bundle size regressions during migration as expected and temporary, but budget them.\n\n## Incremental order of work\n\n1. **Foundation** (see SKILL.md Step 2): latest `marko@5`, modern bundler, deprecations cleared, legacy widgets rewritten, baseline recorded.\n2. **Create `tags/` directories** next to existing `components/`. This is non-disruptive: ambiguous files still default to Class as long as any `components/` dir exists.\n3. **Convert leaf components first** — inert/presentational ones are nearly free, then stateful leaves. Their Class parents keep consuming them through the shim without changes (though renamed events — `on-select` → `onSelect=` — do require touching call sites; do parent call-site edits in the same increment).\n4. **Work subtree-by-subtree, bottom-up**, so that Tags components mostly reference Tags components. A good increment: one page's component cluster, converted leaves-to-root, parents last.\n5. **Flip pages/layouts last.** Once a page's subtree is all Tags, convert the page file and pin it with `// use tags` if it ends up signal-free.\n6. **Bridge unconverted third-party stragglers with [`patch-package`](https://github.com/ds300/patch-package)** when practical: convert the small blocking module inside `node_modules`, commit the patch, and upstream the change — this keeps the final flip unblocked without forking.\n7. **Track the remaining Class surface** with the Step 1 inventory greps after each increment; the numbers only go down.\n8. When zero Class files remain, run the full-migration finish line (swap to `marko@6`, rename `components/` → `tags/`, remove pin comments and interop-era workarounds).\n\nDuring the whole period: new features are written Tags-first in `tags/`, and no new Class API code gets merged.\n\n## Troubleshooting\n\n| Symptom                                                                         | Cause                                                                                                                                                       | Fix                                                                                                                               |\n| ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |\n| `Cannot mix Tags API and Class API features in the same file` (two code frames) | leftover Class syntax in a converted file (scriptlet, `style {}`, attribute argument, `<macro>`/`<while>`/...) or a Tags construct pasted into a Class file | finish the conversion; the two frames point at the exact conflicting features                                                     |\n| Converted file renders but behaves like Class / new syntax rejected             | file is ambiguous and fell back to Class (a `components/` dir exists somewhere in scope)                                                                    | move under `tags/` or add `// use tags`                                                                                           |\n| File under `tags/` refuses Tags syntax                                          | a `components/` segment between the `tags/` dir and the file, or that dir is a `marko.json` `tagsDir`                                                       | check the full path and `marko.json`s up the tree                                                                                 |\n| `Cannot serialize promise across tags/class compat layer`                       | `<await>`/async content crossing the API boundary                                                                                                           | resolve the promise fully on one side; move the `<await>` into the same API as the content it wraps                               |\n| Class child inside Tags parent renders but is dead (no events)                  | its hydration was skipped — often it looked inert (no serialize reason)                                                                                     | upgrade `marko` — this had fixes in 5.39.x; confirm the child actually has a component; report upstream if reproducible on latest |\n| Tags child inside Class page doesn't hydrate                                    | bundler entry isn't the interop hydrate output (both `init` programs are emitted by the interop entry builder, not by any template-level tag)               | check the bundler integration is current and the page's hydrate entry is generated by it                                          |\n| `with { load }` component loads eagerly instead of code-splitting               | no `linkAssets` (eg `@marko/vite` with `linked: false`, or lasso), so lazy loading degrades to an eager import                                              | use `@marko/vite` (linked)/`@marko/run`/`@marko/webpack` to code-split; the eager fallback is otherwise harmless                  |\n| Duplicate/large client bundles                                                  | both runtimes on the page (expected while mixed); or boundaries scattered across many small islands                                                         | consolidate: convert whole subtrees; finish the migration                                                                         |\n","isInternal":false,"tokens":2779,"sizeBytes":13308},{"name":"patterns.md","path":"skills/marko-5-to-6-migration/patterns.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/skills/marko-5-to-6-migration/patterns.md","title":"Marko-5-to-6-migration Skill","category":"anthropic-skill","format":"markdown","content":"# Conversion Patterns\n\nWorked Marko 5 → Marko 6 conversions for the recurring component shapes. Each shows the Class API original, the Tags API result, and the traps. Combine as needed — real components mix several shapes.\n\n## Stateful component\n\n```marko\n/* marko 5 */\nclass {\n  onCreate() {\n    this.state = { count: 0 };\n  }\n  increment() {\n    this.state.count++;\n  }\n}\n\n<button on-click(\"increment\")>\n  Count: ${state.count}\n</button>\n```\n\n```marko\n/* marko 6 */\n<let/count=0>\n\n<button onClick() { count++ }>\n  Count: ${count}\n</button>\n```\n\nOne `<let>` per independently-updating state key. Reads of `state.x` become `x`; writes become plain assignment. Methods that only served as event handlers become inline handlers or `<const/fn() { ... }>` when shared.\n\n**Trap:** mutation. `this.state.list.push(x)` + `setStateDirty(\"list\")` must become `list = [...list, x]` — in Marko 6 only assignment triggers updates, and there is deliberately no dirty-marking escape hatch.\n\n## Derived values\n\n```marko\n/* marko 5 */\n$ const total = input.items.reduce((sum, item) => sum + item.price, 0);\n$ const formatted = total.toFixed(2);\n<div>Total: $${formatted}</div>\n```\n\n```marko\n/* marko 6 */\n<const/total=input.items.reduce((sum, item) => sum + item.price, 0)>\n<const/formatted=total.toFixed(2)>\n<div>Total: $${formatted}</div>\n```\n\nMulti-statement scriptlets that build one value collapse into an IIFE: `<const/list=(() => { ...; return list })()>`. Components that \"normalized\" input by mutating it in `onInput(input)` become `<const>` derivations — never mutate `input`.\n\nDestructuring input is the standard opener of a converted file:\n\n```marko\n<const/{ label, disabled = false, ...restAttrs } = input>\n```\n\n## Controllable state (state initialized from input + change events)\n\nThe Class API pattern of copying input into state and emitting on change:\n\n```marko\n/* marko 5 */\nclass {\n  onCreate(input) {\n    this.state = { open: input.open || false };\n  }\n  onInput(input) {\n    this.state.open = input.open || false;\n  }\n  toggle() {\n    this.setState(\"open\", !this.state.open);\n    this.emit(\"toggle\", { open: this.state.open });\n  }\n}\n\n<button on-click(\"toggle\")>Toggle</button>\n<if(state.open)>\n  <div>Drawer content</div>\n</if>\n```\n\nbecomes a controllable `<let>`:\n\n```marko\n/* marko 6 */\nexport interface Input {\n  open?: boolean;\n  openChange?: (open: boolean) => void;\n}\n\n<let/open=input.open || false valueChange=input.openChange>\n\n<button onClick() { open = !open }>Toggle</button>\n<if=open>\n  <div>Drawer content</div>\n</if>\n```\n\nWhen no default/transform is needed, the shorthand `<let/open:=input.open>` is equivalent. Semantics: with no `openChange` from the parent, the component owns its state (uncontrolled); when the parent passes `openChange`, the parent owns it (controlled) and `open` tracks `input.open`.\n\nCall sites:\n\n```marko\n/* parent.marko (marko 5, via interop) */\n<drawer open=state.drawerOpen openChange(open) { component.handleOpenChange(open) }/>\n```\n\nNote the Class API parent passes `openChange` as a **function attribute** — the converted child reads `input.openChange` and emits no events, so a Class-style `on-open-change(\"handleOpenChange\")` binding would compile but never fire (see `interop.md`).\n\n```marko\n/* parent.marko (marko 6) */\n<let/drawerOpen=false>\n<drawer open:=drawerOpen/>\n```\n\n**Traps:** name the change handler `<prop>Change` (that is what `:=` desugars to — `openChange`, `valueChange`); a differently-named event (`on-toggle`) forfeits the shorthand. Marko 5 events conventionally wrapped payloads (`{ originalEvent, open }`) — Marko 6 passes plain arguments; document the new signature for consumers.\n\n## Element refs and focus\n\n```marko\n/* marko 5 */\nclass {\n  focusName() {\n    this.getEl(\"name\").focus();\n  }\n}\n\n<input key=\"name\" placeholder=\"Name\"/>\n<button on-click(\"focusName\")>Focus</button>\n```\n\n```marko\n/* marko 6 */\n<input/nameInput placeholder=\"Name\">\n<button onClick() { nameInput().focus() }>Focus</button>\n```\n\nThe tag variable is a **getter function** (`nameInput()`), browser-only. For repeated elements (`key=\"opt[]\"` + `getEls(\"opt\")`), the hoisted variable is iterable:\n\n```marko\n<for|opt, i| of=input.options>\n  <input/optEl value=opt>\n</for>\n\n<button onClick() {\n  for (const el of optEl) console.log(el.value);\n  [...optEl][0]?.focus();\n}>Read all</button>\n```\n\n`getElId()` / `id:scoped` uses become the `<id>` tag:\n\n```marko\n<id/inputId>\n<label for=inputId>Name</label>\n<input id=inputId>\n```\n\n## Global listeners, timers, effects\n\n```marko\n/* marko 5 */\nclass {\n  onMount() {\n    this.subscribeTo(window).on(\"resize\", this.onResize.bind(this));\n    this.timer = setInterval(() => this.tick(), 1000);\n  }\n  onDestroy() {\n    clearInterval(this.timer);\n  }\n  onResize() { this.setState(\"width\", window.innerWidth); }\n  tick() { this.setState(\"now\", Date.now()); }\n}\n```\n\n```marko\n/* marko 6 */\n<let/width=0>\n<let/now=Date.now()>\n\n<script>\n  window.addEventListener(\"resize\", () => { width = window.innerWidth }, { signal: $signal });\n\n  const timer = setInterval(() => { now = Date.now() }, 1000);\n  $signal.onabort = () => clearInterval(timer);\n</script>\n```\n\n`<script>` runs in the browser after mount and **re-runs whenever a tag variable it references changes**; `$signal` aborts on cleanup (before re-run and on removal). Keep effect scripts free of incidental state reads or they re-run more than intended — split unrelated effects into separate `<script>` tags.\n\n## Third-party imperative libraries\n\nWhen an instance must persist across updates (charts, maps, editors), `<script>` re-running is the wrong shape — use `<lifecycle>`:\n\n```marko\n/* marko 5 */\nclass {\n  onMount() {\n    this.chart = new Chart(this.getEl(\"canvas\"), { data: this.input.data });\n  }\n  onUpdate() {\n    this.chart.setData(this.input.data);\n  }\n  onDestroy() {\n    this.chart.destroy();\n  }\n}\n\n<canvas key=\"canvas\"/>\n```\n\n```marko\n/* marko 6 */\nclient import { Chart } from \"chart-lib\"\n\n<canvas/canvas/>\n<lifecycle\n  onMount() {\n    return { chart: new Chart(canvas(), { data: input.data }) };\n  }\n  onUpdate() {\n    this.chart.setData(input.data);\n  }\n  onDestroy() {\n    this.chart.destroy();\n  }\n/>\n```\n\n`this` is stable across the three hooks; `onMount`'s returned object merges into it. `onUpdate` re-runs when its own referenced dependencies change. The `client import` keeps the library out of the server bundle (replaces `component-browser.js` tricks).\n\n## Attribute tags (named/nested content)\n\n```marko\n/* marko 5: my-menu.marko + marko-tag.json declaring \"@item\" */\n<ul>\n  <for|item| of=input.item>\n    <li on-click(\"handleSelect\", item.value)>\n      <${item.renderBody}/>\n    </li>\n  </for>\n</ul>\n```\n\n```marko\n/* marko 6: my-menu.marko (marko-tag.json deleted) */\nexport interface Input {\n  item?: Marko.AttrTag<{\n    value: string;\n    content?: Marko.Body;\n  }>;\n  onSelect?: (value: string) => void;\n}\n\n<ul>\n  <for|item| of=input.item>\n    <li onClick() { (input.onSelect || null)?.(item.value) }>\n      <${item.content}/>\n    </li>\n  </for>\n</ul>\n```\n\nCall sites are unchanged (`<my-menu><@item value=\"a\">A</@item>...</my-menu>`). The type declarations from `marko-tag.json` (`\"@item <item>[]\"`, attribute lists) move into `Input` with `Marko.AttrTag<T>`; repeated tags are consumed by iterating the singular property. `(input.onSelect || null)?.(...)` is the standard optional-handler call — handler props may be conditionally _falsy_, and `false?.()` would throw.\n\n## Async content (`<await>`)\n\n```marko\n/* marko 5 */\n<await(getUser()) client-reorder>\n  <@placeholder>Loading…</@placeholder>\n  <@then|user|>Hi ${user.name}</@then>\n  <@catch|err|>${err.message}</@catch>\n</await>\n```\n\n```marko\n/* marko 6 */\n<try>\n  <await|user|=getUser()>\n    Hi ${user.name}\n  </await>\n\n  <@placeholder>Loading…</@placeholder>\n  <@catch|err|>${err.message}</@catch>\n</try>\n```\n\nThe body of `<await>` is the \"then\"; placeholder and error handling move to a wrapping `<try>` (which may cover several awaits). A `@placeholder` opts the section into out-of-order streaming automatically — `client-reorder`, `<await-reorderer>`, `timeout=`, and `show-after=` are removed (implement timeouts on the promise itself, e.g. `AbortSignal.timeout`). Explicit `<await-reorderer/>` (and `<init-components/>`) tags were implicitly injected by Marko 5 anyway — delete them unconditionally, even before migrating.\n\n**Interop trap:** while mixed 5/6, keep an `<await>` and the components it renders on the same side of the Class/Tags boundary — pending promises cannot cross it.\n\n## Split components (`component-browser.js`)\n\nMarko 5 split components separate server-safe rendering from browser behavior:\n\n```text\ncomponents/fancy-toggle/\n  index.marko            # template + component.js lifecycle\n  component-browser.js   # onMount/onUpdate + handlers, browser-only bundle\n```\n\nSplit components exist for two different reasons — treat them differently:\n\n1. **A glorified `client import`.** Many `component-browser.js` files carry no real lifecycle logic; they exist only to keep browser-only code out of the server bundle. Replace these directly with a `client import` in the template — even **before** migrating, since `server`/`client` statements were backported to Marko 5 (5.38+) and are neutral for interop classification:\n\n   ```marko\n   client import \"./browser-only-setup\"\n   ```\n\n2. **Real browser lifecycle** (`onMount`/`onUpdate` + handlers). These collapse into `index.marko` during conversion. There is nothing to preserve about the split itself: targeted compilation already generates separate server/client outputs per template, and only the reactive/handler code ships to the browser.\n\nEither way the end state is one `.marko` file: browser-only imports become `client import`, server-only ones `server import`. Convert the template plus _both_ JS files as one unit using the patterns above, then delete the JS files.\n\n## Parent calls child methods (`getComponent`)\n\n```marko\n/* marko 5 parent */\nclass {\n  reset() {\n    this.getComponent(\"picker\").setColor(\"#ffffff\");\n  }\n}\n<color-picker key=\"picker\"/>\n<button on-click(\"reset\")>Reset</button>\n```\n\nMarko 6 children export an API with `<return>`, received as a tag variable:\n\n```marko\n/* color-picker.marko (marko 6) */\n<let/color=\"#ff8000\">\n<input type=\"color\" value:=color>\n<return={ setColor(c) { color = c } }/>\n```\n\n```marko\n/* parent.marko (marko 6) */\n<color-picker/picker/>\n<button onClick() { picker.setColor(\"#ffffff\") }>Reset</button>\n```\n\nBefore reaching for this, check whether the controllable pattern (`color:=`) removes the need for imperative calls entirely — it usually does.\n\n## Legacy widgets (marko-widgets / `@marko/compat-v4`)\n\n```js\n// marko 5-era legacy widget (widget.js)\nmodule.exports = require(\"marko-widgets\").defineComponent({\n  template: require(\"./template.marko\"),\n  getInitialState(input) {\n    return { expanded: !!input.expanded };\n  },\n  init() {\n    this.el.classList.add(\"ready\");\n  },\n  handleHeaderClick() {\n    this.setState(\"expanded\", !this.state.expanded);\n  },\n});\n```\n\nRewrite directly as one Tags API file — the same shapes apply: `getInitialState` → `<let>` initials, `getTemplateData`/`getInitialProps` → `<const>`, `init()` → `<script>`, `w-on-*`/`w-id` in the template → `onEvent=` handlers and tag variables, `w-body` → `content`. There is no interop for widgets, so this rewrite cannot be deferred in either migration flow. For sprawling widgets, an intermediate rewrite to the Class API (which _does_ interop) is acceptable to unblock the incremental flow, but budget the second pass.\n","isInternal":false,"tokens":2978,"sizeBytes":11607},{"name":"SKILL.md","path":"skills/marko-5-to-6-migration/SKILL.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/skills/marko-5-to-6-migration/SKILL.md","title":"marko-5-to-6-migration","category":"anthropic-skill","format":"markdown","content":"---\nname: marko-5-to-6-migration\ndescription: Migrate Marko 5 (Class API / legacy widget API) applications and component libraries to Marko 6 (Tags API). Use when asked to upgrade Marko, convert class components to tags, remove the Class or widget API, or plan an incremental Marko 6 adoption using the Marko 5 interop layer.\n---\n\n# Marko 5 → Marko 6 Migration\n\nMarko 6 replaces the Class API (`class {}` blocks, `component.js` files, `this.state`, `this.emit`, legacy widgets) with the Tags API (`<let>`, `<const>`, tag variables, function-valued event attributes). `marko@6` is **not** backward compatible: it cannot compile Class API files at all. `marko@5` **is** forward compatible: through the interop layer built into modern `marko@5`, one app compiles Tags API and Class API files side by side, classifying each `.marko` file individually.\n\nThat gives two supported migration strategies. **Confirm with the user which one they want before editing code** (unless they already said):\n\n| Strategy                  | End state                                                                                                                                                              | Choose when                                                                                  |\n| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |\n| **Full migration**        | `marko@6` installed; zero Class/widget API anywhere                                                                                                                    | Small-to-medium codebase, you control all `.marko` sources, one big change is acceptable     |\n| **Incremental migration** | Stays on latest `marko@5`; files convert to Tags API one at a time via interop; app is shippable after every step; ends with the same final flip as the full migration | Large codebase, must keep shipping, third-party Marko 5 tag libraries in use, multiple teams |\n\nHard constraints that force the choice:\n\n- A dependency that ships Class API tags you cannot fork (e.g. `@ebay/ebayui-core`) blocks the final flip to `marko@6`. Use the incremental flow and stay on `marko@5` until every dependency has a Tags API release. For a small straggler module, converting it locally and carrying the diff with [`patch-package`](https://github.com/ds300/patch-package) is often practical — patch, verify, and upstream the conversion.\n- Legacy widget usage (`marko-widgets`, `@marko/compat-v4`, `w-bind`, `defineComponent`) has no interop with Marko 6 and no automated path. Those components must be rewritten to Tags API (or at minimum to the Class API first) in either flow.\n\nThere is **no automatic source-to-source converter** from Class API to Tags API. Every file is converted by hand (by you), using the mapping tables in this skill.\n\n## Reference files\n\nRead these on demand; do not guess at mappings from memory:\n\n- [`api-mapping.md`](./api-mapping.md) — exhaustive Marko 5 → 6 translation tables: template syntax, core tags, the full `Marko.Component` API, legacy widget API, server/template rendering APIs, taglib metadata, TypeScript types. **Read before converting your first file.**\n- [`patterns.md`](./patterns.md) — worked before/after conversions of the common component shapes (stateful, controllable, refs, third-party DOM libraries, attribute tags, `<await>`, split components, legacy widgets).\n- [`interop.md`](./interop.md) — exact file-classification rules, boundary semantics, limitations, and troubleshooting for running both APIs in one app. **Read before any incremental work**, and when debugging \"Cannot mix Tags API and Class API features\" or hydration issues in a mixed app.\n- The Marko 6 cheat sheet (`cheatsheet.md`, shipped with Marko 6) — compact rules for idiomatic Tags API code, including traps the files above don't cover: a top-level `>` in an attribute value silently ends the tag, and native inputs stay uncontrolled until their `*Change` handler is added. **Read before writing Tags API code.** While the app is still on `marko@5` it ships only in its `@marko/runtime-tags` dependency: `node -p \"require.resolve('@marko/runtime-tags/cheatsheet.md', { paths: [require.resolve('marko/package.json')] })\"`. Once on `marko@6` it is `node -p \"require.resolve('marko/cheatsheet.md')\"`, the file compile errors point to.\n\n## Step 1 — Assess\n\nGather facts before proposing anything:\n\n```sh\nnpm ls marko @marko/compiler   # current versions (use the project's package manager: pnpm ls / yarn why)\nfind . -type d \\( -name components -o -name tags \\) -not -path '*/node_modules/*'  # directory conventions in use\n```\n\nInventory the migration surface (run from the project root; counts of affected files). The greps are heuristics for sizing the work, not an exact list — review matches before acting on them, and extend the exclusions to cover this project's build output, docs, and any installed skills:\n\n```sh\ncf() { grep -rlE --exclude-dir={node_modules,.git,dist,build,coverage,.claude} \"$@\" . | wc -l; }  # count files matching\n\n# Class API\ncf '^\\s*class \\{' --include='*.marko'                 # inline class blocks\nfind . -not -path '*/node_modules/*' \\( -name 'component.js' -o -name 'component.ts' \\\n  -o -name 'component-browser.js' -o -name 'component-browser.ts' \\\n  -o -name '*.component.js' -o -name '*.component-browser.js' \\) | wc -l  # external/split components\ncf '^\\$ ' --include='*.marko'                         # $ scriptlets\ncf 'on-[a-zA-Z-]+\\(' --include='*.marko'              # attribute-argument event handlers\ncf 'renderBody' --include='*.marko'\ncf 'this\\.(state|emit|getEl|getComponent|subscribeTo|setState|forceUpdate)'\ncf ':scoped|:no-update|no-update' --include='*.marko'\ncf '<(while|macro|include-text|include-html|module-code|await-reorderer|init-components)' --include='*.marko'\ncf '<await' --include='*.marko'                       # async boundaries (interop-sensitive)\n\n# Legacy widget API (Marko 3/4 era) — must be rewritten in every flow\ncf 'w-bind|w-on-|widget-types|defineComponent|defineWidget|defineRenderer|legacy-components|marko-widgets|@marko/compat-v4'\n\n# Server / rendering API\ncf 'renderSync|renderToString|\\.stream\\(|out\\.global|beginAsync|res\\.marko|marko/node-require|marko/components'\n```\n\nAlso identify: the bundler (lasso / webpack / rollup / vite / `@marko/run` / `browser.json` files), the server integration (`@marko/express`, koa, fastify, raw http), the test setup, and whether TypeScript or `marko.json` `\"script-lang\": \"ts\"` is configured.\n\nReport the inventory to the user together with the recommended strategy, then proceed on the agreed flow.\n\n## Step 2 — Modernize the foundation (both flows, still on Marko 5)\n\nEach of these is an independently shippable change. Verify the app builds and tests pass after each.\n\n1. **Upgrade to the latest `marko@5`** and `@marko/compiler` 5.x. Modern `marko@5` (5.39+) depends on `@marko/runtime-tags` and its `marko/translator` entry _is_ the interop translator, so this alone enables Tags API files — no other configuration.\n2. **Clear existing deprecations** (they become hard errors or dead ends in 6): see \"Already deprecated in Marko 5\" in [`api-mapping.md`](./api-mapping.md). Run the app with `MARKO_DEBUG` / non-production `NODE_ENV` and fix every `complain()` deprecation warning.\n3. **Rewrite legacy widgets** (`defineComponent` / `defineWidget` / `w-bind` / `getInitialState`). Rewrite straight to Tags API when the component is small; otherwise to Class API first so it rides the normal conversion path later. Mapping table: \"Legacy widget API\" in `api-mapping.md`.\n4. **Delete explicit `<init-components/>` and `<await-reorderer/>` tags unconditionally.** Marko 5 injects both implicitly, so explicit usages are already redundant — removing them is safe today and required eventually (both are Class-only signals to the interop classifier).\n5. **Adopt `server` and `client` statements early.** These were backported to Marko 5 (5.38+) and are API-neutral for interop classification, so they work in Class files today. Replace environment guards (`typeof window` checks, browser-only `require`s) and — importantly — any `component-browser.js` that exists only as a glorified bundling trick to keep code out of the server build: `client import \"./browser-only\"` expresses that directly in the template. This shrinks the real migration surface before any API conversion.\n6. **Consider modernizing the bundler.** `@marko/vite`, `@marko/webpack`, `@marko/rollup`, and `@marko/run` all support Marko 5 _and_ 6 (e.g. `@marko/run` declares `\"marko\": \"5 - 6\"`), so this ships while still fully on Marko 5. Lasso also keeps working with Marko 6 — staying on it is viable; you only give up code-splitting of lazy imports (`with { load }` needs the bundler-provided `linkAssets`; without it those imports just load eagerly). `browser.json` component wiring should be retired regardless.\n7. **Baseline**: record SSR output of key pages (curl to files) and make the test suite green. These are your regression oracle.\n\n## Step 3 — Convert files\n\nThe per-file mechanics are identical in both flows; the flows differ in ordering and in when the dependency flips.\n\nFor each `.marko` component (work **leaf-first**, bottom-up):\n\n1. Read _everything_ that makes up the component: `index.marko`, `component.js` / `component-browser.js` (also `.ts` and `*.component[-browser].js` variants), `marko-tag.json`, `browser.json`, adjacent `style.*` files, plus every call site of the tag.\n2. Classify its shape and open the matching worked example in [`patterns.md`](./patterns.md): inert/presentational · stateful · controllable (state initialized from input + change events) · element refs / imperative DOM · third-party library host · attribute tags · async (`<await>`) · split component · legacy widget.\n3. Translate template syntax first, then the component class, using [`api-mapping.md`](./api-mapping.md). Everything from `component.js` / `component-browser.js` folds into the one `.marko` file; delete the JS files, `marko-tag.json` (types move into `export interface Input`), and `browser.json`.\n4. Convert state mutations to **immutable updates** (`items = items.concat(x)`, `obj = { ...obj, k: v }`). Marko 6 reactivity is assignment-driven; `setStateDirty`-style mutation has intentionally no equivalent. Marko 6 serializes to the browser only what client-side code actually references (the compiler computes serialization reasons/intersections per value) — so keep class instances, DOM nodes, and server-only resources out of values that browser code touches.\n5. Update call sites: `on-foo(\"method\")` → `onFoo=fn` function attributes, `renderBody` → `content`, `key=` on loop children → `by=` on `<for>`. In the incremental flow, Class API parents keep working for attributes and body content (the interop bridges `renderBody`/`content` and props automatically), but any `on-foo(\"method\")` bindings on the converted child **must** flip to function attributes in the same change — Class-style event bindings on a Tags API child compile but never fire (see `interop.md`).\n6. Place the file correctly. Incremental flow: converted files should live in a `tags/` directory or contain an unambiguous Tags signal; add a `// use tags` comment to converted route/page files that could be ambiguous. Never leave a file with signals from both APIs — that is a compile error, not a preference.\n7. Verify (Step 4) before moving to the next component.\n\n### Flow A — Full migration finish line\n\nWhen every `.marko` file uses the Tags API and the inventory greps from Step 1 return zero:\n\n1. Rename remaining `components/` directories to `tags/` (Marko 6 discovers relative tags from `tags/` only). For **published tag libraries**, move `marko.json` from `\"tags-dir\"` to `\"exports\"` — `exports` exists only for packages consumed from `node_modules`; `tags-dir` still works in both majors but is discouraged, and apps shouldn't need a `marko.json` at all.\n2. Migrate server entry points and any `template.render(input, cb/stream)` / `renderSync` / `renderToString` / `out.*` usage per \"Template & server API\" in `api-mapping.md`. Remove `marko/components` `init()` calls and `marko/node-require` (→ `@marko/compiler/register`); explicit `<init-components>` / `<await-reorderer>` tags should already be gone from Step 2.\n3. Swap the dependency to `marko@^6` using the project's package manager (npm/pnpm/yarn — detect via the `packageManager` field or the lockfile; e.g. `npm rm marko && npm i marko@^6`). `@marko/compiler` stays 5.x — that is expected; only the `marko` runtime major changes.\n4. Delete now-inert `// use tags` / `// use class` comments, run the full verification suite, and diff SSR output against the Step 2 baseline.\n5. Grep once more for stragglers. Unambiguous Class API tokens must be gone from app code: `renderBody`, `getEl(`, `subscribeTo`, `:scoped`, `no-update`, `<await-reorderer`, `legacy-components`. Broad patterns are review lists, not mandatory zeroes — inspect each match, since they also occur in unrelated code: `key=` (matches `apiKey=` etc.), `\\bout\\.`, `\\bcomponent\\.`, `\\.emit\\(`.\n\n### Flow B — Incremental migration loop\n\nRead [`interop.md`](./interop.md) first. The mechanism that makes per-file adoption safe is the compiler's **Class/Tags feature detection** — each `.marko` file is classified individually, so drive the classification deliberately instead of leaving files ambiguous:\n\n1. Files under a `tags/` directory are seeded **Tags API**.\n2. An exact `// use tags` or `// use class` comment pins a file explicitly.\n3. Class syntax anywhere in the file (a `$ scriptlet`, `class {}`, `style {}` block, attribute arguments like `on-click(\"m\")`, or `<while>`/`<macro>`/`<include-*>`/…) marks it Class; Tags syntax (a tag variable, `:=`, or `<let>`/`<const>`/`<id>`/`<return>`/…) marks it Tags. Signals from **both** APIs in one file are a compile error.\n4. A file with no signals is Tags only when _no_ `components/` directory is discoverable anywhere — otherwise it silently defaults to **Class**.\n\n(Full rules, escape hatches, and troubleshooting: `interop.md`.) In practice: converted and new components go under `tags/`, shells and route files get pinned with a comment when signal-free, and each conversion is completed fully so no file mixes APIs.\n\nThen repeat, in increments sized to one subtree/page per PR:\n\n1. Pick the next subtree (a page or a self-contained component cluster). Prefer converting **whole subtrees** so Tags components mostly reference Tags components — every Class↔Tags boundary costs compat runtime and serialization.\n2. Convert leaf components of that subtree first (inert/presentational ones are nearly free), parents next, using Step 3 mechanics. Route/page/layout files flip last, once their whole subtree is Tags — flipping a shell early maximizes boundary crossings below it.\n3. Do not put an `<await>`/async boundary across the API seam: a pending promise crossing the compat layer throws `Cannot serialize promise across tags/class compat layer`. Resolve async fully on one side.\n4. Ship the increment. Verify SSR + hydration + interactions on the affected pages (Step 4).\n5. When the last Class file is gone, run the Flow A finish line.\n\nNew code during the migration goes in `tags/` directories and uses the Tags API from day one.\n\n## Step 4 — Verify each change\n\n- **Build + typecheck**: run the app build; if TS/jsconfig is set up, run `mtc` (`@marko/type-check`). Format with `prettier` (v3 `prettier-plugin-marko` handles both syntaxes).\n- **Tests**: run the project's suite. `@marko/testing-library` supports both runtimes; update `rerender`-era assertions to reflect that Marko 6 batches updates (await a microtask / use `find*` queries).\n- **SSR parity**: render the affected page server-side and diff against the baseline HTML. Expect attribute-order/comment-marker noise; investigate _content_ differences.\n- **Hydration**: load the page in a browser; check the console for hydration/serialization errors and verify every interaction on the page (clicks, inputs, focus) still works. In mixed apps also confirm Class children inside Tags parents come alive (buttons actually respond, not just render).\n- **Common regressions to hunt**: state that silently stopped updating (mutation instead of assignment), event payload shape changes (`emit(\"change\", a, b)` → single object argument conventions), lost `:scoped` id uniqueness (→ `<id>`), form elements fighting Marko over state (→ change handlers / `:=`), `<select>`/`checked` behavior, and `no-update` regions that relied on Marko _not_ touching third-party DOM (→ `<lifecycle>` owning a container element).\n\n## Renamed / removed quick list\n\nThe ten highest-frequency rewrites (full tables in `api-mapping.md`):\n\n| Marko 5                                                             | Marko 6                                                                           |\n| ------------------------------------------------------------------- | --------------------------------------------------------------------------------- |\n| `$ const x = ...;` scriptlet                                        | `<const/x=...>` (derived) or `<let/x=...>` (mutable)                              |\n| `class { onCreate() { this.state = { n: 0 } } }` + `state.n`        | `<let/n=0>` per state key                                                         |\n| `this.state.n = v` / `setState(\"n\", v)`                             | `n = v` (plain assignment)                                                        |\n| `on-click(\"handleClick\")` / `once-click(...)`                       | `onClick() { ... }` or `onClick=fn`                                               |\n| `this.emit(\"select\", x)`                                            | call `(input.onSelect \\|\\| null)?.(x)` — events become function props             |\n| `<${input.renderBody}/>` / `renderBody`                             | `<${input.content}/>` / `content`                                                 |\n| `key=\"el\"` + `this.getEl(\"el\")`                                     | tag variable `<div/el>` … `el()` (browser getter)                                 |\n| `onMount`/`onUpdate`/`onDestroy`                                    | `<script>` (+ `$signal` for cleanup); `<lifecycle>` only for imperative libraries |\n| `key=` on loop children                                             | `by=` attribute on `<for>`                                                        |\n| `component-browser.js` as a bundling trick / `typeof window` guards | `client import` / `server` statements (backported to Marko 5.38+)                 |\n| `out.global`                                                        | `$global`                                                                         |\n\n## Escalate to the user\n\nStop and ask (with your analysis) when you hit:\n\n- `shouldUpdate`, `update_<state>` handlers, `forceUpdate`-driven flows, or `no-update` regions whose _behavior_ (not just syntax) has no 1:1 equivalent — the replacement is a design decision.\n- Public component APIs consumed by code you can't see (published libraries): event rename (`on-change` → `onChange`) and payload shape changes are breaking for consumers.\n- `out.beginAsync` / manual `out.write` streaming code, custom taglib `transformer`/codegen hooks, or `<module-code>` — these need bespoke redesign.\n- Anything where SSR baseline diffs show content changes you cannot explain.\n","frontmatter":{"name":"marko-5-to-6-migration","description":"Migrate Marko 5 (Class API / legacy widget API) applications and component libraries to Marko 6 (Tags API). Use when asked to upgrade Marko, convert class components to tags, remove the Class or widget API, or plan an incremental Marko 6 adoption using the Marko 5 interop layer."},"isInternal":false,"tokens":4529,"sizeBytes":19767},{"name":"SKILL.md","path":"skills/marko-best-practices/SKILL.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/skills/marko-best-practices/SKILL.md","title":"marko-best-practices","category":"anthropic-skill","format":"markdown","content":"---\nname: marko-best-practices\ndescription: Apply Marko syntax and best practices when editing `.marko` files and building Marko components.\n---\n\n# Marko Best Practices\n\nMarko is a modern UI framework for building web applications. It features a declarative component-based syntax, fine-grained reactivity, and a highly optimized compiler. Marko is designed for both server-rendered and interactive client-side experiences with a focus on streaming, partial hydration, and shipping the smallest possible amount of JavaScript to each page.\n\n## Marko Documentation\n\nThe Marko documentation is the source of truth for all Marko-related information. Always refer to the official docs for information about syntax and behavior. Marko changes over time, so prefer fetching current docs over relying on training data.\n\nThe [docs index](https://markojs.com/llms.txt) lists every available page with its URL and a short description.\n\nAll Marko docs pages can be fetched as markdown by appending `.md` to the URL (<https://markojs.com/docs/introduction/getting-started.md>)\n\n## Marko 6 Syntax\n\nDocumentation and this skill target **Marko 6**. Do not use Marko 5 syntax.\n\n## Checklist for New or Edited .marko Files\n\n- [ ] Uses Marko 6 syntax only (no scriptlets, old event syntax, or Marko 5 blocks).\n- [ ] `<script>` is never used when state (`<let>` or `<const>`) could accomplish the same behavior.\n- [ ] Event handlers use function form: `onClick() { ... }` or a reference, not string names.\n- [ ] `<show=cond>` for toggled content that should keep its state; `<if>` destroys and rebuilds.\n- [ ] Component stays small and readable; consider splitting large templates.\n- [ ] No unnecessary client-side JS; prefer built-in browser APIs and HTML/CSS features over scripts.\n- [ ] Props are declared with an exported `Input` interface, and templates are type checked with `mtc` (`@marko/type-check`) — `tsc` skips `.marko` files and reports nothing.\n","frontmatter":{"name":"marko-best-practices","description":"Apply Marko syntax and best practices when editing `.marko` files and building Marko components."},"isInternal":false,"tokens":443,"sizeBytes":1941},{"name":"README.md","path":"skills/README.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/skills/README.md","title":"Skills Skill","category":"anthropic-skill","format":"markdown","content":"# Skills\n\nAgent skills for AI coding assistants working with Marko. Each skill is a folder with a `SKILL.md` entry point (frontmatter `name`/`description` plus instructions); sibling `.md` files are references the agent loads on demand.\n\n| Skill                                                | Use it to                                                                                                                |\n| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |\n| [`marko-best-practices`](./marko-best-practices)     | write idiomatic Marko 6 when creating or editing `.marko` files                                                          |\n| [`marko-5-to-6-migration`](./marko-5-to-6-migration) | migrate Marko 5 (Class API / legacy widgets) apps and libraries to Marko 6, fully or incrementally via the interop layer |\n\n## Installation\n\nSkills run inside your own project, not this repo.\n\nWith the [skills CLI](https://skills.sh) (installs into the current project for Claude Code, Cursor, and other supported agents; pick the skills when prompted):\n\n```sh\nnpx skills add marko-js/marko\n```\n\nOr manually, for Claude Code: copy a skill folder into your project's `.claude/skills/` directory (or `~/.claude/skills/` to enable it globally):\n\n```sh\ncp -r skills/marko-5-to-6-migration YOUR_APP/.claude/skills/\n```\n\nAny agent that supports the `SKILL.md` convention can consume these folders the same way.\n\n## Usage\n\nOnce installed, the agent applies a skill automatically when a request matches its description, or invoke it explicitly (in Claude Code, type `/` plus the skill name). For example, in a Marko 5 project:\n\n```text\n/marko-5-to-6-migration plan an incremental migration of this app\n```\n\n```text\nMigrate this component library to Marko 6 and remove all class components.\n```\n","isInternal":false,"tokens":399,"sizeBytes":1921},{"name":"README.md","path":"packages/compiler/README.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/compiler/README.md","title":"compiler Documentation","category":"plugin-manifest","format":"markdown","content":"# @marko/compiler\n\nCompiles [Marko](https://markojs.com/) templates into JavaScript modules.\n\nThe [bundler integrations](https://markojs.com/docs/introduction/integrations#bundlers) call the compiler for every template, so applications rarely use it directly. It is the API for building a bundler integration, a test transform, or other tooling around Marko templates.\n\n```sh\nnpm install @marko/compiler\n```\n\n```js\nimport * as compiler from \"@marko/compiler\";\n\nconst { code, map } = await compiler.compileFile(\"./src/card.marko\", {\n  output: \"dom\",\n  sourceMaps: true,\n});\n```\n\nSee the [Compiler API reference](https://markojs.com/docs/reference/compiler) for the compile functions, their options and the compile result.\n","isInternal":false,"tokens":173,"sizeBytes":721},{"name":"README.md","path":"packages/runtime-class/helpers/README.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/helpers/README.md","title":"helpers Documentation","category":"plugin-manifest","format":"markdown","content":"# Marko Helpers\n\nThis directory contains helpers that were deprecated in Marko v3. Marko v4/5 no longer adds these helpers to every compiled template, but you can still import them if needed.\n","isInternal":false,"tokens":43,"sizeBytes":192},{"name":"README.md","path":"packages/runtime-class/README.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-class/README.md","title":"runtime-class Documentation","category":"plugin-manifest","format":"markdown","content":"<div align=\"center\">\n\n# [<img alt=\"Marko\" src=\"https://raw.githubusercontent.com/marko-js/branding/master/marko-logo-medium-cropped.png\" width=\"250\">](https://markojs.com/)\n\n**A declarative, HTML-based language that makes building web apps fun 🔥**\n\n[![NPM](https://img.shields.io/npm/v/marko.svg)](https://www.npmjs.com/package/marko)\n[![Discord Chat](https://img.shields.io/badge/discord-chat-7188da.svg)](https://discord.gg/RFGxYGs)\n[![Continuous Integration status](https://github.com/marko-js/marko/actions/workflows/ci.yml/badge.svg)](https://github.com/marko-js/marko/actions/workflows/ci.yml)\n[![Code coverage %](https://codecov.io/gh/marko-js/marko/branch/master/graph/badge.svg)](https://codecov.io/gh/marko-js/marko)\n[![# of monthly downloads](https://img.shields.io/npm/dm/marko.svg)](https://npm-stat.com/charts.html?package=marko)\n[![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/7029/badge)](https://bestpractices.coreinfrastructure.org/projects/7029)\n\n[Docs](https://markojs.com/docs/getting-started/) ∙ [Try Online](https://markojs.com/try-online/) ∙ [Contribute](#contributors) ∙ [Get Support](#community--support)\n\n</div>\n\n## Intro\n\nMarko is HTML _reimagined_ as a language for building dynamic and reactive user interfaces. Almost any valid HTML is valid Marko, and Marko extends HTML for building modern applications more declaratively. Among these extensions are [conditionals and lists](https://markojs.com/docs/conditionals-and-lists/), [state](https://markojs.com/docs/state/), and [components](https://markojs.com/docs/class-components/).\n\nMarko supports both single-file components and components across separate files.\n\n### Single-file component\n\nThe following renders a button and a counter of how many times the button has been pressed:\n\n**click-count.marko**\n\n```marko\nclass {\n  onCreate() {\n    this.state = { count: 0 };\n  }\n  increment() {\n    this.state.count++;\n  }\n}\n\nstyle {\n  .count {\n    color: #09c;\n    font-size: 3em;\n  }\n  .press-me {\n    padding: 0.5em;\n  }\n}\n\n<output.count>\n  ${state.count}\n</output>\n<button.press-me on-click('increment')>\n  Press me!\n</button>\n```\n\n### Multi-file component\n\nThe same component as above, but split into:\n\n- `index.marko` template file\n- `component.js` component JS logic file\n- `style.css` component styles file\n\n**index.marko**\n\n```marko\n<output.count>\n  ${state.count}\n</output>\n<button.press-me on-click('increment')>\n  Press me!\n</button>\n```\n\n**component.js**\n\n```js\nexport default {\n  onCreate() {\n    this.state = { count: 0 };\n  },\n  increment() {\n    this.state.count++;\n  },\n};\n```\n\n**style.css**\n\n```css\n.count {\n  color: #09c;\n  font-size: 3em;\n}\n.press-me {\n  padding: 0.5em;\n}\n```\n\n## Concise Syntax\n\nMarko also supports [a beautifully concise syntax as an alternative](https://markojs.com/docs/concise/) to its HTML syntax:\n\n<table><thead><tr><th>Concise syntax<th>HTML syntax\n<tbody><tr>\n<td>\n\n```marko\nul.example-list\n  for|color| of=[a, b, c]\n    li -- ${color}\n```\n\n<td>\n\n```marko\n<ul class=\"example-list\">\n  <for|color| of=[a, b, c]>\n    <li>${color}</li>\n  </for>\n</ul>\n```\n\n</table>\n\n## Getting Started\n\n1. `npm install marko`\n2. Read the [docs](https://markojs.com/docs/getting-started/)\n\n## Community & Support\n\n<table>\n<thead><tr>\n  <th><img alt=\"Stack Overflow\" src=\"https://user-images.githubusercontent.com/1958812/56055468-619b3e00-5d0e-11e9-92ae-200c212cafb8.png\" width=\"205\"> \n  <th><img alt=\"Discord\" src=\"https://user-images.githubusercontent.com/4985201/89313514-6edbea80-d62d-11ea-8447-ca2fd8983661.png\" width=\"162\">\n  <th><img alt=\"Twitter\" src=\"https://user-images.githubusercontent.com/1958812/56055707-07e74380-5d0f-11e9-8a59-d529fbb5a81e.png\" width=\"53\">\n<tbody><tr><td>\n\nAsk and answer [StackOverflow questions with the `#marko` tag](https://stackoverflow.com/questions/tagged/marko)<td>\n\nCome [hang out in our Discord chat](https://discord.gg/RFGxYGs), ask questions, and discuss project direction<td>\n\n[Tweet to `@MarkoDevTeam`](https://twitter.com/MarkoDevTeam), or with the [`#markojs` hashtag](https://twitter.com/search?q=%23markojs&f=live)\n\n</table>\n\n### Contributors\n\nMarko would not be what it is without all those who have contributed ✨\n\n[![All marko-js/marko GitHub contributors](https://opencollective.com/marko-js/contributors.svg?width=890&button=false)](https://github.com/marko-js/marko/graphs/contributors)\n\n### Get Involved!\n\n- Pull requests are welcome!\n- Submit [GitHub issues](https://github.com/marko-js/marko/issues) for any feature enhancements, bugs, or documentation problems\n- [Read the Contribution Tips and Guidelines](.github/CONTRIBUTING.md)\n- Participants in this project agree to abide by [its Code of Conduct](https://github.com/eBay/.github/blob/main/CODE_OF_CONDUCT.md)\n","isInternal":false,"tokens":1356,"sizeBytes":4771},{"name":"README.md","path":"packages/runtime-tags/README.md","rawUrl":"https://raw.githubusercontent.com/marko-js/marko/HEAD/packages/runtime-tags/README.md","title":"runtime-tags Documentation","category":"plugin-manifest","format":"markdown","content":"<div align=\"center\">\n\n# [<img alt=\"Marko\" src=\"https://raw.githubusercontent.com/marko-js/website/refs/heads/main/public/assets/logo.svg\" width=\"250\">](https://markojs.com/)\n\n**A declarative, HTML-based language that makes building web apps fun 🔥**\n\n[![NPM](https://img.shields.io/npm/v/marko.svg)](https://www.npmjs.com/package/marko)\n[![Discord Chat](https://img.shields.io/badge/discord-chat-7188da.svg)](https://discord.gg/RFGxYGs)\n[![Continuous Integration status](https://github.com/marko-js/marko/actions/workflows/ci.yml/badge.svg)](https://github.com/marko-js/marko/actions/workflows/ci.yml)\n[![Code coverage %](https://codecov.io/gh/marko-js/marko/branch/master/graph/badge.svg)](https://codecov.io/gh/marko-js/marko)\n[![# of monthly downloads](https://img.shields.io/npm/dm/marko.svg)](https://npm-stat.com/charts.html?package=marko)\n[![OpenSSF Best Practices](https://bestpractices.coreinfrastructure.org/projects/7029/badge)](https://bestpractices.coreinfrastructure.org/projects/7029)\n\n[Docs](https://markojs.com/docs/introduction/getting-started) ∙ [Try Online](https://markojs.com/playground) ∙ [Contribute](#contributors) ∙ [Get Support](#community--support)\n\n</div>\n\n## Intro\n\nMarko is HTML _reimagined_ as a language for building dynamic and reactive user interfaces. Almost any valid HTML is valid Marko, and Marko extends HTML for building modern applications more declaratively. Among these extensions are [components](https://markojs.com/docs/reference/custom-tag), [conditionals](https://markojs.com/docs/reference/core-tag#if--else) and [loops](https://markojs.com/docs/reference/core-tag#for), and a full [reactivity system](https://markojs.com/docs/reference/reactivity).\n\n### Example Component\n\nThe following renders a button and a counter of how many times the button has been pressed:\n\n**click-count.marko**\n\n```marko\n// HTML + JavaScript = 💜\n<let/count=0>\n<button onClick() { count++ }>\n  Clicked ${count} times\n</button>\n```\n\n## Getting Started\n\n1. `npm init marko`\n2. Read the [docs](https://markojs.com/docs/introduction/getting-started)\n\n## Community & Support\n\n<table>\n<thead><tr>\n  <th><svg viewBox=\"0 0 576 512\"><path d=\"M492.5 69.8c-.2-.3-.4-.6-.8-.7-38.1-17.5-78.4-30-119.7-37.1-.4-.1-.8 0-1.1 .1s-.6 .4-.8 .8c-5.5 9.9-10.5 20.2-14.9 30.6-44.6-6.8-89.9-6.8-134.4 0-4.5-10.5-9.5-20.7-15.1-30.6-.2-.3-.5-.6-.8-.8s-.7-.2-1.1-.2c-41.3 7.1-81.6 19.6-119.7 37.1-.3 .1-.6 .4-.8 .7-76.2 113.8-97.1 224.9-86.9 334.5 0 .3 .1 .5 .2 .8s.3 .4 .5 .6c44.4 32.9 94 58 146.8 74.2 .4 .1 .8 .1 1.1 0s.7-.4 .9-.7c11.3-15.4 21.4-31.8 30-48.8 .1-.2 .2-.5 .2-.8s0-.5-.1-.8-.2-.5-.4-.6-.4-.3-.7-.4c-15.8-6.1-31.2-13.4-45.9-21.9-.3-.2-.5-.4-.7-.6s-.3-.6-.3-.9 0-.6 .2-.9 .3-.5 .6-.7c3.1-2.3 6.2-4.7 9.1-7.1 .3-.2 .6-.4 .9-.4s.7 0 1 .1c96.2 43.9 200.4 43.9 295.5 0 .3-.1 .7-.2 1-.2s.7 .2 .9 .4c2.9 2.4 6 4.9 9.1 7.2 .2 .2 .4 .4 .6 .7s.2 .6 .2 .9-.1 .6-.3 .9-.4 .5-.6 .6c-14.7 8.6-30 15.9-45.9 21.8-.2 .1-.5 .2-.7 .4s-.3 .4-.4 .7-.1 .5-.1 .8 .1 .5 .2 .8c8.8 17 18.8 33.3 30 48.8 .2 .3 .6 .6 .9 .7s.8 .1 1.1 0c52.9-16.2 102.6-41.3 147.1-74.2 .2-.2 .4-.4 .5-.6s.2-.5 .2-.8c12.3-126.8-20.5-236.9-86.9-334.5zm-302 267.7c-29 0-52.8-26.6-52.8-59.2s23.4-59.2 52.8-59.2c29.7 0 53.3 26.8 52.8 59.2 0 32.7-23.4 59.2-52.8 59.2zm195.4 0c-29 0-52.8-26.6-52.8-59.2s23.4-59.2 52.8-59.2c29.7 0 53.3 26.8 52.8 59.2 0 32.7-23.2 59.2-52.8 59.2z\"></path></svg>\n  <th><svg viewBox=\"0 0 576 512\"><path d=\"M407.8 294.7c-3.3-.4-6.7-.8-10-1.3 3.4 .4 6.7 .9 10 1.3zM288 227.1C261.9 176.4 190.9 81.9 124.9 35.3 61.6-9.4 37.5-1.7 21.6 5.5 3.3 13.8 0 41.9 0 58.4S9.1 194 15 213.9c19.5 65.7 89.1 87.9 153.2 80.7 3.3-.5 6.6-.9 10-1.4-3.3 .5-6.6 1-10 1.4-93.9 14-177.3 48.2-67.9 169.9 120.3 124.6 164.8-26.7 187.7-103.4 22.9 76.7 49.2 222.5 185.6 103.4 102.4-103.4 28.1-156-65.8-169.9-3.3-.4-6.7-.8-10-1.3 3.4 .4 6.7 .9 10 1.3 64.1 7.1 133.6-15.1 153.2-80.7 5.9-19.9 15-138.9 15-155.5s-3.3-44.7-21.6-52.9c-15.8-7.1-40-14.9-103.2 29.8-66.1 46.6-137.1 141.1-163.2 191.8z\"></path></svg>\n  <th><svg viewBox=\"0 0 448 512\"><path d=\"M357.2 48L427.8 48 273.6 224.2 455 464 313 464 201.7 318.6 74.5 464 3.8 464 168.7 275.5-5.2 48 140.4 48 240.9 180.9 357.2 48zM332.4 421.8l39.1 0-252.4-333.8-42 0 255.3 333.8z\"></path></svg>\n  <th><svg viewBox=\"0 0 512 512\"><path d=\"M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3 .3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5 .3-6.2 2.3zm44.2-1.7c-2.9 .7-4.9 2.6-4.6 4.9 .3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM252.8 8c-138.7 0-244.8 105.3-244.8 244 0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1 100-33.2 167.8-128.1 167.8-239 0-138.7-112.5-244-251.2-244zM105.2 352.9c-1.3 1-1 3.3 .7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3 .3 2.9 2.3 3.9 1.6 1 3.6 .7 4.3-.7 .7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3 .7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3 .7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z\"></path></svg>\n<tbody><tr><td>\n\nHang out in our [Discord server](https://discord.gg/marko) to ask questions & discuss marko<td>\n\nKeep up with the community on Bluesky at [@markojs.com](https://bsky.app/profile/markojs.com)<td>\n\nTweet to [@MarkoDevTeam](https://twitter.com/MarkoDevTeam) or use the [#markojs](https://twitter.com/search?q=%23markojs%20OR%20%40markodevteam&f=live) hashtag<td>\n\nBrowse the code, open issues, & make pull requests on [GitHub](https://github.com/marko-js/marko)\n\n</table>\n\n### Contributors\n\nMarko would not be what it is without all those who have contributed ✨\n\n[![All marko-js/marko GitHub contributors](https://opencollective.com/marko-js/contributors.svg?width=890&button=false)](https://github.com/marko-js/marko/graphs/contributors)\n\n### Get Involved!\n\n- Pull requests are welcome!\n- Submit [GitHub issues](https://github.com/marko-js/marko/issues) for any feature enhancements, bugs, or documentation problems\n- [Read the Contribution Tips and Guidelines](.github/CONTRIBUTING.md)\n- Participants in this project agree to abide by [its Code of Conduct](https://github.com/eBay/.github/blob/main/CODE_OF_CONDUCT.md)\n","isInternal":false,"tokens":3545,"sizeBytes":6723}],"systemPromptSnippet":"<yakaai_skills repo=\"marko-js/marko\">\n<!-- File: AGENTS.md (Tokens: ~1938 | Category: root-instruction) -->\n# Marko Monorepo\n\nMarko compiles `.marko` templates into optimized server (streaming HTML) and client (fine-grained DOM) JavaScript. pnpm workspaces; Node >= 22.18 (native TS type stripping + module.registerHooks). Primary development happens in `packages/runtime-tags`.\n\n## Packages\n\n- [`packages/compiler`](packages/compiler/AGENTS.md) — `@marko/compiler`. Translator-agnostic: parses `.marko` into a (patched) Babel AST, then hands off to a translator for codegen.\n- [`packages/runtime-tags`](packages/runtime-tags/AGENTS.md) — `marko@6` / `@marko/runtime-tags`. The Marko 6 runtime **and** its translator. **Primary development.**\n- [`packages/runtime-class`](packages/runtime-class/AGENTS.md) — `marko@5` (private package, published only as `marko`). Marko 5, in maintenance; its translator wraps the class-API translator with runtime-tags' interop layer.\n\nA \"translator\" is the Babel-plugin half of a runtime package; the compiler loads it as `<pkg>/translator`. \"Marko 6\" is the runtime-tags version — the compiler stays 5.x.\n\n## Commands\n\nAll from repo root. Tests and tooling run directly from TS source (native Node type stripping plus the `~ts` resolve hook for extensionless imports; package `exports` point at `src/` until publish), so no build step is needed to iterate.\n\n```sh\npnpm test                                                 # whole suite fanned across CPU cores (~3x faster than serial)\npnpm test -- --grep \"runtime-tags/translator <fixture> \"  # scoped test run\npnpm run test:serial -- --grep \"...\"                      # same run in one process: bail at first failure, live output, --inspect-brk\npnpm test -- <file.test.ts>                               # only the given spec files (dirs and globs work too)\npnpm run test:update -- --grep \"...\"                      # regenerate snapshots (review the diff!)\npnpm run compile -- -o dom -d foo.marko                   # print compiled output (-o html for SSR; omit -d for optimized)\npnpm run build                                            # all packages -> dist/ + .d.ts\npnpm run build:sizes                                      # bundle-size table; diffs vs .sizes.json\npnpm run lint                                             # oxlint + oxfmt check\npnpm run format                                           # oxlint --fix + oxfmt write\npnpm run change                                           # add a changeset (required for user-facing changes)\n```\n\n`pnpm run compile` is the fastest way to inspect what the translator generates. It writes nothing: each compiled module, and then any module the translator generates for it, prints to stdout under a `// <resolved path>` header. (Pass `-t class` for the Marko 5 translator; `-t` also accepts a full translator module id.)\n\n`pnpm run change` prompts, so write `.changeset/<name>.md` directly, naming the package that owns the changed code: `packages/compiler` is `@marko/compiler`, `packages/runtime-tags` is `@marko/runtime-tags`, `packages/runtime-class` is `marko`. `pnpm exec changeset status` fails on a name that is no workspace package (which would break the release on `main`), but not on the wrong one: `marko` for a runtime-tags fix passes and publishes the wrong package. Restricting behavior that was already broken is a fix (`patch`), never described as a breaking change.\n\n## Repo invariants\n\n- **Dependencies are patched.** `patches/` (applied by pnpm patchedDependencies on install) adds Marko AST node types to `@babel/types`/`traverse`/`generator`, and makes mocha print the `require()` error it otherwise drops when its `import()` fallback rescues a spec. The Babel patches only add Marko AST support; never patch Babel's own behavior. Import Babel only via `@marko/compiler/internal/babel` and helpers via `@marko/compiler/babel-utils`, never `@babel/*` directly. Bumping any patched dependency requires regenerating its patch.\n- **Bundle size is a feature.** The pre-commit hook runs lint-staged, a full build, and `build:sizes`, staging `.sizes.json`/`.sizes/` — that diff is the size impact of the change. Commits are slow by design. The floor is `.sizes/counter.ssr` and `.sizes/comments.ssr` (a resumed page with no async, reorder, lazy, or dynamic html): code for an optional feature, even one `?.`, must fold out of them. Lint rules whose fix rewrites runtime code into larger output stay off in `.oxlintrc.json` (`unicorn/prefer-string-starts-ends-with`, `unicorn/no-new-array`); enabling one means checking `build:sizes` first.\n- **Snapshots and sizes are generated.** Never hand-edit _or delete_ `__snapshots__/**`, fixture `sizes.json`, or `.sizes*`; regenerate with `pnpm run test:update` (which also prunes stale snapshots after a green run) and the commit hook.\n- **CI** (`.github/workflows/ci.yml`): build + lint on Node 26; tests on Node 22/24/26 (zcov coverage). Releases go out via changesets on push to `main`.\n\n## Conventions\n\nOrganize files top-down (progressive disclosure): public API/exports first, then orchestration, helpers, and low-level detail last — use function-declaration hoisting.\n\nComments are a last resort and never exceed two lines: prefer self-describing code, and when one is needed it captures intent — never what the code was or what was removed. Wording is plain and direct, with no invented shorthand.\n\nDerive before adding. Before a new field, flag, helper, state container, parameter, test config, or module, find the existing analysis, helper, or runtime structure that already answers it and extend that. A parallel mechanism for one feature (one the rest of the code never needed) is a smell: say in the summary why nothing existing fits.\n\nEvery line needs a reason you can name. No guards, `?.`, fallbacks, casts (`as never`, `as any`, or one the type already satisfies), or parameters for states the design rules out; lean on the invariant (`!`, or a `MARKO_DEBUG` assert). Name checks, dependency method overrides, and machine heuristics are hacks: find the structural fix. A perf or config knob ships only with a measured win, and never restates a default. Measure performance on the bundled build that ships (`pnpm run build`), not the TS source that tests and tooling run: V8 inlines the bundle's module-level function declarations but not those of an ES module, so source timings can mislead.\n\nDon't bend the code around an edge case. Input the design has no reason to support (a `NaN` loop key, say) gets a compile error or a `MARKO_DEBUG` error that rules it out, not runtime handling that every caller pays for in size or speed. Harden the invariant, then rely on it.\n\nWrite the direct form. No rest or spread to copy, extend, or strip an object: share one record, or key a collection by the field it lacks. Client runtime code, where bundle size comes first, may keep a spread that `build:sizes` shows is smallest, but it is still a red flag to justify. No function that only forwards, and no type named for a single use. A helper every caller guards takes the `undefined` itself, and a flag is set as `flag ||= condition`.\n\nDon't add Babel `NodePath` helper calls (`findParent`, `find`, `getFunctionParent`, …): walk `parentPath` and compare node types directly; existing uses are migrated later.\n\nNames come from the code. Reuse the vocabulary of neighboring code, [`CONTEXT.md`](packages/runtime-tags/CONTEXT.md), and the markojs.com docs; never coin a term the codebase does not already use.\n\nTest through existing fixture families; add a test file only when no fixture can reach the behavior. A fix adds a fixture that fails without it, and so does every branch or statement a change adds: revert each one and confirm a fixture fails. Code no fixture needs is deleted, never kept behind a fixture that passes either way.\n\nMarko language reference: <https://markojs.com/llms.txt> lists every docs page; append `.md` to any docs URL for markdown.\n\n## Agent feedback\n\nAnything actionable but out of scope for the current task (suspected bug, cleanup, perf or size win, tooling friction, confusing code) must be filed in [`agent-feedback/`](agent-feedback/README.md) before finishing. Never drop it silently. Never fix it inside an unrelated diff. In scope, so fixed rather than filed: a defect in code the diff touches or exposes, and anything in the unreleased feature a branch builds (which also takes no changesets). A deliberate limitation gets a site comment, not an item.\n\n<!-- File: CLAUDE.md (Tokens: ~3 | Category: claude-rule) -->\nAGENTS.md\n\n<!-- File: packages/compiler/AGENTS.md (Tokens: ~1079 | Category: anthropic-skill) -->\n# `@marko/compiler`\n\nTranslator-agnostic compiler: parses `.marko` into a Babel AST (custom node types like `MarkoTag`, `MarkoAttribute` — added to Babel by the root `patches/`), runs migrate/transform passes, then hands the AST to a **translator** (`@marko/runtime-tags/translator` or `marko/translator`) for codegen. Stays at v5.x; language changes belong in the translators, not here.\n\n## Map\n\n- `src/index.js` — public API: `compile[File][Sync](src, filename, config)` → `{ code, map, meta, ast }`, `configure`, `taglib`, `types`.\n- `src/config.js` — config defaults, and the `globalConfig` that `configure()` sets (both re-exported by `index.js`); an omitted translator in `getRuntimeEntryFiles`, `getRuntimeVersion` and `taglib.buildLookup` reads it. Key options: `output` (`\"html\"` | `\"dom\"` | `\"source\"` | `\"migrate\"`), `optimize`, `translator`, `modules` (`\"esm\"`/`\"cjs\"`), `optimizeKnownTemplates`, `errorRecovery`, `cache`, `fileSystem`.\n- `src/babel-plugin/` — pipeline core. Stages: `parse → migrate → transform → analyze` (cached per template) then `translate` on a clone. Taglib visitors run in `migrate`, `transform` and `translate` — including those from the taglibs a translator registers via `taglibs`/`optionalTaglibs`, which is how a translator contributes migrators. The translator's own hooks are `transform` (optional), `analyze` and `translate`; there is no `translator.migrate` hook, and `analyze` is translator-only — a taglib-level `analyze` prop is a hard load error. Taglib `translate` is skipped for `output: \"hydrate\"`.\n- `src/taglib/` — tag registry/discovery: built-in HTML/SVG/MathML JSON taglibs, `marko.json` / `marko-tag.json` discovery walking up from the template, `buildLookup`.\n- `src/babel-utils/` — the helper API for translator authors (`assert*`, `diagnostic*`, `import*`, `parse*`, `getTagDef`, `isNativeTag`, `resolveTagImport`, ...). Exported as `@marko/compiler/babel-utils`.\n- `internal/babel/index.ts` — the single controlled Babel entry, re-exported as `@marko/compiler/internal/babel`. All Babel access (here and in translators) goes through it, never `@babel/*` directly.\n\n## Translator contract\n\nA translator module exports: `translate` (required visitor), `taglibs` (required, `[[id, props]]`), optional `transform` / `analyze` visitors, `tagDiscoveryDirs`, `optionalTaglibs`, `preferAPI` (`\"tags\"` | `\"class\"`), `getRuntimeEntryFiles(output, optimize)`, and optionally `cheatsheet` (a module-relative path to an LLM syntax reference; `tryLoadTranslator` resolves it to a cwd-relative path and `util/agent-fix-guide.js` points coding agents at it on compile errors). Loading is resolved from `config.translator` or auto-detected from the app's dependencies (`util/try-load-translator.js`, default logic in `config.js`).\n\n## Notes\n\n- `output: \"source\"` / `\"migrate\"` re-print `.marko` source (tooling/codemods) — no translator codegen.\n- Bumping any `@babel/*` version requires regenerating the corresponding patch in root `patches/` (pnpm patchedDependencies); the custom AST types and generated `dist/types.d.ts` (`pnpm --filter @marko/compiler run build-babel-types`) depend on them.\n- Adding a core tag in a translator shows up in taglib-lookup expectations here and in `packages/runtime-class/test/taglib-lookup/`.\n- `util/agent-fix-guide.js` — when a terminal coding agent is detected (env markers; `AI_AGENT=1` is the generic opt-in for harnesses not on the list) and the loaded translator declares a `cheatsheet`, thrown compile errors get a one-line pointer to it (relative to `cwd`) appended at the `compile[Sync]` boundary (to `message`, and to a `CompileError`'s `label`, which bundler plugins like `@marko/vite` print in place of the framed message), and under `errorRecovery` — where nothing throws — the same pointer is appended to the first error in `meta.diagnostics` instead. `MARKO_AGENT_FIX_GUIDE` overrides the sniff in either direction: `0` suppresses the guide, any other value forces it on (e.g. when compiling in a subprocess that drops the inherited marker). No-op for humans, for runtimes without a cheat sheet, and for inline translator objects (so error snapshots, which compile with an inline translator object, are unaffected).\n\n<!-- File: packages/runtime-class/AGENTS.md (Tokens: ~901 | Category: anthropic-skill) -->\n# Marko 5 (runtime & translator)\n\n## Architecture\n\nThe package is organized into four layers:\n\n| Directory              | Purpose                                                                |\n| ---------------------- | ---------------------------------------------------------------------- |\n| `src/runtime/helpers/` | Shared runtime helpers (class/style values, dynamic tags, attr-tags)   |\n| `src/runtime/html/`    | SSR runtime: streaming HTML output, helpers, hot reload                |\n| `src/runtime/vdom/`    | CSR runtime: virtual DOM, morphdom reconciliation, component lifecycle |\n| `src/translator/`      | Babel-based compiler that transforms `.marko` into SSR/CSR JavaScript  |\n\nThe compiler/translator entry is `src/translator/index.js`, but the package's exported translator (`src/translator.js`) wraps it with `createInteropTranslator` from `@marko/runtime-tags/translator`, so Marko 5 projects can mix in Marko 6 (Tags API) components. Interop behavior changes are usually made in `packages/runtime-tags/src/translator/interop/`, not here.\n\nNote: the package is private (named `marko`); `scripts/publish-alias.mts` publishes it as `marko` under the `m5` dist-tag.\n\nCompiled templates import runtime helpers by string path (`marko/src/runtime/helpers/...`, see `translator/util/load-import.js`), so a source search for importers misses those uses.\n\n`src` mixes ESM and CommonJS `.js` with no `\"type\"`, so Node warns `MODULE_TYPELESS_PACKAGE_JSON` under `-t class`. Accepted: Marko 5 is in maintenance and `src` ships in `files`, so a `{\"type\":\"module\"}` marker would force converting every CJS file.\n\n## Naming Conventions\n\n### Triple-underscore prefix (`___name`)\n\nAll internal properties and methods on runtime objects use a triple-underscore prefix:\n\n```js\nthis.___state;\ncomponent.___queueUpdate();\nexports.___batchUpdate = batchUpdate;\n```\n\nThe build step mangles these names into short single-character identifiers.\n\n### `MARKO_DEBUG` pattern\n\nDebug-only code is wrapped in string-compared conditionals that tree-shake in prod:\n\n```js\n// eslint-disable-next-line no-constant-binary-expression\nvar complain = \"MARKO_DEBUG\" && require(\"complain\");\nif (\"MARKO_DEBUG\") {\n  complain(\"Deprecated: ...\");\n}\n```\n\nThe build step replaces `\"MARKO_DEBUG\"` with `false` and dead-code-eliminates the branches.\n\n## Output Modes\n\n- **HTML (SSR)** — `src/runtime/html/index.js` creates a `Template` produces `AsyncStream`. Output is HTML strings piped to a Node.js stream.\n- **VDOM (browser)** — `src/runtime/vdom/index.js` creates a `Template` produces `AsyncVDOMBuilder`. Output is a virtual DOM tree reconciled via local morphdom .\n\nBoth stacks share `src/runtime/renderable.js`, which mixes `render()`, `renderSync()`, `renderToString()`, and `mount()` into `Template.prototype`.\n\n## Error Handling\n\n- Compile-time errors use Babel's `path.buildCodeFrameError(message)` to include source locations\n- Most validation happens at compile time; runtime errors in production are minimal\n\n## Testing\n\n### Test structure\n\n```\ntest/\n  translator/              # Snapshot tests for compiler output\n  components-pages/        # Full page hydration (ssr + csr) tests\n  components-browser/      # jsdom-based browser component tests\n  components-server/       # SSR rendering tests\n  morphdom/                # morphdom unit tests\n  vdom-create/             # VNode construction unit tests\n  async-stream/            # AsyncStream unit tests\n```\n\n### Translator tests\n\nEach fixture has a `template.marko` input and a `snapshots/` directory:\n\n```\nfixtures/<name>/\n  template.marko\n  snapshots/\n    vdom-expected.js\n    html-expected.js\n    htmlProduction-expected.js\n    hydrate-expected.js\n    cjs-expected.js\n    generated-expected.marko\n```\n\n### Running tests\n\nFrom the repo root:\n\n```sh\npnpm test # all tests\npnpm test -- --grep \"<fixture> \" # specific fixture\npnpm run test:update # update snapshots\n```\n\n<!-- File: packages/runtime-class/docs/10-awesome-marko-features.md (Tokens: ~2015 | Category: anthropic-skill) -->\n<a href=\"#\">\n  <img src=\"https://cdn-images-1.medium.com/max/1000/1*Cmy6UutD5-ogL8dr1DySMQ.png\" alt=\"Marko logo\" width=\"100%\" />\n</a><br />\n\n> This article was published in August 2017. You can find the original [\"10 Awesome Marko Features\" article here](https://medium.com/@austinkelleher/10-awesome-marko-features-afba9d094d42)!\n\n# 10 Awesome Marko Features\n\n[Marko](https://markojs.com/) is a friendly and super fast UI library that makes\nbuilding web apps<br> fun! In celebration of rapidly approaching [5,000 stars on\nGitHub](https://github.com/marko-js/marko) (the ultimate open source vanity\nmetric), here are 10 features that will make you more productive in no\nparticular order...\n\n#### 1. Shorthand Attributes\n\nTired of constantly typing out `class` and `id` attributes? No need with Marko.\nSimply utilize the shorthand based on CSS selectors:\n\n```marko\nstyle {\n  .count {\n    color:#09c;\n  }\n}\n\n// Equivalent to <div class=\"count\"/>\n<div.count/>\n\n// Equivalent to <span id=\"my-id\"/>\n<span#my-id/>\n\n// Combined\n<button#submit.primary/>\n```\n\n#### 2. All attribute values are Just JavaScript™\n\nUnlike with HTML, you are not limited to string attribute values when using\nMarko. Attributes can have types, which makes it really easy to pass data to\ncustom tags and it works for standard HTML tags too:\n\n```marko\n<div class=input.myClassName/>\n<input type=\"checkbox\" checked=input.isChecked/>\n<awesome-component myString=\"Hello\"/>\n<awesome-component myNumber=1/>\n<awesome-component myTemplateString=`Hello ${name}`/>\n<awesome-component myBoolean=true/>\n<awesome-component myArray=[1, 2, 3]/>\n<awesome-component myObject={hello: 'world'}/>\n<awesome-component myVariable=name/>\n<awesome-component myFunctionCall=input.foo()/>\n```\n\n#### 3. Isomorphic UI components made easy\n\nTired of boilerplate code and trouble managing component input and state? Marko\nmakes it a breeze to develop self-contained and individually testable\ncomponents. Changing state is completely synchronous, so there won’t be any\nheadaches. You can also use inline styles making it very easy to develop small\ncomponents quickly.\n\n```marko\nclass {\n  onInput(input) {\n    this.state = {\n      count: input.count || 0\n    };\n  }\n  increment() {\n    this.state.count++;\n  }\n}\n\nstyle {\n  .count {\n    color:#09c;\n  }\n}\n\n<div.count>${state.count}</div>\n<button on-click('increment')>\n  Click me!\n</button>\n```\n\nDo you see references to “Marko” in the snippet above? Yeah, me neither.\n\nIs your component becoming too large? Do you prefer separating your CSS,\nJavaScript, and markup code? No problem. You can easily [rip out your code into\nmultiple files](https://markojs.com/docs/class-components/#multi-file-components):\n\n```\ncomponents/\n  click-counter/\n    component.js\n    index.marko\n    style.css\n```\n\n#### 4. Concise syntax\n\nThe DOM is just a tree structure. Indentation is a great way to describe a DOM\ntree without having to worry about matching up beginning and ending tags. Marko\nlets you choose between a concise, indentation-based syntax, and a familiar HTML\nsyntax:\n\n```marko\n<!-- Count our clicks! -->\n<div.count>\n  <p>Count: ${state.count}</p>\n</div>\n<button.example-button on-click('increment')>\n  Click me!\n</button>\n```\n\nHere’s the same thing with the concise syntax:\n\n```marko\n// Count our clicks!\ndiv.count\n  p -- Count: ${state.count}\nbutton.example-button on-click('increment') -- Click me!\n```\n\nCan’t make up your mind or just want to paste in that code snippet from\nStackOverflow? HTML syntax can be used within in the concise syntax. You’ll come\nback and make it consistent…_one day_.\n\n#### 5. Import JavaScript modules\n\nDo you have some helper JavaScript functions that you need to use in your views?\nMarko lets you import any JavaScript module into your template using the same\nsyntax as the JavaScript `import` statement without using Babel or any other\nbuild tool. No need for problematic globals (you could do that too, but please\ndon’t or your coworkers will hate you).\n\n```marko\nimport sum from './utils/sum';\n\n<div>The sum of 2 + 3 is ${sum(2, 3)}</div>\n```\n\n#### 6. No need to import custom tags (it’s a good thing, trust me)\n\nMarko uses your directory structure as a method for automatically registering\ncustom tags. This means that Marko can implicitly import tags based on where the\ntemplate is located on disk. Marko will search up the directory looking for\ncustom tags in `components/`directories similar to how Node.js discovers modules\nin `node_modules/` directories.\n\nGiven the following directory structure:\n\n```\ncomponents/\n  fancy-button/\n    index.marko\n  fancy-container/\n    index.marko\n```\n\nIf `fancy-button` is used inside of `fancy-container`, it will be implicitly<br>\nimported:\n\n```marko\n<!-- No need to use `require` or `import` because it will implicitly import custom tags -->\n<div>\n  <fancy-button color=input.buttonColor/>\n</div>\n```\n\n#### 7. Use JavaScript to set CSS classes and styles\n\nSetting CSS classes and styles is made easy using JavaScript! Marko will happily\naccept simple strings, JavaScript objects and arrays (_falsy values will be\nignored)._\n\n```marko\n$ const fontColor = input.color || 'blue';\n$ const isActive = input.active === true;\n\n<div class=['person', isActive && 'active']\n  style={color: fontColor} />\n```\n\n#### 8. Inline JavaScript Statements\n\nMarko takes HTML and makes it more like JavaScript. You can exit out of HTML\nmode to embed a JavaScript statement by starting the line with a `$`. You can\nuse this feature to embed JavaScript variables, functions, etc. where they are\nneeded (take that, “separation of concerns”).\n\n```marko\n$ const randomNumber = Math.random();\n$ const person = {\n  name: 'Frank',\n  age: 32\n};\n\n<div>Random number: ${randomNumber}</div>\n<div>${person.name} is ${person.age} years old</div>\n```\n\nIf you want to combine multiple JavaScript statements you can do that too:\n\n```marko\n$ {\n  const randomNumber = Math.random();\n  const person = {\n    name: 'Frank',\n    age: 32\n  };\n}\n\n<div>Random number: ${randomNumber}</div>\n<div>${person.name} is ${person.age} years old</div>\n```\n\n#### 9. Async rendering with the `<await>` tag\n\nNode.js is asynchronous. Browsers are asynchronous. Why should rendering be\nsynchronous? Pass your promise along to your template and Marko will\nasynchronously render parts of your view. Turns out, [this is good for\nperformance](https://tech.ebayinc.com/engineering/async-fragments-rediscovering-progressive-html-rendering-with-marko/).\n\n```marko\n$ const searchResultsPromise = searchService.performSearch(keywords);\n\n<await(searchResultsPromise)>\n  <@then|person|>\n    Hello ${person.name}!\n  </@then>\n  <@catch|err|>\n    The error was: ${err.message}.\n  </@catch>\n</await>\n```\n\n#### 10. Server side rendering is easy\n\nCan’t decide if you want to do server-side rendering or client-side rendering?\nWhy are we even talking about this in 2017? It doesn’t matter. Seriously, just\ndo both. Marko makes this a no-brainer since you can render a Marko template\ndirectly to a stream (oh, and Marko will automatically mount UI\ncomponents rendered on the server when the page loads in the browser):\n\n```js\nrequire(\"@marko/compiler/register\"); // require .marko files!\n\nconst http = require(\"http\");\nconst template = require(\"./template\");\n\nhttp\n  .createServer()\n  .on(\"request\", (req, res) => {\n    template.render(\n      {\n        name: \"Frank\",\n        count: 30,\n        colors: [\"red\", \"green\", \"blue\"],\n      },\n      res,\n    );\n  })\n  .listen(8080);\n```\n\n#### Bonus: Friendly compile-time errors\n\nWe all make mistakes _every now and then_. Typo in your custom tag? Forgot an\nending tag? No worries! Marko will give you a friendly error message and point\nyou right to the problematic code.\n\n```marko\n<!-- Ahhhh typo! This should be <fancy-button/> -->\n<fancy-buttn/>\n```\n\nYou may have missed it, but it was obvious to Marko:\n\n```\nUnrecognized tag: fancy-buttn — More details: https://github.com/marko-js/marko/wiki/Error:-Unrecognized-Tag at line 2 col 1\n```\n\nComing soon: auto correction and autonomous coding\n\n---\n\n[_Cover image from Wikipedia_](https://commons.wikimedia.org/wiki/File:Amanhecer_no_Hercules_--.jpg)\n\n<!-- File: packages/runtime-class/docs/body-content.md (Tokens: ~2369 | Category: anthropic-skill) -->\n# Body content\n\nWe're used to passing body content to HTML tags. When you do this, the tag has control over where and when this content is rendered. A good example of this is the [HTML `<details>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details):\n\n```html\n<details>\n  <summary>Hello <strong>World</strong></summary>\n  This is some <em>content</em> that can be toggled.\n</details>\n```\n\nThis is what it renders (try clicking it):\n\n---\n\n<details>\n    <summary>Hello <strong>World</strong></summary>\n    This is some <em>content</em> that can be toggled.\n</details>\n\n---\n\nCustom tags can also receive content in the same way. This allows a component to give its user full control over _how_ some section of the content is rendered, but control _where_, _when_, and with _what_ data it is rendered. This feature is necessary to build composable components like overlays, layouts, dropdowns, etc. Imagine a `<table>` that didn't give you control over how its cells were rendered. That would be pretty limited!\n\n## Rendering body content\n\nWhen a custom tag is passed body content, it is received as a special `renderBody` property on the component's `input`. You can include this content anywhere in your component by using the [`<${dynamic}>` syntax](./syntax.md#dynamic-tagname).\n\n_components/fancy-container.marko:_\n\n```marko\n<div class=\"container fancy\">\n    <${input.renderBody}/>\n</div>\n```\n\nIf we were to use this tag like this:\n\n_Marko Source:_\n\n```marko\n<fancy-container>\n    <p>Content goes here...</p>\n</fancy-container>\n```\n\nThe rendered output would be:\n\n_HTML Output:_\n\n```html\n<div class=\"container fancy\"><p>Content goes here...</p></div>\n```\n\nThis is a pretty basic example, but you can imagine how this could be incorporated into a more advanced component to render passed content where/when needed.\n\n> **ProTip:**\n> Body content can be rendered multiple times. Or not at all.\n\n## Passing attributes to body content\n\nWhen rendering body content with `<${dynamic}>`, attributes may also be passed:\n\n_components/random-value.marko:_\n\n```marko\n<!-- heh, it's not actually random -->\n<${input.renderBody} number=1337 />\n```\n\nThese attribute values can be received as a [tag parameter](./syntax.md#parameters):\n\n```marko\n<random-value|{ number }|>\n    The number is ${number}\n</random-value>\n```\n\n> **ProTip:**\n> Some tags (like the above tag) may not render anything except their body content with some data. This can be quite useful, just look at the `<for>` and `<await>` tags!\n\n## Named body content\n\nYou can also pass named content sections to a tag using [attribute tags](./syntax.md#attribute-tag) which are denoted by the `@` prefix.\n\n```marko\n<layout>\n    <@heading>\n        <h1>Hello Marko</h1>\n    </@heading>\n    <@content>\n        <p>...</p>\n    </@content>\n</layout>\n```\n\nLike attributes, these attribute tags are received as `input.heading` and `input.content`, but they each have a `renderBody` property which we can now use:\n\n_components/layout.marko_\n\n```marko\n<!doctype html>\n<html>\n    <body>\n        <${input.heading.renderBody}/>\n        <hr/>\n        <${input.content.renderBody}/>\n    </body>\n</html>\n```\n\n> **ProTip:** The `renderBody` property can be omitted. You could use `<${input.heading}/>`, for example.\n\n### Repeated body content\n\nWhen an attribute tag is repeated, the child component can consume all instances using the [iterable protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol).\n\nThis allows us to, for example, build a custom table component which allows its user to specify any number of columns, while still giving the user control over how each column is rendered.\n\n_Marko Source:_\n\n```marko\n<fancy-table data=people>\n    <@column|person|>\n        Name: ${person.name}\n    </@column>\n    <@column|person|>\n        Age: ${person.age}\n    </@column>\n</fancy-table>\n```\n\n> _Note_\n> For TypeScript the [`Marko.AttrTag` helper](./typescript.md#built-in-marko-types) should be used here.\n\n> _Protip_\n> Since attribute tags are iterable you could pass `input.column` to a `for of` loop, or `[...spread]` it into an array.\n> To `.map`, `.filter` or otherwise work with attribute tags as an array you can use the following pattern:\n>\n> ```marko\n> $ const columns = [...input.column || []];\n> ```\n\nWe can then use the `<for>` tag to render the body content into table, passing the row data to each column's body.\n\n_components/fancy-table/index.marko:_\n\n```marko {4-8}\n<table class=\"fancy\">\n    <for|row| of=input.data>\n        <tr>\n            <for|column| of=input.column>\n                <td>\n                    <${column.renderBody} ...row/>\n                </td>\n            </for>\n        </tr>\n    </for>\n</table>\n```\n\nWe now have a working `<fancy-table>`. Let's see what it renders:\n\n_Example Data:_\n\n```js\n[\n  {\n    name: \"Patrick\",\n    age: 63,\n  },\n  {\n    name: \"Austin\",\n    age: 12,\n  },\n];\n```\n\n_HTML Output:_\n\n```html\n<table class=\"fancy\">\n  <tr>\n    <td>Name: Patrick</td>\n    <td>Age: 63</td>\n  </tr>\n  <tr>\n    <td>Name: Austin</td>\n    <td>Age: 12</td>\n  </tr>\n</table>\n```\n\n### Attributes on attribute tags\n\nIf you look at our previous example, we had to prefix each cell with the column label. It would be better if we could give a name to each column instead and only render that once.\n\n_Marko Source:_\n\n```marko\n<fancy-table>\n    <@column|person| heading=\"Name\">\n        ${person.name}\n    </@column>\n    <@column|person| heading=\"Age\">\n        ${person.age}\n    </@column>\n</fancy-table>\n```\n\nNow, each attribute tag in `input.column` will contain a `heading` property in addition to its `renderBody`. We can use another `<for>` and render the headings in `<th>` tags:\n\n_components/fancy-table/index.marko:_\n\n```marko {3-5}\n<table class=\"fancy\">\n    <tr>\n        <for|column| of=input.column>\n            <th>${column.heading}</th>\n        </for>\n    </tr>\n    <for|row| of=input.data>\n        <tr>\n            <for|column| of=input.column>\n                <td>\n                    <${column.renderBody} ...row/>\n                </td>\n            </for>\n        </tr>\n    </for>\n</table>\n```\n\nWe'll now get a row of headings when we render our `<fancy-table>`\n\n_HTML Output:_\n\n```html\n<table class=\"fancy\">\n  <tr>\n    <th>Name</th>\n    <th>Age</th>\n  </tr>\n  <tr>\n    <td>Patrick</td>\n    <td>63</td>\n  </tr>\n  <tr>\n    <td>Austin</td>\n    <td>12</td>\n  </tr>\n</table>\n```\n\n### Nested attribute tags\n\nContinuing to build on our example, what if we want to add some custom content or even components into the column headings? In this case, we can extend our `<fancy-table>` to use nested attribute tags. We'll now have `<@heading>` and `<@cell>` tags nested under `<@column>`. This gives users of our tag full control over how to render both column headings and the cells within the column!\n\n_Marko Source:_\n\n```marko {3-8}\n<fancy-table>\n    <@column>\n        <@heading>\n            <app-icon type=\"profile\"/> Name\n        </@heading>\n        <@cell|person|>\n            ${person.name}\n        </@cell>\n    </@column>\n    <@column>\n        <@heading>\n            <app-icon type=\"calendar\"/> Age\n        </@heading>\n        <@cell|person|>\n            ${person.age}\n        </@cell>\n    </@column>\n</fancy-table>\n```\n\nNow instead of rendering the heading as text, we'll render the heading's body content.\n\n_components/fancy-table/index.marko:_\n\n```marko {5}\n<table class=\"fancy\">\n    <tr>\n        <for|column| of=input.column>\n            <th>\n                <${column.heading.renderBody}/>\n            </th>\n        </for>\n    </tr>\n    <for|row| of=input.data>\n        <tr>\n            <for|column| of=input.column>\n                <td>\n                    <${column.cell.renderBody} ...row/>\n                </td>\n            </for>\n        </tr>\n    </for>\n</table>\n```\n\nOur headings can now include icons (and anything else)!\n\n_HTML Output:_\n\n```html\n<table class=\"fancy\">\n  <tr>\n    <th><img class=\"icon\" src=\"profile.svg\" /> Name</th>\n    <th><img class=\"icon\" src=\"calendar.svg\" /> Age</th>\n  </tr>\n  <tr>\n    <td>Patrick</td>\n    <td>63</td>\n  </tr>\n  <tr>\n    <td>Austin</td>\n    <td>12</td>\n  </tr>\n</table>\n```\n\n### Dynamic attribute tags\n\nThe flexibility of the `<fancy-table>` is great if you want to render columns differently or have columns that display the data in a special way (such as displaying an age derived from a date of birth). However, if all columns are basically the same, the user might feel they're repeating themselves. As you might expect, you can use `<for>` (and `<if>`) to dynamically render attribute tags.\n\n```marko\n$ const columns = [{\n    property: \"name\",\n    title: \"Name\",\n    icon: \"profile\"\n}, {\n    property: \"age\",\n    title: \"Age\",\n    icon: \"calendar\"\n}]\n\n<fancy-table>\n    <for|{ property, title, icon }|>\n        <@column>\n            <@heading>\n                <app-icon type=icon/> ${title}\n            </@heading>\n            <@cell|person|>\n                ${person[property]}\n            </@cell>\n        </@column>\n    </for>\n</fancy-table>\n```\n\n<!-- File: packages/runtime-class/docs/class-components.md (Tokens: ~8173 | Category: anthropic-skill) -->\n# Class Components\n\nMarko makes it easy to create user interface components to use as building blocks for web pages and applications of any complexity.\n\nMarko promotes self-contained components that:\n\n- Are independently testable\n- Encapsulate the view, client-side behavior (like event handling) and styling\n- Can easily be combined to create composite UI components.\n\nMarko components compile into small, efficient JavaScript modules that hide implementation details from consumers. Components can be published to [npm](https://www.npmjs.com) for reuse across applications.\n\n## UI component diagram\n\n![Component diagram](./component-diagram.svg)\n\nIn Marko, the DOM output of a UI component is based on _input properties_ and optional _internal state_ used to control the view.\n\nIf Marko detects changes to `input` or the internal `state`, then the view (that is, the DOM) will automatically update to reflect the new input and state. Internally, Marko uses virtual DOM diffing/patching to update the view, but that’s an implementation detail that could change at any time.\n\n## Component structure\n\nMarko makes it easy to keep your component’s class and styles next to the HTML view that they correspond to. The following are the key parts of any UI component:\n\n- **View** - The HTML template for your UI component. Receives input properties and states, and renders to either server-side HTML or browser-side virtual DOM nodes.\n- **Client-side behavior** - A JavaScript `class` with methods and properties for initialization, event handling (including DOM events, custom events and lifecycle events), and state management.\n- **Styles** - Cascading StyleSheets, including support for CSS preprocessors like [Less](https://lesscss.org/) or [Sass](https://sass-lang.com/).\n\n## Server-side rendering\n\nA UI component can be rendered on the server or in the browser, but stateful component instances will be automatically mounted to the DOM in the browser for both. If a UI component tree is rendered on the server, then Marko will recreate the UI component tree in the browser with no extra code required. For more details, please see [Rendering](/docs/rendering/).\n\n## Single-file components\n\nMarko lets you define a `class` for a component right in the `.marko` file, and call that class’s methods with `on-*` attributes:\n\n```marko\nclass {\n    onCreate() {\n        this.state = {\n            count: 0\n        };\n    }\n    increment() {\n        this.state.count++;\n    }\n}\n\n<label>The current count is <output>${state.count}</output></label>\n<p><button on-click('increment')>+1</button></p>\n```\n\n### Styles\n\nAdding styles in your view is also made easy:\n\n```marko\nstyle {\n    .primary {\n        background: #09c;\n    }\n}\n\n<label>The current count is <output>${state.count}</output></label>\n<p><button.primary on-click('increment')>+1</button></p>\n```\n\nThese styles aren’t output in a `<style>` tag as inline styles usually are, but are externalized to deduplicate them across multiple component instances on a page.\n\nIf you use a CSS preprocessor, you can add its file extension on `style`:\n\n```marko\nstyle.less {\n    .primary {\n        background: @primaryColor;\n    }\n}\n```\n\n> **Note:** The code in the `style` section is processed in a context separate from the rest of the template, so you can’t use JavaScript variables inside it. If you need variables in your CSS, use a CSS preprocessor that supports them.\n\n## Multi-file components\n\nYou might prefer to keep your component’s class and styles in separate files from the view — the classical separation of HTML, CSS, and JavaScript. Marko makes this possible with a filename-based convention.\n\n> **ProTip:** If your’re moving the component’s class and styles to separate files is because the code is getting too large, consider splitting the component into smaller, more manageable components.\n\n### Supporting files\n\nMarko discovers supporting files in the same directory as a Marko view. For example, if you have a view named `counter.marko`, Marko will automatically look for `counter.component.js` and `counter.style.css`.\n\n```\ncounter.marko\ncounter.component.js\ncounter.style.css\n```\n\nMarko also handles views named `index.marko` specially. It will look for `component.js` and `style.css` in addition to `index.component.js` and `index.style.css`. This allows easily grouping component files into a directory:\n\n```\ncounter/\n    index.marko\n    component.js\n    style.css\n```\n\nIn your `component.js` file, export the component’s class:\n\n```js\nexport default class {\n  onCreate() {\n    this.state = {\n      count: 0,\n    };\n  }\n  increment() {\n    this.state.count++;\n  }\n}\n```\n\nIn your `index.marko` file, you can reference methods from that class with `on-*` attributes:\n\n```marko\n<label>The current count is <output>${state.count}</output></label>\n<p><button.primary on-click('increment')>+1</button></p>\n```\n\nAnd in your `style.css`, define the styles:\n\n```css\n.primary {\n  background: #09c;\n}\n```\n\n> **ProTip:** Marko actually looks any filenames with the pattern `[name].style.*`, so it will pick up any CSS preprocessor file extensions you use: `.less`, `.stylus`, `.scss`, etc.\n\n### Components with plain objects\n\nIf you target browsers that does not support classes, a plain object of methods can be exported:\n\n```js\nexport default {\n  onCreate: function () {\n    this.state = {\n      count: 0,\n    };\n  },\n  increment: function () {\n    this.state.count++;\n  },\n};\n```\n\n## Split components\n\nSplit components optimize for when a component renders on the server, and doesn’t need to dynamically rerender in the browser. As a result, its template and logic aren’t sent to the browser, reducing load time and download size.\n\n> **Note:** If a split component is the child of a stateful component, its full rendering logic will still be sent because the parent may pass new input to the split component and rerender it.\n\nAdditionally, if _all_ components rendered on a page are split components, Marko’s VDOM and rendering runtime is unnecessary, and therefore not sent to the browser.\n\n> **ProTip:** Don’t over-optimize. If your component really doesn’t need rerendering, go ahead and split, but don’t forgo stateful rerendering when it would make your code more maintainable.\n\n### Usage\n\nMarko discovers split components similarly to how it discovers an external component class. For example, if you have a view named `button.marko`, it will automatically look for `button.component-browser.js`. If your view is named `index.marko`, it will look for `component-browser.js` in addition to `index.component-browser.js`.\n\n```\ncounter/\n    index.marko\n    component-browser.js\n```\n\nA split component might need to do some setup as part of its initial render. In this case, the component may define a second component class to use the `onCreate`, `onInput`, and `onRender` [lifecycle methods](#lifecycle-events).\n\nThis class can be exported from `component.js`, or defined right in the template as a single-file components. In this case, your component folder may contain a `component.js` file, and must contain a `component-browser.js`. The following [lifecycle methods](#lifecycle-events) can go inside the `component.js` file:\n\n```\nclass {\n  onCreate(input, out) { }\n  onInput(input, out) { }\n  onRender(out) { }\n  onDestroy() { }\n}\n```\n\nAnd the following [lifecycle methods](#lifecycle-events) can go inside the `component-browser.js` file:\n\n```\nclass {\n  onMount() { }\n  onUpdate() { }\n}\n```\n\nAny JavaScript code related to the DOM or browser should also be inside `component-browser.js`.\n\n### Example\n\n`index.marko`\n\n```marko\nclass {\n    onCreate() {\n        this.number = 123;\n    }\n}\n\n<button on-click('shout')>What’s my favorite number?</button>\n```\n\n`component-browser.js`\n\n```js\nexport default {\n  shout() {\n    alert(`My favorite number is ${this.number}!`);\n  },\n};\n```\n\n## Event handling\n\nThe `on-[event](methodName|function, ...args)` attributes allow event listeners to be attached for either:\n\n- A native DOM event, when used on a native DOM element such as a `<button>`\n- Or a UI component event, when used on a custom tag for a UI component such as `<my-component>`\n\nThe `on-*` attributes are used to associate event handler methods with an event name. Event handlers may be specified by `'methodName'` — a string that matches a method on the component instance, or they may be a `function`. Attaching listeners for native DOM events and UI component custom events is explained in more detail in the sections below.\n\nYou may also use the `once-[event](methodName|function, ...args)` syntax, which will listen for only the first event, and then remove the listener.\n\n### Attaching DOM event listeners\n\nThe code below illustrates how to attach an event listener for native DOM events:\n\n```marko\nclass {\n  onButtonClick(name, event, el) {\n    alert(`Hello ${name}!`);\n  }\n}\n\nstatic function fadeIn(event, el) {\n  el.hidden = false;\n  el.style.opacity = 0;\n  el.style.transition = 'opacity 1s';\n  setTimeout(() => el.style.opacity = 1);\n}\n\n<button on-click('onButtonClick', 'Frank')>\n  Say Hello to Frank\n</button>\n\n<button on-click('onButtonClick', 'John')>\n  Say Hello to John\n</button>\n\n<img src='foo.jpg' once-load(fadeIn) hidden />\n```\n\nThe following arguments are passed to the event handler when the event occurs:\n\n1.  `...args` - Any extra bound arguments are _prepended_ to the arguments passed to the component’s handler method.\n    For example: `on-click('onButtonClick', arg1, arg2)` → `onButtonClick(arg1, arg2, event, el)`\n2.  `event` - The native DOM event object.\n3.  `el` - The DOM element that the event listener was attached to.\n\nWhen using the `on-*` or `once-*` attributes to attach event listeners, Marko uses event delegation that is more efficient than direct attachment of `el.addEventListener()`. Please see [Why is Marko Fast? § Event delegation](/docs/why-is-marko-fast/#event-delegation) for more details.\n\n<a id=\"declarative-custom-events\"></a>\n\n### Attaching custom event listeners\n\nThe code below illustrates how to attach an event listener for a UI component’s custom event:\n\n```marko\nclass {\n  onCounterChange(newValue, el) {\n    alert(`New value: ${newValue}!`);\n  }\n  onCounterMax(max) {\n    alert(`It reached the max: ${max}!`);\n  }\n}\n\n<counter on-change('onCounterChange') once-max('onCounterMax') />\n```\n\nThe following arguments are passed to the event handler when the event occurs:\n\n1.  `...args` - Any extra bound arguments are _prepended_ to the arguments passed to the component’s handler method.\n2.  `...eventArgs` - The arguments passed to `this.emit()` by the target UI component.\n3.  `component` - The component instance that the event listener was attached to.\n\nThe following code illustrates how the UI component for `<counter>` might emit its `change` event:\n\n`counter/index.marko`\n\n```marko\nclass {\n  onCreate() {\n    this.max = 50;\n    this.state = { count: 0 };\n  }\n  increment() {\n    if (this.state.count < this.max) {\n        this.emit('change', ++this.state.count);\n    }\n    if (this.state.count === this.max) {\n        this.emit('max', this.state.count);\n    }\n  }\n}\n\n\n<button.example-button on-click('increment')>\n  Increment\n</button>\n```\n\n> **ProTip:** Unlike native DOM events, UI component custom events may be emitted with multiple arguments. For example:\n>\n> ```js\n> this.emit(\"foo\", \"bar\", \"baz\");\n> ```\n\n## Attributes\n\n### `on-[event](methodName|function, ...args)`\n\nThe `on-*` attribute syntax attaches an event listener to either a native DOM event or a UI component event. The `on-*` attribute associates an event handler method with an event name. Please see the [Event handling](#event-handling) section above for details.\n\n### `once-[event](methodName|function, ...args)`\n\nThe same as the `on-*` attribute, except that its listener is only invoked for the first event, and then removed from memory. Please see the [Event handling](#event-handling) section above for more details.\n\n### `key`\n\nThe `key` property does 2 things in Marko:\n\n- Obtains references to nested HTML elements and nested UI components.\n- Matches corresponding elements together when DOM diffing/patching after a rerender. When updating the DOM, keyed elements/components are matched up and reused rather than discarded and recreated.\n\nInternally, Marko assigns a unique key to all HTML elements and UI components in a `.marko` file, based on the order they appear in the file. If you have repeated elements or elements that move between locations in the DOM, then you likely want to assign a custom `key` by adding a `key` attribute. The `key` attribute can be applied to both HTML elements and custom tags.\n\n#### Referencing nested HTML elements and components\n\n```marko\nclass {\n  onMount() {\n    const headerElement = this.getEl('header');\n    const colorListItems = this.getEls('colors');\n    const myFancyButton = this.getComponent('myFancyButton');\n  }\n}\n\n<h1 key=\"header\">Hello</h1>\n\n<ul>\n  <for|color| of=['red', 'green', 'blue']>\n      <li key=\"colors[]\">${color}</li>\n  </for>\n</ul>\n\n<fancy-button key=\"myFancyButton\"/>\n```\n\n> **Note:** The `[]` suffix (e.g. `key=\"colors[]\"`) lets Marko know that the element will be repeated multiple times with the same key.\n\n#### Keyed matching\n\nThe `key` attribute can pair an HTML element or UI component that moves to a new location in the DOM. For example:\n\n```marko\nclass {\n  onCreate() {\n    this.state = {\n      swapped: false\n    }\n  }\n}\n\n<if(state.swapped)>\n  <p key=\"b\">B</p>\n  <p key=\"a\">A</p>\n</if>\n<else>\n  <p key=\"a\">A</p>\n  <p key=\"b\">B</p>\n</else>\n```\n\nThe `key` attribute can be used to pair HTML elements or UI components that are repeated:\n\n```marko\n<ul>\n  <for|user| of=input.users>\n      <li key=user.id>${user.name}</li>\n  </for>\n</ul>\n```\n\nThis way, if the order of `input.users` changes, the DOM will be rerendered more efficiently.\n\n#### `*:scoped`\n\nThe `:scoped` attribute modifier results in the attribute value getting prefixed with a unique ID associated with the current UI component. `:scoped` attribute modifiers can be used to assign a globally unique attribute value from a value that only needs to be unique to the current UI component.\n\nHere’s a use-case: certain HTML attributes reference the `id` of other elements on the page. For example, the [HTML `<label>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label) `for` attribute takes an `id` as its value. Many `ARIA` attributes like [`aria-describedby`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-describedby_attribute) also take an `id` as their value.\n\nThe `:scoped` modifier on an attribute allows you to reference another element without fear of duplicate `id`s, as shown in the following examples:\n\n**`for:scoped`**\n\n```marko\n<label for:scoped=\"name\">Name</label>\n<input id:scoped=\"name\" value=\"Frank\"/>\n```\n\nThe above code will output HTML similar to the following:\n\n```html\n<label for=\"c0-name\">Name</label> <input id=\"c0-name\" value=\"Frank\" />\n```\n\n**`aria-describedby:scoped`**\n\n```marko\n<button\n   aria-describedby:scoped=\"closeDisclaimer\"\n   on-click('closeDialog')>Close</button>\n\n<p id:scoped=\"closeDisclaimer\">\n   Closing this window will discard any entered information and return you to the main page.\n</p>\n```\n\n```html\n<button aria-describedby=\"c0-closeDisclaimer\">Close</button>\n\n<p id=\"c0-closeDisclaimer\">\n  Closing this window will discard any entered information and return you to the\n  main page.\n</p>\n```\n\n**`href:scoped`**\n\n```marko\n<a href:scoped=\"#anchor\">Jump to section</a>\n<section id:scoped=\"anchor\"></section>\n```\n\n```html\n<a href=\"#c0-anchor\">Jump to section</a>\n<section id=\"c0-anchor\"></section>\n```\n\n### `no-update`\n\nPreserves the DOM subtree associated with the element or component, so it won’t be modified when rerendering.\n\n```marko\n<!-- Never rerender this table -->\n<table no-update>\n  …\n</table>\n```\n\n```marko\n<!-- N ever rerender this UI component -->\n<app-map no-update/>\n```\n\nThis is most useful when other JavaScript modifies the DOM tree of an element, like for embeds.\n\n### `no-update-if`\n\nSimilar to [no-update](#no-update), except that the DOM subtree is _conditionally_ preserved:\n\n```marko\n<!-- Don’t re-render this table without table data -->\n<table no-update-if(input.tableData == null)>\n  …\n</table>\n```\n\n### `no-update-body`\n\nSimilar to [no-update](#no-update), except that only the descendant DOM nodes are preserved:\n\n```marko\n<!-- Never rerender any nested DOM elements -->\n<div no-update-body>\n  …\n</div>\n```\n\n### `no-update-body-if`\n\nSimilar to [no-update-body](#no-update-body), except that its descendant DOM nodes are _conditionally_ preserved:\n\n```marko\n<!-- Never rerender any nested DOM elements without table data -->\n<table no-update-body-if(input.tableData == null)>\n  …\n</table>\n```\n\n### `:no-update`\n\nPrevents certain attributes from being modified during a rerender. The attribute(s) that should not be modified should have a `:no-update` modifier:\n\n```marko\n<!-- Never modify the `class` attribute -->\n<div class:no-update=input.className>\n  …\n</div>\n```\n\n## Properties\n\n### `this.id`\n\nA string identifier for the root HTML element that the component is bound to. (Not the `id` attribute.)\n\n### `this.state`\n\nThe current state for the component. Changing `this.state` or its direct properties will cause the component to rerender.\n\nOnly properties that exist when `this.state` is first defined will be watched for changes. If you don’t need a property initially, you can set its value to `null`:\n\n```marko\nclass {\n    onCreate() {\n        this.state = {\n            data: null,\n            error: null\n        }\n    }\n    getData() {\n        fetch('/endpoint')\n            .then(data => this.state.data = data)\n            .catch(error => this.state.error = error);\n    }\n}\n```\n\nBeware: setting a `state` property only _nominates_ the component for a possible rerender, and properties are only watched one level deep. Thus, the component is only rerendered if at least one of the component state properties changed (`oldValue !== newValue`).\n\nIf none of the properties changed (because the new value is identical, or no difference is detected by a shallow comparison), the assignment is considered a no-operation (great for performance).\n\nWe recommend using [immutable data structures](https://wecodetheweb.com/2016/02/12/immutable-javascript-using-es6-and-beyond/), but if you want to mutate a state property (perhaps push a new item into an array), you can mark it as dirty with `setStateDirty`:\n\n```js\nthis.state.numbers.push(num);\n\n// Mark numbers as dirty, because a `push`\n// won’t be automatically detected by Marko\nthis.setStateDirty(\"numbers\");\n```\n\n### `this.input`\n\nThe current input for the component. Setting `this.input` will rerender the component which can be useful for testing, but generally avoided (prefer `state` instead).\n\n## Variables\n\nWhen a Marko component is compiled, some additional variables are available to the rendering function. These variables are described below.\n\n### `component`\n\nThe `component` variable refers to the instance of the currently rendering UI component. This variable can be used to call methods on the UI component instance:\n\n```marko\nclass {\n    getFullName() {\n        const { person } = this.input;\n        return `${person.firstName} ${person.lastName}`;\n    }\n}\n\n<h1>Hello, ${component.getFullName()}</h1>\n```\n\n### `input`\n\nThe `input` variable refers to the `input` object, and is equivalent to `component.input`|`this.input`.\n\n```marko\n<h1>Hello, ${input.name}</h1>\n```\n\n### `state`\n\nThe `state` variable refers to the UI component’s `state` object, and is the _unwatched_ equivalent of `component.state`|`this.state`.\n\n```marko\n<h1>Hello ${state.name}</h1>\n```\n\n## Methods\n\n### `destroy([options])`\n\n| Option       | Type      | Default | Description                                                                       |\n| ------------ | --------- | ------- | --------------------------------------------------------------------------------- |\n| `removeNode` | `Boolean` | `true`  | `false` will keep the component in the DOM while unsubscribing all events from it |\n| `recursive`  | `Boolean` | `true`  | `false` will prevent child components from being destroyed                        |\n\nDestroys the component by unsubscribing from all listeners made using the `subscribeTo` method, and then detaching the component’s root element from the DOM. All nested components (discovered by querying the DOM) are also destroyed.\n\n```js\ncomponent.destroy({\n  removeNode: false, // true by default\n  recursive: false, // true by default\n});\n```\n\n### `forceUpdate()`\n\nQueue the component to re-render and skip all checks to see if it actually needs it.\n\n> When using `forceUpdate()` the updating of the DOM will be queued up. If you want to immediately update the DOM\n> then call `this.update()` after calling `this.forceUpdate()`.\n\n### `getEl([key, index])`\n\n| Signature    | Type          | Description                                                                       |\n| ------------ | ------------- | --------------------------------------------------------------------------------- |\n| `key`        | `String`      | _optional_ — the scoped identifier for the element                                |\n| `index`      | `Number`      | _optional_ — the index of the component, if `key` references a repeated component |\n| return value | `HTMLElement` | The element matching the key, or `this.el` if no key is provided                  |\n\nReturns a nested DOM element by prefixing the provided `key` with the component’s ID. For Marko, nested DOM elements should be assigned an ID with the `key` attribute.\n\n### `getEls(key)`\n\n| Signature    | Type                 | Description                                           |\n| ------------ | -------------------- | ----------------------------------------------------- |\n| `key`        | `String`             | The scoped identifier for the element                 |\n| return value | `Array<HTMLElement>` | An array of _repeated_ DOM elements for the given key |\n\nRepeated DOM elements must have a value for the `key` attribute that ends with `[]`. For example, `key=\"items[]\"`.\n\n### `getElId([key, index])`\n\n| Signature    | Type     | Description                                                                       |\n| ------------ | -------- | --------------------------------------------------------------------------------- |\n| `key`        | `String` | _optional_ — The scoped identifier for the element                                |\n| `index`      | `Number` | _optional_ — The index of the component, if `key` references a repeated component |\n| return value | `String` | The element ID matching the key, or `this.el.id` if `key` is undefined            |\n\nSimilar to `getEl`, but only returns the String ID of the nested DOM element instead of the actual DOM element.\n\n### `getComponent(key[, index])`\n\n| Signature    | Type        | Description                                                                                                                                                                                                       |\n| ------------ | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `key`        | `String`    | The scoped identifier for the element                                                                                                                                                                             |\n| `index`      | `Number`    | _optional_ — The index of the component, if `key` references a repeated component                                                                                                                                 |\n| return value | `Component` | A reference to a nested `Component` for the given key. If an `index` is provided and the target component is a repeated component (i.e. `key=\"items[]\"`), then the component at the given index will be returned. |\n\nFor example, given the following component,\n\n```marko\n<app-main>\n  <app-child key=\"child\"/>\n</app-main>\n```\n\nThe following code can be used to get the `<app-child/>` component:\n\n```js\nconst childComponent = this.getComponent(\"child\");\n```\n\n### `getComponents(key, [, index])`\n\n| Signature    | Type               | Description                                                                       |\n| ------------ | ------------------ | --------------------------------------------------------------------------------- |\n| `key`        | `String`           | The scoped identifier for the element                                             |\n| `index`      | `Number`           | _optional_ — The index of the component, if `key` references a repeated component |\n| return value | `Array<Component>` | An array of _repeated_ `Component` instances for the given key                    |\n\nRepeated components must have a value for the `key` attribute that ends with `[]`, like `key=\"items[]\"`.\n\n### `isDestroyed()`\n\nReturns `true` if a component has been destroyed using [`component.destroy()`](#ondestroy), otherwise `false`.\n\n### `isDirty()`\n\nReturns `true` if the component needs a bath.\n\n### `replaceState(newState)`\n\n| Signature  | Type     | Description                                      |\n| ---------- | -------- | ------------------------------------------------ |\n| `newState` | `Object` | A new state object to replace the previous state |\n\nReplaces the state with an entirely new state. Equivalent to `this.state = newState`.\n\n> **Note:** While `setState()` is additive and will not remove properties that are in the old state but not in the new state, `replaceState()` _will_ add the new state and remove the old state properties that are not found in the new state. Thus, if `replaceState()` is used, consider possible side effects if the new state contains less or other properties than the replaced state.\n\n### `rerender([input])`\n\n| Signature | Type     | Description                                         |\n| --------- | -------- | --------------------------------------------------- |\n| `input`   | `Object` | _optional_ — New input data to use when rerendering |\n\nRerenders the component using its `renderer`, and either supplied `input` or internal `input` and `state`.\n\n### `setState(name, value)`\n\n| Signature | Type     | Description                                |\n| --------- | -------- | ------------------------------------------ |\n| `name`    | `String` | The name of the `state` property to update |\n| `value`   | `Any`    | The new value for the `state` property     |\n\nChanges the value of a single `state` property. Equivalent to `this.state[name] = value`, except it will also work for adding new properties to the component state.\n\n```js\nthis.setState(\"disabled\", true);\n```\n\n### `setState(newState)`\n\n| Signature  | Type     | Description                                         |\n| ---------- | -------- | --------------------------------------------------- |\n| `newState` | `Object` | A new state object to merge into the previous state |\n\nChanges the value of multiple state properties:\n\n```js\nthis.setState({\n  disabled: true,\n  size: \"large\",\n});\n```\n\n### `setStateDirty(name[, value])`\n\n| Signature | Type     | Description                                       |\n| --------- | -------- | ------------------------------------------------- |\n| `name`    | `String` | The name of the `state` property to mark as dirty |\n| `value`   | `Any`    | _optional_ — A new value for the `state` property |\n\nForces a state property change, even if the value is equal to the old value. This is helpful in cases where a change occurs to a complex object that would not be detected by a shallow compare. Invoking this function completely circumvents all property equality checks (shallow compares) and always rerenders the component.\n\n#### More details\n\nThe first parameter, `name`, is used to allow update handlers (e.g. `update_foo(newValue)`) to handle the state transition for the specific state property that was marked dirty.\n\nThe second parameter, `value`, is used as the new value that is given to update handlers. Because `setStateDirty()` always bypasses all property equality checks, this parameter is optional. If not given or equal to the old value, the old value will be used for the update handler.\n\nImportant: the given parameters do not affect how or if `setStateDirty()` rerenders a component; they are only considered as additional information to update handlers.\n\n```js\n// Because this does not create a new array, the change\n// would not be detected by a shallow property comparison\nthis.state.colors.push(\"red\");\n\n// Force that particular state property to be considered dirty so\n// that it will trigger the component's view to be updated\nthis.setStateDirty(\"colors\");\n```\n\n### `subscribeTo(emitter)`\n\n| Signature    | Description                                                                                                                                           |\n| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `emitter`    | A [Node.js `EventEmitter`](https://nodejs.org/api/events.html#events_class_eventemitter) or DOM object that emits events (`window`, `document`, etc.) |\n| return value | A tracked subscription                                                                                                                                |\n\nWhen a component is destroyed, it is necessary to remove any listeners that were attached by the component to prevent memory leaks. By using `subscribeTo`, Marko will automatically track and remove any listeners you attach when the component is destroyed.\n\nMarko uses [`listener-tracker`](https://github.com/patrick-steele-idem/listener-tracker) to provide this feature.\n\n```js\nthis.subscribeTo(window).on(\"scroll\", () =>\n  console.log(\"The user scrolled the window!\"),\n);\n```\n\n### `update()`\n\nImmediately executes any pending updates to the DOM, rather than following the normal queued update mechanism for rendering.\n\n```js\nthis.setState(\"foo\", \"bar\");\nthis.update(); // Force the DOM to update\nthis.setState(\"hello\", \"world\");\nthis.update(); // Force the DOM to update\n```\n\n## Event methods\n\nMarko components inherit from [`EventEmitter`](https://nodejs.org/api/events.html#events_class_eventemitter). Below are a few commonly used methods — view the Node.js docs for the full list.\n\n### `emit(eventName, ...args)`\n\n| Signature   | Type     | Description                                           |\n| ----------- | -------- | ----------------------------------------------------- |\n| `eventName` | `String` | Name of the event                                     |\n| `...args`   | `Any`    | All subsequent parameters are passed to the listeners |\n\nEmits a UI component custom event. If a UI component attached a listener with the matching `eventName`, then the corresponding event listener method will be invoked. Event listeners can be attached using either the [`on-[event](methodName|function, ...args)`](#declarative-custom-events) attribute syntax, or `targetComponent.on()`.\n\n### `on(eventName, handler)`\n\n| Signature   | Type       | Description                               |\n| ----------- | ---------- | ----------------------------------------- |\n| `eventName` | `String`   | Name of the event to listen for           |\n| `handler`   | `Function` | The function to call when the event fires |\n\nAdds the listener function to the end of the listeners array for the `eventName` event. Does not check to see if the listener has already been added. Multiple calls passing the same combination of `eventName` and `handler` will result in the listener being added and called multiple times.\n\n### `once(eventName, handler)`\n\n| Signature   | Type       | Description                               |\n| ----------- | ---------- | ----------------------------------------- |\n| `eventName` | `String`   | Name of the event to listen for           |\n| `handler`   | `Function` | The function to call when the event fires |\n\nAdds a one-time listener function for the `eventName` event. The next time `eventName` triggers, this listener is removed and then invoked.\n\n## Lifecycle events\n\nMarko defines six lifecycle events:\n\n- `create`\n- `input`\n- `render`\n- `mount`\n- `update`\n- `destroy`\n\nThese events are emitted at specific points over the lifecycle of a component, as shown below:\n\n**First render**\n\n```js\nemit('create') → emit('input') → emit('render') → emit('mount')\n```\n\n**New input**\n\n```js\nemit('input') → emit('render') → emit('update')\n```\n\n**Internal state change**\n\n```js\nemit('render') → emit('update')\n```\n\n**Destroy**\n\n```js\nemit(\"destroy\");\n```\n\n### Lifecycle event methods\n\nEach lifecycle event has a corresponding component lifecycle method that can listen for the event:\n\n```js\nclass {\n  onCreate(input, out) { }\n  onInput(input, out) { }\n  onRender(out) { }\n  onMount() { }\n  onUpdate() { }\n  onDestroy() { }\n}\n```\n\n> **ProTip:** When a lifecycle event occurs in the browser, the corresponding event is emitted on the component instance. A parent component, or other code that has access to the component instance, can listen for these events. For example:\n>\n> ```js\n> component.on(\"input\", function (input, out) {\n>   // The component received an input\n> });\n> ```\n\n### `onCreate(input, out)`\n\n| Signature | Description                                                     |\n| --------- | --------------------------------------------------------------- |\n| `input`   | The input data used to render the component for the first time  |\n| `out`     | The async `out` used to render the component for the first time |\n\nThe `create` event is emitted (and `onCreate` is called) when the component is first created.\n\n`onCreate` is typically used to set the initial state for stateful components:\n\n```marko\nclass {\n    onCreate(input) {\n        this.state = { count: input.initialCount };\n    }\n}\n```\n\n### `onInput(input, out)`\n\n| Signature | Description        |\n| --------- | ------------------ |\n| `input`   | The new input data |\n\nThe `input` event is emitted (and `onInput` is called) when the component receives input: both the initial input, and for any subsequent updates to its input.\n\n### `onRender(out)`\n\n| Signature | Description                            |\n| --------- | -------------------------------------- |\n| `out`     | The async `out` for the current render |\n\nThe `render` event is emitted (and `onRender` is called) when the component is about to render or rerender.\n\n### `onMount()`\n\nThe `mount` event is emitted (and `onMount` is called) when the component is first mounted to the DOM. For server-rendered components, this is the first event that is emitted only in the browser.\n\nThis is the first point at which `this.el` and `this.els` are defined. `onMount` is commonly used to attach third-party JavaScript to the newly-mounted DOM.\n\nFor example, attaching a library that monitors if the component is in the viewport:\n\n```marko\nimport scrollmonitor from 'scrollmonitor';\n\nclass {\n    onMount() {\n        this.watcher = scrollmonitor.create(this.el);\n        this.watcher.enterViewport(() => console.log('I have entered the viewport'));\n        this.watcher.exitViewport(() => console.log('I have left the viewport'));\n    }\n}\n```\n\n### `onUpdate()`\n\nThe `update` event is emitted (and `onUpdate` is called) when the component is called after a component rerenders and the DOM has been updated. If a rerender does not update the DOM (nothing changed), this event will not fire.\n\n### `onDestroy()`\n\nThe `destroy` event is emitted (and `onDestroy` is called) when the component is about to unmount from the DOM and cleaned up. `onDestroy` should be used to do any additional cleanup beyond what Marko handles itself.\n\nFor example, cleaning up from our `scrollmonitor` example in [`onMount`](#onmount):\n\n```marko\nimport scrollmonitor from 'scrollmonitor';\n\nclass {\n    onMount() {\n        this.watcher = scrollmonitor.create(this.el);\n        this.watcher.enterViewport(() => console.log('Entered the viewport'));\n        this.watcher.exitViewport(() => console.log('Left the viewport'));\n    }\n    onDestroy() {\n        this.watcher.destroy();\n    }\n}\n```\n\n## DOM manipulation methods\n\nThe following methods move the component’s root DOM node(s) from the current parent element to a new parent element (or out of the DOM in the case of `detach`).\n\n### `appendTo(targetEl)`\n\nMoves the UI component’s DOM elements into the position after the target element’s last child.\n\n```js\nthis.appendTo(document.body);\n```\n\n### `insertAfter(targetEl)`\n\nMoves the UI component’s DOM elements into the position after the target DOM element.\n\n### `insertBefore(targetEl)`\n\nMoves the UI component’s DOM elements into the position before the target DOM element.\n\n### `prependTo(targetEl)`\n\nMoves the UI component’s DOM elements into the position before the target element’s first child.\n\n### `replace(targetEl)`\n\nReplaces the target element with the UI component’s DOM elements.\n\n### `replaceChildrenOf(targetEl)`\n\nReplaces the target element’s children with the UI component’s DOM elements.\n\n<!-- File: packages/runtime-class/docs/cloudflare-workers.md (Tokens: ~307 | Category: anthropic-skill) -->\n# Marko + Cloudflare Workers\n\nSee the [the cloudflare sample](https://github.com/marko-js/examples/tree/master/examples/vite-cloudflare)\nproject for a working example.\n\n## Usage\n\nWhen using Marko with [Cloudflare Workers](https://workers.cloudflare.com/), make sure that Marko is loaded with a `worker` [export condition](https://nodejs.org/api/packages.html#conditional-exports). Most bundlers support defining export conditions.\n\nAfter that point, imported `.marko` files will export a `.stream` method that returns a worker compatible [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream). You can then respond with that returned stream:\n\n```js\nimport Template from \"./index.marko\";\n\naddEventListener(\"fetch\", (event) => {\n  event.respondWith(handleRequest(event.request));\n});\n\nasync function handleRequest(request) {\n  return new Response(Template.stream(), {\n    headers: {\n      status: 200,\n      headers: { \"content-type\": \"text/html;charset=UTF-8\" },\n    },\n  });\n}\n```\n\n### BYOB (Bring your own bundler)\n\nFor the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.\nMarko supports a number of bundlers, [take a look through our supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) and pick what works best for you.\n\n<!-- File: packages/runtime-class/docs/compiler.md (Tokens: ~4823 | Category: anthropic-skill) -->\n# Compiler\n\n> **Note**:\n> This page documents the compiler for Marko 5. The [Compiler API reference](https://markojs.com/docs/reference/compiler) covers the current compiler, including the options Marko 6 adds.\n\n> **Warning**:\n> The compiler API and hooks are not terribly stable. They’re intended for advanced integrations or userland experimentation with new language features.\n>\n> Prefer existing official plugins and the standard tag library when possible.\n\n## Compile API\n\n> **Warning**:\n> The Compile API is intended for advanced integration with build tools, like Webpack and Rollup. Unless you’re doing that, you probably instead want [`build`/`serve` in the Marko CLI](https://github.com/marko-js/cli#readme), or one of [Marko’s bundler integrations](https://markojs.com/docs/bundler-integrations-overview/).\n\n### Compile Functions\n\nCompile functions take two arguments:\n\n1. A source Marko template\n2. [`CompileOptions`](#options)\n\nThen, they return a `CompileResult`:\n\n```ts\ntype CompileResult = {\n  code: string;\n  map?: SourceMap;\n  meta: Record<string, unknown>;\n};\n```\n\n- `code`: The compiled output of executable JavaScript code.\n- `map`: [A source map, used for debugging.](https://firefox-source-docs.mozilla.org/devtools-user/debugger/how_to/use_a_source_map/index.html)\n- `meta`: Metadata gathered while compiling — nothing terribly useful, probably going to get deprecated.\n  - Data about child dependencies. Was useful back when it was primarily the bundlers that handled tree-shaking out server components. Now that happens in the compiler, so we don’t use this anymore and therefore might become inaccurate in the future.\n  - A list of `watchFiles`: files that were used to compile the template (e.g. `marko.json`). Used to tell bundlers which files should be watched in dev mode.\n\n#### `compileFile()` and `compileFileSync`\n\n```ts\ncompiler.compileFile(filename: string, options?: CompileOptions): Promise<CompileResult>\ncompiler.compileFileSync(filename: string, options?: CompileOptions): CompileResult\n```\n\n`compileFile` and `compileFileSync` load `filename` from disk to use as a source template, then translate it into JavaScript.\n\n```js\nimport * as compiler from \"@marko/compiler\";\n\nconst asyncResult = await compiler.compileFile(\"./src/index.marko\", {\n  modules: \"cjs\",\n});\nconst syncResult = compiler.compileFileSync(\"./src/index.marko\", {\n  modules: \"cjs\",\n});\n```\n\n#### `compile()` and `compileSync()`\n\n```ts\ncompiler.compile(src: string, filename: string, options?: CompileOptions): Promise<CompileResult>\ncompiler.compileSync(src: string, filename: string, options?: CompileOptions): CompileResult\n```\n\n`compile` and `compileSync` accept source templates as a string, rather than loading from disk.\n\nThe `filename` location is used for resolving taglibs and imports, but does not have to be an actually existing file. <!-- TODO: should it be renamed to baseFile or importBase or something? -->\n\n```js\nimport * as compiler from \"@marko/compiler\";\n\nconst asyncResult = await compiler.compile(\n  \"<h1>Hello!</>\",\n  \"./src/index.marko\",\n  { modules: \"cjs\" },\n);\nconst syncResult = compiler.compileSync(\"<h1>Hello!</>\", \"./src/index.marko\", {\n  modules: \"cjs\",\n});\n```\n\n### Options\n\nThe compiler may be configured globally to change its default options:\n\n```js\nimport * as compiler from \"@marko/compiler\";\ncompiler.configure({ output: \"dom\" });\n```\n\nOr you can pass options objects when calling compile functions. Each property will override individual properties set by `configure()`:\n\n```js\nimport * as compiler from \"@marko/compiler\";\ncompiler.configure({\n  output: \"dom\",\n  sourceMaps: true,\n});\nconst result = compiler.compileFileSync(\"./example.marko\", {\n  output: \"html\",\n});\n```\n\nIn the above example, `result` would be compiled with the options of `{ output: \"html\", sourceMaps: true }`.\n\n#### `output`\n\nType: `string`<br>\nDefault: `\"html\"`\n\n- `\"html\"`: compiles templates to JavaScript that generates HTML strings for server HTTP responses, writing `.html` files, or maybe even constructing `Response`s in Web Workers.\n- `\"dom\"`: compiles templates to JavaScript that generates DOM nodes for client-side rendering in browsers.\n- `\"hydrate\"`: like `\"dom\"`, but only includes assets & components needed in-browser, assuming the page was rendered on the server.\n- `\"migrate\"`: only runs migrations (no transforms or translation) and returns the migrated template code.\n- `\"source\"`: parses templates without running any migrations or transforms. (Useful with `ast: true`)\n\n> **Note**:\n> For `dom` or `hydrate` outputs, you should also specify a [`resolveVirtualDependency`](#resolvevirtualdependency) function.\n\n#### `code`\n\nType: `boolean`<br>\nDefault: `true`\n\nIf `false`, will not generate or return the compiled `code` string.\n\n#### `ast`\n\nType: `boolean`<br>\nDefault: `false`\n\nIf `true`, the compiler will provide the `ast` in its output.\n\n#### `stripTypes`\n\nType: `boolean|undefined`<br>\nDefault: `undefined`\n\nIf `true`, removes all TypeScript types from the output.\nIf the value is `undefined` (the default), the compiler will remove types if the `output` option is not `source` or `migrate`.\n\nFor example, to run migrations _and_ strip types, you can set both `output: \"migrate\"` and `stripTypes: true`.\n\n#### `runtimeId`\n\nType: `string`<br>\nDefault: `undefined`\n\nOptionally use to override the runtime ID used to differentiate multiple copies of Marko on the same page, which is passed to `marko/components.init(runtimeId)` when compiling in the `hydrate` output.\n\n#### `writeVersionComment`\n\nType: `boolean`<br>\nDefault: `true`\n\nWhether the Marko version should be written to the template in a comment, like so:\n\n```js\n// Compiled using marko@x.x.x - DO NOT EDIT\n```\n\n#### `ignoreUnrecognizedTags`\n\nType: `boolean`<br>\nDefault: `false`\n\nWhether unrecognized tags should be silently ignored or throw a compile error. Ignored tags will be output as native elements.\n\n> **ProTip**:\n> Some test setups use this alongside `taglib.excludeDir` and `taglib.excludePackage` from `@marko/compiler` to simulate \"shallow\" rendering.\n\n#### `sourceMaps`\n\nType: `boolean` or `string`<br>\nDefault: `false`\n\nWhether source maps should be output with the compiled templates.\n\n- When `true` a `map` property will be available on the compile result.\n- When `\"inline\"` the sourcemap will be inlined as a comment in the output code.\n- When `\"both\"` both of the above will be used.\n\n#### `meta`\n\nType: `boolean`<br>\nDefault: `false`\n\n_Deprecated_. This option inlines the metadata in the output Javascript code. Metadata should be accessed instead from the `CompileResult`.\n\n#### `fileSystem`\n\nType: typeof [`fs`](https://nodejs.org/api/fs.html) (specifically read APIs)<br>\nDefault: Cached `fs`\n\nUse a different file system object (eg. webpack's [CachedInputFileSystem](https://github.com/webpack/enhanced-resolve/blob/f08fe3f1a22c90c722eca14b38a9300ad00c62e8/lib/CachedInputFileSystem.js) or [`arc-fs`](https://github.com/eBay/arc/tree/master/packages/arc-fs))\n\n#### `modules`\n\nType: `string` (`\"esm\"` or `\"cjs\"`)<br>\nDefault: `\"esm\"`\n\nBy default Marko outputs ES Modules. You can optionally specify `\"cjs\"` for CommonJS/`require()`.\n\n#### `optimize`\n\nType: `boolean`<br>\nDefault: [environment based](https://github.com/marko-js/marko/blob/0f212897d2d3ec30b12c2f18ba950818bccb83b4/packages/compiler/src/babel-plugin/index.js#L277-L284) (`false` in development, `true` in production)\n\nEnables production mode optimizations.\n\n#### `optimizeKnownTemplates`\n\nType: `string[]`<br>\nDefault: `undefined`\n\nIf `optimize` is enabled you can provide an array of template paths which the compiler will use to generate shorter registry/template ids using incrementing ids. This can only be used if the same `optimizeKnownTemplates` are used for both server and client compilations.\n\n#### `resolveVirtualDependency`\n\nType:\n\n```ts\n(\n  filename: string,\n  dep: {\n    code: string;\n    virtualPath: string;\n    map?: SourceMap;\n  },\n) => string;\n```\n\nDefault: `undefined`\n\nThis option should be set for `dom` or `hydrate` outputs. Since Marko templates can represent multiple output files (eg. JS renderer and CSS styles), a single source `.marko` file must be treated as potentially multiple virtual files.\n\nDifferent build tools have different mechanisms for handling virtual files. You should pass a function that returns a virtual path that can be handled by your build tool.\n\n##### Example based on `@marko/webpack/loader`:\n\n```js\n// lookup is shared between resolveVirtualDependency and markoLoader\nconst virtualSources = new Map();\n\nfunction resolveVirtualDependency(filename, { virtualPath, code, map }) {\n  const virtualFilename = `${filename}?virtual=${virtualPath}`;\n\n  // Add virtual source to the lookup to be later accessed by the loader\n  virtualSources.set(virtualFilename, { code, map });\n\n  // Generate the webpack path, from right to left...\n  // 1. Pass the virtualFilename so webpack can find the real file\n  //    located at sourceFilename, but the virtualPath is also present\n  //    (eg. \"./index.marko?virtual=./index.marko.css\")\n  // 2. Use an inline loader to run this file through @marko/webpack/loader\n  //    https://webpack.js.org/concepts/loaders/#inline\n  // 3. Use an inline matchResource to redefine this as the virtualPath\n  //    which allows the appropriate loaders to match the virtual dependency\n  //    https://webpack.js.org/api/loaders/#inline-matchresource\n  return `${virtualPath}!=!@marko/webpack/loader!${virtualFilename}`;\n}\n\nexport default function markoLoader(source) {\n  let code, map;\n\n  if (virtualSources.has(this.resource)) {\n    // If the resource has a ?virtual query param, we should\n    // find it in the lookup and then return the virtual code\n    // rather than performing the normal compilation\n    ({ code, map } = virtualSources.get(this.resource));\n    virtualSources.delete(this.resource);\n  } else {\n    // The default behavior is to compile the template in dom output mode\n    ({ code, map } = markoCompiler.compileSync(source, this.resourcePath, {\n      output: \"dom\",\n      resolveVirtualDependency,\n    }));\n  }\n\n  return this.callback(null, code, map);\n}\n```\n\n#### `hydrateIncludeImports`\n\nThis option is only used for `output: \"hydrate\"`. By default, `import`s in server-only files are not included in the hydrate output. However, for some assets, like stylesheets, it is useful to have them included in hydrate mode.\n\nThe `hydrateIncludeImports` option allows you to provide a function which receives an import path, or a regexp to match against that path which tells Marko to include that import in the hydrate mode output.\n\nThe default regexp includes a list of common known asset file extensions, and is as follows:\n\n```js\n/\\.(css(\\.[cm]?[jt]s)?|less|s[ac]ss|styl(us)?|p(ost)?css|sss|png|jpe?g|gif|svg|ico|webp|avif|mp4|webm|ogg|mp3|wav|flac|aac|woff2?|eot|ttf|otf)$/;\n```\n\nLooking at a partial Marko file such as:\n\n```marko\nimport \"./bar\"\nimport \"./foo.css\";\nimport \"./baz.wasm\";\n\n<div/>\n```\n\nFor `hydrate` output, with the default `hydrateIncludeImports`, would only cause `./foo.css` to be loaded in the browser.\n\n#### `hydrateInit`\n\nThis option is only used for `output: \"hydrate\"`. It defaults to `true` and causes the hydrate output to include code which tells the Marko runtime to begin hydrating any registered components.\n\nSetting to false will disable that `init` call and allow you to generate code which _just_ imports any hydrate dependencies for a template.\n\n#### `cache`\n\nType: typeof [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) (specifically, `.get()` is required)<br>\nDefault: `new Map()`\n\nCompiling a Marko template may require other (used) Marko templates to compile. To prevent compiling templates more than once, most of the compilation is cached.\n\nThe default cache strategy is to clear the cache each macrotask. If the default cache is overwritten, it is up to the user to determine when the cache is cleared.\n\n#### `babelConfig`\n\nType: see [babel options](https://babeljs.io/docs/en/options)<br>\nDefault: babel defaults, plus\n\n```js\n{\n  filename,\n  sourceType: \"module\",\n  sourceMaps: config.sourceMaps\n}\n```\n\n#### `translator`\n\nType: `{ analyze: Visitor, transform:Visitor }`<br>\nDefault: [autodiscovers](https://github.com/marko-js/marko/blob/0f212897d2d3ec30b12c2f18ba950818bccb83b4/packages/compiler/src/config.js#L46-L89) a translator package starting with `@marko/translator-` or `marko-translator-`\n\nThe translator is a collection of transforms that translates the Marko AST into a valid JavaScript AST based on the `output` option. There is a default translator in Marko, but this option may be used to switch to experimental translators for alternate runtimes.\n\nThe translator is an object with `analyze` and `transform` [Babel Visitors](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#visitors):\n\n- The result of the `analyze` visitor is cached and may be requested by other templates.\n- The `transform` visitor transforms the AST to its final JavaScript AST.\n\nSee [`@marko/translator-default`](https://github.com/marko-js/marko/blob/11a10f82cdb5389880e6deca5f77d17727acb831/packages/translator-default/src/index.js) for a reference implementation.\n\n## Hooks\n\n> **Note**:\n> These compiler hooks aren’t terribly stable either. Using hooks for one-time migrations, like a codemod, is the best-supported way to use the compiler hooks, since you won’t have to worry about the code changing underneath you in the future.\n\n![1. Parse (angle bracket source code) 2. Migrate (old Marko to new Marko) 3. Transform (objects to different objects) 4. Translate (Marko to JavaScript.)](./compiler-hooks.png)\n\nThe Marko compiler runs a series of stages to produce its final JavaScript output. These stages handle different steps of template processing, and can be tweaked, extended, and hooked into with [`marko.json` configuration files](./marko-json.md).\n\n- All compiler hooks must have a default export of a [Babel-style visitor function](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#toc-visitors), which will receive a [babel `NodePath`](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#paths) with a `MarkoTag` node.\n\n- Hooks will also receive a `types` object that matches the [`@babel/types`](https://babeljs.io/docs/en/babel-types) API extended with the [Marko AST types](#marko-ast). (You may also reference the types by importing `{ types } from \"@marko/compiler\"`.)\n\n- Hooks may alternatively export an `enter` function (alias of `default`), and optionally an `exit` function. These map to [`@babel/traverse`’s `enter` and `exit` methods](https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#babel-traverse).\n\nHere is an example hook:\n\n```js\nexport default (tag, types) => {\n  if (types.isStringLiteral(tag.node.name)) {\n    console.log(`Found a tag called ${tag.node.name.value}`);\n    tag.remove();\n  }\n};\n```\n\n### Parse\n\nMarko compilation starts by converting the raw text of your Marko template into an [AST (Abstract Syntax Tree)](https://en.wikipedia.org/wiki/Abstract_syntax_tree) — an object representation of your code.\n\n```marko\n<h1>Hello!</h1>\n```\n\n…will roughly become:\n\n```json\n{\n  \"type\": \"MarkoTag\",\n  \"name\": {\n    \"type\": \"StringLiteral\",\n    \"value\": \"h1\"\n  },\n  \"body\": {\n    \"type\": \"MarkoTagBody\",\n    \"body\": [\n      {\n        \"type\": \"MarkoText\",\n        \"value\": \"Hello!\"\n      }\n    ]\n  }\n}\n```\n\nThis might look a bit verbose, but ASTs aim for completeness, not terseness.\n\nMarko parses in two steps to stay flexible with the ever-changing syntax of JavaScript:\n\n1. The first parsing pass happens in our [`htmljs-parser`](https://github.com/marko-js/htmljs-parser), which understands the HTML and HTML-like parts of your template.\n\n2. For JavaScript expressions, Marko defers to [`@babel/parser`](https://babeljs.io/docs/en/babel-parser). The resulting [Marko AST](#marko-ast) is a superset of what `@babel/parser` would return.\n\nTo hook into the `parse` stage, use [the `parse` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n> **Note**: The `parse` hook deviates from the other compiler hooks:\n>\n> - It does not support the `enter` & `exit` API.\n> - You _must return_ a replacement AST node.\n\n### Migrate\n\nThat’s right, Marko has _first-class_ support for migrations. The **migration stage** can translate outdated APIs into modern counterparts, leaving the rest of the compilation none the wiser.\n\nMigrations run automatically in the background, and can be written to disk when users are ready by running the [`@marko/migrate` CLI command](https://github.com/marko-js/cli/blob/master/packages/migrate/README.md).\n\nTo hook into the `migrate` stage, [use the `migrate` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n> **Note:**\n> To make the compiler stop at this point and output the migrated template, rather than continuing to produce the JavaScript output, [set `output: \"migrate\"`](#output) in the [compilation options](#options).\n\n### Transform\n\nThe **transform stage** is meant for userland transformations of Marko code into different Marko code. Think of it like [`babel.transform`](https://babeljs.io/docs/en/babel-core#transform) for Marko templates.\nAt this stage, you are given a fully parsed and migrated AST to do what you will with.\n\nTo hook into the `transform` stage, [use the `transform` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n### Analyze\n\nNext is the **analyze stage**, intended for non-mutative analysis of the entire AST in a way that can be cached in RAM.\n\n> **Note**:\n> “Non-mutative analysis” means that if you modify the AST during this stage, _you’ll probably regret it_ someday.\n\nMetadata should be stored on nodes’ `.extra` property. These `.extra` properties are typically read in [the translate stage](#translate), or when using the child template analysis helpers.\n\nTo hook into the `analyze` stage, [use the `analyze` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n### Translate\n\nFinally, we have the **translation stage**. This stage is Marko’s “Rosetta Stone”, and is responsible for turning your beautiful `.marko` code into different versions of optimized JavaScript you’d rather not write yourself.\n\nTo hook into the `translate` stage, [use the `translate` option in the `marko.json` file](https://markojs.com/docs/marko-json/#paths).\n\n## Utilities\n\n[The `@marko/babel-utils` package](https://github.com/marko-js/marko/tree/master/packages/babel-utils/index.d.ts) exposes a handful of utilities for various tasks on [Marko ASTs](#marko-ast).\n\n### Marko AST\n\nMarko extends Babel’s AST types to add nodes for `MarkoTag`, `MarkoAttribute`, etc.\n\nFor AST creation and assertion utilities, you can import Marko’s `@babel/types` superset from the compiler package:\n\n```js\nimport { types } from \"@marko/compiler\";\n```\n\nThe [`@babel/types` documentation](https://babeljs.io/docs/en/babel-types) shows all utility methods available for Babel AST nodes. When importing `types` from `@marko/compiler`, you also get the same types of utilities for Marko nodes: `types.markoTag`, `types.isMarkoTag`, `types.assertMarkoTag`, and so on.\n\nFor full definitions, view the source code for Babel and Marko:\n\n- [Babel’s Core Definitions](https://github.com/babel/babel/blob/master/packages/babel-types/src/definitions/core.js)\n- [Babel’s Extended Definitions](https://github.com/babel/babel/tree/master/packages/babel-types/src/definitions)\n- [Marko’s Definitions](https://github.com/marko-js/marko/blob/main/packages/compiler/src/babel-types/types/definitions.js)\n\n<!-- File: packages/runtime-class/docs/concise.md (Tokens: ~668 | Category: anthropic-skill) -->\n# Concise syntax\n\nMarko's concise syntax is very similar to the HTML syntax, except it's more... concise. Essentially, you take an HTML tag, remove the angle brackets (`<>`) and use indentation rather than a closing tag:\n\n_input.marko_\n\n```marko\ndiv class=\"thumbnail\"\n    img src=\"https://example.com/thumb.png\"\n```\n\n_output.html_\n\n```html\n<div class=\"thumbnail\"><img src=\"https://example.com/thumb.png\" /></div>\n```\n\n## Shorthand attributes\n\nMarko provides a shorthand for declaring classes and ids on an element:\n\n_input.marko_\n\n```marko\ndiv.my-class\nspan#my-id\nbutton#submit.primary.large\n```\n\nYields this HTML:\n\n_output.html_\n\n```html\n<div class=\"my-class\"></div>\n<span id=\"my-id\"></span> <button id=\"submit\" class=\"primary large\"></button>\n```\n\n> **ProTip:** These shorthand attributes are available within the HTML syntax as well\n\n## Attributes on multiple lines\n\nIf a component has lots of attributes, you can spread them across multiple lines by surrounding them with square brackets\n\n_input.marko_\n\n```marko\ndiv [\n    id=\"hello\"\n    class=[\"class1\", \"class2\", \"class3\"]\n    style={ border: \"1px solid red\" }\n] -- hello\n```\n\n_output.html_\n\n```html\n<div id=\"hello\" class=\"class1 class2 class3\" style=\"border:1px solid red\">\n  hello\n</div>\n```\n\n## Text\n\nText in concise mode is denoted by two or more dashes (`--`).\n\nIf there is text on the same line following `--`, it is single-line text:\n\n_single-line-text.marko_\n\n```marko\n-- Hello world\n```\n\nThe dashes can also follow an element to give it a single text node as a child\n\n_single-line-text.marko_\n\n```marko\ndiv -- Hello world\n```\n\nIf there is a line break immediately following `--`, everything following the `--` at the current indentation is parsed as multi-line line text.\n\n_multi-line-text.marko_\n\n```marko\ndiv\n    --\n    Hello world\n    this text\n    is multi-line\n\ndiv\n    --\n    this is more\n    text\n```\n\nA multi-line text block can be ended by the same number of dashes that opened it. This allows it to have siblings:\n\n_multi-line-text.marko_\n\n```marko\ndiv\n    img src=\"https://example.com/photo.png\"\n    --\n    Hello world\n    this text\n    is multi-line\n    --\n    span -- text after\n```\n\n### Root level text\n\nThere is one \"gotcha\" that you need to be aware of. The Marko parser starts out in the concise mode. Therefore, given the following template:\n\n_input.marko_\n\n```marko\nHello World\nWelcome to Marko\n```\n\nThe output would be the following:\n\n_output.html_\n\n```html\n<Hello World></Hello> <Welcome to Marko></Welcome>\n```\n\nInstead, prefix the lines with `--` so they are parsed as text:\n\n_input.marko_\n\n```marko\n-- Hello World\n-- Welcome to Marko\n```\n\n<!-- File: packages/runtime-class/docs/conditionals-and-lists.md (Tokens: ~910 | Category: anthropic-skill) -->\n# Conditionals and Lists\n\nWhile HTML itself does not support conditionally displaying elements or repeating elements, it is a critical part of building any web application. In Marko, this functionality is provided by the `<if>` and `<for>` tags.\n\n## Conditionals\n\nThe `<if>` tag receives an [argument](./syntax.md#arguments) which is used to determine if its body content should be present.\n\n```marko\n<if(user.loggedOut)>\n    <a href=\"/login\">Log in</a>\n</if>\n```\n\nAs you might expect, there are also `<else>` and `<else-if>` tags as well:\n\n```marko\n<if(user.loggedOut)>\n    <a href=\"/login\">Log in</a>\n</if>\n<else-if(!user.trappedForever)>\n    <a href=\"/logout\">Log out</a>\n</else-if>\n<else>\n    Hey ${user.name}!\n</else>\n```\n\n## Lists\n\nIf you have a list of data and need to represent it in the UI, the `<for>` tag is probably what you're looking for. The `<for>` tag passes each item and its index to its body as [parameters](./syntax.md#parameters).\n\n```marko\n<ul>\n    <for|color, index| of=colors>\n        <li>${index}: ${color}</li>\n    </for>\n</ul>\n```\n\nThe `<for>` tag actually support 3 different flavors:\n\n- [`<for|item, index, array| of=array>`](./core-tags.md#iterating-over-a-list) renders its body for each item of an array. It's similar to the JavaScript [`for...of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) loop.\n- [`<for|key, value| in=object>`](./core-tags.md#iterating-over-an-objects-properties) renders its body for each property in an object. It's similar to the JavaScript [`for...in`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in) loop.\n- [`<for|value| from=first to=last step=increment>`](./core-tags.md#iterating-between-a-range-of-numbers) renders its body for each value in between and including `from` and `to`.\n\n### Always set a `key`\n\nMarko automatically keeps your UI in sync with the state behind it, but one place where it needs a little extra help is repeated content. Specifying keys gives Marko a way to identify items in a list and keep track of which items have been changed, added, or removed.\n\nA key should be a string or number that uniquely identifies an item in the list and differentiates it from its siblings. The same key value should never be used twice! Often, you will use something like an `id` property.\n\n```marko\n<for|user| of=users>\n    <user-card key=user.id data=user/>\n</for>\n```\n\n> **ProTip:** If you have multiple tags underneath `<for>`, you can key only the first tag and that is enough to properly identify its siblings as well\n>\n> ```marko\n> <dl>\n>     <for|entry| of=entries>\n>         <!-- only the first tag needs a key -->\n>         <dt key=entry.id>${entry.word}</dt>\n>         <!-- This key can be omitted -->\n>         <dd>${entry.definition}</dd>\n>     </for>\n> </dl>\n> ```\n\n> **Note:** If a key is not set, Marko will use the index of an item as its key. However this only works perfectly if items are only ever added or removed at the end of a list. Here's an example where things break down: if we have a list of `[\"A\", \"B\", \"C\"]` and reverse the order, index keys would cause \"A\" to be transformed into \"C\" (and \"C\" into \"A\"), rather than just swapping them. Additionally if these components contained state, the new \"C\" would contain the state from the old \"A\" (and vice-versa). Be aware, stateful components include tags like the native `<input>` element. For this reason **it is always recommended to set a `key` on tags in a `<for>`.**\n\n<!-- File: packages/runtime-class/docs/core-tags.md (Tokens: ~2527 | Category: anthropic-skill) -->\n# Core tags and attributes\n\nMuch like [HTML has its own native tags](https://developer.mozilla.org/en-US/docs/Web/HTML/Element), Marko includes **core tags** and **global attributes** for declaratively building modern applications.\n\n## `<if>`, `<else-if>`, `<else>`\n\nLike the [equivalent JavaScript statements](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else), these tags render [conditional content](./conditionals-and-lists.md#conditionals):\n\n```marko\n<if(arriving)>\n  Hey there\n</if>\n<else-if(leaving)>\n  Bye now\n</else-if>\n<else>\n  What’s up?\n</else>\n```\n\nThey support any JavaScript expression in their [tag arguments](./syntax.md#arguments):\n\n```marko\n<if(Math.random() > 0.5)>\n  <p>50% chance to see this</p>\n</if>\n```\n\n## `<for>`\n\nThe `<for>` tag iterates over [arrays/array-likes](#iterating-over-a-list), [object properties](#iterating-over-an-objects-properties), and [ranges of numbers](#iterating-between-a-range-of-numbers).\n\n### Iterating over a list\n\nLike the [JavaScript `for...of` loop statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of), giving `<for>`’s `of` attribute a value will loop over that value as an array or iterable.\n\nThe current **item**, **index**, and the **iterating list** are provided as [tag parameters](./syntax.md#parameters):\n\n```marko\n$ const colors = [\"red\", \"green\", \"blue\"];\n<ol>\n  <for|color, index, colorList| of=colors>\n    <li value=index>${color}</li>\n  </for>\n</ol>\n```\n\nThe output HTML would be:\n\n```html\n<ol>\n  <li value=\"0\">red</li>\n  <li value=\"1\">green</li>\n  <li value=\"2\">blue</li>\n</ol>\n```\n\n> **Pro Tip**: `<for>`’s `of` attribute can loop over any iterable, just like JavaScript’s [`for...of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of). This includes strings, `NodeList`s, `Set`s… any object with zero-indexed numeric properties and a `.length`, basically.\n\n### Iterating over an object’s properties\n\nLike [JavaScript’s `for...in` loop statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in), giving `<for>` an object as its `in` attribute will loop over that object’s properties.\n\nThe current **property name** and **property value** are provided as [tag parameters](./syntax.md#parameters):\n\n```marko\n$ const settings = {\n  \"Dark Mode\": false,\n  \"Fullscreen\": true\n};\n\n<dl>\n  <for|name, enabled| in=settings>\n    <dt>${name}:</dt>\n    <dd>${enabled ? \"on\" : \"off\"}</dd>\n  </for>\n</dl>\n```\n\nThe output HTML would be:\n\n```html\n<dl>\n  <dt>Dark Mode:</dt>\n  <dd>off</dd>\n  <dt>Fullscreen:</dt>\n  <dd>on</dd>\n</dl>\n```\n\n### Iterating between a range of numbers\n\nThe final `<for>` variant loops between two numbers, by providing `from` and `to` attributes. The current number in the range will be provided as a [tag parameter](./syntax.md#parameters):\n\n```marko\n<ol type=\"I\">\n  <for|i| from=0 to=10>\n    <li value=i>${i}</li>\n  </for>\n</ol>\n```\n\nYou can also pass an optional `step` attribute, which defaults to 1 otherwise. `step` lets you increment by a specific amount:\n\n```marko\n<ol type=\"I\">\n  <for|i| from=0 to=10 step=2>\n    <li value=i>${i}</li>\n  </for>\n</ol>\n```\n\n…becomes:\n\n```marko\n<ol type=\"I\">\n  <li value=\"0\">0</li>\n  <li value=\"2\">2</li>\n  <li value=\"4\">4</li>\n  <li value=\"6\">6</li>\n  <li value=\"8\">8</li>\n  <li value=\"10\">10</li>\n</ol>\n```\n\n> **ProTip:** This syntax is for generating numbers from nothing. Don’t use it to iterate over an object, like so:\n>\n> ```marko\n> <!-- Inefficient code, do not copy -->\n> <ul>\n>   <for|i| from=0 to=(myArray.length - 1)>\n>     <li>${myArray[i]}</li>\n>   </for>\n> </ul>\n> ```\n>\n> Use [`<for of>`](#iterating-over-a-list) instead.\n\n## `<while>`\n\n> **Warning:** Using `<while>` is not recommended. Instead, replicate it with [an iterable and `<for>`](#iterating-over-a-list).\n>\n> In the future, Marko may restrict value mutation during rendering, for runtime optimizations.\n\nYou can repeat a chunk of markup _until a condition is met_ with the `while` tag:\n\n```marko\n$ let n = 0;\n\n<while(n < 4)>\n  <p>${n++}</p>\n</while>\n```\n\n…becomes:\n\n```html\n<p>0</p>\n<p>1</p>\n<p>2</p>\n<p>3</p>\n```\n\n## `<macro>`\n\nMacros create reusable markup fragments for later use in the same template they were defined in.\n\nThe `<macro>` tag defines a macro as a tag via the `name` attribute. For example, the following macro is registered as the `<greeting>` tag:\n\n```marko\n<macro name=\"greeting\">\n  <p>Welcome!</p>\n</macro>\n\n<greeting/>\n<greeting/>\n```\n\n…the output HTML would be:\n\n```html\n<p>Welcome!</p>\n<p>Welcome!</p>\n```\n\nMacros become more useful with [tag parameters](./syntax.md#parameters), allowing complex templates. In this next example, `<greeting>` can now receive `firstName` and `count` parameters from its parent:\n\n```marko\n<macro|{ firstName, count }| name=\"greeting\">\n  <p>Hello ${firstName}!\n    <output>You have ${count} new messages.</output>\n  </p>\n</macro>\n\n<greeting firstName=\"Frank\" count=20/>\n```\n\n…the output HTML would be:\n\n```html\n<p>\n  Hello Frank!\n  <output>You have 20 new messages.</output>\n</p>\n```\n\nMacros receive input like components do, including [a `renderBody` for provided body content](./body-content.md):\n\n```marko\n<macro|{ renderBody }| name=\"special-heading\">\n  <h1>\n    <${renderBody}/>!\n  </h1>\n</macro>\n\n<special-heading>\n  Hello\n</special-heading>\n```\n\n…the output HTML would be:\n\n```html\n<h1>Hello!</h1>\n```\n\n> **ProTip:** You can use a macro inside itself for recursive layouts, like displaying directory contents.\n\n## `<await>`\n\nThe `<await>` tag **renders markup asynchronously using a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)**.\n\n- Its `<@then>` [attribute tag](./syntax.md#attribute-tag) displays when the Promise _resolves_, optionally receiving the resolved value as a [tag parameter](./syntax.md#parameters).\n- Its `<@catch>` attribute tag displays when the Promise _rejects_, optionally receiving the rejected value as a tag parameter.\n- Its optional `<@placeholder>` attribute tag displays while the Promise is pending.\n\n```marko\n$ const personPromise = new Promise((resolve, reject) => {\n  setTimeout(() => resolve({ name: 'Frank' }), 1000);\n});\n\n<await(personPromise) client-reorder=true>\n  <@placeholder>\n    <!-- Displays while promise is pending -->\n    <label>Loading…\n      <progress></progress>\n    </label>\n  </@placeholder>\n\n  <@then|person|>\n    <!-- Displays if promise resolves -->\n    <p>Hello ${person.name}!</p>\n  </@then>\n\n  <@catch|err|>\n    <!-- Displays if promise rejects -->\n    ${err.name} error: ${err.message}\n  </@catch>\n</await>\n```\n\nOptional attributes for `<await>`:\n\n|        Attribute | Type    | Description                                                                                                                                                                   |\n| ---------------: | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n|        `timeout` | integer | An optional timeout. If reached, rejects the promise with a `TimeoutError`.                                                                                                   |\n|           `name` | string  | Improves debugging and ensures ordering with the `show-after` attribute.                                                                                                      |\n|     `show-after` | string  | Another `<await>` tag’s `name`. Use with `client-reorder` to ensure that the current `<await>` will always render alongside or after the named `<await>`.                     |\n| `client-reorder` | boolean | If true, anything after this `<await>` will be server-rendered before the Promise completes, then the fulfilled Promise’s result will be updated with client-side JavaScript. |\n\nRegardless of these attributes, the promise is executed as eagerly as possible. The attributes control how to coordinate rendering with the rest of the page:\n\n- `client-reorder` prevents `<await>` blocks from delaying the HTTP stream, at the expense of making their rendering rely on client-side JS. Useful for making non-critical page sections not block HTML streaming of important content.\n\n- Using `show-after` with `client-reorder` ensures that the current `<await>` block will always render simultaneously with or after the named `<await>`. Useful for cutting down on [layout shift](https://web.dev/debug-layout-shifts/). `<@placeholder>`s can help fine-tune the user experience while loading.\n\n- `timeout` is useful for limiting non-critical content from slowing down the rest of the page too much.\n\n> **Pro Tip**: When using `timeout`, you can distinguish between `TimeoutError`s and promise rejections by checking the error’s `name`:\n>\n> ```marko\n> <await(slowPromise) timeout=5000>\n>   <@then>Done</@then>\n>   <@catch|err|>\n>     <if(err.name === \"TimeoutError\")>\n>       Took too long to fetch the data!\n>     </if>\n>     <else>\n>       Promise failed with ${err.message}.\n>     </else>\n>   </@catch>\n> </await>\n> ```\n\n## `<include-text>`\n\n`<include-text>` inlines text files into a template, escaping HTML syntax characters (`<`, `\"`, etc.).\n\n```marko\n<include-text('./foo.txt')/>\n```\n\nIf you do not want escaping, use [`<include-html>`](#include-html) instead.\n\n## `<include-html>`\n\nLike `<include-text>`, `<include-html>` inlines the contents of a file. However, this tag **does _not_ escape** special HTML characters.\n\n```marko\n<include-html('./foo.html')/>\n```\n\n## `<html-comment>`\n\nMarko removes HTML comment tags from its output. But if you need comments in the output, that’s what `<html-comment>` is for:\n\n```marko\n<html-comment>[if IE]><script src=\"html-shiv.js\"></script><![endif]</html-comment>\n```\n\n…becomes:\n\n```html\n<!--[if IE]><script src=\"html-shiv.js\"></script><![endif]-->\n```\n\n<!-- File: packages/runtime-class/docs/custom-tags.md (Tokens: ~1271 | Category: anthropic-skill) -->\n# Custom tags\n\nCustom tags allow you to break up your application UI into encapsulated, reusable components.\n\n## Your first custom tag\n\nLet's say we have a page with the following content:\n\n_page.marko_\n\n```marko\n<!doctype html>\n<html>\n<body>\n    <h1>Hello World!</h1>\n</body>\n</html>\n```\n\nHowever, this page is getting pretty complex and unmaintainable. Let's split out the content into a separate component. To do this, we'll create a `components/` folder and inside it a `hello.marko` file:\n\n_components/hello.marko_\n\n```marko\n<h1>Hello World!</h1>\n```\n\nMarko [automatically discovers](#how-tags-are-discovered) `.marko` files under a `components/` directory, so we can now use the `<hello>` tag in our page:\n\n_page.marko_\n\n```marko\n<!doctype html>\n<html>\n<body>\n    <hello/>\n</body>\n</html>\n```\n\nNow this `<hello>` tag can be used multiple times, and even on multiple pages. But what if we don't only want to say hello to the world? Let's pass some attributes.\n\n_page.marko_\n\n```marko\n<!doctype html>\n<html>\n<body>\n    <hello name=\"World\"/>\n</body>\n</html>\n```\n\nThe component will receive these attributes as `input`:\n\n_components/hello.marko_\n\n```marko\n<h1>Hello ${input.name}!</h1>\n```\n\nNice.\n\n## How tags are discovered\n\nMarko discovers components relative to the `.marko` file where a custom tag is used. From this file, Marko walks up directories until it finds a `components/` folder which contains a component matching the name of the custom tag. If it reaches the project root without finding anything, it will then check installed packages for the component.\n\nLet's take a look at an example directory structure to better understand this:\n\n```dir\ncomponents/\n    app-header.marko\n    app-footer.marko\npages/\n    about/\n        components/\n            team-members.marko\n        page.marko\n    home/\n        components/\n            home-banner.marko\n        page.marko\n```\n\nThe file `pages/home/page.marko` can use the following tags:\n\n- `<app-header>`\n- `<app-footer>`\n- `<home-banner>`\n\nAnd the file `pages/about/page.marko` can use the following tags:\n\n- `<app-header>`\n- `<app-footer>`\n- `<team-members>`\n\nThe home page can't see `<team-members>` and the about page can't see `<home-banner>`. By using nested `component/` directories, we've scoped our page-specific components to their respective pages.\n\n## Tag directories\n\nIn addition to a Marko template, the children of `components/` can be a directory with an `index.marko` template:\n\n```dir\ncomponents/\n    app-header/\n        index.marko\n        logo.png\n        style.css\n    app-footer/\n        index.marko\n```\n\nOr a directory with a template whose name matches its parent directory:\n\n```dir\ncomponents/\n    app-header/\n        app-header.marko\n        app-header.style.css\n        logo.png\n    app-footer/\n        app-footer.marko\n```\n\nThis allows you to create components that have other files associated with them and keep those files together in the directory structure.\n\n> **ProTip:**\n> You can take advantage of nested `components/` directories to create \"subcomponents\" that are only available to the component that contains them.\n>\n> ```dir\n> components/\n>     app-header/\n>         components/\n>             navigation.marko\n>             user-info.marko\n>         app-header.marko\n>     app-footer/\n>         app-footer.marko\n> ```\n\n## Using tags from npm\n\nTo use [tags from npm](https://www.npmjs.com/search?q=keywords%3Amarko%20components), ensure that the package is installed and listed in your `package.json` dependencies:\n\n```\nnpm install --save @marko-tags/match-media\n```\n\nMarko discovers tags from packages defined in your `package.json`, so you can start using them right away:\n\n```marko\n<div>\n    <match-media|{ mobile }| mobile=\"max-width:30em\">\n        <!-- nice -->\n    </match-media>\n</div>\n```\n\n## Publishing tags to npm\n\nWe saw above that tags from npm are automatically discovered. In order to make this work, your package must include a [`marko.json`](./marko-json.md) at the root.\n\n_marko.json_\n\n```json\n{\n  \"tags-dir\": \"./dist/components\"\n}\n```\n\nThis example file tells Marko to expose all components directly under the `dist/components/` directory to the application using your package.\n\nIf your components are written in TypeScript, publish the output of [`mtc`](https://github.com/marko-js/language-server/tree/main/packages/type-check). Editors and type checkers read components under `node_modules` as JavaScript, so consumers get their types from the `.d.marko` files it emits. See [TypeScript in Marko](./typescript.md).\n\nWe recommend adding the `marko` and `components` keywords to your `package.json` so others can find your components. Then `npm publish`!\n\n# Macros\n\nThe [`<macro>`](./core-tags.md#macro) tag allows you to create custom tags in the same file that they are used in.\n\n```marko\n<macro|{ name }| name=\"welcome-message\">\n    <h1>Hello ${name}!</h1>\n</macro>\n\n<welcome-message name=\"Patrick\"/>\n<welcome-message name=\"Austin\"/>\n```\n\n# From Variables\n\nIf no other tag would be discovered Marko will check for an in scope variable that matches the tag name.\n\n```marko\nimport SomeTag from \"./somewhere.marko\"\n\n$ const { renderBody } = input;\n$ const MyTag = input.href ? \"a\" : \"button\";\n\n<SomeTag/>\n<MyTag/>\n<renderBody/>\n```\n\n<!-- File: packages/runtime-class/docs/editor-plugins.md (Tokens: ~291 | Category: anthropic-skill) -->\n# Editor Plugins\n\n## Visual Studio Code\n\n[Documentation](https://marketplace.visualstudio.com/items?itemName=Marko-JS.marko-vscode)\n\n- Syntax highlighting\n- Tag matching\n- Tag, attribute and css autocompletion\n- Hyperclick (clickable tags and attributes)\n- Surfaces errors within the templates.\n- Prettyprinting ([marko-prettyprint](https://github.com/marko-js/marko-prettyprint) is used internally)\n\n## Atom\n\n[Documentation](https://atom.io/packages/language-marko)\n\n- Syntax highlighting\n- Tag matching\n- Tag and attribute autocompletion\n- Code snippets\n- Hyperclick (clickable tags and attributes)\n- Prettyprinting ([marko-prettyprint](https://github.com/marko-js/marko-prettyprint) is used internally)\n\n## Sublime\n\n[Documentation](https://github.com/merwan7/sublime-marko)\n\n- Syntax highlighting\n\n## WebStorm\n\n[Documentation](https://github.com/marko-js/marko-tmbundle)\n\n- Syntax highlighting\n\n## TextMate\n\n[Documentation](https://github.com/marko-js/marko-tmbundle)\n\n- Syntax highlighting\n\n## CodeMirror\n\n[codemirror-atom-modes](https://github.com/patrick-steele-idem/codemirror-atom-modes) + [atom-language-marko](https://github.com/marko-js/atom-language-marko)\n\n<!-- File: packages/runtime-class/docs/events.md (Tokens: ~892 | Category: anthropic-skill) -->\n# Events\n\nMarko’s event API supports:\n\n- [Browser events](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Events) on native tags\n- Custom events from [custom tags](./custom-tags.md)\n\nNote that **you can’t mix event targets and event types**: custom tags can only listen for custom events, and native tags can only listen for native events.\n\n## Listening to events\n\nBoth kinds of events are received with an `on-*` attribute and the [attribute arguments syntax](./syntax.md#arguments):\n\n```marko\n<input type=\"checkbox\"\n  on-change(event => console.info(`Checked? ${event.target.checked}`))\n/>\n```\n\nThe [first argument for the attribute can be a function](#function-handler), or [a string matching a method name](#method-handler) on the [component’s `class` declaration](./class-components.md).\n\n### Function handler\n\nIf you provide a function as the first argument of the `on-*` attribute, the function is called whenever the event fires, like standard event listeners.\n\nBelow we use the [`static` prefix](./syntax.md#static-javascript) to define a function, then use it as a `click` handler:\n\n```marko\nstatic function handleClick(event) {\n  event.preventDefault();\n  console.log(\"Clicked!\");\n}\n\n<button on-click(handleClick)>\n  Log click\n</button>\n```\n\nIn the above example, any time the `<button>` is clicked the `handleClick` function is called.\n\nYou can also use an inline arrow function:\n\n```marko\n<button on-click(() => alert(\"Clicked! 🎉\"))>\n  Celebrate click\n</button>\n```\n\n…or anything that evaluates to a function:\n\n```marko\n$ const handler = (\n  input.dontBreakMyApp ?\n    () => console.error(\"Clicked!\") :\n    () => { throw Error(\"Clicked!\") }\n);\n\n<button on-click(handler)>\n  Do not click\n</button>\n```\n\n### Method handler\n\nWhen a string is the first argument, Marko calls a matching method on the component's `class`.\n\n```marko\nclass {\n  logChange(newTab) {\n    console.log(`changed to: ${newTab}`);\n  }\n}\n\n<my-tabs on-switch-tab(\"logChange\")>\n  …\n</my-tabs>\n```\n\nWhen `<my-tabs>` emits the `switch-tab` event, it will call its `logChange` method.\n\nWithin the handler you can access the current component instance, read data, emit events, update state, etc.\n\n### Binding additional arguments\n\nArguments after the handler are prepended when the handler is called:\n\n```marko\nstatic function removeFriend(friendId, event) {\n  event.preventDefault();\n  window.myAPI.unfriend(friendId);\n}\n\n<for|friend| of=input.friends>\n  <button on-click(removeFriend, friend.id)>\n    Unfriend ${friend.name}\n  </button>\n</for>\n```\n\nHere we share the logic for `removeFriend()` with each `friend` in the `friends` array. When the `<button>` is clicked, the `id` of the removed `friend` is passed to the `removeFriend()`, handler followed by the DOM `click` event.\n\n## Emitting custom events\n\nThe recommended way for a [custom tag](./custom-tags.md) to communicate with its parent is through **custom events**.\n\nAll components implement a [Node.js-style event emitter](https://nodejs.org/api/events.html#events_class_eventemitter) to send events to parent components.\n\n_email-input.marko_\n\n```marko\nclass {\n  handleChange(event) {\n    if (event.target.validity.valid) {\n      // Only emit email-changes if they are valid.\n      this.emit(\"email-change\", { email: event.target.value });\n    }\n  }\n}\n\n<input type=\"email\" name=input.name on-change(\"handleChange\")/>\n```\n\nThe above code listens to native `change` events from the `<input>` element, and then emits its own `email-change` event if the change was valid.\n\n```marko\n<form>\n  <email-input name=\"email\" on-email-change(\"...\")/>\n</form>\n```\n\n> **Note:** Events are not received as `input`; you cannot access `input.onEmailChange`. Instead, they set up subscriptions.\n\n<!-- File: packages/runtime-class/docs/express.md (Tokens: ~775 | Category: anthropic-skill) -->\n# Marko + Express\n\n## Quick Start\n\n```sh\nnpm init marko -- --template vite-express\n# Or `npx create-marko --template vite-express`\n```\n\nSee [Marko’s example projects](https://github.com/marko-js/examples) for working [Express](https://expressjs.com/) integration code, such as:\n\n- [`examples/vite-express`](https://github.com/marko-js/examples/tree/master/examples/vite-express)\n- [`examples/rollup-express`](https://github.com/marko-js/examples/tree/master/examples/rollup-express)\n- [`examples/webpack-express`](https://github.com/marko-js/examples/tree/master/examples/webpack-express)\n\nBut if you want to do things the hard way…\n\n## Doing things the hard way\n\nFirst, install Marko, Express, and the glue to hold them together:\n\n```sh\nnpm install marko express @marko/express --save\n```\n\n### Skip the view engine\n\nExpress’s builtin view engine may be asynchronous, but it doesn’t support streaming — see [Rediscovering Progressive HTML Rendering](https://tech.ebayinc.com/engineering/async-fragments-rediscovering-progressive-html-rendering-with-marko/) for why that’s important. So instead, we [bypass Express’s view engine](https://strongloop.com/strongblog/bypassing-express-view-rendering-for-speed-and-modularity/) to use `@marko/express` instead.\n\n[The `@marko/express` package](https://www.npmjs.com/package/@marko/express) adds a `res.marko()` method to [Express’s response object](https://expressjs.com/en/api.html#res). This method works like [`res.render()`](https://expressjs.com/en/api.html#res.render), but without the restrictions of Express’s view engine, letting you take full advantage of Marko’s streaming and modular template organization.\n\n> **ProTip**: By using `res.marko()`, properties from [`app.locals`](https://expressjs.com/en/api.html#app.locals) and [`res.locals`](https://expressjs.com/en/api.html#res.locals) are automatically [available on `$global`](https://markojs.com/docs/rendering/#global-data).\n\n```js\nimport express from \"express\";\nimport markoPlugin from \"@marko/express\";\nimport template from \"./template.marko\";\n\nconst app = express();\napp.use(markoPlugin()); // Enables `res.marko(template, input)`\n\napp.get(\"/\", function (req, res) {\n  res.marko(template, {\n    name: \"Frank\",\n    count: 30,\n    colors: [\"red\", \"green\", \"blue\"],\n  });\n});\n\napp.listen(8080);\n```\n\n> **Note**: Older versions of `@marko/express` used to also attach Express’s `app`, `req`, and `res` objects onto `$global`. This meant uncontrolled network data could cause new and exciting surprises in your app code. Nowadays we recommend explicitly accessing the specific pieces of the HTTP exchange you’re interested in, like this:\n>\n> ```js\n> app.get(\"/\", function (req, res) {\n>   res.marko(template, {\n>     params: req.params,\n>     submitted: req.method === \"POST\" && req.body,\n>   });\n> });\n> ```\n\n### BYOB (Bring Your Own Bundler)\n\nMost of Marko’s API requires a bundler: the example code above assumes that `.marko` files can be `import`ed in your environment. [Check out Marko’s supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) to see what works best for you.\n\n<!-- File: packages/runtime-class/docs/fastify.md (Tokens: ~474 | Category: anthropic-skill) -->\n# Marko + Fastify\n\n## Quick Start\n\n```terminal\nnpm init marko -- --template vite-fastify\n```\n\nSee the [the fastify sample](https://github.com/marko-js/examples/tree/master/examples/vite-fastify)\nproject for a working example.\n\n## From Scratch\n\nFirst install Marko and the fastify related dependencies:\n\n```terminal\nnpm install marko @marko/fastify fastify --save\n```\n\n### Usage\n\nThe [`@marko/fastify`](https://github.com/marko-js/fastify/) adds a `reply.marko` decorator to the `reply` object. This function allows us to pass in a Marko template and supports Marko's streaming and modular approach to templates.\n\nBy using `reply.marko` you'll automatically have access to `app.locals`, and `reply.locals` from within your Marko template and custom tags. These values are added to `$global`.\n\n```javascript\nimport fastify from \"fastify\";\nimport markoPlugin from \"@marko/fastify\";\nimport Template from \"./template.marko\";\n\nconst app = fastify();\n\napp.register(markoPlugin);\n\napp.get(\"/\", (request, reply) => {\n  // Streams Marko template into the response.\n  // Forwards errors into fa error handler.\n  reply.marko(Template, { hello: \"world\" });\n});\n\nawait fastify.listen(3000);\n```\n\n### Global Outputs\n\nWe can add global outputs from the server side using the reply object or fastify instance.\n\n```javascript\nreply.locals.newProperty = \"Your value\";\n```\n\nTo use this in marko components we just need to refer out.global\n\n```marko\n$ const { newProperty } = $global;\n```\n\nTo know more about sending the data to the browser checkout:\n\n### [Sending global data to browsers](https://markojs.com/docs/rendering/#sending-global-data-to-browsers)\n\n### BYOB (Bring your own bundler)\n\nFor the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.\nMarko supports a number of bundlers, [take a look through our supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) and pick what works best for you.\n\n<!-- File: packages/runtime-class/docs/getting-started.md (Tokens: ~671 | Category: anthropic-skill) -->\n# Getting started\n\n## Setup\n\n### Marko Run (Recommended)\n\n[Marko Run](https://github.com/marko-js/run) makes it easy to get started with little to no config and is the recommended starting point for a new Marko project.\n\nTo set up your project:\n\n1. `npm init marko -- -t basic`\n2. `cd ./<PROJECT_NAME>`\n3. `npm run dev`\n\nOpen `src/routes/_index/+page.marko` in your editor to change the index page. See the [routing documentation](https://github.com/marko-js/run#file-based-routing) to learn how to add additional pages to your project.\n\n### Other setups\n\nIf you just want to test out Marko in your browser, use the [Try Online](https://markojs.com/try-online) feature. You can open it in another tab and follow along. For other setups, check out the [Installation](./installing.md) page.\n\n## Hello world\n\nMarko makes it easy to represent your UI using a [syntax](./syntax.md) that is like HTML:\n\n_hello.marko_\n\n```marko\n<h1>Hello World</h1>\n```\n\nIn fact, Marko is so much like HTML, that you can use it as a replacement for a templating language like handlebars, mustache, or pug:\n\n_template.marko_\n\n```marko\n<!doctype html>\n<html>\n<head>\n    <title>Hello World</title>\n</head>\n<body>\n    <h1>Hello World</h1>\n</body>\n</html>\n```\n\nHowever, Marko is much more than a templating language. It's a language that allows you to declaratively build an application by describing how the application view changes over time and in response to user actions.\n\nIn the browser, when the data representing your UI changes, Marko will automatically and efficiently update the DOM to reflect the changes.\n\n## A simple component\n\nLet's say we want to perform an action once a `<button>` is clicked:\n\n_button.marko_\n\n```marko\n<button>Click me!</button>\n```\n\nMarko makes this really easy, allowing you to define a `class` for a component right in the `.marko` view and call methods of that class with `on-` attributes:\n\n_button.marko_\n\n```marko\nclass {\n    sayHi() {\n        alert(\"Hi!\");\n    }\n}\n\n<button on-click(\"sayHi\")>Click me!</button>\n```\n\n### Adding state\n\nAlerting when a button is clicked is great, but what about updating your UI in response to an action? Marko's stateful components make this easy. All you need to do is set `this.state` from inside your component's class. This makes a new `state` variable available to your view. When a value in `this.state` is changed, the view will automatically re-render and only update the part of the DOM that changed.\n\n_counter.marko_\n\n```marko\nclass {\n    onCreate() {\n        this.state = {\n            count: 0\n        };\n    }\n    increment() {\n        this.state.count++;\n    }\n}\n\n<div>The current count is ${state.count}</div>\n<button on-click(\"increment\")>Click me!</button>\n```\n\n<!-- File: packages/runtime-class/docs/http.md (Tokens: ~252 | Category: anthropic-skill) -->\n# Marko + HTTP Server\n\nSee the [the http sample](https://github.com/marko-js/examples/tree/master/examples/vite-http)\nproject for a working example.\n\n## Usage\n\n```js\nimport http from \"http\";\nimport Template from \"./index.marko\";\n\nconst port = 8080;\nconst server = http.createServer();\n\nserver.on(\"request\", (req, res) => {\n  Template.render(\n    {\n      name: \"Frank\",\n      count: 30,\n      colors: [\"red\", \"green\", \"blue\"],\n    },\n    res,\n  ).on(\"error\", (err) => {\n    // Without a listener, a render error crashes the process.\n    console.error(err);\n  });\n});\n\nserver.listen(port, () => {\n  console.log(`Successfully started server on port ${port}`);\n});\n```\n\n### BYOB (Bring your own bundler)\n\nFor the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.\nMarko supports a number of bundlers, [take a look through our supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) and pick what works best for you.\n\n<!-- File: packages/runtime-class/docs/installing.md (Tokens: ~532 | Category: anthropic-skill) -->\n# Installation\n\n## Trying out Marko\n\nIf you just want to play around with Marko in the browser, head on over to our [Try Online](https://markojs.com/try-online) feature. You'll be able to develop a Marko application right in your browser.\n\n## Creating new apps (Recommended)\n\nIf you're starting from scratch, you can use Marko's [CLI](https://github.com/marko-js/cli) commands to quickly create a starter app:\n\n```bash\nnpm init marko\n```\n\nThis will use an interactive [CLI](https://github.com/marko-js/cli) to automatically create a project for you using the pre-made starter template of your choosing. The `basic` template is the most minimal and the easiest way to get started. It uses our recommended app framework [Marko Run](https://github.com/marko-js/run) that handles building, bundling, and serving your web application. These projects are config-free with built-in file based routing and automatic code reloading.\n\n## Custom Bundling\n\nMarko relies on JavaScript bundlers to package your code on both the client and the server. This is because Marko's client and server bundling works closely together to optimize the smallest client bundles and handle shared assets properly.\n\nUsing the CLI is still the easiest way to get started even when you want to get your hands dirty tweaking every last part of your config files. Marko currently supports Webpack, Lasso, and Rollup.\n\n### Webpack\n\n[Webpack Integration Docs](https://markojs.com/docs/webpack/)\n\n[Marko Webpack Plugin](https://github.com/marko-js/webpack)\n\n[Webpack Example](https://github.com/marko-js/examples/tree/master/examples/webpack-express)\n\nCLI Command: `npx @marko/create --template webpack-express`\n\n### Lasso\n\n[Lasso Integration Docs](https://markojs.com/docs/lasso/)\n\n[Marko Lasso Plugin](https://github.com/lasso-js/lasso-marko)\n\n[Lasso Example](https://github.com/marko-js/examples/tree/master/examples/lasso-express)\n\nCLI Command: `npx @marko/create --template lasso-express`\n\n### Rollup\n\n[Rollup Integration Docs](https://markojs.com/docs/rollup/)\n\n[Marko Rollup Plugin](https://github.com/marko-js/rollup)\n\n<!-- [Rollup Example](https://github.com/marko-js/examples/tree/master/examples/rollup)\n\nCLI Command: `npx @marko/create --template rollup` -->\n\n<!-- File: packages/runtime-class/docs/koa.md (Tokens: ~223 | Category: anthropic-skill) -->\n# Marko + Koa\n\nSee the [the koa sample](https://github.com/marko-js/examples/tree/master/examples/vite-koa)\nproject for a working example.\n\n## Installation\n\n```terminal\nnpm install koa marko --save\n```\n\n## Usage\n\n```javascript\nimport Koa from \"koa\";\nimport Template from \"./index.marko\";\n\nconst app = new Koa();\n\napp.use((ctx, next) => {\n  ctx.type = \"html\";\n  ctx.body = Template.stream({\n    name: \"Frank\",\n    count: 30,\n    colors: [\"red\", \"green\", \"blue\"],\n  });\n});\n\napp.listen(8080);\n```\n\n### BYOB (Bring your own bundler)\n\nFor the large portion of Marko's API a bundler is required. The example code above assumes that Marko templates can be loaded in your environment.\nMarko supports a number of bundlers, [take a look through our supported bundlers](https://markojs.com/docs/bundler-integrations-overview/) and pick what works best for you.\n\n<!-- File: packages/runtime-class/docs/lasso.md (Tokens: ~1558 | Category: anthropic-skill) -->\n# Marko + Lasso\n\nThe [lasso-marko](https://github.com/lasso-js/lasso-marko) plugin for [Lasso.js](https://github.com/lasso-js/lasso) will automatically compile all imported Marko templates during bundling. In addition, the `lasso-marko` plugin will automatically bundle any template dependencies (including required CSS).\n\nLasso.js provides Marko custom tags for injecting JavaScript and CSS bundles, images and other resources.\n\nThe sample [lasso-express](https://github.com/marko-js/examples/tree/master/examples/lasso-express) app demonstrates how to build a production-ready web application using Marko and Lasso. Run `npx @marko/create --template lasso-express` to use this sample as a starting point for a new app.\n\n## Installation\n\n```\nnpm install lasso-marko --save\n```\n\n## Registering the plugin\n\n```js\nrequire('lasso').configure({\n    \"plugins\": [\n        ...\n        \"lasso-marko\"\n    ]\n    ...\n});\n```\n\n## Lasso custom tags\n\nTo inject the required JavaScript and CSS into the page you will want to use the `<lasso-page>`, `<lasso-head>` and `<lasso-body>` tags.\n\nIf you are using lasso@^3 (latest), make sure to install the [lasso-marko-taglib](https://github.com/lasso-js/lasso-marko-taglib), so that you can use the lasso custom tags.\n\n```\nnpm install lasso-marko\nnpm install @lasso/marko-taglib\n```\n\nAfter installing, the lasso custom tags can be used in your templates:\n\n```html\n<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <title>Marko + Lasso</title>\n    <lasso-head />\n  </head>\n  <body>\n    <lasso-body />\n  </body>\n</html>\n```\n\nLasso.js will automatically bundle up transitive dependencies by building and walking a dependency graph.\n\n## Client-side rendering\n\nMarko templates can be imported and rendered by any JavaScript module. The code below shows how to render a top-level UI component and have it be mounted to the DOM as a child `document.body`:\n\n_client.js_\n\n<!-- prettier-ignore -->\n```js\nrequire(\"./components/app/index.marko\")\n  .renderSync({})\n  .appendTo(document.body);\n```\n\nWhen Lasso.js bundles up the code above it will automatically bundle up the required `./components/app/index.marko` file.\n\n## Server-side rendering\n\nIf you are rendering the initial UI on the server then it is necessary to make sure that all UI components are bundled and sent to the browser so that UI components can be mounted in the browser. For example:\n\n_about-me/index.marko_\n\n```marko\n<!DOCTYPE html>\n<html lang=\"en\">\n    <head>\n        <meta charset=\"UTF-8\">\n        <title>Marko + Lasso</title>\n\n        <!-- CSS will be inserted here -->\n        <lasso-head/>\n    </head>\n    <body>\n        <!-- Top-level UI component: -->\n        <app/>\n\n        <!-- JS will be inserted here -->\n        <lasso-body/>\n    </body>\n</html>\n```\n\n## Browser refresh\n\n[browser-refresh](https://github.com/patrick-steele-idem/browser-refresh) is recommended in development for instant page refreshes and hot reloading of Marko templates, styles and other resources. `browser-refresh` works well with Lasso and Marko and is very easy to use as a drop-in replacement for `node`:\n\n```bash\nbrowser-refresh server.js\n```\n\n## Lasso package types commonly used with Marko\n\nFor many use cases, the combination of `lasso-marko` and `@lasso/marko-taglib` is sufficient to render and bundle components without the need for explicit `browser.json` files. For more advanced use cases, the following bundle types may be defined in a `browser.json` for Lasso.\n\n#### `marko-dependencies` _(provided by `lasso-marko`)_\n\nIncludes all the dependencies needed by template and the code to register all components that would be rendered by the template. It does not automatically initialize the component, so is most useful if you need to initialize components manually.\n\n```json\n{\n  \"type\": \"marko-dependencies\",\n  \"path\": \"src/ui-modules/outdated-browser-banner/index.marko\"\n}\n```\n\n**Note:** To initialize the server rendered components, there are 2 steps:\n\n**Step 1:** Manually _retrieve_ server rendered components, shipped via `marko-dependencies`.\n\nTo retrieve the list of server rendered components, do:\n\n```javascript\ntemplate.render(data, (err, output) => {\n  const renderedComponentsList =\n    require(\"marko/components\").getRenderedComponents(output.out);\n  const html = output.getOutput();\n});\nres.json({\n  renderedComponentsList,\n  html,\n});\n```\n\n**Step 2:** Manually _initialize_ server rendered components, shipped via `marko-dependencies`.\n\nTo initialize the list of server rendered components, do:\n\n```javascript\n// from the response received, retrieve as\nrequire(\"marko/components\").init(response.renderedComponentsList);\n```\n\n**Note:** Ensure Step 2 is inside a DOM-ready wrapper, for the legacy widgets layer to load (if there are widgets built out of Marko 3, that is being used inside a Marko 4 component.)\n\n#### `marko-hydrate` _(provided by `lasso-marko`)_\n\nIncludes all the dependencies needed by template and the code to register all components that would be rendered by the template. This also includes the code to initialize the rendered components. Including this bundle on the page will automatically hydrate server rendered components.\n\n```json\n{\n  \"type\": \"marko-hydrate\",\n  \"path\": \"src/ui-modules/outdated-browser-banner/index.marko\"\n}\n```\n\n**Note:** `marko-hydrate` will initialize the component if its defined on the global `window.$components` which is inserted by `Marko` when it sees a `<body>` tag. Else, if you are just rendering out and lasso-ing the a portion of a page with a set of components, include `<init-components/>` at the end of the associated `template.marko` file that builds out the page fragment.\n\n#### `package`\n\nA collection of dependencies. `browser.json` is the most common package type.\nIt could be used to point to another `browser.json` from within one component's `browser.json`.\nTypically also used when the dependencies of the referred `browser.json` have to be packaged inline.\n\n```json\n{\n  \"type\": \"package\",\n  \"path\": \"src/ui-modules/show-diag/browser.json\"\n}\n```\n\n#### `require`\n\nIf a javascript file has to be wrapped over for its common JS syntax, to a browser understandable format.\n\n```json\n{\n  \"type\": \"require\",\n  \"path\": \"src/ui-modules/dynamic-module-loader/dynamic-init-client.js\"\n}\n```\n\n#### `require` and `run`\n\nIf a javascript file has to be wrapped over for its common JS syntax, to a browser understandable format and be executed immediately.\n\n```json\n{\n  \"run\": true,\n  \"type\": \"require\",\n  \"path\": \"src/ui-modules/my-module/init.js\"\n}\n```\n\n<!-- File: packages/runtime-class/docs/marko-5-upgrade.md (Tokens: ~575 | Category: anthropic-skill) -->\n# Upgrading to Marko 5\n\n## Step 0 - Ensure you're in a working state on the latest version of Marko 4\n\nBefore we start, you'll want to make sure that you are already on the latest `4.x` release of `marko`.\n\n```bash\n# Upgrade using yarn\nyarn upgrade marko@^4\n```\n\n```bash\n# Upgrade using npm\nnpm install marko@^4\n```\n\n> [!Warning]\n> Do _not_ run `npm install marko` (without the `@^4`). This will put you on Marko 5 and we're not quite there yet.\n\n> [!Tip]\n> If upgrading from Marko 3 you may want to reference [this guide](https://marko-v4.github.io/docs/marko-4-upgrade/).\n\nRun your application and tests to ensure your project is in a working state. There's little worse than finding an issue after you've started the upgrade process only to figure out the issue existed beforehand.\n\n## Step 1 - Upgrade Marko & Dependencies\n\n**TL;DR**: Paste & run this random shell script. It's safe. Trust us.\n\n```bash\n# Update Marko, and related ecosystem dependencies\nnpx -y npm-check-updates -u \\\n  marko \\\n  `# for webpack projects` \\\n  @marko/webpack \\\n  `# for lasso projects` \\\n  lasso lasso-marko @lasso/marko-taglib \\\n  `# for jest test runner` \\\n  @marko/jest \\\n  `# for projects with v3 widgets` \\\n  marko-widgets\n\n# Install @marko/compat-v4 unless `marko-widgets` is already installed\ngrep -q \"marko-widgets\" package.json || { [[ -f yarn.lock ]] && yarn add @marko/compat-v4 || npm install @marko/compat-v4; }\n[[ -f yarn.lock ]] && npx -y yarn-deduplicate && yarn\n[[ -f yarn.lock ]] || npm i\n```\n\nThis script automates the following steps for you:\n\n- Install the compat package\n  - `marko-widgets` if using Marko 3's Widgets\n  - `@marko/compat-v4` if not using Widgets\n- Update `marko` to 5.x\n- Update any ecosystem packages used by your app (lasso, webpack, jest, etc)\n\n> [!Note]\n> Check your `package.json`. If you have other third-party Marko packages not covered by the script, you may need to update them as well.\n\nYour application should continue to work. Run your tests to ensure everything is working. Congratulations! You've upgraded to Marko 5.\n\n<!-- File: packages/runtime-class/docs/marko-json.md (Tokens: ~1804 | Category: anthropic-skill) -->\n# `marko.json` & `marko-tag.json`\n\nMarko supports configuration files for validation, enabling experimental features, and custom paths for component files.\n\nThese configuration files are automatically found with [the same discovery mechanism as custom tags](./custom-tags.md#how-tags-are-discovered).\n\nThere are 2 types of configuration files:\n\n1. `marko.json` describes an entire suite of components.\n2. `marko-tag.json` describes a single component.\n\n## Single component definition\n\n`marko-tag.json` configures a single component. It’s automatically discovered if placed inside a [tag directory](./custom-tags.md#tag-directories).\n\n### Options\n\n```js\n{\n  \"html\": true, // Treat as a native HTML tag, not a custom tag.\n  \"htmlType\": \"svg\", // Optimizes for specific types of native tags (currently only `svg` and `html`).\n  \"open-tag-only\": true, // Forbids passing body content to this tag.\n  \"featureFlags\": [ \"feature-a\" ], // Enable beta features by passing feature flags.\n  \"nested-tags\": { // This section configures attribute tags.\n    \"tab\": {\n      \"target-property\": \"tabs\", // Puts `<@tab>` tags into `input.tabs`.\n      \"is-repeated\": true,  // Allow more than one nested `<@tab>`.\n      \"attributes\": {\n        // Same as the “Attributes” section below.\n      }\n    }\n  }\n}\n```\n\n### Attributes\n\nOne commonly-used feature of this config file is compile-time checks for attributes.\n\n```js\n{\n  \"attributes\": {\n    \"heading\": \"string\"\n  }\n}\n```\n\nThe above code ensures that the `heading` attribute is the _only_ attribute supplied to this tag.\n\nThe `string` value is used as documentation for the custom tag. It may be picked up by tooling, like Marko’s editor plugins, to provide hints to the user.\n\nThe recommended list of attribute types are as follows:\n\n- `expression` (any JavaScript expression)\n- `string`\n- `number`\n- `boolean`\n- `regexp`\n- `date`\n- `object`\n- `array`\n- `function`\n\nYou can also provide an object for an attribute definition’s value for additional options:\n\n```js\n{\n  \"attributes\": {\n    \"heading\": {\n      \"type\": \"string\", // Same as setting \"string\" above.\n      \"default-value\": 0, // The attribute will default to this value.\n      \"required\": true, // Error during compilation if this attribute is undefined. (Mutually exclusive with \"default-value\"\n      \"preserve-name\": true, // By default component attributes are camelCased; this disables that feature.\n      \"remove-dashes\": true, // By default native tag attributes are dash-cased; this disables that feature.\n\n      // The following attributes do nothing, but are picked up by tooling.\n      \"deprecated\": true,\n      \"description\": \"The component’s heading text\" // Describes the attribute’s purpose.\n    }\n  }\n}\n```\n\nWe can also describe a _pattern_ of attributes to match a definition:\n\n```js\n{\n    \"attributes\": {\n        \"data-*\": {\n          \"type\": \"string\",\n          \"pattern\": true\n        }\n    }\n}\n```\n\nIn the above, all attributes prefixed with `data-` are configured to be a `string`.\n\n> **Note:** Future Marko versions will describe these definitions/types in the component itself, reducing the need for this configuration file.\n\n### Paths\n\nThere are several options that override the default discovery of component files, such as the template.\n\nTypically, you should let Marko find these files automatically, but here is a reference in case you encounter these settings in the wild.\n\n```javascript\n{\n  \"template\": \"./template.marko\", // Custom path to the `.marko` template.\n  \"renderer\": \"./renderer.js\", // Custom path to the `renderer.js` file.\n\n  // Compiler file hooks\n  \"parse\": \"./parse.js\", // Used to augment parsing.\n  \"migrate\": \"./migrate.js\", // Used for migrating deprecated features.\n  \"transform\": \"./transform.js\", // Used to modify the AST before generating it.\n  \"analyze\": \"./analyze.js\" // Used to analyze metadata the entire ast before beginning to translate it.\n  \"translate\": \"./translate.js\" // Used to generate custom JS.\n}\n```\n\nFor more information about the compiler hooks [jump over here](./compiler.md#hooks).\n\n## Tag library definition\n\nAlong with configuring a single component, you can use a `marko.json` file to configure an _entire library of components_.\n\nSimilar to [`marko-tag.json`](#single-component-definition), this file is discovered if placed within a [tag directory](./custom-tags.md#tag-directories). It will also be discovered at the root directory of a project, or [in a `node_module` package](./custom-tags.md#publishing-tags-to-npm).\n\n### Options\n\n```js\n{\n  \"taglib-id\": \"my-custom-tag-library\", // Names the component library, for better errors.\n  \"exports\": \"./dist\", // Where to export the compiled components.\n  \"tags-dir\": \"./ui-modules\", // What directory to crawl to autodiscover components. Default:`./components/`\n  \"taglib-imports\": [\"./some-folder/marko.json\", \"./other-folder/marko.json\"], // Creates a _combined_ tag library by referencing others.\n  \"script-lang\": \"ts\", // Overrides the default script language, \"js\" or \"ts\", for mixed code such as an incremental TypeScript migration.\n\n  \"tags\": { // Definitions for individual tags.\n    \"my-tag\": {\n      // Same options as “marko-tag.json”.\n    }\n  },\n\n  \"attributes\": {\n    // Defines attributes on all tags.\n    // Options are the same as the “attributes” section in “marko-tag.json”.\n  },\n\n  // Compiler file hooks (run on all templates)\n  \"migrator\": \"./migrator.js\", // Hooks into the migration stage for migrating deprecated features.\n  \"transformer\": \"./transformer.js\", // Used to modify the AST before generating it.\n  \"text-transformer\": \"./text-transformer.js\", // Used to transform all static text in the template.\n}\n```\n\n> **⚠️ Note:** Compiler hooks are currently undocumented: avoid using them. The compiler API is overhauled in Marko 5, and will be documented once that transition is complete.\n\n## Shorthands\n\nBoth configuration files support _shorthands_ for defining `tags` and `attributes`. For example, take this `marko.json` file:\n\n_marko.json_\n\n```js\n{\n  \"taglib-id\": \"my-custom-tag-library\",\n  \"tags\": {\n    \"my-layout\": {\n      \"attributes\": {\n        \"name\": \"string\",\n        \"age\": \"number\"\n      },\n      \"nested-tags\": {\n        \"heading\": {\n          \"attributes\": {\n            \"color\": \"string\"\n          }\n        },\n        \"body\": {\n          \"attributes\": {\n            \"color\": \"string\"\n          }\n        }\n      }\n    }\n  }\n}\n```\n\nAs a shorthand, anywhere `tags` or `nested-tags` is used, you can remove the outer object and wrap the individual tags in `<angle-brackets>`.\n\nFor `attributes`, you can remove the outer object and prefix the attributes with an `@`.\n\nThe above example using the shorthand syntax would become:\n\n_marko.json_\n\n```js\n{\n  \"taglib-id\": \"my-custom-tag-library\",\n  \"<my-layout>\": {\n    \"@name\": \"string\",\n    \"@age\": \"number\",\n    \"<heading>\": {\n      \"@color\": \"string\"\n    },\n    \"<body>\": {\n      \"@color\": \"string\"\n    }\n  }\n}\n```\n\nFor `nested-tags`, there is also a shorthand for `is-repeated` (a postfix of `[]`) and `target-property` (a prefix of `@newName`):\n\n_marko.json_\n\n```javascript\n{\n  \"<my-layout>\": {\n    \"@sections <section>[]\": {\n      \"@color\": \"string\"\n    }\n  }\n}\n```\n\nIs equivalent to:\n\n_marko.json_\n\n```javascript\n{\n  \"tags\": {\n    \"my-layout\": {\n      \"nested-tags\": {\n        \"section\": {\n          \"target-property\": \"sections\",\n          \"is-repeated\": true,\n          \"attributes\": {\n            \"color\": \"string\"\n          }\n        }\n      }\n    }\n  }\n}\n```\n\n<!-- File: packages/runtime-class/docs/marko-vs-react.md (Tokens: ~6038 | Category: anthropic-skill) -->\n# Marko vs React: An In-depth Look\n\n<a href=\"https://hackernoon.com/marko-vs-react-an-in-depth-look-767de0a5f9a6\">\n  <img src=\"https://cdn-images-1.medium.com/max/2000/1*4BP6tPQtwImj6_QseeybwQ.png\" alt=\"Marko logo\" width=\"100%\" />\n</a><br />\n\n> This article was published March 2017. Both frameworks have gone through several updates since. You can find the original [\"Marko vs React: An In-depth Look\" article here](https://hackernoon.com/marko-vs-react-an-in-depth-look-767de0a5f9a6)!\n\nIn this article we will take an in-depth look at the differences and\nsimilarities between [Marko](https://markojs.com/) and React from the perspective\nof the maintainers of Marko.\n\nOn the surface, Marko and React have a lot in common and both are trying to\nsolve very similar problems. Specifically, both Marko and React allow developers\nto build web applications based on UI components and both free developers from\nhaving to write code to manually update the DOM. While many of the features in\nMarko were inspired by React, Marko and React offer very different usability and\nperformance characteristics. Marko was designed to avoid almost all boilerplate\nand is more closely aligned with HTML. In almost all cases, a Marko UI component\nwill require less lines of code than its React JSX equivalent while maintaining\nreadability and allowing the same expressiveness as JSX. In addition, Marko is\nhighly optimized for use on the server and in the browser and has a much smaller\nweight:\n\n<img src=\"https://cdn-images-1.medium.com/max/1600/1*a9hL_pfNrRq1UU3Mxkf3Jg.png\" alt=\"Marko logo\" width=\"100%\" /><br />\n\nBecause the Marko JavaScript library is much smaller than React, it will require\nless time to load and parse and this will drastically improve page load times on\nslow connections or on older devices. Based on [our\nbenchmarks](https://markojs.com/#benchmarks), Marko consistently outperforms\nReact by a significant margin on both the server and in the browser.\n\n### Example\n\nThe following code highlights some of the differences between Marko and React\nJSX using a somewhat contrived UI component as an example:\n\n#### React JSX\n\n```jsx\nclass Counter extends React.Component {\n  constructor(props) {\n    super(props);\n\n    this.state = { count: 0 };\n  }\n\n  increment(delta) {\n    this.setState({ count: this.state.count + delta });\n  }\n\n  render() {\n    const count = this.state.count;\n    let countClassName = \"count\";\n\n    if (count > 0) {\n      countClassName += \" positive\";\n    } else if (count < 0) {\n      countClassName += \" negative\";\n    }\n\n    return (\n      <div className=\"click-count\">\n        <div className={countClassName}>{count}</div>\n        <button\n          onClick={() => {\n            this.increment(-1);\n          }}\n        >\n          -1\n        </button>\n        <button\n          onClick={() => {\n            this.increment(1);\n          }}\n        >\n          +1\n        </button>\n      </div>\n    );\n  }\n}\n```\n\n<span class=\"figcaption_hack\">[▶ Try Online](https://codepen.io/mlrawlings/pen/wJXOWR?editors=0010)</span>\n\n#### Marko\n\n```marko\nclass {\n  onCreate() {\n    this.state = { count: 0 };\n  }\n  increment(delta) {\n    this.state.count += delta;\n  }\n}\n\n$ var count = state.count;\n\n<div.click-count>\n  <div.count class={\n      positive: count > 0,\n      negative: count < 0\n    }>\n    ${count}\n  </div>\n  <button on-click('increment', -1)>\n    -1\n  </button>\n  <button on-click('increment', 1)>\n    +1\n  </button>\n</div>\n```\n\n<span class=\"figcaption_hack\">[▶ Try\nOnline](https://markojs.com/try-online/?gist=8fe46bc5866605aca0dfeec202604011)</span>\n\n### Similarities\n\nMarko and React have the following in common:\n\n- UI component-based\n- JavaScript and HTML markup can be intertwined\n- No restrictions on JavaScript (use ES5 or ES2015+, your choice)\n- Virtual DOM rendering in the browser\n- DOM diffing/patching is used to reconcile views\n- Both support keyed element matching\n- UI components can have input properties\n- UI components can have internal state\n- Changes to state trigger an asynchronous update to the DOM\n- Updates to the DOM are batched\n- Compatible with central application state stores such as Redux and MobX\n- UI components can be embedded using custom tags\n- Declarative event binding (no `domEl.addEventListener()` needed)\n- Support for all DOM events\n- Event delegation utilized internally for DOM events that bubble\n- IE9+ support\n- Similar lifecycle events for UI components\n- JSX and Marko both compile to JavaScript\n\n### Differences\n\nAt a high level here are some differences:\n\n#### Differences in rendering\n\n- **Improved performance:** Marko renders to a virtual DOM in the browser and\n  directly to an HTML stream on the server (Marko supports multiple compilation\n  targets).\n- **Improved performance:** Marko supports asynchronous rendering with [early\n  flushing of\n  HTML](https://tech.ebayinc.com/engineering/async-fragments-rediscovering-progressive-html-rendering-with-marko/)\n  for improvements in actual and perceived page load times.\n- **Improved performance:** React requires an additional client-side re-render if\n  a page is initially rendered on the server while Marko does not.\n- **Improved ease of use:** Marko automatically serializes UI component state and\n  input down to the browser so that the browser can pick up right where the server\n  left off.\n- **Improved ease of use:** Marko is suitable for rendering an entire HTML page on\n  the server with support for tags such as `<doctype>` and `<html>`\n\n#### Differences in syntax\n\n- **Improved ease of use:** Marko uses the\n  [HTML-JS](https://markojs.com/docs/syntax/) syntax and the\n  [JSX](https://facebook.github.io/react/docs/jsx-in-depth.html) syntax is offered\n  for React.\n- **Improved ease of use:** Marko supports both a concise syntax and a familiar\n  HTML syntax.\n- **Improved ease of use:** JSX requires strict XML while Marko aligns with less\n  strict HTML that web developers are used to.\n- **Improved ease of use:** With Marko, _all_ HTML attribute values are parsed as\n  JavaScript expressions.\n- **Improved ease of use:** Marko supports simple directives for conditionals,\n  looping, etc.\n- **JSX limitation:** JSX is “just JavaScript” but requires expressions that\n  preclude the usage of JavaScript statements such as in certain places.\n\n#### Differences in compilation\n\n- **Improved performance:** Marko supports multiple compilation outputs (Marko\n  VDOM and HTML streaming are currently supported).\n- **Improved ease of use:** Marko compiles UI components to JavaScript modules\n  that export a rendering API.\n- **Expanded capabilities:** Marko supports a robust API for controlling how\n  custom tags and custom attributes get compiled and it supports compile-time\n  transforms based on a friendly Abstract Syntax Tree (AST).\n- **Improved performance:** JSX is just syntactic sugar that translates elements\n  to `createElement()` function calls while the Marko compiler has full control over how things are\n  compiled and optimized.\n- **Improved ease of use:** React requires all UI components to be explicitly\n  imported before they can be used as custom tags while Marko supports both\n  explicit importing and implicit importing.\n- **Improved performance:** Marko has a modular runtime and the compiler generates\n  code that only imports the parts of the Marko runtime that are needed for much\n  smaller builds.\n- **Improved ease of use:** Marko supports optional compile-time checks to ensure\n  that only allowed attributes are passed to custom tags. (React `PropTypes` only provide\n  validation at render-time)\n- **Improved ease of use:** Marko validates _all_ tag names at compile-time.\n- **Improved ease of use:** Marko provides its own compiler that integrates with\n  Node.js and JavaScript module bundlers while React JSX requires babel and custom\n  babel transforms.\n\n#### Differences in UI components\n\n- **Reduced boilerplate:** No explicit extending of JavaScript classes in Marko\n  (in contrast to `class Counter extends React.Component` in React).\n- **Improved ease of use:** Modifications to UI component state are synchronous\n  with Marko while [the rules for React are more\n  complicated](https://facebook.github.io/react/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous).\n- **Improved ease of use:** Marko watches UI component state objects to allow\n  state to be modified directly (e.g., `this.state.count++`).\n- **Improved ease of use:** Marko supports single-file UI components combining\n  JavaScript behavior, CSS styling (with support for CSS preprocessors) and HTML\n  markup. (React requires using one of the many [CSS in JS\n  solutions](https://github.com/MicheleBertoli/css-in-js) if you want styles in\n  the same file as your component and there is no standard in the community)\n- **Improved maintainability:** Marko supports a seamless transition from a\n  single-file UI component to a multi-file UI component.\n- **Improved performance:** Marko assumes UI components are pure by default and\n  skips re-rendering when input properties and state are unchanged (React requires\n  extending\n  [React.PureComponent](https://facebook.github.io/react/docs/react-api.html#react.purecomponent)).\n\n#### Differences in event systems\n\n- **Reduced complexity:** React utilizes [synthetic\n  events](https://facebook.github.io/react/docs/events.html) while Marko utilizes\n  real DOM events.\n- **Improved ease of use:** Custom events are emitted using the [EventEmitter\n  API](https://nodejs.org/api/events.html) in Marko (e.g., `this.emit('myCustomEvent', arg1, arg2)`).\n- **Improved ease of use:** Marko has a consistent approach for listening to both\n  native DOM events and custom events.\n- **Improved ease of use:** React requires passing around `Function` references for custom\n  events while Marko automatically delegates emitted custom events to event\n  handler methods on components.\n- **Improved ease of use:** Marko provides a simple mechanism for binding\n  additional arguments to event handler methods and `this` will be the component\n  instance.\n\n#### Differences in compatibility\n\n- **Marko limitation:** Marko has no support for native mobile similar to React\n  Native (although with Marko VDOM rendering, this is possible).\n- **Marko limitation:** Marko requires a JavaScript module bundler (such as\n  [Lasso](https://markojs.com/docs/lasso/),\n  [Webpack](https://markojs.com/docs/webpack/),\n  [Rollup](https://markojs.com/docs/rollup/)\n  since Marko UI components compile down to JavaScript modules. (we consider using\n  a JavaScript module bundler a best practice)\n\n---\n\nIn the sections below we will take a closer look at some of the differences\nbetween Marko and React.\n\n### Syntax\n\nBoth Marko and React JSX allow HTML markup and JavaScript to be combined into a\nsingle file and both support building web applications based on UI components.\nMarko utilizes an [HTML-JS syntax](https://markojs.com/docs/syntax/) while most\nReact apps use the JSX syntax.\n\n> React JSX makes JavaScript more like HTML and Marko makes HTML more like\n> JavaScript.\n\nIn the end, both Marko and React allow JavaScript and HTML to be intertwined.\n\n### Syntax: attributes\n\n#### React JSX\n\nIn React JSX, all attribute values are parsed as string values unless `{}` is used.\n\n```jsx\n<MyComponent\n  name=\"Frank\"\n  messageCount={30}\n  visible={true}\n  person={{ firstName: 'John', lastName: 'Doe' }}\n  colors={['red', 'green', 'blue']} />\n\n<div id=\"content\" className=\"foo\">Hello</div>\n```\n\n#### Marko\n\nWith Marko, _all_ attribute values are parsed as JavaScript expressions. The\nfollowing Marko code is equivalent to the React JSX code above:\n\n```marko\n<my-component\n  name=\"Frank\"\n  message-count=30\n  visible=true\n  person={ firstName: 'John', lastName: 'Doe' }\n  colors=['red', 'green', 'blue'] />\n\n<div id=\"content\" class=\"foo\">Hello</div>\n```\n\n### Syntax: inline JavaScript\n\n#### React JSX\n\nReact JSX starts with JavaScript and allows XML elements to be inlined as shown\nbelow:\n\n```jsx\nimport { formatDate } from \"./util\";\n\nfunction formatName(person) {\n  return person.firstName + \" \" + person.lastName.charAt(0) + \".\";\n}\n\nexport default function HelloMessage(props) {\n  var person = props.person;\n\n  return (\n    <div>\n      Hello {formatName(person)}!\n      <span>You were born on {formatDate(person.birthday)}.</span>\n    </div>\n  );\n}\n```\n\n#### Marko\n\nMarko starts out in HTML, but it allows JavaScript to be inlined in a clean and\nmaintainable way. Unlike other template languages, Marko aims to allow the full\npower of JavaScript. The following Marko code is equivalent to the React JSX\ncode above:\n\n```marko\nimport { formatDate } from './util';\n\nstatic function formatName(person) {\n    return person.firstName + ' ' + person.lastName.charAt(0) + '.';\n}\n\n$ var person = input.person;\n\n<div>\n    Hello ${formatName(person)}!\n    <span>\n      You were born on ${formatDate(person.birthday)}.\n    </span>\n</div>\n```\n\nLines prefixed with `$` are directly added to the compiled JavaScript output inside\nthe compiled `render()` function (for JavaScript code that should run for every render).\nLines prefixed with `static` are directly added to the compiled JavaScript output\noutside the `render()` function (for code that should only run _once_ when the template is\nloaded).\n\n### Syntax: HTML support\n\nWith Marko any valid HTML markup can be used inside a Marko template. This is\nnot the case with React. The following quote is from the [React\ndocumentation](https://facebook.github.io/react/docs/introducing-jsx.html#specifying-children-with-jsx):\n\n> **Caveat:**\n\n> Since JSX is closer to JavaScript than HTML, React DOM uses `camelCase` property naming\n> convention instead of HTML attribute names.\n\n> For example, `class` becomes `className` in JSX, and `tabindex` becomes `tabIndex`.\n\nAs a result of this caveat for React, [tools for converting HTML to JSX\nexist](https://magic.reactjs.net/htmltojsx.htm).\n\n#### React JSX\n\n```jsx\n<div id=\"content\" className=\"my-component\">Hello</div>\n\n<input type=\"text\" name=\"firstName\" value=\"John\" />\n```\n\n#### Marko\n\n```marko\n<div id=\"content\" class=\"my-component\">Hello</div>\n\n<input type=\"text\" name=\"firstName\" value=\"John\">\n```\n\n### Syntax: conditionals\n\nJSX is syntactic sugar on top of JavaScript, but it requires expressions, so\nsimple things like an `if/else/for` statement don’t work on their own within a JSX element. As\na result, you must either use a ternary expression, an immediately invoked\nfunction expression, function call expression, or the experimental `do {}` expression\n(stage 0 at the time of writing). This is not an issue for Marko, and tags\nsuch as `if()` and `for` can be used anywhere as shown below:\n\n#### React JSX\n\n```jsx\nfunction counterMessage(count) {\n  return (\n    <div className=\"counter-message\">\n      (function() {\n        if (count < 0) {\n          return <div>Count is negative</div>\n        } else if (count === 0) {\n          return <div>Count is zero</div>\n        } else {\n          return <div>Count is positive</div>\n        }\n      }())\n    </div>\n  )\n}\n```\n\n#### Marko\n\n```marko\n<div.counter-message>\n  <if(count < 0)>\n    <div>Count is negative</div>\n  </if>\n  <else if(count === 0)>\n    <div>Count is zero</div>\n  </else>\n  <else>\n    <div>Count is positive</div>\n  </else>\n</div>\n```\n\nMarko also allows directives to be used as attributes for a more condensed\ntemplate:\n\n```marko\n<div.counter-message>\n  <div if(count < 0)>Count is negative</div>\n  <div if(count === 0)>Count is zero</div>\n  <div else>Count is positive</div>\n</div>\n```\n\n### Syntax: looping\n\n#### React JSX\n\n```jsx\nfunction renderColors(colors) {\n  return (\n    <ul>\n      {colors.map((color) => (\n        <li\n          className=\"color\"\n          style={{\n            backgroundColor: color,\n          }}\n        >\n          {color}\n        </li>\n      ))}\n    </ul>\n  );\n}\n```\n\n#### Marko\n\n```marko\n<ul>\n  <for|color| of=colors>\n    <li.color style={ backgroundColor: color }>\n        ${color}\n    </li>\n  </for>\n</ul>\n```\n\n### Syntax: HTML shorthand\n\n```marko\n<div id=\"content\"/>\n<h1 class=\"subheader\"/>\n<h1 id=\"pageTitle\" class=\"foo bar\"/>\n\n<!-- Shorthand equivalent: -->\n<div#content/>\n<h1.subheader/>\n<h1#pageTitle.foo.bar/>\n```\n\nMarko supports a shorthand based on CSS selectors for less code.\n\nReact does not support these helpful shorthands.\n\n### Syntax: concise\n\nMarko supports a concise syntax that drops angled brackets and ending tags in\nfavor of indentation. Here’s how the Marko syntax options compare:\n\n#### Marko HTML syntax\n\n```marko\n<ul>\n  <for|color| of=colors>\n    <li>${color}</li>\n  </for>\n</ul>\n```\n\n#### Marko concise syntax\n\n```marko\nul\n  for|color| of=colors\n    li -- ${color}\n```\n\n#### Marko mixed syntax\n\n```marko\nul\n  for|color| of=colors\n    <li>${color}</li>\n```\n\nThe HTML syntax and the concise syntax can be used together:\n\n#### React JSX\n\nReact does not offer a concise syntax.\n\n### Components\n\nMarko starts with simple HTML and allows UI component logic to easily be layered\non top.\n\n#### React JSX\n\nA React UI component is typically implemented as a class that extends `ReactComponent`:\n\n```jsx\nclass HelloMessage extends React.Component {\n  render() {\n    return <div>Hello {this.props.name.toUpperCase()}</div>;\n  }\n}\n```\n\nReact also supports a more concise functional component:\n\n```jsx\nfunction HelloMessage(props) {\n  return <div>Hello {props.name.toUpperCase()}</div>;\n}\n```\n\nHowever, if state or lifecycle events are needed then a functional UI component\nmust be converted to a class component:\n\n```jsx\nclass HelloMessage extends React.Component {\n  componentDidMount() {\n    // ...\n  }\n  render() {\n    return <div>Hello {this.props.name.toUpperCase()}</div>;\n  }\n}\n```\n\n#### Marko\n\nHere is the same component in Marko:\n\n```marko\n<div>Hello ${input.name.toUpperCase()}</div>\n```\n\nBehavior can easily be added to any Marko UI component:\n\n```marko\nclass {\n  onMount() {\n    // ...\n  }\n}\n\n<div>Hello ${input.name.toUpperCase()}</div>\n```\n\nMarko also allows JavaScript behavior, CSS styling and HTML markup to be\nembedded in the Marko template as a single file UI component:\n\n```marko\nclass {\n  onMount() {\n    // ...\n  }\n}\n\nstyle.less {\n  .hello {\n    color: red;\n  }\n}\n\n<div.hello>\n  Hello ${input.name.toUpperCase()}\n</div>\n```\n\n### API\n\nMarko compiles components to JavaScript modules that export their rendering APIs,\nas shown below:\n\n```js\nimport Greeting from \"./components/greeting.marko\";\nGreeting.renderSync({ name: \"Frank\" }).appendTo(document.body);\n```\n\nThe same UI component can render to streams, such as a writable HTTP\nresponse stream:\n\n```js\nimport Greeting from \"./components/greeting.marko\";\nGreeting.render({ name: \"John\" }, res);\n```\n\n> The users of a Marko UI component do not need to know that the component was\n> implemented using Marko.\n\nContrast this with React as an example:\n\n```jsx\nimport ReactDOM from \"react-dom\";\n\nReactDOM.render(\n  <HelloMessage name=\"John\" />,\n  document.getElementById(\"container\"),\n);\n```\n\nOn top of that, React requires that a different module be imported to render the\nexact same UI component on the server:\n\n```jsx\nimport ReactDOMServer from \"react-dom/server\";\n\nvar html = ReactDOMServer.renderToString(<HelloMessage name=\"John\" />);\n```\n\n### Custom tags\n\n#### React JSX\n\nWith React, all custom tags for UI components must be explicitly imported:\n\n```jsx\nimport Hello from \"./components/Hello\";\nimport GoodBye from \"./components/GoodBye\";\n\nexport default function HelloGoodBye(props) {\n  return (\n    <div>\n      <Hello name={props.name} />\n      <GoodBye name={props.name} />\n    </div>\n  );\n}\n```\n\n#### Marko\n\nMarko supports a mechanism for [automatically discovering custom\ntags](https://markojs.com/docs/custom-tags/#discovering-tags) for UI components\nbased on the project directory structure. Marko walks up the directory tree to\ndiscover all directories and it will also automatically discover custom tags\nexported by installed packages. This approach negates the need for explicitly\nimporting a custom tag to reduce the amount of code needed in a Marko template.\nFor example given the following directory structure:\n\n```\n    .\n    ├── components/\n    │   ├── hello.marko\n    │   └── good-bye.marko\n    └── index.marko\n```\n\nThe `<hello>` tag and the `<good-bye>` tag nested below the `components/`\ndirectory will automatically be made available to the `index.marko` at the root:\n\n```marko\n<div>\n  <hello name=input.name />\n  <good-bye name=input.name />\n</div>\n```\n\nThis approach also allows editors and IDEs to offer autocompletion for custom\ntags.\n\n### Async\n\nEven after rendering has started, Marko allows parts of the view to be rendered\nasynchronously using the [`<await>`](https://markojs.com/docs/core-tags#await)\ntag as shown in the following Marko template:\n\n```marko\nimport fsp from 'fs-promise';\n\n$ var filePath = __dirname + '/hello.txt';\n$ var readPromise = fsp.readFile(filePath, {encoding: 'utf8'});\n\n<await(readPromise)>\n  <@then|helloText|>\n    <p>${helloText}</p>\n  </@then>\n</await>\n```\n\n### Compiler\n\nMarko compiles a template differently based on whether or not it will be used on\nthe server or in the browser. For example, given the following template:\n\n```marko\n<div>Hello ${input.name}!</div>\n```\n\n#### Compiled for the server:\n\n```js\nvar marko_template = require(\"marko/html\").t(__filename),\n  marko_helpers = require(\"marko/runtime/html/helpers\"),\n  marko_escapeXml = marko_helpers.x;\n\nfunction render(input, out) {\n  out.w(\"<div>Hello \" + marko_escapeXml(input.name) + \"!</div>\");\n}\n```\n\n#### Compiled for the browser:\n\n```js\nvar marko_template = require(\"marko/vdom\").t(__filename);\n\nfunction render(input, out) {\n  out.e(\"DIV\", null, 3).t(\"Hello \").t(input.name).t(\"!\");\n}\n```\n\n### Compile-time code transforms\n\nThe Marko compiler was built to support compile-time code generators for custom\ntags and it also provides support for compile-time transforms. While Babel\nallows code transformations of JavaScript, the Marko compiler provides support\nfor resolving custom tags declaratively and the Marko AST provides for very\npowerful and simple transformations as shown in the following code for rendering\nMarkdown to HTML at _compile-time_:\n\n**components/markdown/code-generator.js:**\n\n```js\nimport marked from \"marked\";\nimport { removeIndentation } from \"./util\";\n\nexport default function generateCode(el, codegen) {\n  var bodyText = removeIndentation(el.bodyText);\n  var html = marked(bodyText);\n  var builder = codegen.builder;\n  return builder.html(builder.literal(html));\n}\n```\n\nThe `<markdown>` tag can then be used as shown below:\n\n```marko\n<markdown>\n\n> This section demonstrates Markdown in Marko\n\n# Marko is awesome!\n\n- High performance\n- Small\n- Intuitive\n\n</markdown>\n```\n\nIn this example, after the template is compiled, the\n[marked](https://github.com/chjj/marked) library is no longer needed at\nrender-time.\n\n### Tools\n\nMarko and React offer a variety of developer tools. The [Marko developer\ntools](https://github.com/marko-js/marko-devtools) are constantly evolving, but\nMarko currently provides tools for unit testing UI components, precompiling `.marko`\nfiles and generating configuration-less apps (similar to\n[create-react-app](https://github.com/facebookincubator/create-react-app)).\nCurrently, there are no Marko developer tools that integrate with the browser,\nbut this is something we would like to see in the future. We will go into more\ndetail on the Marko developer tools in a future post.\n\n#### IDE and editor support\n\nMarko offers syntax highlighting across all major IDEs and editors, as well as\non GitHub. Marko provides first-class support for the Atom editor with syntax\nhighlighting,\n[Autocomplete](https://github.com/marko-js/atom-language-marko#autocomplete) for\nboth HTML and custom tags,\n[Hyperclick](https://github.com/marko-js/atom-language-marko#hyperclick) to\nquickly jump to referenced files and methods, and [Pretty\nprinting](https://github.com/marko-js/atom-language-marko#prettyprint) to keep\nyour code readable.\n\n---\n\n### Why Marko?\n\nHere are just a few reasons you should consider using\n[Marko](https://markojs.com/) over React:\n\n- Marko requires much less boilerplate.\n- Marko has much better performance based on our benchmarks.\n- Marko offers a clean and powerful syntax that aligns with HTML while also\n  allowing the full power of JavaScript.\n- Marko has much less complexity and a very small runtime.\n- Marko has a much lower page weight for faster page loads.\n- Marko has strong integrations with Node.js.\n- Marko allows for extremely powerful IDE and editor plugins (see the [Marko\n  plugin for Atom](https://github.com/marko-js/atom-language-marko) as an\n  example).\n- Marko has a powerful compiler that allows new features to be added without\n  introducing bloat.\n- eBay relies heavily on Marko and it is being used to build ebay.com (including\n  the mobile web).\n- Marko has a strong and growing community on\n  [GitHub](https://github.com/marko-js/marko) and in\n  [Discord](https://discord.gg/RFGxYGs).\n\nInterested in learning more about Marko? If so, you can get additional\ninformation on the [Marko website](https://markojs.com/). Join the conversation\nand contribute on [GitHub](https://github.com/marko-js/marko) and follow us on\n[Twitter](https://twitter.com/MarkoDevTeam).\n\n<!-- File: packages/runtime-class/docs/redux.md (Tokens: ~325 | Category: anthropic-skill) -->\n# Redux + Marko\n\nSee the [`marko-redux` sample project](https://github.com/marko-js/examples/tree/master/examples/redux) for a fully-working example.\n\n## Installation\n\nFirst, save the [`marko`](https://www.npmjs.com/package/marko) and [`redux`](https://www.npmjs.com/package/redux) packages to your project’s dependencies:\n\n```bash\nnpm i marko redux\n```\n\n## Usage\n\nThe partial code below shows how a Marko UI component can connect to a Redux store, using Redux’s `store.subscribe()` method and Marko’s `forceUpdate()` method:\n\n### `counter.marko`\n\n```marko\nimport store from './store.js';\n\nclass {\n  onMount () {\n    store.subscribe(() => {\n      // Force this UI component to rerender\n      this.forceUpdate();\n\n      // The UI component will rerender with the new\n      // state returned by `store.getState()`\n      //\n      // You could also force an update like this:\n      // this.input = store.getState();\n    });\n  }\n}\n\n<counter(store.getState()) />\n```\n\n### `reducer.js`\n\n```js\nexport default function (state, action) {\n  state = state || { value: 0 };\n\n  // Additional reducer logic here…\n\n  return state;\n}\n```\n\n### `store.js`\n\nIn `counter.marko`, the imported store module exports a Redux store created with the following code:\n\n```js\nimport redux from \"redux\";\nimport counter from \"./reducer.js\";\n\nexport default redux.createStore(counter);\n```\n\n<!-- File: packages/runtime-class/docs/rendering.md (Tokens: ~2136 | Category: anthropic-skill) -->\n# Rendering\n\nTo render a Marko view, you need to `import` it.\n\n_example.js_\n\n```js\nimport FancyButton from \"./components/fancy-button.marko\";\n```\n\n> **Note:** If you are targeting node.js, you will need to enable the [require extension](./installing.md#require-marko-views) in order to require `.marko` files or you will need to precompile all of your templates using [Marko CLI](https://github.com/marko-js/cli). If you are targeting the browser, you will need to use a bundler like [`lasso`](./lasso.md), [`webpack`](./webpack.md) or [`rollup`](./rollup.md).\n\nOnce you have a view, you can pass input data and render it:\n\n_example.js_\n\n```js\nimport FancyButton from \"./components/fancy-button.marko\";\nconst html = FancyButton.renderToString({ label: \"Click me!\" });\n\nconsole.log(html);\n```\n\nThe data passed to `renderToString` becomes available as `input` in the component, so if `fancy-button.marko` looked like this:\n\n_./components/fancy-button.marko_\n\n```marko\n<button>${input.label}</button>\n```\n\nThe output HTML would be:\n\n```html\n<button>Click me!</button>\n```\n\n## Rendering methods\n\nWe used the `renderToString` method above to render the view, but there are a number of different method signatures that can be used to render.\n\nMany of these methods return a [`RenderResult`](#renderresult) which is an object with helper methods for working with the rendered output.\n\n### `renderSync(input)`\n\n| params       | type                            | description                            |\n| ------------ | ------------------------------- | -------------------------------------- |\n| `input`      | `Object`                        | the input data used to render the view |\n| return value | [`RenderResult`](#renderresult) | The result of the render               |\n\nUsing `renderSync` forces the render to complete synchronously. If a tag attempts to run asynchronously, an error will be thrown.\n\n```js\nimport View from \"./view.marko\";\nvar result = View.renderSync({});\n\nresult.appendTo(document.body);\n```\n\n### `render(input)`\n\n| params       | type                             | description                            |\n| ------------ | -------------------------------- | -------------------------------------- |\n| `input`      | `Object`                         | the input data used to render the view |\n| return value | `AsyncStream`/`AsyncVDOMBuilder` | the async `out` render target          |\n\nThe `render` method returns an async `out` which is used to generate HTML on the server or a virtual DOM in the browser. In either case, the async `out` has a `then` method that follows the Promises/A+ spec, so it can be used as if it were a Promise. This promise resolves to a [`RenderResult`](#renderresult).\n\n```js\nimport View from \"./view.marko\";\nvar resultPromise = View.render({});\n\nresultPromise.then((result) => {\n  result.appendTo(document.body);\n});\n```\n\n### `render(input, callback)`\n\n| params         | type                             | description                                    |\n| -------------- | -------------------------------- | ---------------------------------------------- |\n| `input`        | `Object`                         | the input data used to render the view         |\n| `callback`     | `Function`                       | a function to call when the render is complete |\n| callback value | [`RenderResult`](#renderresult)  | The result of the render                       |\n| return value   | `AsyncStream`/`AsyncVDOMBuilder` | the async `out` render target                  |\n\n```js\nimport View from \"./view.marko\";\n\nView.render({}, (err, result) => {\n  result.appendTo(document.body);\n});\n```\n\n### `render(input, stream)`\n\n| params       | type                             | description                            |\n| ------------ | -------------------------------- | -------------------------------------- |\n| `input`      | `Object`                         | the input data used to render the view |\n| `stream`     | `WritableStream`                 | a writeable stream                     |\n| return value | `AsyncStream`/`AsyncVDOMBuilder` | the async `out` render target          |\n\nThe HTML output is written to the passed `stream`. Render errors are emitted as `\"error\"` events on the stream, and like any unhandled stream `\"error\"` event, one without a listener crashes the process, so always attach one:\n\n```js\nimport http from \"http\";\nimport View from \"./view.marko\";\n\nhttp.createServer((req, res) => {\n  res.setHeader(\"content-type\", \"text/html\");\n  View.render({}, res).on(\"error\", (err) => {\n    console.error(err);\n  });\n});\n```\n\n### `render(input, out)`\n\n| params       | type                             | description                            |\n| ------------ | -------------------------------- | -------------------------------------- |\n| `input`      | `Object`                         | the input data used to render the view |\n| `out`        | `AsyncStream`/`AsyncVDOMBuilder` | The async `out` to render to           |\n| return value | `AsyncStream`/`AsyncVDOMBuilder` | The `out` that was passed              |\n\nThe `render` method also allows passing an existing async `out`. If you do this, `render` will not automatically end the async `out` (this allows rendering a view in the middle of another view). If the async `out` won't be ended by other means, you are responsible for ending it.\n\n```js\nimport View from \"./view.marko\";\nvar out = View.createOut();\n\nView.render({}, out);\n\nout.on(\"finish\", () => {\n  console.log(out.getOutput());\n});\n\nout.end();\n```\n\n### `renderToString(input)`\n\n| params       | type     | description                            |\n| ------------ | -------- | -------------------------------------- |\n| `input`      | `Object` | the input data used to render the view |\n| return value | `String` | The HTML string produced by the render |\n\nReturns an HTML string and forces the render to complete synchronously. If a tag attempts to run asynchronously, an error will be thrown.\n\n```js\nimport View from \"./view.marko\";\nvar html = View.renderToString({});\n\ndocument.body.innerHTML = html;\n```\n\n### `renderToString(input, callback)`\n\n| params         | type        | description                            |\n| -------------- | ----------- | -------------------------------------- |\n| `input`        | `Object`    | the input data used to render the view |\n| callback value | `String`    | The HTML string produced by the render |\n| return value   | `undefined` | N/A                                    |\n\nAn HTML string is passed to the callback.\n\n```js\nimport View from \"./view.marko\";\n\nView.renderToString({}, (err, html) => {\n  document.body.innerHTML = html;\n});\n```\n\n### `stream(input)`\n\nThe `stream` method returns a Node.js-style stream of the output HTML.\n\n```js\nimport fs from \"fs\";\nimport View from \"./view.marko\";\nconst writeStream = fs.createWriteStream(\"output.html\");\n\nView.stream({}).pipe(writeStream);\n```\n\nThis method is available on the server, but not available by default in the browser. If you need to use streams in the browser, you may `import 'marko/stream'` as part of your client-side bundle.\n\n## RenderResult\n\n### `getComponent()`\n\n### `getComponents(selector)`\n\n### `afterInsert(doc)`\n\n### `getNode(doc)`\n\n### `getOutput()`\n\n### `appendTo(targetEl)`\n\n### `insertAfter(targetEl)`\n\n### `insertBefore(targetEl)`\n\n### `prependTo(targetEl)`\n\n### `replace(targetEl)`\n\n### `replaceChildrenOf(targetEl)`\n\n## Global data\n\nIf you need to make data available to all rendered views, use the `$global` property on the input data object. This property will be removed from `input` and provided to the template through a variable called `$global`. It is also made available on the `out.global` property.\n\nGlobal values persist across renders.\n\n```js\nView.render({\n  $global: {\n    flags: [\"mobile\"],\n  },\n});\n```\n\nWithin the template you can access `$global` similar to accessing `input`.\n\n```marko\n<div>\n  You are on ${$global.flags.includes(\"mobile\") ? \"mobile\" : \"desktop\"}\n</div>\n```\n\n> **Note:** `$global` is not available within [`static`](./syntax.md#static-javascript) parts of the template. In order to reference `$global` within the component class you must use `out.global` from one of the lifecycle methods that provide it.\n\n> **Warning:** Use `$global` with caution; it is visible in any component.\n\n### Sending global data to browsers\n\n⚠️ To prevent accidentally exposing sensitive data, by default **no keys** in `$global` are sent to browsers. To serialize data to the frontend, name the desired properties in `$global.serializedGlobals`.\n\nValues must be serializable by [the `warp10` module](https://www.npmjs.com/package/warp10).\n\n```js\nimport Page from \"./index.marko\";\n\napp.get(\"/\", (req, res) => {\n  const ua = req.get(\"User-Agent\");\n\n  Page.render(\n    {\n      $global: {\n        isIos: /iPad|iPhone/.test(ua), // Serialized and available on the server and browser as `$global.isIos`\n        isAndroid: /Android/.test(ua), // Serialized and available on the server and browser as `$global.isAndroid`\n        req, // Only available server-side and not serialized, because it’s not in `serializedGlobals`\n\n        serializedGlobals: {\n          isIos: true, // Tell Marko to serialize `isIos`\n          isAndroid: true, // Tell Marko to serialize `isAndroid`\n        },\n      },\n    },\n    res,\n  );\n});\n```\n\n> **Warning:** Ensure that you serialize only data which is necessary for the browser. Serialization is expensive for both server rendering performance and HTML output size.\n\nFor details, check [#672: “Serialize only input and state on top-level server-rendered UI components”](https://github.com/marko-js/marko/pull/672).\n\n<!-- File: packages/runtime-class/docs/rollup.md (Tokens: ~3035 | Category: anthropic-skill) -->\n# Marko + Rollup\n\nThis is Marko’s official integration plugin for [the Rollup bundler](https://rollupjs.org/).\n\n## Installation\n\n```sh\nnpm install --save-dev \\\n  @marko/rollup \\\n  rollup \\\n  @rollup/plugin-node-resolve \\\n  @rollup/plugin-commonjs\n```\n\n> **Note**: The Marko runtime is CommonJS, so don’t forget the `@rollup/plugin-commonjs` package!\n\n## Configuration\n\n`@marko/rollup` exports two methods for use in [Rollup configuration files](https://rollupjs.org/guide/en/#configuration-files): `.browser()` and `.server()`.\n\nYou _probably_ want to use both, since that’ll get you…\n\n- Automatic [`input` entrypoint configuration](https://rollupjs.org/guide/en/#input) for route-based bundle splitting\n- Complete control over asset loading with [the `<rollup>` tag](#rollup-tag)\n- The strengths behind why Marko exists in the first place: cooperation between servers and browsers for high performance in both\n\n> **ProTip**: You _could_ use only `.browser()` or only `.server()` to build a completely client-side-rendered or server-side-rendered app. That would be a little odd, but you could.\n\n### Config example\n\n```js\nimport nodeResolve from \"@rollup/plugin-node-resolve\";\nimport commonjs from \"@rollup/plugin-commonjs\";\nimport marko from \"@marko/rollup\";\n\nconst sharedPlugins = [\n  commonjs({\n    extensions: [\".js\", \".marko\"]\n  }),\n  // If using Marko’s `style {}` blocks, you’ll need an appropriate plugin, like npmjs.com/rollup-plugin-postcss\n  postcss({ external: true })\n]\n\nconst serverAssetsConfig = {\n  input: \"src/start-server.js\",\n  plugins: [\n    marko.server(),\n    nodeResolve({ preferBuiltins: true })\n    ...sharedPlugins\n  ]\n};\nconst browsersAssetsConfig = {\n  plugins: [\n    marko.browser(),\n    nodeResolve({ browser: true })\n    ...sharedPlugins\n  ]\n};\n\nexport default [serverAssetsConfig, browsersAssetsConfig];\n```\n\n### Advanced config example\n\nThe following configuration file is long and hairy, which may be upsetting to some viewers. However, it does show how to accomplish the following:\n\n- Support for Rollup’s watch mode\n- A bundle analyzer\n- The ability to `import` JSON files to use their data\n- The ability to `import` image files to use their asset URLs for `img[src]` and such\n- Dead-code elimination for development-only code\n- Static compression of assets for something like [NGiNX’s `gzip_static`](https://nginx.org/en/docs/http/ngx_http_gzip_static_module.html)\n- A CSS preprocessor (Sass, in this case)\n- Browserslist to automatically configure:\n  - Babel for JS transpilation\n  - Autoprefixer for CSS transpilation\n\n<details><summary>Big ugly production-esque Rollup config</summary>\n\n```js\nimport { builtinModules } from \"module\";\nimport path from \"path\";\nimport autoprefixer from \"autoprefixer\";\nimport babelPlugin from \"@rollup/plugin-babel\";\nimport commonjsPlugin from \"@rollup/plugin-commonjs\";\nimport jsonPlugin from \"@rollup/plugin-json\";\nimport markoPlugin from \"@marko/rollup\";\nimport nodeResolvePlugin from \"@rollup/plugin-node-resolve\";\nimport replacePlugin from \"@rollup/plugin-replace\";\nimport runPlugin from \"@rollup/plugin-run\";\nimport stylesPlugin from \"rollup-plugin-styles\";\nimport urlPlugin from \"@rollup/plugin-url\";\nimport pkg from \"./package.json\";\n\nconst __DEV__ = process.env.NODE_ENV === \"development\";\nconst __PROD__ = !__DEV__;\n\nconst isWatch = Boolean(process.env.ROLLUP_WATCH);\n\nconst publicPath = \"/s/\"; // Guess what character is only 5 bits under HPACK\nconst assetFileNames = \"[name]-[hash][extname]\";\n\nconst externalDependencies = [\n  ...Object.keys(pkg.dependencies),\n  ...builtinModules,\n];\n\nprocess.env.SASS_PATH = \"./:./node_modules\";\n\nexport default (async () => [\n  compiler(\"server\", {\n    input: \"index.js\",\n    output: {\n      dir: \"built/server/\",\n      assetFileNames: `../browser/${assetFileNames}`,\n      format: \"cjs\",\n      sourcemap: true,\n    },\n    external: (id) =>\n      externalDependencies.some(\n        (dependency) => id === dependency || id.startsWith(dependency + \"/\"),\n      ),\n    plugins: [isWatch && runPlugin({ execArgv: [\"--enable-source-maps\"] })],\n  }),\n\n  compiler(\"browser\", {\n    output: {\n      dir: \"built/browser/\",\n      chunkFileNames: __PROD__ ? \"[name]-[hash].js\" : null,\n      entryFileNames: __PROD__ ? \"[name]-[hash].js\" : null,\n      assetFileNames,\n      sourcemap: true,\n      sourcemapExcludeSources: __PROD__,\n    },\n    plugins: [\n      stylesPlugin({\n        mode: \"extract\",\n        sourceMap: true,\n        config: {\n          target: \"browserslist:css\",\n          plugins: [autoprefixer({ env: \"css\" })],\n        },\n        minimize: __PROD__,\n        url: {\n          publicPath,\n          hash: assetFileNames,\n        },\n      }),\n      __PROD__ && (await import(\"rollup-plugin-terser\")).terser(),\n      __PROD__ &&\n        (await import(\"rollup-plugin-gzip\")).default({\n          filter: /\\.(?:js|css|svg|json|xml|txt)$/,\n          minSize: 1024,\n          gzipOptions: {\n            level: 9,\n            memLevel: 9,\n          },\n        }),\n      __PROD__ &&\n        !isWatch &&\n        (await import(\"rollup-plugin-visualizer\")).default(),\n      __PROD__ &&\n        !isWatch && {\n          name: \"bundle-visualizer-location\",\n          writeBundle() {\n            console.info(\n              `📊 Bundle visualizer at \\x1b[4;36mfile://${path.join(\n                __dirname,\n                \"../../\",\n                bundleAnalyzerFilename,\n              )}\\x1b[0m`,\n            );\n          },\n        },\n    ],\n  }),\n])();\n\nfunction compiler(target, config) {\n  const isBrowser = target === \"browser\";\n  const browserslistEnv = isBrowser ? \"js\" : \"server\";\n  const babelConfig = {\n    comments: false,\n    browserslistEnv,\n    compact: false,\n    babelrc: false,\n    caller: { target },\n  };\n  if (isBrowser) {\n    babelConfig.presets = [\n      [\n        \"@babel/preset-env\",\n        {\n          browserslistEnv,\n          bugfixes: true,\n        },\n      ],\n    ];\n  }\n\n  return {\n    ...config,\n    preserveEntrySignatures: false,\n    plugins: [\n      markoPlugin[target]({ babelConfig }),\n      nodeResolvePlugin({\n        browser: isBrowser,\n        preferBuiltins: !isBrowser,\n      }),\n      commonjsPlugin(),\n      replacePlugin({\n        preventAssignment: true,\n        values: { __DEV__, __PROD__ },\n      }),\n      babelPlugin({\n        babelHelpers: \"bundled\",\n        ...babelConfig,\n      }),\n      jsonPlugin(),\n      urlPlugin({\n        publicPath,\n        destDir: \"built/browser/\",\n        fileName: assetFileNames,\n        include: \"**/*.{svg,png,jpg,jpeg}\",\n        limit: 0, // Never Base64 & inline\n        emitFiles: !isBrowser,\n      }),\n      ...config.plugins,\n    ],\n  };\n}\n```\n\n</details>\n\n## `<rollup>` tag\n\nUsing both `.server()` and `.browser()` enables **the `<rollup>` tag**, which gives you complete control over how your app loads assets. That lets you do things like:\n\n- [Critical CSS](https://web.dev/extract-critical-css/) for components as they write out within a kB budget, or [as components first appear on the page](https://jakearchibald.com/2016/link-in-body/#a-simpler-better-way), or any other style-loading mad science\n- [`module`/`nomodule` scripts](https://philipwalton.com/articles/using-native-javascript-modules-in-production-today/) for smaller bundles in modern browsers\n- [Content-Security Policy `nonce`s](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce) or [Subresource `integrity` hashes](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)\n- Anything a web page can do, really. You can even combine `<rollup>` with [the `serialize` option](#options.serialize) to be as fancy as you wanna be.\n\nThe `<rollup>` tag provides two [tag parameters](https://markojs.com/docs/syntax/#parameters):\n\n1. `entry` is the generated `input` string that the `server` plugin gave to the `browser` plugin. You can use it to find the corresponding entry chunk from Rollup’s `output` (the next parameter).\n\n2. `output` is an array of `AssetInfo | ChunkInfo` objects with most of [the data returned from Rollup's `generateBundle` hook](https://rollupjs.org/guide/en/#generatebundle). Some properties are omitted, like `code` and `map`, since they’re often too large to inline directly. However, each chunk also has a `size` property, to let you filter out empty chunks, inline code yourself below a certain size, or other delightful devilishness.\n\nFor example, using the `entry` name and properties of `output` items to load scripts:\n\n```marko\n<head>\n  <rollup|entry, output|>\n    $ const entryChunk = output.find(chunk => chunk.name === entry);\n\n    <if(entryChunk.size /* only load non-empty JS entry points */)>\n      <for|fileName| of=entryChunk.imports>\n        <link rel=\"modulepreload\" href=fileName />\n      </for>\n\n      <script async type=\"module\" src=entryChunk.fileName></script>\n    </if>\n  </rollup>\n</head>\n```\n\n> **Note**: It’s up to you to transform the chunk data (also called the **manifest**) into `<link>`s, `<script>`s, and other HTML to load assets. Opting into complete control means we can’t do any of it for you.\n\nIf your Rollup `browser` config contains multiple `output` options, or you have multiple `browser` configs, every `output`’s chunk is passed to the `<rollup>` tag.\n\nFor example, if you have both `esm` and `iife` build outputs configured:\n\n```js\n{\n  output: [\n    { dir: \"dist/iife\", format: \"iife\" },\n    { dir: \"dist/esm\", format: \"esm\" },\n  ];\n}\n```\n\n…you could cross-reference assets from both…\n\n```marko\n<rollup|entry, iifeOutput, esmOutput|>\n  $ const iifeEntryChunk = iifeOutput.find(chunk => chunk.name === entry);\n  $ const esmEntryChunk = esmOutput.find(chunk => chunk.name === entry);\n\n  <script src=esmEntryChunk.fileName type=\"module\" async></script>\n  <script src=iifeEntryChunk.fileName nomodule async></script>\n</rollup>\n```\n\n…and _boom:_ you now have [a `module`/`nomodule` setup](https://philipwalton.com/articles/using-native-javascript-modules-in-production-today/).\n\n## Options\n\n### `options.babelConfig`\n\nBoth the `.server()` and `.browser()` plugins accept this option.\n\nYou can manually override the builtin Babel configuration by passing a `babelConfig` object. By default, [Babel’s regular config file resolution](https://babeljs.io/docs/en/config-files) will be used.\n\n```js\nmarko.browser({\n  babelConfig: {\n    presets: [\"@babel/preset-env\"],\n  },\n});\n```\n\n### `options.runtimeId`\n\nBoth the `.server()` and `.browser()` plugins accept this option. In fact, you _really_ want to use it with both simultaneously.\n\nIn some cases, you may want to embed multiple isolated copies of Marko on the page. (If you can’t think of why, then don’t worry about this option.)\n\nSince Marko uses some `window` properties to initialize, multiple instances can cause issues. For example, by default Marko checks `window.$components` for server-rendered hydration. Usually you can change these `window` properties by [rendering with `{ $global: { runtimeId: \"MY_MARKO_RUNTIME_ID\" } }` as input](https://markojs.com/docs/rendering/#global-data) on the server, but since `@marko/rollup` usually writes the autoinitialization code for you, instead this plugin exposes a `runtimeId` option to automatically set `$global.runtimeId` to initialize properly in the browser:\n\n```js\nconst runtimeId = \"MY_MARKO_RUNTIME_ID\";\n// Make the `runtimeId` the same across `server` and `browser`, or it’ll error!\nmarko.server({ runtimeId });\nmarko.browser({ runtimeId });\n```\n\n### `options.serialize`\n\nThis option is only available for the `.browser()` plugin. It lets you inspect and transform the `output` chunks before they’re passed to [the `<rollup>` tag](#rollup-tag).\n\nFor example, if you _did_ want to include the `code` property from the Rollup chunk — say, to inline code small enough that it’s not worth the overhead of an HTTP request, you’d try something like the following:\n\n```js\nmarko.browser({\n  serialize(output) {\n    return output.map(({ type, fileName, isEntry, code }) =>\n      type === \"asset\"\n        ? { type, fileName }\n        : {\n            type,\n            name,\n            isEntry,\n            fileName,\n            // only inline code chunks below 1kB\n            inline: code.trim().length < 1024 && code,\n          },\n    );\n  },\n});\n```\n\n<!-- File: packages/runtime-class/docs/state.md (Tokens: ~1155 | Category: anthropic-skill) -->\n# State\n\nThe output of a component is based on input properties passed from its parent as attributes. However, a component may also maintain internal state that it uses to control its view. If Marko detects a change to either input or to the internal state, the view will automatically be updated.\n\n> **ProTip:**\n> Only data that is owned and modified by the component should go into its `state`. State should be exclusively used for data that triggers rerenders. Parents control `input`, and the component controls its own `state`.\n\n## Initializing state\n\nTo use `state` in Marko, you must first create a [class component](./class-components.md) and initialize the state within the [`onCreate`](./class-components.md#oncreateinput-out) method. In class methods, `this.state` may be used and within the template section, a `state` variable is available.\n\n```marko\nclass {\n    onCreate() {\n        this.state = { count: 0 };\n    }\n}\n\n<div>The count is ${state.count}</div>\n```\n\n> **Note:** Only properties that exist when `this.state` is first defined will be watched for changes. If you don't need a property initially, you can set it to `null`.\n\n## Updating state\n\nYou can update `state` in response to DOM events, browser events, ajax calls, etc. When a property on the state changes, the view will be updated to match.\n\n```marko\nclass {\n    onCreate() {\n        this.state = { count: 0 };\n    }\n    increment() {\n        this.state.count++;\n    }\n}\n\n<div>The count is ${state.count}</div>\n<button on-click('increment')>Increment</button>\n```\n\nWe've extended our example above to add a button with an [event handler](./events.md), so that, when clicked, the `state.count` value is incremented.\n\n> **Note:**\n> When browsing existing code, you may see `this.setState('name', value)` being used. This is equivalent to `this.state.name = value`.\n\n### How updates work\n\nWhen a property on `state` is set, the component will be scheduled for an update if the property has changed. All updates are batched together for performance. This means you can update multiple state properties at the same time without causing multiple updates.\n\n> **ProTip:** If you need to know when the update has been applied, you can use `this.once('update', fn)` within a component method.\n\n> **Note:** The state object only watches its properties one level deep. This means updates to nested properties on the state (e.g. `this.state.object.something = newValue`) will not be detected.\n>\n> Using [immutable](https://wecodetheweb.com/2016/02/12/immutable-javascript-using-es6-and-beyond/) data structures is recommended, but if you want to mutate a state property (perhaps push a new item into an array) you can let Marko know it changed using `setStateDirty`.\n>\n> ```js\n> this.state.numbers.push(num);\n>\n> // mark numbers as dirty, because a `push`\n> // won't be automatically detected by Marko\n> this.setStateDirty(\"numbers\");\n> ```\n\n## Cross component state management\n\nThere are various tools available to manage state outside of a single component. Here are some basic guidelines.\n\nTypically we recommend using `attributes` to pass data in to a child component, and children can [emit events](./events.md#emitting-custom-events) to communicate back up to their parents. In some cases this can become cumbersome with deeply nested data dependencies or global state.\n\n### Global/Subtree\n\nFor passing state throughout a component tree without explicit attribute setting throughout the entire app, you can leverage the [`<context>`](https://github.com/marko-js/tags/tree/master/tags/context) tag. This tag can be [installed from npm](./custom-tags.md#using-tags-from-npm).\n\nThis tag allows you to pull state from any level above in the tree and can also be used to pass global state throughout your app.\nContext providers can register event handlers that any child in the tree can trigger similar to the [events API](./events.md).\n\n_fancy-form.marko_\n\n```marko\n<context coupon=input.coupon on-buy(handleBuy)>\n    <!-- Somewhere nested in the container will be the buy button -->\n    <fancy-container/>\n</context>\n```\n\n_fancy-save-button.marko_\n\n```marko\n<context|{ coupon }, emit| from=\"fancy-form\">\n    Coupon: ${coupon}.\n    <button on-click(emit, \"buy\")>Buy</button>\n</context>\n```\n\n> **Note:** Context _couples_ tags together and can limit reuse of components.\n\n### When to use a Redux like pattern\n\nOften the above two approaches are enough, and many people [jump to this part far too quickly](https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367). Like `<context>`, often anything stored in redux is `global`. This means that it can (if abused) create components that are hard to reuse, reason about and test. However it is important to understand when a tool like `redux` is useful in any UI library.\n\nRedux provides indirection to updating any state that it controls. This is useful if you need the following:\n\n- Single state update, multiple actions (eg: logging, computed data, etc).\n- Time travel debugging and other [redux-specific tooling](https://redux.js.org/introduction/ecosystem).\n\n<!-- File: packages/runtime-class/docs/structure.json (Tokens: ~269 | Category: anthropic-skill) -->\n[\n  {\n    \"title\": \"Guides\",\n    \"docs\": [\n      \"Installing\",\n      \"Getting started\",\n      \"Conditionals and lists\",\n      \"Custom tags\",\n      \"State\",\n      \"Styles\",\n      \"Events\",\n      \"Body content\",\n      \"TypeScript\",\n      \"Marko 5 upgrade\",\n      \"Troubleshooting Streaming\"\n    ]\n  },\n  {\n    \"title\": \"Tutorials\",\n    \"docs\": [\"Color Picker\"]\n  },\n  {\n    \"title\": \"Reference\",\n    \"docs\": [\n      \"Rendering\",\n      \"Syntax\",\n      \"Core tags\",\n      \"Class components\",\n      \"marko.json\",\n      \"Compiler\"\n    ]\n  },\n  {\n    \"title\": \"Bundler Integrations\",\n    \"docs\": [\"Vite\", \"Webpack\", \"Rollup\", \"Lasso\"]\n  },\n  {\n    \"title\": \"Server Integrations\",\n    \"docs\": [\"Cloudflare Workers\", \"Express\", \"Fastify\", \"Koa\", \"HTTP\"]\n  },\n  {\n    \"title\": \"Tooling\",\n    \"docs\": [\"Editor plugins\"]\n  },\n  {\n    \"title\": \"Articles\",\n    \"docs\": [\"Marko vs React\", \"Why is Marko Fast\", \"10 Awesome Marko Features\"]\n  }\n]\n\n<!-- ... +18 more modular skills available via /api/skills/marko-js/marko?path={path} -->\n</yakaai_skills>"}