@nisli/core 0.55.0 → 0.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/README.md +58 -1
  2. package/dist/bundler/component.js +409 -0
  3. package/dist/bundler/component.js.map +7 -0
  4. package/dist/bundler/context.js +27 -0
  5. package/dist/bundler/context.js.map +7 -0
  6. package/dist/bundler/diagnostics.js +55 -0
  7. package/dist/bundler/diagnostics.js.map +7 -0
  8. package/dist/bundler/disposable.js +9 -0
  9. package/dist/bundler/disposable.js.map +7 -0
  10. package/dist/bundler/element-context.js +47 -0
  11. package/dist/bundler/element-context.js.map +7 -0
  12. package/dist/bundler/emitter.js +70 -0
  13. package/dist/bundler/emitter.js.map +7 -0
  14. package/dist/bundler/hmr/registry.js +72 -0
  15. package/dist/bundler/hmr/registry.js.map +7 -0
  16. package/dist/bundler/hmr/transform.js +30 -0
  17. package/dist/bundler/hmr/transform.js.map +7 -0
  18. package/dist/bundler/index.js +103 -0
  19. package/dist/bundler/index.js.map +7 -0
  20. package/dist/bundler/injector.js +75 -0
  21. package/dist/bundler/injector.js.map +7 -0
  22. package/dist/bundler/lifecycle.js +56 -0
  23. package/dist/bundler/lifecycle.js.map +7 -0
  24. package/dist/bundler/projection.js +92 -0
  25. package/dist/bundler/projection.js.map +7 -0
  26. package/dist/bundler/query.js +302 -0
  27. package/dist/bundler/query.js.map +7 -0
  28. package/dist/bundler/ref.js +16 -0
  29. package/dist/bundler/ref.js.map +7 -0
  30. package/dist/bundler/resource.js +99 -0
  31. package/dist/bundler/resource.js.map +7 -0
  32. package/dist/bundler/settle.js +43 -0
  33. package/dist/bundler/settle.js.map +7 -0
  34. package/dist/bundler/signal.js +403 -0
  35. package/dist/bundler/signal.js.map +7 -0
  36. package/dist/bundler/template-audit.js +162 -0
  37. package/dist/bundler/template-audit.js.map +7 -0
  38. package/dist/bundler/template.js +847 -0
  39. package/dist/bundler/template.js.map +7 -0
  40. package/dist/bundler/view-transition.js +20 -0
  41. package/dist/bundler/view-transition.js.map +7 -0
  42. package/dist/bundler/vite-hmr/plugin.js +32 -0
  43. package/dist/bundler/vite-hmr/plugin.js.map +7 -0
  44. package/dist/bundler/vite-hmr/runtime.js +8 -0
  45. package/dist/bundler/vite-hmr/runtime.js.map +7 -0
  46. package/dist/index.js +2607 -44
  47. package/dist/index.js.map +7 -1
  48. package/dist/index.production.js +2 -0
  49. package/dist/index.production.js.map +6 -0
  50. package/dist/{diagnostics.d.ts → types/diagnostics.d.ts} +8 -15
  51. package/dist/{index.d.ts → types/index.d.ts} +1 -0
  52. package/dist/{template-audit.d.ts → types/template-audit.d.ts} +4 -5
  53. package/dist/{template.d.ts → types/template.d.ts} +3 -15
  54. package/package.json +12 -9
  55. package/dist/component.js +0 -633
  56. package/dist/component.js.map +0 -1
  57. package/dist/context.js +0 -55
  58. package/dist/context.js.map +0 -1
  59. package/dist/diagnostics.js +0 -118
  60. package/dist/diagnostics.js.map +0 -1
  61. package/dist/disposable.js +0 -8
  62. package/dist/disposable.js.map +0 -1
  63. package/dist/element-context.js +0 -108
  64. package/dist/element-context.js.map +0 -1
  65. package/dist/emitter.js +0 -91
  66. package/dist/emitter.js.map +0 -1
  67. package/dist/hmr/registry.js +0 -136
  68. package/dist/hmr/registry.js.map +0 -1
  69. package/dist/hmr/transform.js +0 -52
  70. package/dist/hmr/transform.js.map +0 -1
  71. package/dist/injector.js +0 -118
  72. package/dist/injector.js.map +0 -1
  73. package/dist/lifecycle.js +0 -117
  74. package/dist/lifecycle.js.map +0 -1
  75. package/dist/projection.js +0 -179
  76. package/dist/projection.js.map +0 -1
  77. package/dist/query.js +0 -429
  78. package/dist/query.js.map +0 -1
  79. package/dist/ref.js +0 -43
  80. package/dist/ref.js.map +0 -1
  81. package/dist/resource.js +0 -129
  82. package/dist/resource.js.map +0 -1
  83. package/dist/settle.js +0 -106
  84. package/dist/settle.js.map +0 -1
  85. package/dist/signal.js +0 -645
  86. package/dist/signal.js.map +0 -1
  87. package/dist/template-audit.js +0 -246
  88. package/dist/template-audit.js.map +0 -1
  89. package/dist/template.js +0 -1218
  90. package/dist/template.js.map +0 -1
  91. package/dist/view-transition.js +0 -98
  92. package/dist/view-transition.js.map +0 -1
  93. package/dist/vite-hmr/plugin.js +0 -62
  94. package/dist/vite-hmr/plugin.js.map +0 -1
  95. package/dist/vite-hmr/runtime.js +0 -17
  96. package/dist/vite-hmr/runtime.js.map +0 -1
  97. /package/dist/{component.d.ts → types/component.d.ts} +0 -0
  98. /package/dist/{context.d.ts → types/context.d.ts} +0 -0
  99. /package/dist/{disposable.d.ts → types/disposable.d.ts} +0 -0
  100. /package/dist/{element-context.d.ts → types/element-context.d.ts} +0 -0
  101. /package/dist/{emitter.d.ts → types/emitter.d.ts} +0 -0
  102. /package/dist/{hmr → types/hmr}/registry.d.ts +0 -0
  103. /package/dist/{hmr → types/hmr}/transform.d.ts +0 -0
  104. /package/dist/{injector.d.ts → types/injector.d.ts} +0 -0
  105. /package/dist/{lifecycle.d.ts → types/lifecycle.d.ts} +0 -0
  106. /package/dist/{projection.d.ts → types/projection.d.ts} +0 -0
  107. /package/dist/{query.d.ts → types/query.d.ts} +0 -0
  108. /package/dist/{ref.d.ts → types/ref.d.ts} +0 -0
  109. /package/dist/{resource.d.ts → types/resource.d.ts} +0 -0
  110. /package/dist/{settle.d.ts → types/settle.d.ts} +0 -0
  111. /package/dist/{signal.d.ts → types/signal.d.ts} +0 -0
  112. /package/dist/{view-transition.d.ts → types/view-transition.d.ts} +0 -0
  113. /package/dist/{vite-hmr → types/vite-hmr}/plugin.d.ts +0 -0
  114. /package/dist/{vite-hmr → types/vite-hmr}/runtime.d.ts +0 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/template.ts"],
4
+ "sourcesContent": ["/**\n * template.ts \u2014 Tagged template engine with targeted DOM binding\n *\n * The html tagged template literal parses HTML with expression slots,\n * creates bindings for signals, and produces a TemplateResult that\n * can be mounted into the DOM with surgical updates.\n *\n * Two phases:\n * 1. First render: parse template, clone, create bindings, mount\n * 2. Updates: signal changes trigger individual binding updates (O(1))\n */\n\nimport {\n signal,\n isSignal,\n effect,\n computed,\n untrack,\n type Signal,\n type ReadonlySignal,\n} from './signal.js';\nimport { isRef, type Ref } from './ref.js';\n// First-parse audit (ADR 0030.2 T4). The import is static \u2014 core has no\n// build-time dev/prod define yet (a named Wave-1 deliverable, \u00A78) \u2014 but every\n// entry point is a no-op behind template-audit's own dev flag.\nimport { auditTemplate, captureCallsite } from './template-audit.js';\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface TemplateResult {\n /** Mount this template into a host element */\n mount(host: HTMLElement): void;\n /** Dispose all bindings and effects */\n dispose(): void;\n /** Brand for type checking */\n __templateResult: true;\n}\n\n// TypeScript's DOM library does not expose moveBefore() yet.\ninterface MoveCapableParent extends ParentNode {\n moveBefore(node: Node, child: Node | null): void;\n}\n\nconst canMoveWithin = (parent: ParentNode): parent is MoveCapableParent =>\n typeof (parent as Partial<MoveCapableParent>).moveBefore === 'function';\n\n/** A DOM event handler whose event type is inferred from its native event name. */\nexport type TypedEventHandler<K extends keyof HTMLElementEventMap> = (\n event: HTMLElementEventMap[K],\n) => void;\n\n/**\n * Value-returning untrack. signal.ts's `untrack` is `(fn: () => void) => void`\n * (the value-returning form is a 0030.2 \u00A73 papercut owned elsewhere); this\n * local wrapper closes over the result until that lands.\n */\nfunction untracked<T>(fn: () => T): T {\n let result!: T;\n untrack(() => { result = fn(); });\n return result;\n}\n\n// \u2500\u2500 Trusted HTML brand (raw) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Branded trusted-HTML value accepted by `html:inner` (and by @nisli/ssg's\n * static renderer, which re-exports this brand \u2014 core owns it, ADR 0030.2 \u00A78).\n * Structural, not nominal: cross-package/cross-realm values with the same\n * shape stay valid.\n */\nexport interface RawHtml {\n value: string;\n __raw: true;\n}\n\n/**\n * Mark a string as trusted raw HTML. `html:inner` accepts ONLY branded\n * values \u2014 a bare string throws N106 (the accidental-XSS-sink class closes,\n * ADR 0030.2 \u00A73). NEVER wrap user-generated input.\n */\nexport function raw(value: string): RawHtml {\n return { __raw: true as const, value };\n}\n\nfunction isRawHtml(value: unknown): value is RawHtml {\n return (\n typeof value === 'object'\n && value !== null\n && '__raw' in value\n && (value as RawHtml).__raw === true\n && typeof (value as RawHtml).value === 'string'\n );\n}\n\n// \u2500\u2500 Sanitized HTML brand (untrusted markup) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Branded UNTRUSTED-HTML value accepted by `html:inner`. The mirror image of\n * {@link RawHtml}: where `raw()` is the author asserting markup is already\n * trustworthy, this brand asserts the opposite \u2014 the string is untrusted and\n * MUST pass a sanitizer before it reaches the DOM (ADR 0019:124\u2013128, executed\n * by bet-09(c)). Structural, not nominal, on the same rule as RawHtml.\n */\nexport interface SanitizedHtml {\n value: string;\n __sanitize: true;\n}\n\n/**\n * Mark a string as untrusted markup to be sanitized at the sink \u2014 the brand\n * for user-generated HTML, which must NEVER go through `raw()`.\n *\n * `html:inner` writes it with the platform's `Element.setHTML()` (the spec's\n * XSS-safe default sanitizer) when the engine has one, otherwise with the hook\n * registered by {@link setSanitizerFallback}. With NEITHER available the\n * binding throws N107: it never falls back to `innerHTML`. nisli bundles no\n * sanitizer \u2014 the trust decision, and its bytes, stay in the app.\n */\nexport function sanitized(value: string): SanitizedHtml {\n return { __sanitize: true as const, value };\n}\n\nfunction isSanitizedHtml(value: unknown): value is SanitizedHtml {\n return (\n typeof value === 'object'\n && value !== null\n && '__sanitize' in value\n && (value as SanitizedHtml).__sanitize === true\n && typeof (value as SanitizedHtml).value === 'string'\n );\n}\n\n// \u2500\u2500 Sanitizer sinks \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** A sanitizing writer: sanitize `html`, then put the result inside `el`. */\nexport type SanitizerFallback = (el: Element, html: string) => void;\n\nlet sanitizerFallback: SanitizerFallback | null = null;\n\n/**\n * Register the sanitizing writer used for `sanitized()` values on engines\n * WITHOUT native `Element.setHTML()` (Safari today, older Chromium/Firefox),\n * or `null` to unregister. Native `setHTML()` always wins where it exists, so\n * modern engines never pay the hook. nisli ships no sanitizer; wire one:\n *\n * setSanitizerFallback((el, html) => {\n * el.innerHTML = DOMPurify.sanitize(html);\n * });\n */\nexport function setSanitizerFallback(fn: SanitizerFallback | null): void {\n sanitizerFallback = fn;\n}\n\n// TypeScript's DOM library does not expose Element.setHTML() yet.\ninterface SanitizeCapableElement extends Element {\n setHTML(html: string): void;\n}\n\nconst nativeSetHtml: SanitizerFallback = (el, html) => {\n (el as SanitizeCapableElement).setHTML(html);\n};\n\n/**\n * The sanitizing writer for this element, or `null` when the engine has none\n * and the app registered none \u2014 the fail-closed signal N107 is thrown on.\n *\n * The method must be the one on `Element.prototype`, not merely *a* callable\n * named `setHTML`. A duck-typed check here is a sanitizer bypass: an element\n * carrying its own `setHTML` \u2014 DOM clobbering, an unsafe polyfill, a library\n * shim \u2014 would be trusted as the platform sanitizer and would preempt the\n * fallback the app explicitly registered as safe. Verified: with an\n * own-property `setHTML`, the registered fallback was never called and\n * `<img src=x onerror=\u2026>` reached innerHTML intact.\n *\n * Read from the prototype per write rather than captured at module load, so a\n * late polyfill or a test's stub is still honoured; identity is what is\n * checked, not existence. Replacing `Element.prototype.setHTML` wholesale is\n * out of scope \u2014 an attacker who can do that owns the realm regardless.\n */\nfunction sanitizerFor(el: Element): SanitizerFallback | null {\n const platform = typeof Element === 'function'\n ? (Element.prototype as Partial<SanitizeCapableElement>).setHTML\n : undefined;\n return typeof platform === 'function'\n && (el as Partial<SanitizeCapableElement>).setHTML === platform\n ? nativeSetHtml\n : sanitizerFallback;\n}\n\n// \u2500\u2500 Trusted Types pass-through \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * The native `TrustedHTML` shape \u2014 also missing from TypeScript's DOM library.\n * Only `isHTML()` recognition is needed: under CSP\n * `require-trusted-types-for 'script'` the raw sink's plain-string `innerHTML`\n * assignment throws, so policy-created values pass through `html:inner`\n * unwrapped instead of being re-wrapped in `raw()`.\n */\ninterface TrustedHtml {\n toJSON(): string;\n}\n\ninterface TrustedTypeChecker {\n isHTML(value: unknown): boolean;\n}\n\nfunction isTrustedHtml(value: unknown): value is TrustedHtml {\n const tt = (globalThis as { trustedTypes?: TrustedTypeChecker }).trustedTypes;\n return tt !== undefined && tt.isHTML(value);\n}\n\n// TODO(diagnostics): replace with the core diagnostics leaf (parallel\n// worktree); template-layer codes N101\u2013N107 register there. N105\u2013N107 are\n// thrown (correctness/security guards), unlike the warn-level audit codes.\nfunction nisliError(code: string, message: string): Error {\n return new Error(`[nisli] ${code}: ${message}`);\n}\n\n// \u2500\u2500 Template cache \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Cache parsed templates by their static string parts.\n * Since tagged templates always produce the same static strings array\n * reference per call site, we use WeakMap for efficient caching.\n */\nconst templateCache = new WeakMap<TemplateStringsArray, HTMLTemplateElement>();\n\n/** Parses performed since module load \u2014 test-only regression hook (issue 0015). */\nlet parseCount = 0;\n\n/** @internal Test-only: number of actual `<template>` parses performed. */\nexport function __templateParseCount(): number {\n return parseCount;\n}\n\n/**\n * Parse-once (ADR 0030.2 T4, issue 0015): build the marker HTML string and\n * parse it into a `<template>` exactly once per callsite, keyed by\n * TemplateStringsArray identity. The string depends only on the static\n * `strings` (marker indices are positional), so every TemplateResult from the\n * same callsite shares one parsed template and clones per mount.\n *\n * The first parse also runs the one-time static audit (template-audit.ts)\n * over the pristine parsed element \u2014 it still carries the raw `@event`/\n * `class:`/marker attributes that processAttributes later strips from clones.\n */\nfunction parseTemplate(strings: TemplateStringsArray, valueCount: number): HTMLTemplateElement {\n let template = templateCache.get(strings);\n if (template) return template;\n\n // Build the HTML string with markers.\n // Track HTML parsing state to auto-quote markers in unquoted\n // attribute positions where the > in --> would close the tag.\n // See ADR 0069.\n let htmlStr = '';\n let inTag = false;\n let quoteChar: string | null = null;\n\n for (let i = 0; i < strings.length; i++) {\n const s = strings[i] ?? '';\n for (let c = 0; c < s.length; c++) {\n const ch = s.charAt(c);\n if (quoteChar) { if (ch === quoteChar) quoteChar = null; }\n else if (inTag) {\n if (ch === '>') inTag = false;\n else if (ch === '\"' || ch === \"'\") quoteChar = ch;\n } else { if (ch === '<') inTag = true; }\n }\n htmlStr += s;\n if (i < valueCount) {\n const needsQuotes = inTag && !quoteChar && /=\\s*$/.test(s);\n htmlStr += needsQuotes ? `\"${createMarker(i)}\"` : createMarker(i);\n }\n }\n\n parseCount++;\n template = document.createElement('template');\n template.innerHTML = htmlStr;\n templateCache.set(strings, template);\n\n // Dev-only first-parse audit (N101\u2013N104); no-op when disabled.\n if (process.env.NODE_ENV !== 'production') auditTemplate(strings, template);\n\n return template;\n}\n\n// \u2500\u2500 Marker for expression slots \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst MARKER_PREFIX = '<!--bk-';\nconst MARKER_SUFFIX = '-->';\nconst ATTR_MARKER = 'bk-';\n\n/**\n * Generate a unique marker for each expression slot.\n * We use HTML comments as markers in text positions and\n * special attribute prefixes for attribute positions.\n */\nfunction createMarker(index: number): string {\n return `${MARKER_PREFIX}${index}${MARKER_SUFFIX}`;\n}\n\n// \u2500\u2500 Binding types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface TextBinding {\n type: 'text';\n node: Text;\n dispose?: () => void;\n}\n\ninterface AttributeBinding {\n type: 'attribute';\n element: Element;\n name: string;\n dispose?: () => void;\n}\n\ninterface ClassBinding {\n type: 'class';\n element: Element;\n className: string;\n dispose?: () => void;\n}\n\ninterface EventBinding {\n type: 'event';\n element: Element;\n eventName: string;\n handler: EventListener;\n modifiers: string[];\n dispose?: () => void;\n}\n\ninterface InnerHtmlBinding {\n type: 'innerHtml';\n element: Element;\n dispose?: () => void;\n}\n\ninterface ChildBinding {\n type: 'child';\n startMarker: Comment;\n endMarker: Comment;\n currentNodes: Node[];\n dispose?: () => void;\n}\n\ntype Binding = TextBinding | AttributeBinding | ClassBinding | EventBinding | InnerHtmlBinding | ChildBinding;\n\n// \u2500\u2500 html tagged template \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Tagged template literal for creating reactive DOM templates.\n *\n * ```ts\n * const name = signal('World');\n * const greeting = html`<h1>Hello, ${name}!</h1>`;\n * ```\n *\n * Signals in expression slots are detected automatically and\n * create fine-grained bindings. When the signal changes, only\n * the specific text node or attribute updates \u2014 no diffing needed.\n */\nexport function html(\n strings: TemplateStringsArray,\n ...values: unknown[]\n): TemplateResult {\n const bindings: Binding[] = [];\n const disposers: (() => void)[] = [];\n // Dev-only: remember the authoring callsite for first-parse audit\n // diagnostics \u2014 by first-mount time this frame is gone from the stack.\n if (process.env.NODE_ENV !== 'production') captureCallsite(strings);\n let mounted = false;\n\n return {\n __templateResult: true as const,\n\n mount(host: HTMLElement): void {\n // Single-mount guard (ADR 0030.2 T4 + \u00A78): a second mount of a live,\n // un-disposed result with value bindings would attach a second set of\n // bindings to the same shared arrays \u2014 shared-binding corruption.\n // Zero-binding templates (the registry's shared static icon pattern)\n // stay multi-mountable; dispose() \u2192 mount() stays legal.\n if (mounted && values.length > 0) {\n throw nisliError(\n 'N105',\n `mount() on an already-mounted TemplateResult with ${values.length} value ` +\n `binding(s) \u2014 dispose() it first or create a fresh template per mount. ` +\n `Template starts: ${JSON.stringify((strings[0] ?? '').slice(0, 60))}`,\n );\n }\n mounted = true;\n\n // Parse-once: the parsed template is cached per callsite; each mount\n // only pays the clone + binding walk. The per-mount processNode walk\n // below REMAINS by design until the ADR 0014-class work \u2014 caching\n // removes the *parse*, not the walk (ADR 0030.2 \u00A78).\n const template = parseTemplate(strings, values.length);\n const fragment = template.content.cloneNode(true) as DocumentFragment;\n\n // Walk the DOM tree and replace markers with bindings\n processNode(fragment, values, bindings, disposers);\n\n // Mount into host\n host.appendChild(fragment);\n },\n\n dispose(): void {\n for (const d of disposers) {\n try { d(); } catch (_) {}\n }\n disposers.length = 0;\n for (const b of bindings) {\n if ('dispose' in b && b.dispose) {\n try { b.dispose(); } catch (_) {}\n }\n }\n bindings.length = 0;\n mounted = false;\n },\n };\n}\n\n// \u2500\u2500 DOM walking and binding creation \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction processNode(\n node: Node,\n values: unknown[],\n bindings: Binding[],\n disposers: (() => void)[],\n): void {\n // Process element attributes\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as Element;\n processAttributes(el, values, bindings, disposers);\n }\n\n // Process text nodes and comments (markers)\n if (node.nodeType === Node.COMMENT_NODE) {\n const comment = node as Comment;\n const text = comment.textContent || '';\n // Check if this is one of our markers\n if (text.startsWith('bk-') && !isNaN(Number(text.slice(3)))) {\n const index = Number(text.slice(3));\n const value = values[index];\n replaceMarkerWithBinding(comment, value, bindings, disposers);\n return; // Don't recurse into replaced content\n }\n }\n\n // Process child nodes (make a copy since we may mutate)\n const children = [...node.childNodes];\n for (const child of children) {\n processNode(child, values, bindings, disposers);\n }\n}\n\nfunction processAttributes(\n el: Element,\n values: unknown[],\n bindings: Binding[],\n disposers: (() => void)[],\n): void {\n // We need to find attributes that contain markers\n const attrsToRemove: string[] = [];\n\n for (const attr of [...el.attributes]) {\n const name = attr.name;\n const attrValue = attr.value;\n\n // Check for @event bindings\n if (name.startsWith('@')) {\n const eventParts = name.slice(1).split('.');\n const eventName = eventParts[0] ?? '';\n const modifiers = eventParts.slice(1);\n\n // The value should be a marker containing the handler\n const markerMatch = attrValue.match(/<!--bk-(\\d+)-->/);\n if (markerMatch) {\n const index = Number(markerMatch[1]);\n const handler = values[index];\n if (typeof handler === 'function') {\n // Cleanup is registered on the EventBinding (removes the installed\n // safeHandler); a manual removeEventListener here would target the\n // original handler and no-op. See bindEvent (UI-33-R).\n bindEvent(el, eventName, handler as EventListener, modifiers, bindings);\n }\n }\n attrsToRemove.push(name);\n continue;\n }\n\n // Check for class:name bindings\n if (name.startsWith('class:')) {\n const className = name.slice(6);\n const markerMatch = attrValue.match(/<!--bk-(\\d+)-->/);\n if (markerMatch) {\n const index = Number(markerMatch[1]);\n const value = values[index];\n bindClass(el, className, value, bindings, disposers);\n }\n attrsToRemove.push(name);\n continue;\n }\n\n // Check for html:inner binding (trusted HTML rendering)\n if (name === 'html:inner') {\n const markerMatch = attrValue.match(/<!--bk-(\\d+)-->/);\n if (markerMatch) {\n const index = Number(markerMatch[1]);\n const value = values[index];\n bindInnerHtml(el, value, bindings, disposers);\n }\n attrsToRemove.push(name);\n continue;\n }\n\n // Check for ref binding: ref=\"${myRef}\"\n if (name === 'ref' && attrValue.includes(MARKER_PREFIX)) {\n const markerMatch = attrValue.match(/<!--bk-(\\d+)-->/);\n if (markerMatch) {\n const index = Number(markerMatch[1]);\n const value = values[index];\n if (isRef(value)) {\n (value as Ref).current = el;\n disposers.push(() => { (value as Ref).current = null; });\n }\n }\n attrsToRemove.push(name);\n continue;\n }\n\n // Check for regular attribute bindings with markers\n if (attrValue.includes(MARKER_PREFIX)) {\n const markers = [...attrValue.matchAll(/<!--bk-(\\d+)-->/g)];\n if (markers.length) {\n const first = markers[0];\n // Single expression = entire value: preserve raw type and signal\n if (markers.length === 1 && first && attrValue === first[0]) {\n bindAttribute(el, name, values[Number(first[1])], bindings, disposers);\n } else {\n // Mixed static + dynamic: resolve markers into string\n const resolve = () => attrValue.replace(/<!--bk-(\\d+)-->/g, (_, i) => {\n const v = values[Number(i)];\n const raw = isSignal(v) ? (v as ReadonlySignal<unknown>).value : v;\n return raw == null || raw === false ? '' : String(raw);\n });\n const hasSignals = markers.some(m => isSignal(values[Number(m[1])]));\n bindAttribute(el, name, hasSignals ? computed(resolve) : resolve(), bindings, disposers);\n }\n }\n continue;\n }\n }\n\n for (const name of attrsToRemove) {\n el.removeAttribute(name);\n }\n}\n\n/**\n * Mount a factory result (from component() factory functions) into a DOM element.\n * Handles prop forwarding (with signal subscriptions) and host-level class attrs.\n */\nfunction mountFactoryResult(\n factory: { tagName: string; props: Record<string, unknown>; hostAttrs?: { class?: unknown } },\n): { element: HTMLElement; dispose: () => void } {\n const el = document.createElement(factory.tagName);\n const localDisposers: (() => void)[] = [];\n for (const [key, raw] of Object.entries(factory.props)) {\n if (isSignal(raw)) {\n const sig = raw as ReadonlySignal<unknown>;\n const unsub = sig.subscribe((newVal: unknown) => {\n (el as any)._setProp?.(key, newVal);\n });\n localDisposers.push(unsub);\n } else {\n (el as any)._setProp?.(key, raw);\n }\n }\n if (factory.hostAttrs?.class != null) {\n const classVal = factory.hostAttrs.class;\n if (isSignal(classVal)) {\n const sig = classVal as ReadonlySignal<string>;\n let prevClasses: string[] = [];\n const applyClasses = (raw: string) => {\n const next = raw ? raw.split(/\\s+/).filter(Boolean) : [];\n for (const cls of prevClasses) {\n if (!next.includes(cls)) el.classList.remove(cls);\n }\n for (const cls of next) {\n if (!prevClasses.includes(cls)) el.classList.add(cls);\n }\n prevClasses = next;\n };\n const unsub = sig.subscribe(applyClasses);\n localDisposers.push(unsub);\n } else if (typeof classVal === 'string' && classVal) {\n for (const cls of classVal.split(/\\s+/).filter(Boolean)) {\n el.classList.add(cls);\n }\n }\n }\n return {\n element: el,\n dispose() {\n for (const dispose of localDisposers.splice(0)) {\n try { dispose(); } catch (_) { /* swallow */ }\n }\n },\n };\n}\n\nfunction replaceMarkerWithBinding(\n comment: Comment,\n value: unknown,\n bindings: Binding[],\n disposers: (() => void)[],\n): void {\n const parent = comment.parentNode;\n if (!parent) return;\n\n if (isSignal(value)) {\n // Every reactive child is a slot because its future values may have any\n // documented child type. The slot still keeps a single Text node alive for\n // primitive-to-primitive updates, preserving the O(1) text fast path.\n const startMarker = document.createComment('slot-start');\n const endMarker = document.createComment('slot-end');\n parent.replaceChild(endMarker, comment);\n parent.insertBefore(startMarker, endMarker);\n\n let currentResults: TemplateResult[] = [];\n let currentNodes: Node[] = [];\n let currentFactoryDisposers: (() => void)[] = [];\n let currentText: Text | null = null;\n // Sentinel distinct from any resolvable value (including null/undefined)\n // so the FIRST effect run always mounts. See ADR 0008.1.\n const NOT_RENDERED = Symbol('not-rendered');\n let lastValue: unknown = NOT_RENDERED;\n\n const dispose = effect(() => {\n const newValue = (value as ReadonlySignal<unknown>).value;\n // Use endMarker.parentNode \u2014 the captured `parent` may be a\n // DocumentFragment that was already appended to the real DOM,\n // leaving the markers reparented under the actual DOM element.\n const liveParent = endMarker.parentNode;\n if (!liveParent) return;\n\n // Memoize by referential identity. A computed/signal only notifies\n // when its value changes by Object.is, so an EQUAL value here means\n // this effect was re-triggered by some OTHER dependency (a tracking\n // leak), not by an actual change to this slot. Re-mounting identical\n // content would destroy live DOM (and reset scroll/focus) for nothing.\n // See ADR 0008.1.\n if (newValue === lastValue) return;\n lastValue = newValue;\n\n const isTemplate = Boolean(\n newValue\n && typeof newValue === 'object'\n && '__templateResult' in newValue,\n );\n const isFactory = Boolean(\n newValue\n && typeof newValue === 'object'\n && '__type' in newValue\n && (newValue as any).__type === 'factory',\n );\n const isPrimitive = newValue != null\n && newValue !== false\n && !Array.isArray(newValue)\n && !isTemplate\n && !isFactory;\n\n if (isPrimitive && currentText) {\n currentText.data = String(newValue);\n return;\n }\n\n // Dispose and remove the previous slot value before mounting the next.\n // Ownership is per VALUE, not per outer template lifetime: factory prop\n // subscriptions must stop as soon as their child leaves (issue 0011).\n for (const r of currentResults) {\n try { r.dispose(); } catch (_) {}\n }\n for (const dispose of currentFactoryDisposers) {\n try { dispose(); } catch (_) {}\n }\n for (const node of currentNodes) {\n node.parentNode?.removeChild(node);\n }\n currentNodes = [];\n currentResults = [];\n currentFactoryDisposers = [];\n currentText = null;\n\n if (newValue == null) {\n // null/undefined \u2014 nothing to mount\n } else if (Array.isArray(newValue)) {\n // Array of TemplateResults (or mixed content)\n for (const item of newValue) {\n if (item && typeof item === 'object' && '__templateResult' in item) {\n const tpl = item as TemplateResult;\n const wrapper = document.createDocumentFragment();\n tpl.mount(wrapper as unknown as HTMLElement);\n const nodes = [...wrapper.childNodes];\n currentNodes.push(...nodes);\n currentResults.push(tpl);\n liveParent.insertBefore(wrapper, endMarker);\n } else if (item && typeof item === 'object' && '__type' in item && (item as any).__type === 'factory') {\n const mounted = mountFactoryResult(item as any);\n currentNodes.push(mounted.element);\n currentFactoryDisposers.push(mounted.dispose);\n liveParent.insertBefore(mounted.element, endMarker);\n } else if (item != null && item !== false) {\n const textNode = document.createTextNode(String(item));\n currentNodes.push(textNode);\n liveParent.insertBefore(textNode, endMarker);\n }\n }\n } else if (isTemplate) {\n // Single TemplateResult\n const tpl = newValue as TemplateResult;\n const wrapper = document.createDocumentFragment();\n tpl.mount(wrapper as unknown as HTMLElement);\n currentNodes = [...wrapper.childNodes];\n currentResults.push(tpl);\n liveParent.insertBefore(wrapper, endMarker);\n } else if (isFactory) {\n // Factory result \u2014 create child element\n const mounted = mountFactoryResult(newValue as any);\n currentNodes.push(mounted.element);\n currentFactoryDisposers.push(mounted.dispose);\n liveParent.insertBefore(mounted.element, endMarker);\n } else if (newValue !== false) {\n currentText = document.createTextNode(String(newValue));\n currentNodes.push(currentText);\n liveParent.insertBefore(currentText, endMarker);\n }\n });\n disposers.push(dispose);\n // TemplateResult.dispose() intentionally leaves mounted DOM in place, but\n // it must still dispose bindings owned by the CURRENT reactive slot value.\n disposers.push(() => {\n for (const r of currentResults.splice(0)) {\n try { r.dispose(); } catch (_) {}\n }\n for (const factoryDispose of currentFactoryDisposers.splice(0)) {\n try { factoryDispose(); } catch (_) {}\n }\n currentNodes = [];\n currentText = null;\n });\n } else if (value && typeof value === 'object' && '__templateResult' in value) {\n // Nested template result \u2014 mount it\n const result = value as TemplateResult;\n const startMarker = document.createComment('tpl-start');\n const endMarker = document.createComment('tpl-end');\n parent.replaceChild(endMarker, comment);\n parent.insertBefore(startMarker, endMarker);\n\n // Create a wrapper element to mount into\n const wrapper = document.createDocumentFragment();\n result.mount(wrapper as unknown as HTMLElement);\n parent.insertBefore(wrapper, endMarker);\n\n disposers.push(() => result.dispose());\n } else if (value && typeof value === 'object' && '__type' in value && (value as any).__type === 'factory') {\n // Factory result \u2014 create child element\n const mounted = mountFactoryResult(value as any);\n parent.replaceChild(mounted.element, comment);\n disposers.push(mounted.dispose);\n } else if (Array.isArray(value)) {\n // Array of template results\n const startMarker = document.createComment('list-start');\n const endMarker = document.createComment('list-end');\n parent.replaceChild(endMarker, comment);\n parent.insertBefore(startMarker, endMarker);\n\n for (const item of value) {\n if (item && typeof item === 'object' && '__templateResult' in item) {\n const wrapper = document.createDocumentFragment();\n (item as TemplateResult).mount(wrapper as unknown as HTMLElement);\n parent.insertBefore(wrapper, endMarker);\n disposers.push(() => (item as TemplateResult).dispose());\n } else if (item && typeof item === 'object' && '__type' in item && (item as any).__type === 'factory') {\n const mounted = mountFactoryResult(item as any);\n parent.insertBefore(mounted.element, endMarker);\n disposers.push(mounted.dispose);\n } else {\n const textNode = document.createTextNode(String(item));\n parent.insertBefore(textNode, endMarker);\n }\n }\n } else if (value == null || value === false) {\n // null, undefined, false \u2014 render nothing\n parent.removeChild(comment);\n } else {\n // Primitive value \u2014 render as text\n const textNode = document.createTextNode(String(value));\n parent.replaceChild(textNode, comment);\n }\n}\n\nfunction bindAttribute(\n el: Element,\n name: string,\n value: unknown,\n bindings: Binding[],\n disposers: (() => void)[],\n): void {\n // class attribute gets special handling to avoid conflicts with\n // class:name directives (see bindClassAttribute for details).\n if (name === 'class') {\n bindClassAttribute(el, value, bindings, disposers);\n return;\n }\n\n // Auto-resolution: framework components get _setProp for custom props\n // (preserves types). Standard HTML attributes (id, style, data-*, aria-*,\n // and \u2014 ADR 0030.2 \u00A78 \u2014 title/role/tabindex/name) always use setAttribute\n // even on framework components: routed through _setProp they were silently\n // dead (no component declares them as props).\n const isHtmlAttr = name === 'id' || name === 'style'\n || name === 'slot' || name === 'title' || name === 'role'\n || name === 'tabindex' || name === 'name'\n || name.startsWith('data-') || name.startsWith('aria-');\n const hasPropSetter = !isHtmlAttr && typeof (el as any)._setProp === 'function';\n\n if (hasPropSetter) {\n if (isSignal(value)) {\n const binding: AttributeBinding = { type: 'attribute', element: el, name };\n bindings.push(binding);\n const dispose = effect(() => {\n (el as any)._setProp(name, (value as ReadonlySignal<unknown>).value);\n });\n binding.dispose = dispose;\n disposers.push(dispose);\n } else {\n (el as any)._setProp(name, value);\n }\n return;\n }\n\n bindPlainAttribute(el, name, value, bindings, disposers);\n}\n\n/**\n * Bind a value as a plain HTML attribute via `setAttribute`, reactive when it\n * is a signal, with `html`'s boolean/null semantics (true \u2192 present empty,\n * false/null/undefined \u2192 absent). NEVER uses `_setProp` \u2014 this is the shared\n * attribute path used by both `bindAttribute` (its non-component branch) and\n * `el()`, whose contract is *plain-HTML authoring*: a framework component tag\n * reached this way receives its values as attributes and resolves them through\n * its `attr()`/`boolAttr()` fallbacks, not typed prop setters.\n */\nfunction bindPlainAttribute(\n el: Element,\n name: string,\n value: unknown,\n bindings: Binding[],\n disposers: (() => void)[],\n): void {\n if (isSignal(value)) {\n const binding: AttributeBinding = { type: 'attribute', element: el, name };\n bindings.push(binding);\n\n const dispose = effect(() => {\n const v = (value as ReadonlySignal<unknown>).value;\n if (v == null || v === false) {\n el.removeAttribute(name);\n } else if (v === true) {\n el.setAttribute(name, '');\n } else {\n el.setAttribute(name, String(v));\n }\n });\n binding.dispose = dispose;\n disposers.push(dispose);\n } else {\n if (value == null || value === false) {\n el.removeAttribute(name);\n } else if (value === true) {\n el.setAttribute(name, '');\n } else {\n el.setAttribute(name, String(value));\n }\n }\n}\n\n/**\n * Bind a reactive class attribute using classList.add/remove instead of\n * setAttribute('class', ...). This prevents the class attribute binding\n * from overwriting classes toggled by class:name directives.\n *\n * The problem: setAttribute('class', 'foo bar') replaces ALL classes,\n * wiping out any classes added by classList.toggle() from class:name\n * bindings. By tracking which classes \"belong\" to the class attribute\n * and using classList operations, we only manage our own classes.\n */\nfunction bindClassAttribute(\n el: Element,\n value: unknown,\n bindings: Binding[],\n disposers: (() => void)[],\n): void {\n // On first call, we must clear the parser-set class attribute which\n // contains raw marker text (e.g. \"badge status-<!--bk-0-->\").\n // We snapshot any non-marker classes set by the parser before clearing.\n let initialized = false;\n let prevClasses: string[] = [];\n\n const applyClasses = (raw: unknown) => {\n if (!initialized) {\n // Clear the parser's class attribute (contains marker text)\n el.setAttribute('class', '');\n initialized = true;\n }\n const str = raw == null || raw === false ? '' : String(raw);\n const next = str.split(/\\s+/).filter(Boolean);\n\n // Remove classes no longer in the attribute value\n for (const cls of prevClasses) {\n if (!next.includes(cls)) {\n el.classList.remove(cls);\n }\n }\n // Add new classes\n for (const cls of next) {\n if (!prevClasses.includes(cls)) {\n el.classList.add(cls);\n }\n }\n prevClasses = next;\n };\n\n if (isSignal(value)) {\n const binding: AttributeBinding = { type: 'attribute', element: el, name: 'class' };\n bindings.push(binding);\n\n const dispose = effect(() => {\n applyClasses((value as ReadonlySignal<unknown>).value);\n });\n binding.dispose = dispose;\n disposers.push(dispose);\n } else {\n applyClasses(value);\n }\n}\n\nfunction bindClass(\n el: Element,\n className: string,\n value: unknown,\n bindings: Binding[],\n disposers: (() => void)[],\n): void {\n if (isSignal(value)) {\n const binding: ClassBinding = { type: 'class', element: el, className };\n bindings.push(binding);\n\n const dispose = effect(() => {\n const v = (value as ReadonlySignal<unknown>).value;\n el.classList.toggle(className, !!v);\n });\n binding.dispose = dispose;\n disposers.push(dispose);\n } else {\n el.classList.toggle(className, !!value);\n }\n}\n\n/**\n * Bind branded HTML content to an element's inner markup.\n *\n * Never a bare string \u2014 a brand is the author's explicit decision about where\n * the markup came from, which is what closes the accidental-XSS-sink class\n * (ADR 0030.2 \u00A73/\u00A78). Three shapes resolve, in the order they are checked:\n *\n * - `raw()` (core owns the `__raw` brand; @nisli/ssg re-exports it):\n * author-asserted trust \u2192 today's `innerHTML` sink, unchanged.\n * NEVER wrap user-generated input in raw().\n * - `sanitized()` \u2192 the sanitizer sink: native `Element.setHTML()`, else the\n * `setSanitizerFallback()` hook, else N107. It NEVER reaches `innerHTML`\n * (ADR 0019:124\u2013128, bet-09(c)).\n * - A native `TrustedHTML` object \u2192 the same `innerHTML` sink as `raw()`,\n * passed through unwrapped so Trusted-Types-enforcing apps can assign\n * policy output directly.\n *\n * Anything else throws N106. Supports both static values and reactive\n * `Signal`s of them; when the signal changes the content is rewritten through\n * the same branch. null/undefined (branded or not) clears the content.\n *\n * Usage in templates:\n * html`<span html:inner=\"${raw(highlightedHtml)}\"></span>`\n * html`<span html:inner=\"${sanitized(userComment)}\"></span>`\n */\nfunction bindInnerHtml(\n el: Element,\n value: unknown,\n bindings: Binding[],\n disposers: (() => void)[],\n): void {\n // PURE \u2014 validates the brand and proves a sink exists without writing\n // anything, so the eager signal check below can run it for its throw alone.\n // A SanitizedHtml resolves to ITSELF (the writer routes it to the\n // sanitizer); everything else resolves to the innerHTML payload.\n const resolveHtml = (v: unknown): string | SanitizedHtml | TrustedHtml => {\n if (v == null) return '';\n if (isRawHtml(v)) {\n // Both brands at once: trust is not resolvable in favour of the raw\n // sink, so reject rather than guess which one the author meant.\n if (isSanitizedHtml(v)) {\n throw nisliError(\n 'N106',\n `html:inner rejects a value branded both raw() and sanitized() \u2014 the ` +\n `trust decision is ambiguous. Pick one brand.`,\n );\n }\n return v.value;\n }\n if (isSanitizedHtml(v)) {\n // FAIL CLOSED. Untrusted markup is only ever eligible to be written once\n // a sanitizing sink is proven to exist; no native setHTML() and no\n // registered hook is a hard error, because silently downgrading to\n // innerHTML would reopen the exact XSS hole this brand closes.\n if (sanitizerFor(el) === null) {\n throw nisliError(\n 'N107',\n `html:inner cannot render sanitized() markup: this engine has no native ` +\n `Element.setHTML() and no fallback is registered. Wire one at startup \u2014 ` +\n `setSanitizerFallback((el, html) => { el.innerHTML = DOMPurify.sanitize(html) }) ` +\n `\u2014 nisli ships no sanitizer and will not fall back to innerHTML.`,\n );\n }\n return v;\n }\n if (isTrustedHtml(v)) return v;\n throw nisliError(\n 'N106',\n `html:inner rejects unbranded values (got ${typeof v}). Wrap trusted markup ` +\n `in raw(html), untrusted markup in sanitized(html) \u2014 and never wrap ` +\n `user-generated input in raw().`,\n );\n };\n\n const writeHtml = (v: unknown): void => {\n const resolved = resolveHtml(v);\n if (isSanitizedHtml(resolved)) {\n // The sanitizer sink. resolveHtml has already proven a writer exists,\n // and `el.innerHTML` is unreachable from this branch by construction.\n sanitizerFor(el)?.(el, resolved.value);\n return;\n }\n // The raw sink, unchanged: a plain string, or a TrustedHTML object handed\n // over WITHOUT stringifying it (stringifying would defeat the CSP check).\n // The cast only satisfies the DOM library's `string` typing.\n el.innerHTML = resolved as string;\n };\n\n if (isSignal(value)) {\n // Validate the INITIAL value untracked and eagerly so an unbranded or\n // unsanitizable signal throws synchronously out of mount(); later invalid\n // values throw inside the effect and land in effect error containment\n // (console.error, element content untouched).\n untracked(() => resolveHtml((value as ReadonlySignal<unknown>).value));\n\n const binding: InnerHtmlBinding = { type: 'innerHtml', element: el };\n bindings.push(binding);\n\n const dispose = effect(() => {\n writeHtml((value as ReadonlySignal<unknown>).value);\n });\n binding.dispose = dispose;\n disposers.push(dispose);\n } else {\n writeHtml(value);\n }\n}\n\nfunction bindEvent(\n el: Element,\n eventName: string,\n handler: EventListener,\n modifiers: string[],\n bindings: Binding[],\n): void {\n // One canonical INSTALLED identity that every removal path references \u2014 the\n // EventBinding `dispose` below AND the `once` self-removal. Forward-declared\n // so the modifier wrappers close over it before it is assigned; it is only\n // ever *called* after addEventListener, so the reference always resolves.\n // This identity-mismatch class bit el() dispose, html dispose, and once \u2014 a\n // single installed handler that all removals target closes it (UI-33-R2).\n let safeHandler!: EventListener;\n\n // Compose the modifier chain (inner); safeHandler wraps it in try/catch below.\n let composed: EventListener = handler;\n\n if (modifiers.includes('stop')) {\n const inner = composed;\n composed = (e: Event) => {\n e.stopPropagation();\n inner(e);\n };\n }\n if (modifiers.includes('prevent')) {\n const inner = composed;\n composed = (e: Event) => {\n e.preventDefault();\n inner(e);\n };\n }\n if (modifiers.includes('once')) {\n const inner = composed;\n composed = (e: Event) => {\n // Remove the ACTUALLY-INSTALLED listener, not this intermediate wrapper.\n el.removeEventListener(eventName, safeHandler);\n inner(e);\n };\n }\n\n // Keyboard modifiers\n for (const mod of modifiers) {\n if (['enter', 'escape', 'space', 'tab'].includes(mod)) {\n const keyMap: Record<string, string> = {\n enter: 'Enter',\n escape: 'Escape',\n space: ' ',\n tab: 'Tab',\n };\n const inner = composed;\n composed = (e: Event) => {\n if ((e as KeyboardEvent).key === keyMap[mod]) {\n inner(e);\n }\n };\n }\n }\n\n // Wrap in try/catch for error containment \u2014 THIS is the installed handler.\n // Handler bodies run UNTRACKED (ADR 0030.2 \u00A78, surfaced by the T5 review):\n // synchronous dispatchEvent from inside an effect would otherwise run the\n // handler under that effect's observer \u2014 widening the effect's dependency\n // set with every signal the handler reads and mis-attributing its writes.\n safeHandler = (e: Event) => {\n try {\n untrack(() => composed(e));\n } catch (err) {\n console.error(`Event handler error for '${eventName}':`, err);\n }\n };\n\n el.addEventListener(eventName, safeHandler);\n\n // Register cleanup of the ACTUALLY-INSTALLED handler (safeHandler), not the\n // caller's original \u2014 their identities differ, so a removeEventListener with\n // the original is a silent no-op (the UI-33-R leak). Both `html` dispose and\n // `el()` dispose iterate bindings and call `dispose`, so this is the single\n // correct cleanup path for event listeners.\n bindings.push({\n type: 'event',\n element: el,\n eventName,\n handler: safeHandler,\n modifiers,\n dispose: () => el.removeEventListener(eventName, safeHandler),\n });\n}\n\n// \u2500\u2500 each() reactive list rendering \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Brand for each result detection */\nconst EACH_BRAND = Symbol.for('backlog.each');\n\ninterface EachEntry<T> {\n key: string | number;\n itemSignal: Signal<T>;\n indexSignal: Signal<number>;\n templateResult: TemplateResult;\n /** Stable wrapper element that survives inner reactive content changes. */\n wrapper: HTMLElement;\n}\n\n/**\n * Reactive list rendering with keyed reconciliation.\n *\n * Renders a list of items from a signal, tracking each item by key.\n * When the array changes, only affected DOM nodes are added, removed,\n * or reordered \u2014 existing items update in-place via their signals.\n *\n * ```ts\n * const tasks = signal([{ id: '1', title: 'A' }, { id: '2', title: 'B' }]);\n * html`<ul>${each(tasks, t => t.id, (task, index) =>\n * html`<li>${computed(() => task.value.title)}</li>`\n * )}</ul>`\n * ```\n */\n/**\n * Adapt whatever a template callback returned into a mountable TemplateResult.\n * Factory descriptors (the value `component()` factories actually return) are\n * mounted through the same path every other slot uses (issue 0021).\n */\nfunction asTemplateResult(result: unknown): TemplateResult {\n if (result && typeof result === 'object' && '__templateResult' in result) {\n return result as TemplateResult;\n }\n if (result && typeof result === 'object' && (result as any).__type === 'factory') {\n let mounted: { element: HTMLElement; dispose: () => void } | null = null;\n return {\n __templateResult: true as const,\n mount(host: HTMLElement) {\n mounted = mountFactoryResult(result as any);\n host.appendChild(mounted.element);\n },\n dispose() {\n mounted?.dispose();\n mounted?.element.remove();\n mounted = null;\n },\n };\n }\n throw new TypeError(\n `each(): template callback must return a TemplateResult or a component factory result, got ${\n result === null ? 'null' : typeof result\n }`,\n );\n}\n\nexport function each<T>(\n items: ReadonlySignal<T[]>,\n keyFn: (item: T, index: number) => string | number,\n templateFn: (item: ReadonlySignal<T>, index: ReadonlySignal<number>) => TemplateResult | { __type: 'factory' },\n): TemplateResult {\n let startMarker: Comment;\n let endMarker: Comment;\n let entries: EachEntry<T>[] = [];\n let effectDispose: (() => void) | null = null;\n\n return {\n __templateResult: true as const,\n\n mount(host: HTMLElement) {\n startMarker = document.createComment('each-start');\n endMarker = document.createComment('each-end');\n host.appendChild(startMarker);\n host.appendChild(endMarker);\n\n effectDispose = effect(() => {\n const newItems = items.value;\n reconcile(newItems);\n });\n },\n\n dispose() {\n if (effectDispose) {\n effectDispose();\n effectDispose = null;\n }\n for (const entry of entries) {\n entry.templateResult.dispose();\n }\n entries = [];\n },\n };\n\n function reconcile(newItems: T[]) {\n const parent = endMarker.parentNode;\n if (!parent) return;\n\n // Validate the whole key set before updating item signals, mounting new\n // entries, or touching DOM. A duplicate update must leave the last valid\n // reconciliation intact so a later corrected array can recover normally.\n const keyedItems: Array<{ item: T; index: number; key: string | number }> = [];\n const keyIndices = new Map<string | number, number>();\n for (let i = 0; i < newItems.length; i++) {\n const item = newItems[i];\n if (item === undefined) continue;\n const key = keyFn(item, i);\n const previousIndex = keyIndices.get(key);\n if (previousIndex !== undefined) {\n const formattedKey = typeof key === 'string' ? JSON.stringify(key) : String(key);\n console.error(\n `each() requires unique keys. Duplicate key ${formattedKey} ` +\n `found at indices ${previousIndex} and ${i}; reconciliation skipped.`,\n );\n return;\n }\n keyIndices.set(key, i);\n keyedItems.push({ item, index: i, key });\n }\n\n // Build old key \u2192 entry map\n const oldMap = new Map<string | number, EachEntry<T>>();\n for (const entry of entries) {\n oldMap.set(entry.key, entry);\n }\n\n // Build new entries list\n const newEntries: EachEntry<T>[] = [];\n const newKeys = new Set<string | number>();\n\n for (const { item, index, key } of keyedItems) {\n newKeys.add(key);\n\n const existing = oldMap.get(key);\n if (existing) {\n // Reuse \u2014 update signals in place\n existing.itemSignal.value = item;\n existing.indexSignal.value = index;\n newEntries.push(existing);\n } else {\n // Create new entry with a stable wrapper element.\n // Using display:contents so the wrapper is invisible to layout \u2014\n // inner reactive content can freely swap DOM nodes without\n // invalidating the each() reconciler's node tracking.\n const itemSignal = signal(item) as Signal<T>;\n const indexSignal = signal(index);\n const wrapper = document.createElement('each-item');\n wrapper.style.display = 'contents';\n const templateResult = asTemplateResult(templateFn(itemSignal, indexSignal));\n templateResult.mount(wrapper);\n newEntries.push({ key, itemSignal, indexSignal, templateResult, wrapper });\n }\n }\n\n // Remove entries whose key is gone\n for (const entry of entries) {\n if (!newKeys.has(entry.key)) {\n entry.templateResult.dispose();\n entry.wrapper.parentNode?.removeChild(entry.wrapper);\n }\n }\n\n // Reorder DOM nodes to match new order.\n // Each entry has exactly one stable wrapper element, so positioning\n // is simple and immune to inner reactive content swaps.\n let cursor: Node = startMarker;\n for (const entry of newEntries) {\n const nextSibling = cursor.nextSibling;\n if (nextSibling !== entry.wrapper) {\n if (entry.wrapper.parentNode === parent && canMoveWithin(parent)) {\n // Already attached under this parent: atomic move preconditions hold.\n parent.moveBefore(entry.wrapper, nextSibling);\n } else {\n // Fresh wrapper, or a browser without moveBefore().\n parent.insertBefore(entry.wrapper, nextSibling);\n }\n }\n cursor = entry.wrapper;\n }\n\n entries = newEntries;\n }\n}\n\n/**\n * Conditional rendering helper (ADR 0030.2 \u00A73, boolean-gated with `else`).\n *\n * Shows `template` when the condition is truthy, `elseTemplate` (optional)\n * when falsy. Both arms accept a TemplateResult or a lazy callback\n * `() => TemplateResult`; callbacks are only evaluated for the active arm.\n *\n * Semantics for signal conditions:\n * - The gate is `!!condition.value` \u2014 a truthy\u2192truthy (or falsy\u2192falsy)\n * transition returns the memoized previous result, so the live branch is\n * NEVER rebuilt (no state/scroll/focus loss) and callbacks never re-run.\n * - Branch callbacks evaluate UNTRACKED: a signal read during branch\n * construction does not subscribe the when() computed, so it cannot\n * trigger a rebuild. Reactive parts inside a branch must be interpolated\n * as signals/computeds (values), not read raw at construction time.\n */\nexport function when(\n condition: unknown,\n template: TemplateResult | (() => TemplateResult),\n elseTemplate?: TemplateResult | (() => TemplateResult),\n): TemplateResult | ReadonlySignal<TemplateResult | null> | null {\n const resolveBranch = (\n branch: TemplateResult | (() => TemplateResult) | undefined,\n ): TemplateResult | null => {\n if (branch === undefined) return null;\n if (typeof branch === 'function') return untracked(branch);\n return branch;\n };\n\n if (isSignal(condition)) {\n // Boolean-gated memo: notify() marks observers dirty EAGERLY (before\n // value-equality is known), so a computed chain alone cannot stop a\n // truthy\u2192truthy recompute from re-evaluating the branch. The memo pins\n // branch evaluation to actual boolean FLIPS; equal gates return the\n // cached result, which the slot then memoizes by identity (ADR 0008.1).\n let lastGate: boolean | undefined;\n let lastResult: TemplateResult | null = null;\n return computed(() => {\n const gate = !!(condition as ReadonlySignal<unknown>).value;\n if (gate === lastGate) return lastResult;\n const next = gate ? resolveBranch(template) : resolveBranch(elseTemplate);\n // Commit the memo only after a successful resolve so a throwing branch\n // callback retries on the next read (computed error containment).\n lastGate = gate;\n lastResult = next;\n return next;\n });\n }\n return condition ? resolveBranch(template) : resolveBranch(elseTemplate);\n}\n\n// \u2500\u2500 el(): dynamic tag names (ADR 0025 item 11) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** A value bindable to an `el()` attribute \u2014 static or reactive. */\ntype ElAttrValue = string | number | boolean | null | undefined | ReadonlySignal<unknown>;\n\nexport interface ElProps {\n /** Assigned to `.current` on mount, nulled on dispose. */\n ref?: Ref;\n /** Event handlers by native event name; auto-removed on dispose. */\n on?: Record<string, EventListener>;\n /** Any other key is an HTML attribute (static or signal \u2192 reactive). */\n [attr: string]: ElAttrValue | Ref | Record<string, EventListener> | undefined;\n}\n\n/** A child accepted by `el()` \u2014 anything an `html` text slot accepts, plus arrays. */\nexport type ElChild =\n | string\n | number\n | boolean\n | null\n | undefined\n | TemplateResult\n | ReadonlySignal<unknown>\n | { __type: 'factory' }\n | ElChild[];\n\n/**\n * Build a DOM element by a (possibly *dynamic*) tag name with reactive\n * attributes, event handlers, and children, returned as a mountable/disposable\n * `TemplateResult` \u2014 so it composes in an `html` slot:\n * `` html`${el(tag, { class: cls }, children)}` ``.\n *\n * `el()` is the \"author plain HTML programmatically\" primitive. It exists for\n * the one thing `html` cannot express \u2014 a tag name chosen at runtime \u2014 while\n * the `html` PARSER STAYS 100% STATIC: `el()` is a separate construction path\n * that shares `html`'s binding helpers (`bindPlainAttribute`, `bindClassAttribute`,\n * `bindEvent`, and the `replaceMarkerWithBinding` slot mounter). Prefer `html`\n * for static tags and typed factories for typed composition.\n *\n * Semantics (ADR 0025 item 11):\n * - Props are **HTML attributes**: `class` uses the reactive class binder, every\n * other key uses `setAttribute` with `html`'s boolean/null rules \u2014 NEVER\n * `_setProp`. A framework component tag reached via `el()` receives its values\n * as attributes and resolves them through its `attr()`/`boolAttr()` fallbacks.\n * - `ref` assigns `.current`; `on: { event: handler }` adds auto-removed listeners.\n * - Children accept the full `html` text-slot range \u2014 string/number, signals\n * (reactive text or reactive template slot), `TemplateResult`, factory results,\n * and arrays \u2014 via the shared slot mounter.\n * - v1 is HTML-only: SVG/namespaced tags (`createElementNS`) are deferred until a\n * real consumer needs them.\n */\nexport function el(\n tag: string,\n props: ElProps = {},\n children?: ElChild | ElChild[],\n): TemplateResult {\n let node: HTMLElement | null = null;\n const bindings: Binding[] = [];\n const disposers: (() => void)[] = [];\n\n return {\n __templateResult: true,\n\n mount(host: HTMLElement): void {\n const element = document.createElement(tag);\n node = element;\n\n for (const [key, val] of Object.entries(props)) {\n if (val === undefined) continue;\n if (key === 'ref') {\n if (isRef(val)) {\n (val as Ref).current = element;\n disposers.push(() => { (val as Ref).current = null; });\n }\n continue;\n }\n if (key === 'on') {\n // bindEvent registers correct disposal on the EventBinding (removes\n // the installed safeHandler); no manual removeEventListener (UI-33-R).\n for (const [event, handler] of Object.entries(val as Record<string, EventListener>)) {\n bindEvent(element, event, handler, [], bindings);\n }\n continue;\n }\n if (key === 'class') {\n bindClassAttribute(element, val, bindings, disposers);\n continue;\n }\n bindPlainAttribute(element, key, val, bindings, disposers);\n }\n\n // Children reuse html's text-slot mounter: append a comment anchor per\n // child and let replaceMarkerWithBinding resolve its type in place.\n const flat: ElChild[] = [];\n flattenChildren(children, flat);\n for (const child of flat) {\n const anchor = document.createComment('');\n element.appendChild(anchor);\n replaceMarkerWithBinding(anchor, child, bindings, disposers);\n }\n\n host.appendChild(element);\n },\n\n dispose(): void {\n for (const d of disposers) {\n try { d(); } catch (_) { /* swallow */ }\n }\n disposers.length = 0;\n for (const b of bindings) {\n if ('dispose' in b && b.dispose) {\n try { b.dispose(); } catch (_) { /* swallow */ }\n }\n }\n bindings.length = 0;\n node?.parentNode?.removeChild(node);\n node = null;\n },\n };\n}\n\nfunction flattenChildren(children: ElChild | ElChild[] | undefined, out: ElChild[]): void {\n if (children === undefined) return;\n if (Array.isArray(children)) {\n for (const c of children) flattenChildren(c, out);\n } else {\n out.push(children);\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["el", "html", "raw", "dispose"]
7
+ }
@@ -0,0 +1,20 @@
1
+ import { flush } from "./signal.js";
2
+ function supportsTransitionTypes() {
3
+ return typeof ViewTransition !== "undefined" && "types" in ViewTransition.prototype;
4
+ }
5
+ function viewTransition(update, options = {}) {
6
+ const commit = () => {
7
+ update();
8
+ flush();
9
+ };
10
+ if (typeof document === "undefined" || typeof document.startViewTransition !== "function") {
11
+ commit();
12
+ return null;
13
+ }
14
+ const types = options.types;
15
+ return types !== void 0 && types.length > 0 && supportsTransitionTypes() ? document.startViewTransition({ update: commit, types }) : document.startViewTransition(commit);
16
+ }
17
+ export {
18
+ viewTransition
19
+ };
20
+ //# sourceMappingURL=view-transition.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/view-transition.ts"],
4
+ "sourcesContent": ["/**\n * view-transition.ts \u2014 opt-in View Transitions over the synchronous flush.\n *\n * `viewTransition()` wraps a state update so the browser animates between the\n * before and after frames. It is a thin, opt-in wrapper: nothing here runs\n * unless you call it, and no scheduler behaviour changes.\n *\n * ```ts\n * viewTransition(() => { items.value = sorted; }, { types: ['reorder'] });\n * ```\n *\n * ## Why `flush()` is the whole trick\n *\n * `document.startViewTransition()` captures the OLD frame, runs the update\n * callback, then captures the NEW frame. Nisli coalesces signal writes onto a\n * microtask (ADR 0015), so a bare `items.value = sorted` inside that callback\n * would mutate the DOM *after* the capture window \u2014 the browser would animate\n * a frame to itself. Calling `flush()` inside the callback drains the effect\n * cascade synchronously, so the DOM mutation the browser snapshots is nisli's\n * own synchronous flush. `flush()` keeps its documented contract exactly\n * (\"effects executed before the next line\", ADR 0015); this is a consumer of\n * it, not a change to it. N303's cascade cap still applies inside the\n * callback \u2014 a runaway cascade degrades to a skipped transition, not a hang.\n *\n * ## Progressive enhancement\n *\n * Where `document.startViewTransition` is missing (no DOM at all, or an engine\n * without the API) the update still applies \u2014 synchronously, flushed, and\n * unanimated \u2014 and the return is `null`. Where the API exists but the\n * object/`types` form does not (Chrome 111\u2013124), the plain callback form is\n * used: the transition still runs, `:active-view-transition-type()` CSS simply\n * never matches. There is no polyfill and no UA sniffing.\n *\n * ## Companion CSS (author-side, core ships no stylesheet)\n *\n * The root crossfade is the UA default and needs no CSS; tune it, and cut\n * motion for users who ask, with:\n *\n * ```css\n * ::view-transition-old(root),\n * ::view-transition-new(root) { animation-duration: 200ms; }\n *\n * @media (prefers-reduced-motion: reduce) {\n * ::view-transition-group(*),\n * ::view-transition-old(*),\n * ::view-transition-new(*) { animation: none !important; }\n * }\n * ```\n *\n * Reduced motion is answered in CSS, not JS: `viewTransition()` is still\n * called, so the swap stays atomic and typed styles stay active \u2014 only the\n * motion is neutralised. `skipTransition()` on the returned handle is the hard\n * opt-out.\n */\n\nimport { flush } from './signal.js';\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface ViewTransitionOptions {\n /** Transition types, surfaced to `:active-view-transition-type()` CSS. */\n types?: string[];\n}\n\n// \u2500\u2500 Feature detection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Does this engine accept `startViewTransition({ update, types })`?\n *\n * The object form and the `ViewTransition.types` accessor shipped together,\n * so the accessor is the probe. Engines predating it take a bare callback \u2014\n * passing them an object would throw. A false negative costs only type-scoped\n * CSS, never the transition.\n */\nfunction supportsTransitionTypes(): boolean {\n return typeof ViewTransition !== 'undefined'\n && 'types' in ViewTransition.prototype;\n}\n\n// \u2500\u2500 Public API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Run a state update inside a view transition.\n *\n * `update` must be synchronous: everything it does happens inside the\n * browser's capture window, where the page is frozen. Keep async work\n * (loaders, fetches) outside and wrap only the commit.\n *\n * @returns the live `ViewTransition` handle (`finished`, `ready`,\n * `skipTransition()`), or `null` when the platform has no support and the\n * update was applied directly.\n */\nexport function viewTransition(\n update: () => void,\n options: ViewTransitionOptions = {},\n): ViewTransition | null {\n // The commit the browser snapshots: apply the update, then settle the\n // reactive cascade now rather than on the next microtask.\n const commit = (): void => {\n update();\n flush();\n };\n\n if (typeof document === 'undefined'\n || typeof document.startViewTransition !== 'function') {\n commit();\n return null;\n }\n\n const types = options.types;\n return types !== undefined && types.length > 0 && supportsTransitionTypes()\n ? document.startViewTransition({ update: commit, types })\n : document.startViewTransition(commit);\n}\n"],
5
+ "mappings": "AAuDA,SAAS,aAAa;AAmBtB,SAAS,0BAAmC;AAC1C,SAAO,OAAO,mBAAmB,eAC5B,WAAW,eAAe;AACjC;AAeO,SAAS,eACd,QACA,UAAiC,CAAC,GACX;AAGvB,QAAM,SAAS,MAAY;AACzB,WAAO;AACP,UAAM;AAAA,EACR;AAEA,MAAI,OAAO,aAAa,eACnB,OAAO,SAAS,wBAAwB,YAAY;AACvD,WAAO;AACP,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,QAAQ;AACtB,SAAO,UAAU,UAAa,MAAM,SAAS,KAAK,wBAAwB,IACtE,SAAS,oBAAoB,EAAE,QAAQ,QAAQ,MAAM,CAAC,IACtD,SAAS,oBAAoB,MAAM;AACzC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,32 @@
1
+ import { transformSource } from "../hmr/transform.js";
2
+ const DEFAULT_FILTER = /\.[mc]?[jt]sx?$/;
3
+ function nisliHmr(options = {}) {
4
+ const coreSpecifier = options.coreSpecifier ?? "@nisli/core";
5
+ const runtimeSpecifier = options.runtimeSpecifier ?? "@nisli/core/vite-hmr/runtime";
6
+ const filter = options.filter ?? DEFAULT_FILTER;
7
+ return {
8
+ name: "nisli-vite-hmr",
9
+ // Run on the raw TS source before Vite's own transforms rewrite imports.
10
+ enforce: "pre",
11
+ // Dev server only — never transform the production build.
12
+ apply: "serve",
13
+ transform(code, id) {
14
+ const clean = id.split("?")[0] ?? id;
15
+ if (clean.includes("node_modules")) return void 0;
16
+ if (!filter.test(clean)) return void 0;
17
+ const wrapped = transformSource(code, coreSpecifier, runtimeSpecifier);
18
+ if (wrapped === code) return void 0;
19
+ const out = `import { __drain as __nisliViteDrain } from ${JSON.stringify(runtimeSpecifier)};
20
+ ` + wrapped + `
21
+ if (import.meta.hot) {
22
+ import.meta.hot.accept(() => { __nisliViteDrain(); });
23
+ }
24
+ `;
25
+ return { code: out, map: null };
26
+ }
27
+ };
28
+ }
29
+ export {
30
+ nisliHmr
31
+ };
32
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/vite-hmr/plugin.ts"],
4
+ "sourcesContent": ["/**\n * vite-hmr/plugin.ts \u2014 Dev-only Vite plugin for Nisli HMR (ADR 0110).\n *\n * Vite plugin that wraps component() calls (shared `transformSource`),\n * but drives re-mount through Vite's native `import.meta.hot` instead of an SSE\n * hub + whole-bundle re-import. For each source module that imports `component`\n * from `@nisli/core`, it:\n * 1. wraps `component(tag, setup)` \u2192 `component(tag, __register(tag, setup))`\n * so a re-evaluated module swaps its setup in the shared registry, and\n * 2. appends `import.meta.hot.accept(() => __drain())` so Vite replaces JUST\n * this module (granular HMR) and the queued re-mounts are applied.\n *\n * Because Vite re-evaluates only the changed module against a STABLE framework\n * module, there is exactly one `@nisli/core` instance \u2014 the dual-instance\n * \"split-brain\" of whole-bundle re-import cannot occur.\n *\n * `apply: 'serve'` makes this dev-only: the production `vite build` never runs\n * the transform, so no wrapper, no registry import, and no `import.meta.hot`\n * reach the prod bundle (zero prod HMR bytes).\n */\nimport { transformSource } from '../hmr/transform.js';\n\n/**\n * Minimal structural subset of Vite's `Plugin` we implement. Declared\n * structurally (not imported from `vite`) so `@nisli/core` keeps its\n * zero-dependency footprint \u2014 `vite` is the consumer's dependency, not ours.\n */\nexport interface NisliVitePlugin {\n name: string;\n enforce?: 'pre' | 'post';\n apply?: 'serve' | 'build';\n transform(code: string, id: string): { code: string; map: null } | undefined;\n}\n\nexport interface NisliViteHmrOptions {\n /** The specifier modules import `component` from. Default `@nisli/core`. */\n coreSpecifier?: string;\n /** The runtime subpath providing `__register`/`__drain`. Default `@nisli/core/vite-hmr/runtime`. */\n runtimeSpecifier?: string;\n /** Which module ids to transform. Default: TS/JS sources. */\n filter?: RegExp;\n}\n\nconst DEFAULT_FILTER = /\\.[mc]?[jt]sx?$/;\n\n/**\n * Create the dev-only Nisli Vite HMR plugin. Add it to `plugins` in\n * `vite.config.ts`; `apply: 'serve'` keeps it off the production build path.\n */\nexport function nisliHmr(options: NisliViteHmrOptions = {}): NisliVitePlugin {\n const coreSpecifier = options.coreSpecifier ?? '@nisli/core';\n const runtimeSpecifier = options.runtimeSpecifier ?? '@nisli/core/vite-hmr/runtime';\n const filter = options.filter ?? DEFAULT_FILTER;\n\n return {\n name: 'nisli-vite-hmr',\n // Run on the raw TS source before Vite's own transforms rewrite imports.\n enforce: 'pre',\n // Dev server only \u2014 never transform the production build.\n apply: 'serve',\n transform(code: string, id: string) {\n const clean = id.split('?')[0] ?? id;\n if (clean.includes('node_modules')) return undefined;\n if (!filter.test(clean)) return undefined;\n\n const wrapped = transformSource(code, coreSpecifier, runtimeSpecifier);\n // Identity \u21D2 the module does not import `component` \u2014 not HMR-relevant.\n // Leaving it un-accepted lets Vite propagate to a full reload (correct for\n // services/utils edits).\n if (wrapped === code) return undefined;\n\n const out =\n `import { __drain as __nisliViteDrain } from ${JSON.stringify(runtimeSpecifier)};\\n` +\n wrapped +\n `\\nif (import.meta.hot) {\\n` +\n ` import.meta.hot.accept(() => { __nisliViteDrain(); });\\n` +\n `}\\n`;\n\n // map: null \u2014 the injection is an additive prepend/append on a handful of\n // component modules in DEV only; a precise map would require a sourcemap\n // dependency (magic-string), which `@nisli/core` deliberately avoids to\n // stay zero-dependency. Original statements keep their column offsets.\n return { code: out, map: null };\n },\n };\n}\n"],
5
+ "mappings": "AAoBA,SAAS,uBAAuB;AAuBhC,MAAM,iBAAiB;AAMhB,SAAS,SAAS,UAA+B,CAAC,GAAoB;AAC3E,QAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,QAAM,mBAAmB,QAAQ,oBAAoB;AACrD,QAAM,SAAS,QAAQ,UAAU;AAEjC,SAAO;AAAA,IACL,MAAM;AAAA;AAAA,IAEN,SAAS;AAAA;AAAA,IAET,OAAO;AAAA,IACP,UAAU,MAAc,IAAY;AAClC,YAAM,QAAQ,GAAG,MAAM,GAAG,EAAE,CAAC,KAAK;AAClC,UAAI,MAAM,SAAS,cAAc,EAAG,QAAO;AAC3C,UAAI,CAAC,OAAO,KAAK,KAAK,EAAG,QAAO;AAEhC,YAAM,UAAU,gBAAgB,MAAM,eAAe,gBAAgB;AAIrE,UAAI,YAAY,KAAM,QAAO;AAE7B,YAAM,MACJ,+CAA+C,KAAK,UAAU,gBAAgB,CAAC;AAAA,IAC/E,UACA;AAAA;AAAA;AAAA;AAAA;AAQF,aAAO,EAAE,MAAM,KAAK,KAAK,KAAK;AAAA,IAChC;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,8 @@
1
+ import { __register, drainRemounts, pendingRemountCount, remount } from "../hmr/registry.js";
2
+ export {
3
+ drainRemounts as __drain,
4
+ __register,
5
+ pendingRemountCount,
6
+ remount
7
+ };
8
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/vite-hmr/runtime.ts"],
4
+ "sourcesContent": ["/**\n * vite-hmr/runtime.ts \u2014 Browser runtime for Nisli HMR under Vite (ADR 0110).\n *\n * DEV-ONLY. The Vite plugin (`./plugin.ts`) injects calls to these into each\n * component module:\n * - `__register(tag, setup)` wraps `component()` so a re-evaluated module swaps\n * its setup in the shared registry and queues an in-place re-mount.\n * - `__drain()` is called from the module's `import.meta.hot.accept` hook to\n * apply the queued re-mounts.\n *\n * Vite re-evaluates ONLY the changed module against a\n * STABLE framework module \u2014 so there is exactly one `@nisli/core` instance and\n * no lifecycle/reactive split-brain. This module just re-exports the\n * transport-agnostic registry core.\n */\nexport { __register, drainRemounts as __drain, pendingRemountCount, remount } from '../hmr/registry.js';\n"],
5
+ "mappings": "AAeA,SAAS,YAA6B,eAAS,qBAAqB,eAAe;",
6
+ "names": []
7
+ }