@emkodev/emroute 1.7.2 → 1.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/emroute.js +135 -31
  2. package/dist/emroute.js.map +2 -2
  3. package/dist/runtime/abstract.runtime.d.ts +11 -0
  4. package/dist/runtime/abstract.runtime.js +53 -0
  5. package/dist/runtime/abstract.runtime.js.map +1 -1
  6. package/dist/runtime/bun/fs/bun-fs.runtime.js +3 -1
  7. package/dist/runtime/bun/fs/bun-fs.runtime.js.map +1 -1
  8. package/dist/runtime/bun/sqlite/bun-sqlite.runtime.js +3 -1
  9. package/dist/runtime/bun/sqlite/bun-sqlite.runtime.js.map +1 -1
  10. package/dist/runtime/universal/fs/universal-fs.runtime.js +3 -1
  11. package/dist/runtime/universal/fs/universal-fs.runtime.js.map +1 -1
  12. package/dist/server/build.util.js +35 -6
  13. package/dist/server/build.util.js.map +1 -1
  14. package/dist/server/emroute.server.js +17 -7
  15. package/dist/server/emroute.server.js.map +1 -1
  16. package/dist/server/server-api.type.d.ts +3 -0
  17. package/dist/src/component/abstract.component.d.ts +1 -1
  18. package/dist/src/component/abstract.component.js.map +1 -1
  19. package/dist/src/element/component.element.js +17 -3
  20. package/dist/src/element/component.element.js.map +1 -1
  21. package/dist/src/element/markdown.element.js +1 -1
  22. package/dist/src/element/markdown.element.js.map +1 -1
  23. package/dist/src/index.d.ts +1 -0
  24. package/dist/src/index.js.map +1 -1
  25. package/dist/src/renderer/spa/thin-client.js +28 -6
  26. package/dist/src/renderer/spa/thin-client.js.map +1 -1
  27. package/dist/src/renderer/ssr/html.renderer.js +1 -1
  28. package/dist/src/renderer/ssr/html.renderer.js.map +1 -1
  29. package/dist/src/renderer/ssr/md.renderer.js +2 -2
  30. package/dist/src/renderer/ssr/md.renderer.js.map +1 -1
  31. package/dist/src/renderer/ssr/ssr.renderer.js +6 -6
  32. package/dist/src/renderer/ssr/ssr.renderer.js.map +1 -1
  33. package/dist/src/route/route.core.js +21 -7
  34. package/dist/src/route/route.core.js.map +1 -1
  35. package/dist/src/type/element.type.d.ts +19 -0
  36. package/dist/src/type/element.type.js +9 -0
  37. package/dist/src/type/element.type.js.map +1 -0
  38. package/dist/src/util/widget-resolve.util.js +1 -1
  39. package/dist/src/util/widget-resolve.util.js.map +1 -1
  40. package/dist/src/widget/widget.registry.js +1 -1
  41. package/dist/src/widget/widget.registry.js.map +1 -1
  42. package/package.json +1 -1
  43. package/runtime/abstract.runtime.ts +67 -0
  44. package/runtime/bun/fs/bun-fs.runtime.ts +2 -0
  45. package/runtime/bun/sqlite/bun-sqlite.runtime.ts +2 -0
  46. package/runtime/universal/fs/universal-fs.runtime.ts +2 -0
  47. package/server/build.util.ts +37 -5
  48. package/server/emroute.server.ts +20 -6
  49. package/server/server-api.type.ts +4 -0
  50. package/src/component/abstract.component.ts +1 -1
  51. package/src/element/component.element.ts +16 -4
  52. package/src/element/markdown.element.ts +1 -1
  53. package/src/index.ts +1 -0
  54. package/src/renderer/spa/thin-client.ts +30 -5
  55. package/src/renderer/ssr/html.renderer.ts +1 -1
  56. package/src/renderer/ssr/md.renderer.ts +5 -4
  57. package/src/renderer/ssr/ssr.renderer.ts +6 -6
  58. package/src/route/route.core.ts +17 -8
  59. package/src/type/element.type.ts +22 -0
  60. package/src/util/widget-resolve.util.ts +4 -4
  61. package/src/widget/widget.registry.ts +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/util/html.util.ts", "../src/element/slot.element.ts", "../src/element/markdown.element.ts", "../src/element/component.element.ts", "../src/widget/widget.registry.ts", "../src/route/route.core.ts", "../src/route/route.trie.ts", "../src/type/logger.type.ts", "../src/util/widget-resolve.util.ts", "../src/component/abstract.component.ts", "../src/component/page.component.ts", "../src/renderer/ssr/ssr.renderer.ts", "../src/renderer/ssr/html.renderer.ts", "../src/widget/widget.parser.ts", "../src/renderer/ssr/md.renderer.ts", "../src/util/md.util.ts", "../src/route/route-tree.util.ts", "../runtime/abstract.runtime.ts", "../server/emroute.server.ts", "../runtime/fetch.runtime.ts", "../src/renderer/spa/thin-client.ts", "../src/component/widget.component.ts", "../src/overlay/overlay.css.ts", "../src/overlay/overlay.service.ts", "../src/widget/page-title.widget.ts", "../src/widget/breadcrumb.widget.ts", "../src/renderer/spa/mod.ts"],
4
- "sourcesContent": ["/**\n * Core HTML utilities for emroute\n */\n\n/** HTML attribute name marking a widget as server-rendered (skip client getData + render). */\nexport const SSR_ATTR = 'ssr';\n\n/** HTML attribute name for lazy-loading widgets via IntersectionObserver. */\nexport const LAZY_ATTR = 'lazy';\n\n/**\n * SSR-compatible ShadowRoot mock.\n * Provides a 1-to-1 subset of the browser ShadowRoot API for server-side rendering.\n */\nclass SsrShadowRoot {\n private _innerHTML = '';\n\n constructor(public readonly host: SsrHTMLElement) {}\n\n get innerHTML(): string {\n return this._innerHTML;\n }\n\n set innerHTML(value: string) {\n this._innerHTML = value;\n }\n\n setHTMLUnsafe(html: string, _options?: Record<string, unknown>): void {\n this._innerHTML = html;\n }\n\n append(..._nodes: (Node | string)[]): void {\n // On the server, append is a no-op \u2014 SSR content is already serialized via innerHTML.\n }\n\n querySelector(_selector: string): Element | null {\n return null;\n }\n\n querySelectorAll(_selector: string): Element[] {\n return [];\n }\n\n get childNodes(): Node[] {\n return [];\n }\n\n get firstChild(): Node | null {\n return null;\n }\n}\n\n/**\n * SSR-compatible HTMLElement mock.\n * Provides a 1-to-1 subset of the browser HTMLElement API for server-side rendering.\n * Methods that require DOM parsing (querySelector, childNodes) return empty results \u2014\n * SSR code should use innerHTML for content, not DOM traversal.\n */\nclass SsrHTMLElement {\n private _innerHTML = '';\n private _shadowRoot: SsrShadowRoot | null = null;\n private _attributes = new Map<string, string>();\n // Accept any CSS property assignment without error\n readonly style = new Proxy({} as CSSStyleDeclaration, {\n set(_target, _prop, _value) {\n return true;\n },\n get(_target, prop) {\n if (typeof prop === 'string') return '';\n return undefined;\n },\n });\n\n get innerHTML(): string {\n return this._innerHTML;\n }\n\n set innerHTML(value: string) {\n this._innerHTML = value;\n }\n\n get shadowRoot(): ShadowRoot | null {\n return this._shadowRoot as unknown as ShadowRoot;\n }\n\n get childNodes(): Node[] {\n return [];\n }\n\n get firstChild(): Node | null {\n return null;\n }\n\n get attributes(): NamedNodeMap {\n const attrs: Attr[] = [];\n for (const [name, value] of this._attributes) {\n attrs.push({ name, value } as Attr);\n }\n return attrs as unknown as NamedNodeMap;\n }\n\n attachShadow(_init: ShadowRootInit): ShadowRoot {\n this._shadowRoot = new SsrShadowRoot(this);\n return this._shadowRoot as unknown as ShadowRoot;\n }\n\n getAttribute(name: string): string | null {\n return this._attributes.get(name) ?? null;\n }\n\n setAttribute(name: string, value: string): void {\n this._attributes.set(name, value);\n }\n\n removeAttribute(name: string): void {\n this._attributes.delete(name);\n }\n\n hasAttribute(name: string): boolean {\n return this._attributes.has(name);\n }\n\n querySelector(_selector: string): Element | null {\n return null;\n }\n\n querySelectorAll(_selector: string): Element[] {\n return [];\n }\n\n append(..._nodes: (Node | string)[]): void {\n // No-op on server \u2014 use innerHTML for content\n }\n\n appendChild(node: Node): Node {\n return node;\n }\n}\n\n/** Server-safe base class: HTMLElement in browser, SSR mock on server. */\nexport const HTMLElementBase = globalThis.HTMLElement ??\n (SsrHTMLElement as unknown as typeof HTMLElement);\n\n/**\n * Escape HTML entities for safe display.\n */\nexport function escapeHtml(text: string): string {\n return text\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;')\n .replaceAll(\"'\", '&#39;')\n .replaceAll('`', '&#96;');\n}\n\n/**\n * Unescape HTML entities back to plain text (server-side, no DOM).\n */\nexport function unescapeHtml(text: string): string {\n return text\n .replaceAll('&#96;', '`')\n .replaceAll('&#39;', \"'\")\n .replaceAll('&quot;', '\"')\n .replaceAll('&gt;', '>')\n .replaceAll('&lt;', '<')\n .replaceAll('&amp;', '&');\n}\n\n/**\n * Wrap CSS in a `@scope` rule scoped to the widget's custom element tag.\n * Used by `WidgetComponent.renderHTML()` for companion CSS files.\n */\nexport function scopeWidgetCss(css: string, widgetName: string): string {\n return `@scope (widget-${widgetName}) {\\n${css}\\n}`;\n}\n\n/**\n * Status code to message mapping.\n */\nexport const STATUS_MESSAGES: Record<number, string> = {\n 401: 'Unauthorized',\n 403: 'Forbidden',\n 404: 'Not Found',\n 500: 'Internal Server Error',\n};\n", "/**\n * Router Slot Element\n *\n * <router-slot> is where page content is rendered.\n * Supports nested routes via parent page containing slot.\n *\n * Usage:\n * ```html\n * <router-slot></router-slot>\n * ```\n *\n * For nested routes, parent page includes:\n * ```typescript\n * export default function render() {\n * return `\n * <header>...</header>\n * <main>\n * <router-slot></router-slot>\n * </main>\n * `;\n * }\n * ```\n */\n\nimport { HTMLElementBase } from '../util/html.util.ts';\n\n/**\n * Router slot web component.\n * Serves as the mounting point for page content.\n */\nexport class RouterSlot extends HTMLElementBase {}\n", "/**\n * Markdown Element \u2014 <mark-down> custom element.\n *\n * Renders markdown content with pluggable renderer.\n * Supports:\n * - Inline content: <mark-down># Title</mark-down>\n * - Source attribute: <mark-down src=\"/path/to.md\"></mark-down>\n */\n\nimport { escapeHtml, HTMLElementBase } from '../util/html.util.ts';\nimport type { MarkdownRenderer } from '../type/markdown.type.ts';\n\nexport class MarkdownElement extends HTMLElementBase {\n private static renderer: MarkdownRenderer | null = null;\n private static rendererInitPromise: Promise<void> | null = null;\n private abortController: AbortController | null = null;\n\n /**\n * Set the markdown renderer.\n * Must be called before any <mark-down> elements are connected.\n *\n * @example\n * ```ts\n * import { createEmkoRenderer } from './emko.renderer.ts';\n * MarkdownElement.setRenderer(await createEmkoRenderer());\n * ```\n */\n static setRenderer(renderer: MarkdownRenderer): void {\n MarkdownElement.renderer = renderer;\n MarkdownElement.rendererInitPromise = renderer.init ? renderer.init() : null;\n }\n\n /** Get the current renderer (if set). Used by bootEmrouteApp to pass through to createEmrouteServer. */\n static getConfiguredRenderer(): MarkdownRenderer | null {\n return MarkdownElement.renderer;\n }\n\n /**\n * Get the current renderer, waiting for init if needed.\n */\n private static async getRenderer(): Promise<MarkdownRenderer> {\n const renderer = MarkdownElement.renderer;\n if (!renderer) {\n throw new Error(\n 'No markdown renderer configured. Call MarkdownElement.setRenderer() before using <mark-down> elements.',\n );\n }\n\n if (MarkdownElement.rendererInitPromise) {\n await MarkdownElement.rendererInitPromise;\n }\n\n return renderer;\n }\n\n async connectedCallback(): Promise<void> {\n this.abortController = new AbortController();\n await this.loadContent();\n }\n\n disconnectedCallback(): void {\n this.abortController?.abort();\n this.abortController = null;\n }\n\n private async loadContent(): Promise<void> {\n const src = this.getAttribute('src');\n const inlineContent = this.textContent?.trim();\n\n if (src) {\n await this.loadFromSrc(src);\n } else if (inlineContent) {\n await this.renderContent(inlineContent);\n } else {\n this.innerHTML = '';\n }\n }\n\n private async loadFromSrc(src: string): Promise<void> {\n const signal = this.abortController?.signal;\n\n try {\n const response = await fetch(src, { signal });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch ${src}: ${response.status}`);\n }\n\n const markdown = await response.text();\n await this.renderContent(markdown);\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n return;\n }\n this.showError(error);\n }\n }\n\n private async renderContent(markdown: string): Promise<void> {\n try {\n const renderer = await MarkdownElement.getRenderer();\n this.innerHTML = renderer.render(markdown);\n } catch (error) {\n this.showError(error);\n }\n }\n\n private showError(error: unknown): void {\n const message = error instanceof Error ? error.message : String(error);\n this.innerHTML = `<div>Markdown Error: ${escapeHtml(message)}</div>`;\n }\n}\n", "/**\n * Widget Element - Browser Custom Element\n *\n * Renders Widget instances in the browser as `widget-{name}` elements.\n * Handles:\n * - SSR hydration (ssr attribute)\n * - Client-side data fetching with AbortSignal\n * - Companion file loading (html, md, css) with caching\n * - Loading/error states\n */\n\nimport type {\n Component,\n ComponentContext,\n ContextProvider,\n} from '../component/abstract.component.ts';\nimport { HTMLElementBase, LAZY_ATTR, SSR_ATTR } from '../util/html.util.ts';\n\ntype ComponentState = 'idle' | 'loading' | 'ready' | 'error';\n\ntype WidgetFiles = { html?: string; md?: string; css?: string };\n\n/**\n * Custom element that renders a Component in the browser.\n */\nexport class ComponentElement<TParams, TData> extends HTMLElementBase {\n /** Shared file content cache \u2014 deduplicates fetches across all widget instances. */\n private static fileCache = new Map<string, Promise<string | undefined>>();\n\n /** Lazy module loaders keyed by tag name \u2014 set by registerLazy(). */\n private static lazyLoaders = new Map<string, () => Promise<unknown>>();\n\n /** Cached module promises for lazy-loaded widgets \u2014 avoids re-fetching. */\n private static lazyModules = new Map<string, Promise<unknown>>();\n\n /** App-level context provider set once during router initialization. */\n private static extendContext: ContextProvider | undefined;\n\n /** Register (or clear) the context provider that enriches every widget's ComponentContext. */\n static setContextProvider(provider: ContextProvider | undefined): void {\n ComponentElement.extendContext = provider;\n }\n\n private component: Component<TParams, TData>;\n private effectiveFiles?: WidgetFiles;\n private params: TParams | null = null;\n private data: TData | null = null;\n private context!: ComponentContext;\n private state: ComponentState = 'idle';\n private errorMessage = '';\n private deferred: PromiseWithResolvers<void> | null = null;\n private abortController: AbortController | null = null;\n private intersectionObserver: IntersectionObserver | null = null;\n\n /** Promise that resolves with fetched data (available after loadData starts) */\n dataPromise: Promise<TData | null> | null = null;\n\n constructor(component: Component<TParams, TData>, files?: WidgetFiles) {\n super();\n this.component = component;\n this.effectiveFiles = files;\n // Attach shadow root if not already present (Declarative Shadow DOM creates it from <template shadowrootmode=\"open\">)\n // This enables progressive enhancement: SSR with DSD works without JS, then hydrates when JS loads\n if (!this.shadowRoot) {\n this.attachShadow({ mode: 'open' });\n }\n }\n\n /**\n * Register a widget as a custom element: `widget-{name}`.\n * Creates a fresh widget instance per DOM element (per-element state).\n * Optional `files` parameter provides discovered file paths without mutating\n * the component instance.\n */\n static register<TP, TD>(\n component: Component<TP, TD>,\n files?: WidgetFiles,\n ): void {\n const tagName = `widget-${component.name}`;\n\n if (!globalThis.customElements || customElements.get(tagName)) {\n return;\n }\n\n const WidgetClass = component.constructor as new () => Component<TP, TD>;\n\n const BoundElement = class extends ComponentElement<TP, TD> {\n constructor() {\n super(new WidgetClass(), files);\n }\n };\n\n customElements.define(tagName, BoundElement);\n }\n\n /**\n * Register a widget class (not instance) as a custom element: `widget-{name}`.\n * Used for manifest-based registration where classes are loaded dynamically.\n */\n static registerClass<TP, TD>(\n WidgetClass: new () => Component<TP, TD>,\n name: string,\n files?: WidgetFiles,\n ): void {\n const tagName = `widget-${name}`;\n\n if (!globalThis.customElements || customElements.get(tagName)) {\n return;\n }\n\n const BoundElement = class extends ComponentElement<TP, TD> {\n constructor() {\n super(new WidgetClass(), files);\n }\n };\n\n customElements.define(tagName, BoundElement);\n }\n\n /**\n * Register a widget lazily: define the custom element immediately (so SSR\n * content via Declarative Shadow DOM is adopted), but defer loading the\n * module until connectedCallback fires. Once loaded, the real component\n * replaces the placeholder and hydration proceeds normally.\n */\n static registerLazy(\n name: string,\n files: WidgetFiles | undefined,\n loader: () => Promise<unknown>,\n ): void {\n const tagName = `widget-${name}`;\n if (!globalThis.customElements || customElements.get(tagName)) return;\n\n ComponentElement.lazyLoaders.set(tagName, loader);\n\n // Placeholder component \u2014 replaced by the real one once the module loads.\n // Cast needed because Component is abstract; the real module replaces this.\n const placeholder = {\n name,\n getData: () => Promise.resolve(null),\n renderHTML: () => '',\n renderMarkdown: () => '',\n renderError: () => '',\n renderMarkdownError: () => '',\n } as unknown as Component<unknown, unknown>;\n\n const BoundElement = class extends ComponentElement<unknown, unknown> {\n constructor() {\n super(placeholder, files);\n }\n };\n\n customElements.define(tagName, BoundElement);\n }\n\n /**\n * Promise that resolves when component is ready (data loaded and rendered).\n * Used by router to wait for async components.\n */\n get ready(): Promise<void> {\n if (this.state === 'ready') {\n return Promise.resolve();\n }\n this.deferred ??= Promise.withResolvers<void>();\n return this.deferred.promise;\n }\n\n async connectedCallback(): Promise<void> {\n // Lazy module loading \u2014 resolve actual component before proceeding\n const tagName = this.tagName.toLowerCase();\n const lazyLoader = ComponentElement.lazyLoaders.get(tagName);\n if (lazyLoader) {\n try {\n let modulePromise = ComponentElement.lazyModules.get(tagName);\n if (!modulePromise) {\n modulePromise = lazyLoader();\n ComponentElement.lazyModules.set(tagName, modulePromise);\n }\n const mod = await modulePromise as Record<string, unknown>;\n for (const exp of Object.values(mod)) {\n if (exp && typeof exp === 'object' && 'getData' in exp) {\n const WidgetClass = exp.constructor as new () => Component<TParams, TData>;\n this.component = new WidgetClass();\n break;\n }\n if (typeof exp === 'function' && (exp as { prototype?: { getData?: unknown } }).prototype?.getData) {\n this.component = new (exp as new () => Component<TParams, TData>)();\n break;\n }\n }\n } catch {\n // Module failed to load (e.g. raw .ts served without transpilation).\n // SSR content is already visible \u2014 skip hydration gracefully.\n if (this.hasAttribute(SSR_ATTR)) {\n this.removeAttribute(SSR_ATTR);\n this.signalReady();\n return;\n }\n }\n }\n\n this.component.element = this;\n this.style.contentVisibility = 'auto';\n this.abortController = new AbortController();\n const signal = this.abortController.signal;\n\n // Parse params from element attributes\n const params: Record<string, unknown> = {};\n for (const attr of this.attributes) {\n if (attr.name === SSR_ATTR || attr.name === LAZY_ATTR) continue;\n const key = attr.name.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n try {\n params[key] = JSON.parse(attr.value);\n } catch {\n params[key] = attr.value;\n }\n }\n this.params = params as TParams;\n\n // Validate params\n if (this.component.validateParams && this.params !== null) {\n const error = this.component.validateParams(this.params);\n if (error) {\n this.setError(error);\n return;\n }\n }\n\n // Load companion files (html, md, css) if declared\n const files = await this.loadFiles();\n if (signal.aborted) return;\n\n const currentUrl = globalThis.location ? new URL(location.href) : new URL('http://localhost/');\n const base: ComponentContext = {\n url: currentUrl,\n pathname: currentUrl.pathname,\n searchParams: currentUrl.searchParams,\n params: this.params ?? {},\n files: (files.html || files.md || files.css) ? files : undefined,\n };\n this.context = ComponentElement.extendContext ? ComponentElement.extendContext(base) : base;\n\n // Hydrate from SSR: adopt content from Declarative Shadow DOM\n if (this.hasAttribute(SSR_ATTR)) {\n this.removeAttribute(SSR_ATTR);\n\n // Read SSR data from light DOM (JSON text placed alongside shadow root)\n const lightText = this.textContent?.trim();\n if (lightText) {\n try {\n this.data = JSON.parse(lightText);\n } catch {\n // Not valid JSON \u2014 proceed with data: null\n }\n }\n // Clear light DOM content (JSON text)\n this.textContent = '';\n\n this.state = 'ready';\n\n // Call hydrate() hook to attach event listeners\n if (this.component.hydrate) {\n const args = { data: this.data, params: this.params!, context: this.context };\n queueMicrotask(() => {\n this.component.hydrate!(args);\n });\n }\n\n this.signalReady();\n return;\n }\n\n // Lazy: defer loadData until element is visible\n if (this.hasAttribute(LAZY_ATTR)) {\n this.intersectionObserver = new IntersectionObserver(([entry]) => {\n if (entry.isIntersecting) {\n this.intersectionObserver?.disconnect();\n this.intersectionObserver = null;\n this.loadData();\n }\n });\n this.intersectionObserver.observe(this);\n return;\n }\n\n await this.loadData();\n }\n\n disconnectedCallback(): void {\n this.component.destroy?.();\n this.component.element = undefined;\n this.intersectionObserver?.disconnect();\n this.intersectionObserver = null;\n this.abortController?.abort();\n this.abortController = null;\n this.state = 'idle';\n this.data = null;\n this.context = undefined!;\n this.dataPromise = null;\n this.errorMessage = '';\n this.signalReady();\n this.deferred = null;\n }\n\n /**\n * Reload component data. Aborts any in-flight request first.\n */\n async reload(): Promise<void> {\n if (this.params === null) return;\n\n // Abort previous and create fresh controller\n this.abortController?.abort();\n this.abortController = new AbortController();\n\n await this.loadData();\n }\n\n /**\n * Fetch a single file by path, with caching.\n * Absolute URLs (http/https) pass through; relative paths get '/' prefix.\n */\n private static loadFile(path: string): Promise<string | undefined> {\n const cached = ComponentElement.fileCache.get(path);\n if (cached) return cached;\n\n const url = path.startsWith('http://') || path.startsWith('https://')\n ? path\n : (path.startsWith('/') ? path : '/' + path);\n\n const promise = fetch(url).then(\n (res) => res.ok ? res.text() : undefined,\n () => undefined,\n );\n\n ComponentElement.fileCache.set(path, promise);\n return promise;\n }\n\n /**\n * Load all companion files for this widget instance.\n * Uses effectiveFiles (from registration) falling back to component.files.\n */\n private async loadFiles(): Promise<{ html?: string; md?: string; css?: string }> {\n const filePaths = this.effectiveFiles ?? this.component.files;\n if (!filePaths) return {};\n\n const [html, md, css] = await Promise.all([\n filePaths.html ? ComponentElement.loadFile(filePaths.html) : undefined,\n filePaths.md ? ComponentElement.loadFile(filePaths.md) : undefined,\n filePaths.css ? ComponentElement.loadFile(filePaths.css) : undefined,\n ]);\n\n return { html, md, css };\n }\n\n private async loadData(): Promise<void> {\n if (this.params === null) return;\n\n const signal = this.abortController?.signal;\n\n this.state = 'loading';\n this.render();\n\n try {\n const promise = this.component.getData({\n params: this.params,\n signal,\n context: this.context,\n });\n this.dataPromise = promise;\n this.data = await promise;\n\n // Check abort after await \u2014 don't touch DOM if disconnected\n if (signal?.aborted) return;\n\n this.state = 'ready';\n } catch (e) {\n if (e instanceof DOMException && e.name === 'AbortError') return;\n if (signal?.aborted) return;\n\n this.setError(e instanceof Error ? e.message : String(e));\n return;\n }\n\n this.render();\n this.signalReady();\n }\n\n private setError(message: string): void {\n this.state = 'error';\n this.errorMessage = message;\n this.render();\n this.signalReady(); // Ready even on error (completed loading)\n }\n\n private signalReady(): void {\n this.deferred?.resolve();\n this.deferred = null;\n }\n\n private render(): void {\n if (this.params === null) {\n this.shadowRoot!.setHTMLUnsafe('');\n return;\n }\n\n if (this.state === 'error') {\n this.shadowRoot!.setHTMLUnsafe(this.component.renderError({\n error: new Error(this.errorMessage),\n params: this.params,\n }));\n return;\n }\n\n this.shadowRoot!.setHTMLUnsafe(this.component.renderHTML({\n data: this.state === 'ready' ? this.data : null,\n params: this.params,\n context: this.context,\n }));\n\n // Call hydrate() after rendering to attach event listeners\n if (this.state === 'ready' && this.component.hydrate) {\n const args = { data: this.data, params: this.params!, context: this.context };\n queueMicrotask(() => {\n this.component.hydrate!(args);\n });\n }\n }\n}\n", "/**\n * Widget Registry\n *\n * Canonical registry where all widgets live. Used by all renderers:\n * - SSR HTML: resolves widgets by name, calls getData() + renderHTML()\n * - SSR Markdown: resolves widgets by name, calls getData() + renderMarkdown()\n * - SPA: registers custom elements for each widget\n *\n * Pages are NOT in this registry \u2014 they live in the routes manifest.\n */\n\nimport type { WidgetComponent } from '../component/widget.component.ts';\nimport type { WidgetManifestEntry, WidgetsManifest } from '../type/widget.type.ts';\n\nexport class WidgetRegistry {\n private widgets = new Map<string, WidgetComponent>();\n\n /** Register a widget by its name. */\n add(widget: WidgetComponent): void {\n this.widgets.set(widget.name, widget);\n }\n\n /** Look up a widget by name. */\n get(name: string): WidgetComponent | undefined {\n return this.widgets.get(name);\n }\n\n /** Iterate all registered widgets. */\n [Symbol.iterator](): IterableIterator<WidgetComponent> {\n return this.widgets.values();\n }\n\n /** Emit a WidgetsManifest from registered widgets. */\n toManifest(): WidgetsManifest {\n const widgets: WidgetManifestEntry[] = [];\n const moduleLoaders: Record<string, () => Promise<unknown>> = {};\n\n for (const [name, widget] of this.widgets) {\n const entry: WidgetManifestEntry = {\n name,\n modulePath: name,\n tagName: `widget-${name}`,\n files: widget.files,\n };\n widgets.push(entry);\n moduleLoaders[name] = () => Promise.resolve({ default: widget.constructor });\n }\n\n return { widgets, moduleLoaders };\n }\n}\n", "/**\n * Route Core\n *\n * Shared routing logic used by all renderers:\n * - Route matching (delegates to RouteResolver)\n * - Module loading and caching\n * - Event emission\n * - URL normalization\n * - BasePath stripping\n */\n\nimport type {\n MatchedRoute,\n RouteConfig,\n RouteInfo,\n RouteParams,\n RouterEvent,\n RouterEventListener,\n} from '../type/route.type.ts';\nimport type { ComponentContext, ContextProvider } from '../component/abstract.component.ts';\nimport type { RouteResolver, ResolvedRoute } from './route.resolver.ts';\n\n/** Base paths for the two SSR rendering endpoints. */\nexport interface BasePath {\n /** Base path for SSR HTML rendering (default: '/html') */\n html: string;\n /** Base path for SSR Markdown rendering (default: '/md') */\n md: string;\n /** Base path for PWA/SPA rendering (default: '/app') */\n app: string;\n}\n\n/** Default base paths \u2014 backward compatible with existing /html/ and /md/ prefixes. */\nexport const DEFAULT_BASE_PATH: BasePath = { html: '/html', md: '/md', app: '/app' };\n\nconst BLOCKED_PROTOCOLS = /^(javascript|data|vbscript):/i;\n\n/** Throw if a redirect URL uses a dangerous protocol. */\nexport function assertSafeRedirect(url: string): void {\n if (BLOCKED_PROTOCOLS.test(url.trim())) {\n throw new Error(`Unsafe redirect URL blocked: ${url}`);\n }\n}\n\n/** Default root route \u2014 renders a slot for child routes. */\nexport const DEFAULT_ROOT_ROUTE: RouteConfig = {\n pattern: '/',\n type: 'page',\n modulePath: '__default_root__',\n};\n\n/** Synthesize a RouteConfig from a ResolvedRoute (bridge for renderer compatibility). */\nfunction toRouteConfig(resolved: ResolvedRoute): RouteConfig {\n const node = resolved.node;\n return {\n pattern: resolved.pattern,\n type: node.redirect ? 'redirect' : 'page',\n modulePath: node.redirect ?? node.files?.ts ?? node.files?.js ?? node.files?.html ?? node.files?.md ?? '',\n files: node.files,\n };\n}\n\n/** Options for RouteCore */\nexport interface RouteCoreOptions {\n /**\n * Read a companion file (.html, .md, .css) by path \u2014 returns its text content.\n * SSR: `(path) => runtime.query(path, { as: 'text' })`.\n * SPA default: `fetch(path, { headers: { Accept: 'text/plain' } }).then(r => r.text())`.\n */\n fileReader?: (path: string) => Promise<string>;\n /** Enriches every ComponentContext with app-level services before it reaches components. */\n extendContext?: ContextProvider;\n /** Module loaders keyed by path \u2014 server provides these for SSR imports. */\n moduleLoaders?: Record<string, () => Promise<unknown>>;\n}\n\n/**\n * Core router functionality shared across all rendering contexts.\n */\nexport class RouteCore {\n private readonly resolver: RouteResolver;\n /** Registered context provider (if any). Exposed so renderers can apply it to inline contexts. */\n readonly contextProvider: ContextProvider | undefined;\n private listeners: Set<RouterEventListener> = new Set();\n private moduleCache: Map<string, unknown> = new Map();\n private widgetFileCache: Map<string, string> = new Map();\n private moduleLoaders: Record<string, () => Promise<unknown>>;\n currentRoute: MatchedRoute | null = null;\n private readFile: (path: string) => Promise<string>;\n\n constructor(resolver: RouteResolver, options: RouteCoreOptions = {}) {\n this.resolver = resolver;\n this.readFile = options.fileReader ??\n ((path) => fetch(path, { headers: { Accept: 'text/plain' } }).then((r) => r.text()));\n this.contextProvider = options.extendContext;\n this.moduleLoaders = options.moduleLoaders ?? {};\n }\n\n /**\n * Get current route parameters.\n */\n getParams(): RouteParams {\n return this.currentRoute?.params ?? {};\n }\n\n /**\n * Add event listener for router events.\n */\n addEventListener(listener: RouterEventListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n /**\n * Emit router event to listeners.\n */\n emit(event: RouterEvent): void {\n for (const listener of this.listeners) {\n try {\n listener(event);\n } catch (e) {\n console.error('[Router] Event listener error:', e);\n }\n }\n }\n\n /**\n * Match a URL to a route.\n * Falls back to the default root route for '/'.\n */\n match(url: URL): MatchedRoute | undefined {\n const pathname = url.pathname;\n\n const resolved = this.resolver.match(pathname);\n if (resolved) {\n return {\n route: toRouteConfig(resolved),\n params: resolved.params,\n };\n }\n\n if (pathname === '/' || pathname === '') {\n return {\n route: DEFAULT_ROOT_ROUTE,\n params: {},\n };\n }\n\n return undefined;\n }\n\n /** Get status-specific page (404, 401, 403). */\n getStatusPage(status: number): RouteConfig | undefined {\n const node = this.resolver.findRoute(`/${status}`);\n if (!node) return undefined;\n return {\n pattern: `/${status}`,\n type: 'page',\n modulePath: node.files?.ts ?? node.files?.js ?? node.files?.html ?? node.files?.md ?? '',\n files: node.files,\n };\n }\n\n /** Get global error handler (root errorBoundary). */\n getErrorHandler(): RouteConfig | undefined {\n const modulePath = this.resolver.findErrorBoundary('/');\n if (!modulePath) return undefined;\n return { pattern: '/', type: 'error', modulePath };\n }\n\n /**\n * Find error boundary for a given pathname.\n * Note: pattern is the input pathname, not the boundary's own pattern.\n * Callers should only rely on modulePath.\n */\n findErrorBoundary(pathname: string): { pattern: string; modulePath: string } | undefined {\n const modulePath = this.resolver.findErrorBoundary(pathname);\n if (!modulePath) return undefined;\n return { pattern: pathname, modulePath };\n }\n\n /**\n * Find a route by its exact pattern.\n * Used for building route hierarchy.\n */\n findRoute(pattern: string): RouteConfig | undefined {\n const node = this.resolver.findRoute(pattern);\n if (!node) return undefined;\n return {\n pattern,\n type: node.redirect ? 'redirect' : 'page',\n modulePath: node.redirect ?? node.files?.ts ?? node.files?.js ?? node.files?.html ?? node.files?.md ?? '',\n files: node.files,\n };\n }\n\n /**\n * Build route hierarchy from a pattern.\n * Patterns are always unprefixed (no basePath).\n *\n * e.g., '/projects/:id/tasks'\n * \u2192 ['/', '/projects', '/projects/:id', '/projects/:id/tasks']\n */\n buildRouteHierarchy(pattern: string): string[] {\n if (pattern === '/') {\n return ['/'];\n }\n\n const segments = pattern.split('/').filter(Boolean);\n\n const hierarchy: string[] = ['/'];\n let current = '';\n for (const segment of segments) {\n current += '/' + segment;\n hierarchy.push(current);\n }\n\n return hierarchy;\n }\n\n /**\n * Normalize URL by removing trailing slashes (except bare '/').\n */\n normalizeUrl(url: string): string {\n if (url.length > 1 && url.endsWith('/')) {\n return url.slice(0, -1);\n }\n return url;\n }\n\n /**\n * Convert relative path to absolute path.\n */\n toAbsolutePath(path: string): string {\n return path.startsWith('/') ? path : '/' + path;\n }\n\n /**\n * Load a module with caching.\n * Uses pre-bundled loaders when available, falls back to dynamic import.\n */\n async loadModule<T>(modulePath: string): Promise<T> {\n if (this.moduleCache.has(modulePath)) {\n return this.moduleCache.get(modulePath) as T;\n }\n\n let module: unknown;\n const loader = this.moduleLoaders[modulePath];\n if (loader) {\n module = await loader();\n } else {\n const absolutePath = this.toAbsolutePath(modulePath);\n module = await import(absolutePath);\n }\n\n this.moduleCache.set(modulePath, module);\n return module as T;\n }\n\n /**\n * Load widget file contents with caching.\n */\n async loadWidgetFiles(\n widgetFiles: { html?: string; md?: string; css?: string },\n ): Promise<{ html?: string; md?: string; css?: string }> {\n const load = async (path: string): Promise<string | undefined> => {\n const absPath = this.toAbsolutePath(path);\n const cached = this.widgetFileCache.get(absPath);\n if (cached !== undefined) return cached;\n\n try {\n const content = await this.readFile(absPath);\n this.widgetFileCache.set(absPath, content);\n return content;\n } catch (e) {\n console.warn(\n `[RouteCore] Failed to load widget file ${path}:`,\n e instanceof Error ? e.message : e,\n );\n return undefined;\n }\n };\n\n const [html, md, css] = await Promise.all([\n widgetFiles.html ? load(widgetFiles.html) : undefined,\n widgetFiles.md ? load(widgetFiles.md) : undefined,\n widgetFiles.css ? load(widgetFiles.css) : undefined,\n ]);\n\n return { html, md, css };\n }\n\n /**\n * Build a RouteInfo from a matched route and the resolved URL pathname.\n * Called once per navigation; the result is reused across the route hierarchy.\n */\n toRouteInfo(matched: MatchedRoute, url: URL): RouteInfo {\n return {\n url,\n params: matched.params,\n };\n }\n\n /**\n * Get inlined `__files` from a cached module (merged module pattern).\n * Returns undefined if the module isn't cached or has no __files.\n */\n getModuleFiles(modulePath: string): { html?: string; md?: string; css?: string } | undefined {\n const cached = this.moduleCache.get(modulePath);\n if (!cached || typeof cached !== 'object') return undefined;\n const files = (cached as Record<string, unknown>).__files;\n if (!files || typeof files !== 'object') return undefined;\n return files as { html?: string; md?: string; css?: string };\n }\n\n /**\n * Build a ComponentContext by extending RouteInfo with loaded file contents.\n *\n * When the route module is a merged module (contains `__files`), uses\n * inlined content directly. Otherwise falls back to reading companion files.\n */\n async buildComponentContext(\n routeInfo: RouteInfo,\n route: RouteConfig,\n signal?: AbortSignal,\n isLeaf?: boolean,\n ): Promise<ComponentContext> {\n const rf = route.files;\n const modulePath = rf?.ts ?? rf?.js;\n\n // Try inlined __files from merged module (already cached by loadRouteContent)\n const inlined = modulePath ? this.getModuleFiles(modulePath) : undefined;\n\n let html: string | undefined;\n let md: string | undefined;\n let css: string | undefined;\n\n if (inlined) {\n html = inlined.html;\n md = inlined.md;\n css = inlined.css;\n } else {\n const fetchFile = (filePath: string): Promise<string> =>\n this.readFile(this.toAbsolutePath(filePath));\n [html, md, css] = await Promise.all([\n rf?.html ? fetchFile(rf.html) : undefined,\n rf?.md ? fetchFile(rf.md) : undefined,\n rf?.css ? fetchFile(rf.css) : undefined,\n ]);\n }\n\n const base: ComponentContext = {\n ...routeInfo,\n pathname: routeInfo.url.pathname,\n searchParams: routeInfo.url.searchParams,\n files: { html, md, css },\n signal,\n isLeaf,\n };\n return this.contextProvider ? this.contextProvider(base) : base;\n }\n}\n", "/**\n * Route Trie\n *\n * Segment-based trie implementing RouteResolver for O(depth) route matching.\n *\n * Each URL segment maps to a trie node. Nodes are tried in order:\n * static \u2192 dynamic (:param) \u2192 wildcard (:rest*). Backtracking handles\n * cases where a dynamic path leads to a dead end but a wildcard at an\n * ancestor would match.\n *\n * Static segment matching is case-sensitive, per RFC 3986.\n *\n * Accepts a RouteNode tree (the JSON-serializable manifest from Runtime)\n * and converts it to an internal trie with Map-based static children for\n * O(1) segment lookup.\n */\n\nimport type { RouteNode } from '../type/route-tree.type.ts';\nimport type { RouteResolver, ResolvedRoute } from './route.resolver.ts';\n\n/** Internal trie node with Map for O(1) static child lookup. */\ninterface TrieNode {\n /** RouteNode when this node is a terminal route. */\n route?: RouteNode;\n /** Reconstructed pattern for this node (e.g. \"/projects/:id\"). */\n pattern?: string;\n /** Error boundary module path scoped to this prefix. */\n errorBoundary?: string;\n /** Static children keyed by exact segment. */\n static: Map<string, TrieNode>;\n /** Dynamic child for single-segment params (:param). */\n dynamic?: { param: string; node: TrieNode };\n /** Wildcard child for catch-all params (:rest*). */\n wildcard?: { param: string; node: TrieNode };\n}\n\nfunction createNode(): TrieNode {\n return { static: new Map() };\n}\n\n/** Try decodeURIComponent, return the original segment on malformed input. */\nfunction safeDecode(segment: string): string {\n try {\n return decodeURIComponent(segment);\n } catch {\n return segment;\n }\n}\n\n/**\n * Split a normalized pathname into segments.\n * Assumes leading slash, no trailing slash. Must NOT be called with '/'.\n */\nfunction splitSegments(pathname: string): string[] {\n return pathname.substring(1).split('/');\n}\n\n/**\n * Convert a RouteNode tree into a TrieNode tree.\n * Recursively walks the RouteNode, converting Record children to Map\n * and reconstructing URL patterns at each node.\n */\nfunction convertNode(source: RouteNode, pattern: string): TrieNode {\n const node = createNode();\n\n // Terminal route (has files or redirect)\n if (source.files || source.redirect) {\n node.route = source;\n node.pattern = pattern;\n }\n\n // Error boundary\n if (source.errorBoundary) {\n node.errorBoundary = source.errorBoundary;\n }\n\n // Static children\n if (source.children) {\n for (const [segment, child] of Object.entries(source.children)) {\n const childPattern = pattern === '/' ? `/${segment}` : `${pattern}/${segment}`;\n node.static.set(segment, convertNode(child, childPattern));\n }\n }\n\n // Dynamic child\n if (source.dynamic) {\n const { param, child } = source.dynamic;\n const childPattern = pattern === '/' ? `/:${param}` : `${pattern}/:${param}`;\n node.dynamic = { param, node: convertNode(child, childPattern) };\n }\n\n // Wildcard child\n if (source.wildcard) {\n const { param, child } = source.wildcard;\n const childPattern = pattern === '/' ? `/:${param}*` : `${pattern}/:${param}*`;\n node.wildcard = { param, node: convertNode(child, childPattern) };\n }\n\n return node;\n}\n\n/**\n * Trie-based route resolver.\n *\n * Implements RouteResolver with O(depth) matching by walking the trie.\n * Constructed from a RouteNode tree (produced by Runtime.scanRoutes).\n */\nexport class RouteTrie implements RouteResolver {\n private readonly root: TrieNode;\n\n constructor(tree: RouteNode) {\n this.root = convertNode(tree, '/');\n }\n\n match(pathname: string): ResolvedRoute | undefined {\n // Normalize: strip trailing slash (except bare '/')\n if (pathname.length > 1 && pathname.endsWith('/')) {\n pathname = pathname.slice(0, -1);\n }\n\n if (!pathname.startsWith('/')) {\n pathname = '/' + pathname;\n }\n\n if (pathname === '/') {\n if (this.root.route) {\n return { node: this.root.route, pattern: '/', params: {} };\n }\n return undefined;\n }\n\n const segments = splitSegments(pathname);\n return this.walk(this.root, segments, 0, {});\n }\n\n findErrorBoundary(pathname: string): string | undefined {\n if (pathname.length > 1 && pathname.endsWith('/')) {\n pathname = pathname.slice(0, -1);\n }\n if (!pathname.startsWith('/')) {\n pathname = '/' + pathname;\n }\n\n if (pathname === '/') return this.root.errorBoundary;\n\n const segments = splitSegments(pathname);\n return this.walkForBoundary(this.root, segments, 0, this.root.errorBoundary);\n }\n\n findRoute(pattern: string): RouteNode | undefined {\n if (pattern === '/') {\n return this.root.route;\n }\n\n const segments = splitSegments(pattern);\n let node = this.root;\n\n for (const segment of segments) {\n let child: TrieNode | undefined;\n\n if (segment.startsWith(':') && segment.endsWith('*')) {\n child = node.wildcard?.node;\n } else if (segment.startsWith(':')) {\n child = node.dynamic?.node;\n } else {\n child = node.static.get(segment);\n }\n\n if (!child) return undefined;\n node = child;\n }\n\n return node.route;\n }\n\n // \u2500\u2500 Private matching \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 private walk(\n node: TrieNode,\n segments: string[],\n index: number,\n params: Record<string, string>,\n ): ResolvedRoute | undefined {\n if (index === segments.length) {\n if (node.route) {\n return { node: node.route, pattern: node.pattern!, params: { ...params } };\n }\n if (node.wildcard?.node.route) {\n return {\n node: node.wildcard.node.route,\n pattern: node.wildcard.node.pattern!,\n params: { ...params, [node.wildcard.param]: '' },\n };\n }\n return undefined;\n }\n\n const segment = segments[index];\n\n // 1. Try static child\n const staticChild = node.static.get(segment);\n if (staticChild) {\n const result = this.walk(staticChild, segments, index + 1, params);\n if (result) return result;\n }\n\n // 2. Try dynamic child (single segment)\n if (node.dynamic) {\n const { param, node: dynamicNode } = node.dynamic;\n params[param] = safeDecode(segment);\n const result = this.walk(dynamicNode, segments, index + 1, params);\n if (result) return result;\n delete params[param];\n }\n\n // 3. Try wildcard (consumes all remaining segments)\n if (node.wildcard?.node.route) {\n const { param, node: wildcardNode } = node.wildcard;\n let rest = safeDecode(segments[index]);\n for (let i = index + 1; i < segments.length; i++) {\n rest += '/' + safeDecode(segments[i]);\n }\n return {\n node: wildcardNode.route!,\n pattern: wildcardNode.pattern!,\n params: { ...params, [param]: rest },\n };\n }\n\n return undefined;\n }\n\n /**\n * Walk for error boundary. Follows the same priority as match\n * (static \u2192 dynamic \u2192 wildcard) without backtracking across branches.\n * Returns the deepest error boundary module path found along the path.\n */\n private walkForBoundary(\n node: TrieNode,\n segments: string[],\n index: number,\n deepest: string | undefined,\n ): string | undefined {\n if (index === segments.length) {\n return node.errorBoundary ?? deepest;\n }\n\n const segment = segments[index];\n\n const staticChild = node.static.get(segment);\n if (staticChild) {\n return this.walkForBoundary(staticChild, segments, index + 1, staticChild.errorBoundary ?? deepest);\n }\n\n if (node.dynamic) {\n return this.walkForBoundary(node.dynamic.node, segments, index + 1, node.dynamic.node.errorBoundary ?? deepest);\n }\n\n if (node.wildcard) {\n return node.wildcard.node.errorBoundary ?? deepest;\n }\n\n return deepest;\n }\n}\n", "/**\n * Logger Interface\n *\n * Minimal pluggable logger for surfacing errors from silent catch blocks.\n * Structurally compatible with hardkore's StructuredLogger \u2014 any instance\n * of that class satisfies this interface without an explicit dependency.\n *\n * Default: no-op (silent degradation). Call setLogger() at startup to wire in.\n */\nexport interface Logger {\n error(msg: string, error?: Error): void;\n warn(msg: string): void;\n}\n\nconst noop = () => {};\n\n/** Module-level logger. Always callable \u2014 defaults to no-op. */\nexport const logger: Logger = { error: noop, warn: noop };\n\n/** Replace the logger implementation. Call once at startup. */\nexport function setLogger(impl: Logger): void {\n logger.error = impl.error.bind(impl);\n logger.warn = impl.warn.bind(impl);\n}\n", "/**\n * Widget Resolve Utilities\n *\n * Server-side resolution of <widget-*> tags in HTML.\n * Calls getData() + renderHTML() on widgets and injects SSR hydration data.\n */\n\nimport type { Component, ContextProvider } from '../component/abstract.component.ts';\nimport { logger } from '../type/logger.type.ts';\nimport type { RouteInfo } from '../type/route.type.ts';\nimport { LAZY_ATTR, SSR_ATTR } from './html.util.ts';\n\n/** Maximum nesting depth for widgets to prevent infinite loops */\nexport const MAX_WIDGET_DEPTH = 10;\n\n/**\n * Recursively resolve widgets in content with depth limit.\n *\n * Generic utility used by both HTML and Markdown widget resolution.\n * Each depth level processes all widgets concurrently, then recurses\n * into each rendered result to resolve nested widgets.\n *\n * @param content - Content containing widgets\n * @param parse - Find widgets in content\n * @param resolve - Resolve a single widget to rendered output\n * @param replace - Replace widgets with resolved content\n * @param depth - Current recursion depth (internal)\n * @returns Content with all widgets recursively resolved\n */\nexport async function resolveRecursively<T>(\n content: string,\n parse: (content: string) => T[],\n resolve: (widget: T) => Promise<string>,\n replace: (content: string, replacements: Map<T, string>) => string,\n depth = 0,\n): Promise<string> {\n if (depth >= MAX_WIDGET_DEPTH) {\n logger.warn(\n `Widget nesting depth limit reached (${MAX_WIDGET_DEPTH}). ` +\n 'Possible circular dependency or excessive nesting.',\n );\n return content;\n }\n\n const widgets = parse(content);\n if (widgets.length === 0) return content;\n\n const replacements = new Map<T, string>();\n await Promise.all(\n widgets.map(async (widget) => {\n let rendered = await resolve(widget);\n\n // Recursively resolve any nested widgets in the rendered output\n rendered = await resolveRecursively(rendered, parse, resolve, replace, depth + 1);\n\n replacements.set(widget, rendered);\n }),\n );\n\n return replace(content, replacements);\n}\n\n/**\n * Resolve <widget-*> tags in HTML by calling getData() + renderHTML()\n * via the widget registry. Injects rendered content and boolean ssr attribute.\n *\n * Supports nested widgets: if a widget's renderHTML() returns HTML containing\n * other <widget-*> tags, those will be resolved recursively up to MAX_WIDGET_DEPTH.\n *\n * Before: <widget-crypto-price coin=\"bitcoin\"></widget-crypto-price>\n * After: <widget-crypto-price coin=\"bitcoin\" ssr><template shadowrootmode=\"open\"><span>$42,000</span></template></widget-crypto-price>\n *\n * When a widget has `exposeSsrData = true`, the getData() result is serialized\n * as JSON text in the light DOM (alongside the shadow root template):\n * After: <widget-crypto-price coin=\"bitcoin\" ssr><template shadowrootmode=\"open\"><span>$42,000</span></template>{\"price\":42000}</widget-crypto-price>\n */\nexport function resolveWidgetTags(\n html: string,\n registry: { get(name: string): Component | undefined },\n routeInfo: RouteInfo,\n loadFiles?: (\n widgetName: string,\n declaredFiles?: { html?: string; md?: string; css?: string },\n ) => Promise<{ html?: string; md?: string; css?: string }>,\n contextProvider?: ContextProvider,\n): Promise<string> {\n const tagPattern =\n /<widget-(?<name>[a-z][a-z0-9-]*)(?<attrs>\\s[^>]*)?>(?<content>.*?)<\\/widget-\\k<name>>/gis;\n\n // Wrapping info stored per-match so replace() can apply it after recursion\n const wrappers = new Map<RegExpExecArray, { tagName: string; attrs: string; ssrData: string }>();\n\n // Matches standalone ssr attribute (boolean or with value), not as substring of another value\n const ssrAttrPattern = new RegExp(`\\\\s${SSR_ATTR}(?:\\\\s|=|$)`);\n\n // Parse: find unprocessed widget tags\n const parse = (content: string) => {\n const matches = content.matchAll(tagPattern).toArray();\n return matches.filter((match) => {\n const attrsString = match.groups!.attrs || '';\n return !ssrAttrPattern.test(attrsString);\n });\n };\n\n // Resolve: render a single widget's inner content (no outer tag wrapping \u2014 that's in replace)\n const resolve = async (match: RegExpExecArray): Promise<string> => {\n const widgetName = match.groups!.name;\n const attrsString = match.groups!.attrs?.trim() ?? '';\n const widget = registry.get(widgetName);\n\n if (!widget) return match[0]; // no widget found \u2014 leave original tag as-is\n\n const params = parseAttrsToParams(attrsString);\n\n try {\n let files: { html?: string; md?: string; css?: string } | undefined;\n if (loadFiles) {\n files = await loadFiles(widgetName, widget.files);\n }\n\n const baseContext = {\n ...routeInfo,\n pathname: routeInfo.url.pathname,\n searchParams: routeInfo.url.searchParams,\n files,\n };\n const context = contextProvider ? contextProvider(baseContext) : baseContext;\n\n const data = await widget.getData({ params, context });\n const rendered = widget.renderHTML({ data, params, context });\n\n // Store wrapping info \u2014 applied in replace() after recursion resolves nested widgets\n wrappers.set(match, {\n tagName: `widget-${widgetName}`,\n attrs: attrsString ? ` ${attrsString}` : '',\n ssrData: widget.exposeSsrData ? escapeAttr(JSON.stringify(data)) : '',\n });\n\n return rendered;\n } catch (e) {\n logger.error(\n `[SSR HTML] Widget \"${widgetName}\" render failed`,\n e instanceof Error ? e : undefined,\n );\n return match[0]; // render failed \u2014 leave original tag as-is\n }\n };\n\n // Replace: wrap resolved content in outer tag + DSD template, then substitute by index\n const replace = (content: string, replacements: Map<RegExpExecArray, string>) => {\n let result = content;\n const entries = [...replacements.entries()].sort((a, b) => b[0].index! - a[0].index!);\n for (const [match, innerHtml] of entries) {\n const start = match.index!;\n const end = start + match[0].length;\n const wrap = wrappers.get(match);\n const lightDomData = wrap?.ssrData ? wrap.ssrData : '';\n const replacement = wrap\n ? `<${wrap.tagName}${wrap.attrs} ${SSR_ATTR}><template shadowrootmode=\"open\">${innerHtml}</template>${lightDomData}</${wrap.tagName}>`\n : innerHtml; // no wrapper = unresolved widget, innerHtml is the original tag\n result = result.slice(0, start) + replacement + result.slice(end);\n }\n return result;\n };\n\n return resolveRecursively(html, parse, resolve, replace);\n}\n\n/** Parse HTML attribute string into params object (kebab\u2192camelCase, JSON.parse with string fallback). */\nexport function parseAttrsToParams(attrsString: string): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n if (!attrsString) return params;\n\n const attrPattern =\n /(?<attr>[a-z][a-z0-9-]*)(?:=\"(?<dq>[^\"]*)\"|='(?<sq>[^']*)'|=(?<uq>[^\\s>]+))?/gi;\n for (const match of attrsString.matchAll(attrPattern)) {\n const { attr: attrName, dq, sq, uq } = match.groups!;\n if (attrName === SSR_ATTR || attrName === LAZY_ATTR) continue;\n const key = attrName.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n const rawValue = dq ?? sq ?? uq;\n if (rawValue === undefined) {\n params[key] = '';\n continue;\n }\n const raw = rawValue.replaceAll('&amp;', '&').replaceAll('&#39;', \"'\").replaceAll(\n '&quot;',\n '\"',\n );\n try {\n params[key] = JSON.parse(raw);\n } catch {\n params[key] = raw;\n }\n }\n\n return params;\n}\n\n/** Escape a value for use in a single-quoted HTML attribute. */\nfunction escapeAttr(value: string): string {\n return value.replaceAll('&', '&amp;').replaceAll(\"'\", '&#39;');\n}\n", "/**\n * Unified Component Architecture\n *\n * Everything is a Component: pages and widgets.\n * Components render differently based on context:\n * - /md/* \u2192 Markdown (LLMs, text clients)\n * - /html/* \u2192 Pre-rendered HTML (SSR)\n * - SPA \u2192 Hydrated custom elements\n *\n * Precedence (like .ts/.html/.md):\n * - renderHTML() if defined \u2192 full HTML control\n * - renderMarkdown() \u2192 converted to HTML via markdown renderer\n */\n\nimport type { RouteInfo } from '../type/route.type.ts';\nimport { escapeHtml } from '../util/html.util.ts';\n\n/**\n * Context passed to components during rendering.\n * Extends RouteInfo (pathname, pattern, params)\n * with pre-loaded file content and an abort signal.\n *\n * Consumers can extend this interface via module augmentation\n * to add app-level services (RPC clients, auth, feature flags, etc.).\n */\n/** Shape of companion file contents (html, md, css). Used by generated `.page.files.g.ts` modules. */\nexport type FileContents = { html?: string; md?: string; css?: string };\n\nexport interface ComponentContext extends RouteInfo {\n /** @deprecated Use context.url.pathname */\n readonly pathname: string;\n /** @deprecated Use context.url.searchParams */\n readonly searchParams: URLSearchParams;\n readonly files?: Readonly<FileContents>;\n readonly signal?: AbortSignal;\n /** True when this component is the leaf (matched) route, false when rendered as a layout parent. */\n readonly isLeaf?: boolean;\n}\n\n/**\n * Callback that enriches the base ComponentContext with app-level services.\n * Registered once at router creation; called for every context construction.\n *\n * **1. Register** \u2014 always spread `base` to preserve routing/file/signal data:\n * ```ts\n * createSpaHtmlRouter(manifest, {\n * extendContext: (base) => ({ ...base, rpc: myRpcClient }),\n * });\n * ```\n *\n * **2. Access** \u2014 expose custom properties to components via module augmentation:\n * ```ts\n * declare module '@emkodev/emroute' {\n * interface ComponentContext { rpc: RpcClient; }\n * }\n * ```\n * or per-component via the third generic:\n * ```ts\n * class MyPage extends PageComponent<Params, Data, AppContext> {}\n * ```\n */\nexport type ContextProvider = (base: ComponentContext) => ComponentContext;\n\n/**\n * Render context determines how components are rendered.\n */\nexport type RenderContext = 'markdown' | 'html' | 'spa';\n\n/**\n * Abstract base class for all components.\n *\n * Subclasses must implement:\n * - name: unique identifier for custom element tag\n * - getData(): fetch/compute data\n * - renderMarkdown(): render as markdown\n *\n * Optional override:\n * - renderHTML(): custom HTML rendering (defaults to markdown\u2192HTML conversion)\n * - validateParams(): params validation\n *\n * @typeParam TContext \u2014 custom context shape; defaults to ComponentContext.\n * Use with `extendContext` on the router to inject app-level services.\n * See {@link ContextProvider} for details.\n */\nexport abstract class Component<\n TParams = unknown,\n TData = unknown,\n TContext extends ComponentContext = ComponentContext,\n> {\n /** Type carrier for getData args \u2014 use as `this['DataArgs']` in overrides. */\n declare readonly DataArgs: {\n params: TParams;\n signal?: AbortSignal;\n context: TContext;\n };\n\n /** Type carrier for render args \u2014 use as `this['RenderArgs']` in overrides. */\n declare readonly RenderArgs: {\n data: TData | null;\n params: TParams;\n context: TContext;\n };\n\n /** Unique name in kebab-case. Used for custom element: `<widget-{name}>` */\n abstract readonly name: string;\n\n /** Host element reference, set by ComponentElement in the browser. */\n element?: HTMLElement;\n\n /** Associated file paths for pre-loaded content (html, md, css). */\n readonly files?: { html?: string; md?: string; css?: string };\n\n /**\n * When true, SSR serializes the getData() result into the element's\n * light DOM so the client can access it immediately in hydrate()\n * without re-fetching.\n *\n * Default is false \u2014 hydrate() receives `data: null`. Most widgets\n * don't need this because the rendered Shadow DOM already contains\n * the visual representation of the data.\n *\n * If you find yourself parsing the shadow DOM in hydrate() trying to\n * reconstruct the original data object, set this to true instead.\n * The server-fetched data will be available as `args.data` in hydrate().\n */\n readonly exposeSsrData?: boolean;\n\n /**\n * Fetch or compute data based on params.\n * Called server-side for SSR, client-side for SPA.\n *\n * @example\n * ```ts\n * override async getData({ params, signal }: this['DataArgs']) {\n * const res = await fetch(`/api/${params.id}`, { signal });\n * return res.json();\n * }\n * ```\n */\n abstract getData(args: this['DataArgs']): Promise<TData | null>;\n\n /**\n * Render as markdown.\n * This is the canonical content representation.\n *\n * @example\n * ```ts\n * override renderMarkdown({ data }: this['RenderArgs']) {\n * return `# ${data?.title}`;\n * }\n * ```\n */\n abstract renderMarkdown(args: this['RenderArgs']): string;\n\n /**\n * Render as HTML for browser context.\n *\n * Default implementation converts renderMarkdown() output to HTML.\n * Override for custom HTML rendering with rich styling/interactivity.\n */\n renderHTML(args: this['RenderArgs']): string {\n if (args.data === null) {\n return `<div data-component=\"${this.name}\">Loading...</div>`;\n }\n // Default: wrap markdown in a container\n // The actual markdown\u2192HTML conversion happens at render time\n const markdown = this.renderMarkdown({\n data: args.data,\n params: args.params,\n context: args.context,\n });\n return `<div data-component=\"${this.name}\" data-markdown>${escapeHtml(markdown)}</div>`;\n }\n\n /**\n * Hydration hook called after SSR content is adopted or after SPA rendering.\n * Use to attach event listeners to existing DOM without re-rendering.\n *\n * @example\n * ```ts\n * override hydrate({ data, params, context }: this['RenderArgs']) {\n * const button = this.element?.querySelector('button');\n * button?.addEventListener('click', () => this.deleteItem(data.id));\n * }\n * ```\n */\n hydrate?(args: this['RenderArgs']): void;\n\n /**\n * Cleanup hook called when the component is removed from the DOM.\n * Use for clearing timers, removing event listeners, unmounting\n * third-party renderers, closing connections, etc.\n *\n * Intentionally synchronous (called from disconnectedCallback). You can\n * fire async cleanup here, but it will not be awaited.\n */\n destroy?(): void;\n\n /**\n * Validate params.\n * @returns Error message if invalid, undefined if valid.\n */\n validateParams?(params: TParams): string | undefined;\n\n /**\n * Render error state.\n */\n renderError(args: { error: unknown; params: TParams }): string {\n const msg = args.error instanceof Error ? args.error.message : String(args.error);\n return `<div data-component=\"${this.name}\">Error: ${escapeHtml(msg)}</div>`;\n }\n\n /**\n * Render error as markdown.\n */\n renderMarkdownError(error: unknown): string {\n const msg = error instanceof Error ? error.message : String(error);\n return `> **Error** (\\`${this.name}\\`): ${msg}`;\n }\n}\n\n/**\n * Component manifest entry for code generation.\n */\nexport interface ComponentManifestEntry {\n name: string;\n modulePath: string;\n tagName: string;\n type: 'page' | 'widget';\n pattern?: string;\n}\n", "/**\n * Page Component\n *\n * Page component \u2014 params come from URL, context carries file content.\n *\n * Default implementations follow the fallback table:\n * - renderHTML: html file \u2192 md via <mark-down> \u2192 <router-slot /> (non-leaf only)\n * - renderMarkdown: md file \u2192 ```router-slot\\n``` (non-leaf only)\n * - getData: no-op (returns null)\n */\n\nimport { Component, type ComponentContext } from './abstract.component.ts';\nimport { escapeHtml } from '../util/html.util.ts';\n\nexport class PageComponent<\n TParams extends Record<string, string> = Record<string, string>,\n TData = unknown,\n TContext extends ComponentContext = ComponentContext,\n> extends Component<TParams, TData, TContext> {\n override readonly name: string = 'page';\n\n /** Route pattern this page handles (optional \u2014 set by subclasses) */\n readonly pattern?: string;\n\n /**\n * Fetch or compute page data. Override in subclasses.\n * Default: returns null (no data needed).\n *\n * @example\n * ```ts\n * override getData({ params, context }: this['DataArgs']) {\n * return fetch(`/api/${params.id}`, { signal: context?.signal });\n * }\n * ```\n */\n override getData(\n _args: this['DataArgs'],\n ): Promise<TData | null> {\n return Promise.resolve(null);\n }\n\n /**\n * Render page as HTML.\n *\n * Fallback chain:\n * 1. html file content from context\n * 2. md file content wrapped in `<mark-down>`\n * 3. `<router-slot />` (bare slot for child routes)\n *\n * @example\n * ```ts\n * override renderHTML({ data, params, context }: this['RenderArgs']) {\n * return `<h1>${params.id}</h1><p>${context?.files?.html ?? ''}</p>`;\n * }\n * ```\n */\n override renderHTML(\n args: this['RenderArgs'],\n ): string {\n const files = args.context.files;\n const style = files?.css ? `<style>${files.css}</style>\\n` : '';\n\n if (files?.html) {\n let html = style + files.html;\n if (files.md && html.includes('<mark-down></mark-down>')) {\n html = html.replace(\n '<mark-down></mark-down>',\n `<mark-down>${escapeHtml(files.md)}</mark-down>`,\n );\n }\n return html;\n }\n\n if (files?.md) {\n // HOTFIX: skip external <router-slot> when markdown already defines one\n // via ```router-slot fenced block. Without this, SPA mode produces two\n // slots with the same pattern \u2014 one inside <mark-down> (from the fenced\n // block) and one outside (from this suffix). SSR strips empty duplicates\n // via stripSlots, but SPA has no equivalent cleanup.\n // See: issues/pending/spa-duplicate-router-slot.issue.md\n const hasSlot = files.md.includes('```router-slot');\n const slot = args.context.isLeaf || hasSlot ? '' : '\\n<router-slot></router-slot>';\n return `${style}<mark-down>${escapeHtml(files.md)}</mark-down>${slot}`;\n }\n\n return args.context.isLeaf ? '' : '<router-slot></router-slot>';\n }\n\n /**\n * Render page as Markdown.\n *\n * Fallback chain:\n * 1. md file content from context\n * 2. `` ```router-slot\\n``` `` (slot placeholder in markdown \u2014 newline required)\n *\n * @example\n * ```ts\n * override renderMarkdown({ data, params, context }: this['RenderArgs']) {\n * return `# ${params.id}\\n\\n${context?.files?.md ?? ''}`;\n * }\n * ```\n */\n override renderMarkdown(\n args: this['RenderArgs'],\n ): string {\n const files = args.context.files;\n\n if (files?.md) {\n return files.md;\n }\n\n return args.context.isLeaf ? '' : '```router-slot\\n```';\n }\n\n /**\n * Page title. Override in subclasses.\n * Default: undefined (no title).\n *\n * @example\n * ```ts\n * override getTitle({ data, params }: this['RenderArgs']) {\n * return `Project ${params.id}`;\n * }\n * ```\n */\n getTitle(\n _args: this['RenderArgs'],\n ): string | undefined {\n return undefined;\n }\n}\n\n/** Shared default instance used by renderers when no custom .page.ts exists. */\nexport default new PageComponent();\n", "/**\n * SSR Renderer Base\n *\n * Abstract base class for server-side renderers.\n * Provides the shared render() pipeline; subclasses supply format-specific rendering.\n */\n\nimport type {\n MatchedRoute,\n RouteConfig,\n RouteInfo,\n} from '../../type/route.type.ts';\nimport { logger } from '../../type/logger.type.ts';\nimport type { ComponentContext } from '../../component/abstract.component.ts';\nimport defaultPageComponent, { type PageComponent } from '../../component/page.component.ts';\nimport {\n assertSafeRedirect,\n DEFAULT_ROOT_ROUTE,\n RouteCore,\n type RouteCoreOptions,\n} from '../../route/route.core.ts';\nimport type { RouteResolver } from '../../route/route.resolver.ts';\nimport type { WidgetRegistry } from '../../widget/widget.registry.ts';\n\n/** Base options for SSR renderers */\nexport interface SsrRendererOptions extends RouteCoreOptions {\n /** Widget registry for server-side widget rendering */\n widgets?: WidgetRegistry;\n /** Widget companion file paths, keyed by widget name */\n widgetFiles?: Record<string, { html?: string; md?: string; css?: string }>;\n}\n\n/**\n * Abstract SSR renderer with shared routing pipeline.\n */\nexport abstract class SsrRenderer {\n protected core: RouteCore;\n protected widgets: WidgetRegistry | null;\n protected widgetFiles: Record<string, { html?: string; md?: string; css?: string }>;\n protected abstract readonly label: string;\n\n constructor(resolver: RouteResolver, options: SsrRendererOptions = {}) {\n this.core = new RouteCore(resolver, options);\n this.widgets = options.widgets ?? null;\n this.widgetFiles = options.widgetFiles ?? {};\n }\n\n /**\n * Render a URL to a content string.\n */\n async render(\n url: URL,\n signal?: AbortSignal,\n ): Promise<{ content: string; status: number; title?: string; redirect?: string }> {\n const matched = this.core.match(url);\n\n if (!matched) {\n const statusPage = this.core.getStatusPage(404);\n if (statusPage) {\n try {\n const ri: RouteInfo = { url, params: {} };\n const result = await this.renderRouteContent(ri, statusPage, undefined, signal);\n return { content: this.stripSlots(result.content), status: 404, title: result.title };\n } catch (e) {\n logger.error(\n `[${this.label}] Failed to render 404 status page for ${url.pathname}`,\n e instanceof Error ? e : undefined,\n );\n }\n }\n return { content: this.renderStatusPage(404, url), status: 404 };\n }\n\n // Handle redirect\n if (matched.route.type === 'redirect') {\n const module = await this.core.loadModule<{ default: { to: string; status?: number } }>(\n matched.route.modulePath,\n );\n const redirectConfig = module.default;\n assertSafeRedirect(redirectConfig.to);\n return {\n content: this.renderRedirect(redirectConfig.to),\n status: redirectConfig.status ?? 301,\n redirect: redirectConfig.to,\n };\n }\n\n const routeInfo = this.core.toRouteInfo(matched, url);\n\n try {\n const { content, title } = await this.renderPage(routeInfo, matched, signal);\n return { content, status: 200, title };\n } catch (error) {\n if (error instanceof Response) {\n const statusPage = this.core.getStatusPage(error.status);\n if (statusPage) {\n try {\n const ri: RouteInfo = { url, params: {} };\n const result = await this.renderRouteContent(ri, statusPage, undefined, signal);\n return {\n content: this.stripSlots(result.content),\n status: error.status,\n title: result.title,\n };\n } catch (e) {\n logger.error(\n `[${this.label}] Failed to render ${error.status} status page for ${url.pathname}`,\n e instanceof Error ? e : undefined,\n );\n }\n }\n return { content: this.renderStatusPage(error.status, url), status: error.status };\n }\n logger.error(\n `[${this.label}] Error rendering ${url.pathname}:`,\n error instanceof Error ? error : undefined,\n );\n\n const boundary = this.core.findErrorBoundary(url.pathname);\n if (boundary) {\n const result = await this.tryRenderErrorModule(boundary.modulePath, url, 'boundary');\n if (result) return result;\n }\n\n const errorHandler = this.core.getErrorHandler();\n if (errorHandler) {\n const result = await this.tryRenderErrorModule(errorHandler.modulePath, url, 'handler');\n if (result) return result;\n }\n\n return { content: this.renderErrorPage(error, url), status: 500 };\n }\n }\n\n /**\n * Render a matched page by composing the route hierarchy.\n */\n protected async renderPage(\n routeInfo: RouteInfo,\n matched: MatchedRoute,\n signal?: AbortSignal,\n ): Promise<{ content: string; title?: string }> {\n const hierarchy = this.core.buildRouteHierarchy(matched.route.pattern);\n\n // Resolve routes for each hierarchy segment (skip missing / duplicate wildcard)\n const segments: { route: RouteConfig; isLeaf: boolean }[] = [];\n for (let i = 0; i < hierarchy.length; i++) {\n const routePattern = hierarchy[i];\n let route = this.core.findRoute(routePattern);\n\n if (!route && routePattern === '/') {\n route = DEFAULT_ROOT_ROUTE;\n }\n\n if (!route) continue;\n if (route === matched.route && routePattern !== matched.route.pattern) continue;\n\n segments.push({ route, isLeaf: i === hierarchy.length - 1 });\n }\n\n // Fire all renderRouteContent calls in parallel\n const results = await Promise.all(\n segments.map(({ route, isLeaf }) =>\n this.renderRouteContent(routeInfo, route, isLeaf, signal),\n ),\n );\n\n // Sequential slot injection\n let result = '';\n let pageTitle: string | undefined;\n let lastRenderedPattern = '';\n\n for (let i = 0; i < segments.length; i++) {\n const { content, title } = results[i];\n\n if (title) {\n pageTitle = title;\n }\n\n if (result === '') {\n result = content;\n } else {\n const injected = this.injectSlot(result, content, lastRenderedPattern);\n if (injected === result) {\n logger.warn(\n `[${this.label}] Route \"${lastRenderedPattern}\" has no <router-slot> ` +\n `for child route \"${hierarchy[i]}\" to render into. ` +\n `Add <router-slot></router-slot> to the parent template.`,\n );\n }\n result = injected;\n }\n\n lastRenderedPattern = segments[i].route.pattern;\n }\n\n result = this.stripSlots(result);\n\n return { content: result, title: pageTitle };\n }\n\n protected abstract renderRouteContent(\n routeInfo: RouteInfo,\n route: RouteConfig,\n isLeaf?: boolean,\n signal?: AbortSignal,\n ): Promise<{ content: string; title?: string }>;\n\n /** Load component, build context, get data, render content, get title. */\n protected async loadRouteContent(\n routeInfo: RouteInfo,\n route: RouteConfig,\n isLeaf?: boolean,\n signal?: AbortSignal,\n ): Promise<{ content: string; title?: string }> {\n const files = route.files ?? {};\n\n const tsModule = files.ts ?? files.js;\n const component: PageComponent = tsModule\n ? (await this.core.loadModule<{ default: PageComponent }>(tsModule)).default\n : defaultPageComponent;\n\n const context = await this.core.buildComponentContext(routeInfo, route, signal, isLeaf);\n const data = await component.getData({ params: routeInfo.params, signal, context });\n const content = this.renderContent(component, { data, params: routeInfo.params, context });\n const title = component.getTitle({ data, params: routeInfo.params, context });\n\n return { content, title };\n }\n\n /** Render a component to the output format (HTML or Markdown). */\n protected abstract renderContent(\n component: PageComponent,\n args: PageComponent['RenderArgs'],\n ): string;\n\n /** Render a component for error boundary/handler with minimal context. */\n protected renderComponent(\n component: PageComponent,\n data: unknown,\n context: ComponentContext,\n ): string {\n return this.renderContent(component, { data, params: {}, context });\n }\n\n private static readonly EMPTY_URL = new URL('http://error');\n\n /** Try to load and render an error boundary or handler module. Returns null on failure. */\n private async tryRenderErrorModule(\n modulePath: string,\n url: URL,\n kind: 'boundary' | 'handler',\n ): Promise<{ content: string; status: number } | null> {\n try {\n const module = await this.core.loadModule<{ default: PageComponent }>(modulePath);\n const component = module.default;\n const minCtx: ComponentContext = {\n url: SsrRenderer.EMPTY_URL,\n params: {},\n pathname: '',\n searchParams: new URLSearchParams(),\n };\n const data = await component.getData({ params: {}, context: minCtx });\n const content = this.renderComponent(component, data, minCtx);\n return { content, status: 500 };\n } catch (e) {\n logger.error(\n `[${this.label}] Error ${kind} failed for ${url.pathname}`,\n e instanceof Error ? e : undefined,\n );\n return null;\n }\n }\n\n protected abstract renderRedirect(to: string): string;\n\n protected abstract renderStatusPage(status: number, url: URL): string;\n\n protected abstract renderErrorPage(error: unknown, url: URL): string;\n\n /** Inject child content into the slot owned by parentPattern. */\n protected abstract injectSlot(parent: string, child: string, parentPattern: string): string;\n\n /** Strip all unconsumed slot placeholders from the final result. */\n protected abstract stripSlots(result: string): string;\n}\n", "/**\n * SSR HTML Renderer\n *\n * Server-side HTML rendering.\n * Generates complete HTML strings without DOM manipulation.\n * Expands <mark-down> tags server-side when a markdown renderer is provided.\n */\n\nimport type { RouteConfig, RouteInfo } from '../../type/route.type.ts';\nimport type { RouteResolver } from '../../route/route.resolver.ts';\nimport type { MarkdownRenderer } from '../../type/markdown.type.ts';\nimport type { PageComponent } from '../../component/page.component.ts';\nimport { DEFAULT_ROOT_ROUTE } from '../../route/route.core.ts';\nimport { escapeHtml, STATUS_MESSAGES, unescapeHtml } from '../../util/html.util.ts';\nimport { resolveWidgetTags } from '../../util/widget-resolve.util.ts';\nimport { SsrRenderer, type SsrRendererOptions } from './ssr.renderer.ts';\n\n/** Options for SSR HTML Router */\nexport interface SsrHtmlRouterOptions extends SsrRendererOptions {\n /** Markdown renderer for server-side <mark-down> expansion */\n markdownRenderer?: MarkdownRenderer;\n}\n\n/**\n * SSR HTML Router for server-side rendering.\n */\nexport class SsrHtmlRouter extends SsrRenderer {\n protected override readonly label = 'SSR HTML';\n private markdownRenderer: MarkdownRenderer | null;\n private markdownReady: Promise<void> | null = null;\n\n constructor(resolver: RouteResolver, options: SsrHtmlRouterOptions = {}) {\n super(resolver, options);\n this.markdownRenderer = options.markdownRenderer ?? null;\n\n if (this.markdownRenderer?.init) {\n this.markdownReady = this.markdownRenderer.init();\n }\n }\n\n protected override injectSlot(parent: string, child: string, parentPattern: string): string {\n const escaped = parentPattern.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n return parent.replace(\n new RegExp(`<router-slot\\\\b[^>]*\\\\bpattern=\"${escaped}\"[^>]*></router-slot>`),\n child,\n );\n }\n\n protected override stripSlots(result: string): string {\n return result.replace(/<router-slot[^>]*><\\/router-slot>/g, '');\n }\n\n /**\n * Render a single route's content.\n */\n protected override async renderRouteContent(\n routeInfo: RouteInfo,\n route: RouteConfig,\n isLeaf?: boolean,\n signal?: AbortSignal,\n ): Promise<{ content: string; title?: string }> {\n if (route.modulePath === DEFAULT_ROOT_ROUTE.modulePath) {\n return { content: `<router-slot pattern=\"${route.pattern}\"></router-slot>` };\n }\n\n const { content: rawContent, title } = await this.loadRouteContent(routeInfo, route, isLeaf, signal);\n let content = rawContent;\n\n // Expand <mark-down> tags server-side\n content = await this.expandMarkdown(content);\n\n // Attribute bare <router-slot> tags with this route's pattern (before widget\n // resolution so widget-internal slots inside <template> are not affected)\n content = this.attributeSlots(content, route.pattern);\n\n // Resolve <widget-*> tags: call getData() + renderHTML(), inject ssr attribute\n if (this.widgets) {\n content = await resolveWidgetTags(\n content,\n this.widgets,\n routeInfo,\n (name, declared) => {\n const files = this.widgetFiles[name] ?? declared;\n return files ? this.core.loadWidgetFiles(files) : Promise.resolve({});\n },\n this.core.contextProvider,\n );\n }\n\n return { content, title };\n }\n\n protected override renderContent(\n component: PageComponent,\n args: PageComponent['RenderArgs'],\n ): string {\n return component.renderHTML(args);\n }\n\n protected override renderRedirect(to: string): string {\n return `<meta http-equiv=\"refresh\" content=\"0;url=${escapeHtml(to)}\">`;\n }\n\n protected override renderStatusPage(status: number, url: URL): string {\n return `\n <h1>${STATUS_MESSAGES[status] ?? 'Error'}</h1>\n <p>Path: ${escapeHtml(url.pathname)}</p>\n `;\n }\n\n protected override renderErrorPage(error: unknown, url: URL): string {\n const message = error instanceof Error ? error.message : String(error);\n return `\n <h1>Error</h1>\n <p>Path: ${escapeHtml(url.pathname)}</p>\n <p>${escapeHtml(message)}</p>\n `;\n }\n\n /** Add pattern attribute to bare <router-slot> tags. */\n private attributeSlots(content: string, routePattern: string): string {\n return content.replace(\n /<router-slot(?![^>]*\\bpattern=)([^>]*)><\\/router-slot>/g,\n `<router-slot pattern=\"${routePattern}\"$1></router-slot>`,\n );\n }\n\n /**\n * Expand <mark-down> tags by rendering markdown to HTML server-side.\n * Leaves content unchanged if no markdown renderer is configured.\n */\n private async expandMarkdown(content: string): Promise<string> {\n if (!this.markdownRenderer) return content;\n if (!content.includes('<mark-down>')) return content;\n\n if (this.markdownReady) {\n await this.markdownReady;\n }\n\n const renderer = this.markdownRenderer;\n\n // Match <mark-down>escaped content</mark-down>\n const pattern = /<mark-down>([\\s\\S]*?)<\\/mark-down>/g;\n\n return content.replace(pattern, (_match, escaped: string) => {\n const markdown = unescapeHtml(escaped);\n const rendered = renderer.render(markdown);\n return rendered;\n });\n }\n}\n\n/**\n * Create SSR HTML router.\n */\nexport function createSsrHtmlRouter(\n resolver: RouteResolver,\n options?: SsrHtmlRouterOptions,\n): SsrHtmlRouter {\n return new SsrHtmlRouter(resolver, options);\n}\n", "/**\n * Widget Parser\n *\n * Parses fenced widget blocks from markdown content.\n *\n * Syntax:\n * ```widget:widget-name\n * {\"key\": \"value\"}\n * ```\n */\n\nimport type { ParsedWidgetBlock } from '../type/widget.type.ts';\n\n/**\n * Pattern to match widget fenced code blocks.\n * Captures: widget name, params content\n */\nconst WIDGET_PATTERN = /```widget:(?<name>[a-z][a-z0-9-]*)\\n(?<params>.*?)```/gs;\n\n/**\n * Parse all widget blocks from markdown content.\n *\n * @param markdown - Markdown content to parse\n * @returns Array of parsed widget blocks with positions\n */\nexport function parseWidgetBlocks(markdown: string): ParsedWidgetBlock[] {\n const blocks: ParsedWidgetBlock[] = [];\n\n for (const match of markdown.matchAll(WIDGET_PATTERN)) {\n const fullMatch = match[0];\n const { name: widgetName, params: paramsRaw } = match.groups!;\n const paramsJson = paramsRaw.trim();\n const startIndex = match.index;\n\n const block: ParsedWidgetBlock = {\n fullMatch,\n widgetName,\n params: null,\n startIndex,\n endIndex: startIndex + fullMatch.length,\n };\n\n // Parse JSON params if present\n if (paramsJson) {\n try {\n const parsed = JSON.parse(paramsJson);\n if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {\n block.params = parsed;\n } else {\n block.parseError = 'Params must be a JSON object';\n }\n } catch (e) {\n block.parseError = `Invalid JSON: ${e instanceof Error ? e.message : String(e)}`;\n }\n } else {\n // Empty params is valid - use empty object\n block.params = {};\n }\n\n blocks.push(block);\n }\n\n return blocks;\n}\n\n/**\n * Replace widget blocks in markdown with rendered content.\n *\n * @param markdown - Original markdown content\n * @param replacements - Map of parsed blocks to replacement strings\n * @returns Markdown with widget blocks replaced\n */\nexport function replaceWidgetBlocks(\n markdown: string,\n replacements: Map<ParsedWidgetBlock, string>,\n): string {\n // Sort blocks by position descending to replace from end first\n // This preserves indices during replacement\n const sortedBlocks = [...replacements.entries()].sort(\n ([a], [b]) => b.startIndex - a.startIndex,\n );\n\n let result = markdown;\n for (const [block, replacement] of sortedBlocks) {\n result = result.slice(0, block.startIndex) + replacement + result.slice(block.endIndex);\n }\n\n return result;\n}\n", "/**\n * SSR Markdown Renderer\n *\n * Server-side Markdown rendering.\n * Generates Markdown strings for LLM consumption, text clients, curl.\n */\n\nimport type { RouteConfig, RouteInfo } from '../../type/route.type.ts';\nimport type { RouteResolver } from '../../route/route.resolver.ts';\nimport type { PageComponent } from '../../component/page.component.ts';\nimport { DEFAULT_ROOT_ROUTE } from '../../route/route.core.ts';\nimport { STATUS_MESSAGES } from '../../util/html.util.ts';\nimport { resolveRecursively } from '../../util/widget-resolve.util.ts';\nimport { parseWidgetBlocks, replaceWidgetBlocks } from '../../widget/widget.parser.ts';\nimport { SsrRenderer, type SsrRendererOptions } from './ssr.renderer.ts';\n\nconst BARE_SLOT_BLOCK = '```router-slot\\n```';\n\nfunction routerSlotBlock(pattern: string): string {\n return `\\`\\`\\`router-slot\\n{\"pattern\":\"${pattern}\"}\\n\\`\\`\\``;\n}\n\n/** Options for SSR Markdown Router */\nexport type SsrMdRouterOptions = SsrRendererOptions;\n\n/**\n * SSR Markdown Router for server-side markdown rendering.\n */\nexport class SsrMdRouter extends SsrRenderer {\n protected override readonly label = 'SSR MD';\n\n constructor(resolver: RouteResolver, options: SsrMdRouterOptions = {}) {\n super(resolver, options);\n }\n\n protected override injectSlot(parent: string, child: string, parentPattern: string): string {\n return parent.replace(routerSlotBlock(parentPattern), child);\n }\n\n protected override stripSlots(result: string): string {\n return result\n .replace(/```router-slot\\n(?:\\{[^}]*\\}\\n)?```/g, '')\n .trim();\n }\n\n /**\n * Render a single route's content to Markdown.\n */\n protected override async renderRouteContent(\n routeInfo: RouteInfo,\n route: RouteConfig,\n isLeaf?: boolean,\n signal?: AbortSignal,\n ): Promise<{ content: string; title?: string }> {\n if (route.modulePath === DEFAULT_ROOT_ROUTE.modulePath) {\n return { content: routerSlotBlock(route.pattern) };\n }\n\n const { content: rawContent, title } = await this.loadRouteContent(routeInfo, route, isLeaf, signal);\n let content = rawContent;\n\n // Attribute bare router-slot blocks with this route's pattern\n // (before widget resolution so widget-internal blocks are not affected)\n content = content.replaceAll(BARE_SLOT_BLOCK, routerSlotBlock(route.pattern));\n\n // Resolve fenced widget blocks: call getData() + renderMarkdown()\n if (this.widgets) {\n content = await this.resolveWidgets(content, routeInfo);\n }\n\n return { content, title };\n }\n\n protected override renderContent(\n component: PageComponent,\n args: PageComponent['RenderArgs'],\n ): string {\n return component.renderMarkdown(args);\n }\n\n protected override renderRedirect(to: string): string {\n return `Redirect to: ${to}`;\n }\n\n protected override renderStatusPage(status: number, url: URL): string {\n return `# ${STATUS_MESSAGES[status] ?? 'Error'}\\n\\nPath: \\`${url.pathname}\\``;\n }\n\n protected override renderErrorPage(_error: unknown, url: URL): string {\n return `# Internal Server Error\\n\\nPath: \\`${url.pathname}\\``;\n }\n\n /**\n * Resolve fenced widget blocks in markdown content.\n * Replaces ```widget:name blocks with rendered markdown output.\n */\n private resolveWidgets(\n content: string,\n routeInfo: RouteInfo,\n ): Promise<string> {\n return resolveRecursively(\n content,\n parseWidgetBlocks,\n async (block) => {\n if (block.parseError || !block.params) {\n return `> **Error** (\\`${block.widgetName}\\`): ${block.parseError}`;\n }\n\n const widget = this.widgets!.get(block.widgetName);\n if (!widget) {\n return `> **Error**: Unknown widget \\`${block.widgetName}\\``;\n }\n\n try {\n let files: { html?: string; md?: string } | undefined;\n const filePaths = this.widgetFiles[block.widgetName] ?? widget.files;\n if (filePaths) {\n files = await this.core.loadWidgetFiles(filePaths);\n }\n\n const baseContext = {\n ...routeInfo,\n pathname: routeInfo.url.pathname,\n searchParams: routeInfo.url.searchParams,\n files,\n };\n const context = this.core.contextProvider\n ? this.core.contextProvider(baseContext)\n : baseContext;\n const data = await widget.getData({ params: block.params, context });\n return widget.renderMarkdown({ data, params: block.params, context });\n } catch (e) {\n return widget.renderMarkdownError(e);\n }\n },\n replaceWidgetBlocks,\n );\n }\n}\n\n/**\n * Create SSR Markdown router.\n */\nexport function createSsrMdRouter(\n resolver: RouteResolver,\n options?: SsrMdRouterOptions,\n): SsrMdRouter {\n return new SsrMdRouter(resolver, options);\n}\n", "/**\n * Markdown Link Rewriting\n *\n * Rewrites internal absolute links in markdown to include a base path prefix.\n * Skips fenced code blocks and links already under a known base path.\n */\n\n/** Rewrite internal absolute links in markdown to include the base path prefix. */\nexport function rewriteMdLinks(markdown: string, base: string, skipPrefixes: string[]): string {\n const prefix = base + '/';\n // Negative lookahead: skip links already under a known base path\n const skip = skipPrefixes.map((p) => p.slice(1) + '/').join('|');\n const inlineRe = new RegExp(`\\\\]\\\\(\\\\/(?!${skip})`, 'g');\n const refRe = new RegExp(`^(\\\\[[^\\\\]]+\\\\]:\\\\s+)\\\\/(?!${skip})`, 'g');\n\n const lines = markdown.split('\\n');\n let inCodeBlock = false;\n\n for (let i = 0; i < lines.length; i++) {\n if (lines[i].startsWith('```')) {\n inCodeBlock = !inCodeBlock;\n continue;\n }\n if (inCodeBlock) continue;\n\n lines[i] = lines[i].replaceAll(inlineRe, `](${prefix}`);\n lines[i] = lines[i].replaceAll(refRe, `$1${prefix}`);\n }\n\n return lines.join('\\n');\n}\n", "/**\n * Route Tree Utilities\n *\n * Pure functions for building a RouteNode tree from filesystem paths.\n */\n\nimport type { RouteNode } from '../type/route-tree.type.ts';\n\n/**\n * Resolve the target node for a page or redirect file based on its name.\n *\n * - \"index\" at root \u2192 the node itself (root route)\n * - \"index\" in a subdirectory \u2192 wildcard catch-all on the node\n * - \"[param]\" \u2192 dynamic child\n * - anything else \u2192 static child\n */\nexport function resolveTargetNode(node: RouteNode, name: string, isRoot: boolean): RouteNode {\n if (name === 'index') {\n if (isRoot) return node;\n // Non-root index \u2192 wildcard catch-all\n node.wildcard ??= { param: 'rest', child: {} };\n return node.wildcard.child;\n }\n\n if (name.startsWith('[') && name.endsWith(']')) {\n const param = name.slice(1, -1);\n node.dynamic ??= { param, child: {} };\n return node.dynamic.child;\n }\n\n // Static segment\n node.children ??= {};\n node.children[name] ??= {};\n return node.children[name];\n}\n", "import type { RouteNode, RouteFiles } from '../src/type/route-tree.type.ts';\nimport { resolveTargetNode } from '../src/route/route-tree.util.ts';\nimport type { WidgetManifestEntry } from '../src/type/widget.type.ts';\n\nexport const CONTENT_TYPES: Map<string, string> = new Map<string, string>([\n ['.html', 'text/html; charset=utf-8'],\n ['.css', 'text/css; charset=utf-8'],\n ['.js', 'application/javascript; charset=utf-8'],\n ['.mjs', 'application/javascript; charset=utf-8'],\n ['.ts', 'text/typescript; charset=utf-8'],\n ['.json', 'application/json; charset=utf-8'],\n ['.md', 'text/plain; charset=utf-8'],\n ['.txt', 'text/plain; charset=utf-8'],\n ['.wasm', 'application/wasm'],\n ['.map', 'application/json; charset=utf-8'],\n ['.png', 'image/png'],\n ['.jpg', 'image/jpeg'],\n ['.jpeg', 'image/jpeg'],\n ['.gif', 'image/gif'],\n ['.svg', 'image/svg+xml'],\n ['.ico', 'image/x-icon'],\n ['.webp', 'image/webp'],\n ['.avif', 'image/avif'],\n ['.woff', 'font/woff'],\n ['.woff2', 'font/woff2'],\n ['.ttf', 'font/ttf'],\n]);\n\nexport type FetchParams = Parameters<typeof fetch>;\nexport type FetchReturn = ReturnType<typeof fetch>;\n\nexport const DEFAULT_ROUTES_DIR = '/routes';\nexport const DEFAULT_WIDGETS_DIR = '/widgets';\nexport const ROUTES_MANIFEST_PATH = '/routes.manifest.json';\nexport const WIDGETS_MANIFEST_PATH = '/widgets.manifest.json';\n\nexport interface RuntimeConfig {\n routesDir?: string;\n widgetsDir?: string;\n}\n\n/**\n * Abstract resource provider. Speaks Request/Response (ADR-1).\n *\n * Three access patterns:\n * - `handle()` \u2014 raw passthrough, server forwards browser requests as-is.\n * - `query()` \u2014 read. Returns Response, or string when `{ as: \"text\" }`.\n * - `command()` \u2014 write (PUT by default, override with `{ method }` in options).\n *\n * Includes manifest resolution: when `query(ROUTES_MANIFEST_PATH)` or\n * `query(WIDGETS_MANIFEST_PATH)` returns 404, the runtime scans the\n * configured directories and caches the result.\n */\nexport abstract class Runtime {\n constructor(readonly config: RuntimeConfig = {}) {\n this.config = config;\n }\n /** Concrete runtimes implement this. Accepts the same args as `fetch()`. */\n abstract handle(resource: FetchParams[0], init?: FetchParams[1]): FetchReturn;\n\n /**\n * Read with `{ as: \"text\" }` \u2014 skip metadata, return contents only.\n * Semantically equivalent to `Accept: text/plain`; `as` exists for type safety.\n */\n abstract query(\n resource: FetchParams[0],\n options: FetchParams[1] & { as: 'text' },\n ): Promise<string>;\n /** Read \u2014 returns full Response with headers, status, body. */\n abstract query(\n resource: FetchParams[0],\n options?: FetchParams[1],\n ): FetchReturn;\n\n /** Write. Defaults to PUT; pass `{ method: \"DELETE\" }` etc. to override. */\n command(resource: FetchParams[0], options?: FetchParams[1]): FetchReturn {\n const path = typeof resource === 'string'\n ? resource\n : new URL(resource instanceof Request ? resource.url : resource.toString()).pathname;\n const result = this.handle(resource, { method: 'PUT', ...options });\n const routesDir = this.config.routesDir ?? DEFAULT_ROUTES_DIR;\n if (path.startsWith(routesDir + '/')) {\n return result.then(async (res) => {\n await this.mergeRouteIntoManifest(path, routesDir);\n return res;\n });\n }\n return result;\n }\n\n /**\n * Parse a single route file path and merge it into the stored manifest.\n * Avoids a full directory rescan \u2014 just reads the current manifest,\n * inserts the new entry, and writes it back.\n */\n private async mergeRouteIntoManifest(\n filePath: string,\n routesDir: string,\n ): Promise<void> {\n const relativePath = filePath.slice(routesDir.length + 1);\n const parts = relativePath.split('/');\n const filename = parts[parts.length - 1];\n const dirSegments = parts.slice(0, -1);\n\n const match = filename.match(/^(.+?)\\.(page|error|redirect)\\.(ts|js|html|md|css)$/);\n if (!match) return;\n\n const [, name, kind, ext] = match;\n\n // Read current manifest (or start fresh)\n const response = await this.handle(ROUTES_MANIFEST_PATH);\n const tree: RouteNode = response.status === 404\n ? {}\n : await response.json();\n\n // Walk to the parent node\n let node = tree;\n for (const dir of dirSegments) {\n if (dir.startsWith('[') && dir.endsWith(']')) {\n const param = dir.slice(1, -1);\n node.dynamic ??= { param, child: {} };\n node = node.dynamic.child;\n } else {\n node.children ??= {};\n node.children[dir] ??= {};\n node = node.children[dir];\n }\n }\n\n // Place the file\n if (kind === 'error') {\n node.errorBoundary = filePath;\n } else {\n const target = resolveTargetNode(node, name, dirSegments.length === 0);\n if (kind === 'redirect') {\n target.redirect = filePath;\n } else {\n target.files ??= {};\n target.files[ext as keyof RouteFiles] = filePath;\n }\n }\n\n // Write updated manifest back\n this.routesManifestCache = null;\n await this.handle(ROUTES_MANIFEST_PATH, {\n method: 'PUT',\n body: JSON.stringify(tree),\n });\n }\n\n /**\n * Dynamically import a module from this runtime's storage.\n * Used by the server for SSR imports of `.page.ts` and `.widget.ts` files.\n */\n loadModule(_path: string): Promise<unknown> {\n throw new Error(`loadModule not implemented for ${this.constructor.name}`);\n }\n\n /**\n * Transpile TypeScript source to JavaScript.\n * Used by the build step to produce browser-loadable .js modules.\n */\n transpile(_source: string): Promise<string> {\n throw new Error(`transpile not implemented for ${this.constructor.name}`);\n }\n\n // \u2500\u2500 Manifest resolution \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 private routesManifestCache: Response | null = null;\n private widgetsManifestCache: Response | null = null;\n\n /** Clear cached manifests so the next query triggers a fresh scan. */\n invalidateManifests(): void {\n this.routesManifestCache = null;\n this.widgetsManifestCache = null;\n }\n\n /**\n * Resolve the routes manifest. Called when the concrete runtime returns\n * 404 for ROUTES_MANIFEST_PATH. Scans `config.routesDir` (or default).\n */\n async resolveRoutesManifest(): Promise<Response> {\n if (this.routesManifestCache) return this.routesManifestCache.clone();\n\n const routesDir = this.config.routesDir ?? DEFAULT_ROUTES_DIR;\n\n // Check if directory exists by querying it\n const dirResponse = await this.query(routesDir + '/');\n if (dirResponse.status === 404) {\n return new Response('Not Found', { status: 404 });\n }\n\n const tree = await this.scanRoutes(routesDir);\n\n this.routesManifestCache = Response.json(tree);\n return this.routesManifestCache.clone();\n }\n\n /**\n * Resolve the widgets manifest. Called when the concrete runtime returns\n * 404 for WIDGETS_MANIFEST_PATH. Scans `config.widgetsDir` (or default).\n */\n async resolveWidgetsManifest(): Promise<Response> {\n if (this.widgetsManifestCache) return this.widgetsManifestCache.clone();\n\n const widgetsDir = this.config.widgetsDir ?? DEFAULT_WIDGETS_DIR;\n\n const dirResponse = await this.query(widgetsDir + '/');\n if (dirResponse.status === 404) {\n return new Response('Not Found', { status: 404 });\n }\n\n const entries = await this.scanWidgets(widgetsDir, widgetsDir.replace(/^\\//, ''));\n this.widgetsManifestCache = Response.json(entries);\n return this.widgetsManifestCache.clone();\n }\n\n // \u2500\u2500 Scanning \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 protected async *walkDirectory(dir: string): AsyncGenerator<string> {\n const trailingDir = dir.endsWith('/') ? dir : dir + '/';\n const response = await this.query(trailingDir);\n const entries: string[] = await response.json();\n\n for (const entry of entries) {\n const path = `${trailingDir}${entry}`;\n if (entry.endsWith('/')) {\n yield* this.walkDirectory(path);\n } else {\n yield path;\n }\n }\n }\n\n /**\n * Scan a routes directory and build a RouteNode tree.\n * The filesystem structure maps directly to the tree \u2014 no intermediate array.\n */\n protected async scanRoutes(routesDir: string): Promise<RouteNode> {\n const root: RouteNode = {};\n\n const allFiles: string[] = [];\n for await (const file of this.walkDirectory(routesDir)) {\n allFiles.push(file);\n }\n\n for (const filePath of allFiles) {\n const relativePath = filePath.replace(`${routesDir}/`, '');\n const parts = relativePath.split('/');\n const filename = parts[parts.length - 1];\n const dirSegments = parts.slice(0, -1);\n\n // Parse filename: name.kind.ext (e.g. \"about.page.ts\", \"[id].page.html\", \"index.error.ts\")\n const match = filename.match(/^(.+?)\\.(page|error|redirect)\\.(ts|js|html|md|css)$/);\n if (!match) continue;\n\n const [, name, kind, ext] = match;\n\n // Walk directory segments to reach the parent node\n let node = root;\n for (const dir of dirSegments) {\n if (dir.startsWith('[') && dir.endsWith(']')) {\n const param = dir.slice(1, -1);\n node.dynamic ??= { param, child: {} };\n node = node.dynamic.child;\n } else {\n node.children ??= {};\n node.children[dir] ??= {};\n node = node.children[dir];\n }\n }\n\n // Place the file on the correct node\n if (kind === 'error') {\n // Error boundary scopes to the directory it's in.\n // Root index.error.ts \u2192 root.errorBoundary (global handler).\n // projects/projects.error.ts \u2192 projects node errorBoundary.\n node.errorBoundary = filePath;\n continue;\n }\n\n // For page and redirect files, the name determines the final node\n const target = resolveTargetNode(node, name, dirSegments.length === 0);\n\n if (kind === 'redirect') {\n target.redirect = filePath;\n } else {\n // kind === 'page'\n target.files ??= {};\n target.files[ext as keyof RouteFiles] = filePath;\n }\n }\n\n return root;\n }\n\n protected async scanWidgets(\n widgetsDir: string,\n pathPrefix?: string,\n ): Promise<WidgetManifestEntry[]> {\n const COMPANION_EXTENSIONS = ['html', 'md', 'css'] as const;\n const entries: WidgetManifestEntry[] = [];\n\n const trailingDir = widgetsDir.endsWith('/') ? widgetsDir : widgetsDir + '/';\n const response = await this.query(trailingDir);\n const listing: string[] = await response.json();\n\n for (const item of listing) {\n if (!item.endsWith('/')) continue;\n\n const name = item.slice(0, -1);\n\n // Try .widget.ts first, then .widget.js\n let moduleFile = `${name}.widget.ts`;\n let modulePath = `${trailingDir}${name}/${moduleFile}`;\n if ((await this.query(modulePath)).status === 404) {\n moduleFile = `${name}.widget.js`;\n modulePath = `${trailingDir}${name}/${moduleFile}`;\n if ((await this.query(modulePath)).status === 404) continue;\n }\n\n const prefix = pathPrefix ? `${pathPrefix}/` : '';\n const entry: WidgetManifestEntry = {\n name,\n modulePath: `${prefix}${name}/${moduleFile}`,\n tagName: `widget-${name}`,\n };\n\n const files: { html?: string; md?: string; css?: string } = {};\n let hasFiles = false;\n for (const ext of COMPANION_EXTENSIONS) {\n const companionFile = `${name}.widget.${ext}`;\n const companionPath = `${trailingDir}${name}/${companionFile}`;\n if ((await this.query(companionPath)).status !== 404) {\n files[ext] = `${prefix}${name}/${companionFile}`;\n hasFiles = true;\n }\n }\n\n if (hasFiles) entry.files = files;\n entries.push(entry);\n }\n\n entries.sort((a, b) => a.name.localeCompare(b.name));\n return entries;\n }\n}\n", "/**\n * Emroute Server\n *\n * Runtime-agnostic server that handles SSR rendering, manifest resolution,\n * static file serving, and route matching. Works with any Runtime implementation.\n *\n * Usage (standalone):\n * ```ts\n * import { createEmrouteServer } from '@emkodev/emroute/server';\n * import { BunFsRuntime } from '@emkodev/emroute/runtime/bun/fs';\n *\n * const runtime = new BunFsRuntime('.', { routesDir: '/routes' });\n * const emroute = await createEmrouteServer({ spa: 'root' }, runtime);\n *\n * Bun.serve({ fetch: (req) => emroute.handleRequest(req) ?? new Response('Not Found', { status: 404 }) });\n * ```\n *\n * Usage (composable):\n * ```ts\n * const emroute = await createEmrouteServer(config, runtime);\n *\n * Bun.serve({ async fetch(req) {\n * if (isApiRoute(req)) return handleApi(req);\n * const response = await emroute.handleRequest(req);\n * if (response) return response;\n * return new Response('Not Found', { status: 404 });\n * }});\n * ```\n */\n\nimport { DEFAULT_BASE_PATH } from '../src/route/route.core.ts';\nimport { RouteTrie } from '../src/route/route.trie.ts';\nimport { SsrHtmlRouter } from '../src/renderer/ssr/html.renderer.ts';\nimport { SsrMdRouter } from '../src/renderer/ssr/md.renderer.ts';\nimport type { RouteNode } from '../src/type/route-tree.type.ts';\nimport type { WidgetManifestEntry } from '../src/type/widget.type.ts';\nimport { WidgetRegistry } from '../src/widget/widget.registry.ts';\nimport type { WidgetComponent } from '../src/component/widget.component.ts';\nimport { escapeHtml } from '../src/util/html.util.ts';\nimport { rewriteMdLinks } from '../src/util/md.util.ts';\nimport {\n ROUTES_MANIFEST_PATH,\n Runtime,\n WIDGETS_MANIFEST_PATH,\n} from '../runtime/abstract.runtime.ts';\nimport type { EmrouteServer, EmrouteServerConfig } from './server-api.type.ts';\n\n// \u2500\u2500 Module loaders \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * Collect all .ts module paths from a RouteNode tree and create loaders.\n * Uses `runtime.loadModule()` \u2014 each runtime decides how to load modules\n * (filesystem import, SQLite transpile + blob URL, etc.).\n */\nfunction createModuleLoaders(\n tree: RouteNode,\n runtime: Runtime,\n): Record<string, () => Promise<unknown>> {\n const paths = new Set<string>();\n\n function walk(node: RouteNode): void {\n const modulePath = node.files?.ts ?? node.files?.js;\n if (modulePath) paths.add(modulePath);\n if (node.redirect) paths.add(node.redirect);\n if (node.errorBoundary) paths.add(node.errorBoundary);\n\n if (node.children) {\n for (const child of Object.values(node.children)) walk(child);\n }\n if (node.dynamic) walk(node.dynamic.child);\n if (node.wildcard) walk(node.wildcard.child);\n }\n\n walk(tree);\n\n const loaders: Record<string, () => Promise<unknown>> = {};\n for (const path of paths) {\n loaders[path] = () => runtime.loadModule(path);\n }\n return loaders;\n}\n\n// \u2500\u2500 Widget helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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/** Find a WidgetComponent export from a module. */\nfunction extractWidgetExport(\n mod: Record<string, unknown>,\n): WidgetComponent | null {\n for (const value of Object.values(mod)) {\n if (!value) continue;\n if (typeof value === 'object' && 'getData' in value) {\n return value as WidgetComponent;\n }\n if (typeof value === 'function' && value.prototype?.getData) {\n return new (value as new () => WidgetComponent)();\n }\n }\n return null;\n}\n\n/** Import widget modules for SSR via runtime.loadModule(). */\nasync function importWidgets(\n entries: WidgetManifestEntry[],\n runtime: Runtime,\n manual?: WidgetRegistry,\n): Promise<{\n registry: WidgetRegistry;\n widgetFiles: Record<string, { html?: string; md?: string; css?: string }>;\n}> {\n const registry = new WidgetRegistry();\n const widgetFiles: Record<string, { html?: string; md?: string; css?: string }> = {};\n\n for (const entry of entries) {\n try {\n const runtimePath = entry.modulePath.startsWith('/')\n ? entry.modulePath\n : `/${entry.modulePath}`;\n\n const mod = await runtime.loadModule(runtimePath) as Record<string, unknown>;\n const instance = extractWidgetExport(mod);\n if (!instance) continue;\n registry.add(instance);\n\n // Prefer inlined __files from merged module over manifest paths\n const inlined = mod.__files;\n if (inlined && typeof inlined === 'object') {\n widgetFiles[entry.name] = inlined as { html?: string; md?: string; css?: string };\n } else if (entry.files) {\n widgetFiles[entry.name] = entry.files;\n }\n } catch (e) {\n console.error(`[emroute] Failed to load widget ${entry.modulePath}:`, e);\n if (entry.files) widgetFiles[entry.name] = entry.files;\n }\n }\n\n if (manual) {\n for (const widget of manual) {\n registry.add(widget);\n }\n }\n\n return { registry, widgetFiles };\n}\n\n// \u2500\u2500 HTML shell \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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/** Build a default HTML shell. */\nfunction buildHtmlShell(title: string, htmlBase: string): string {\n const baseTag = htmlBase ? `\\n <base href=\"${escapeHtml(htmlBase)}/\">` : '';\n return `<!DOCTYPE html>\n<html>\n<head>${baseTag}\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <title>${escapeHtml(title)}</title>\n <style>@view-transition { navigation: auto; } router-slot { display: contents; }</style>\n</head>\n<body>\n <router-slot></router-slot>\n</body>\n</html>`;\n}\n\n/** Inject SSR-rendered content into an HTML shell. */\nfunction injectSsrContent(\n html: string,\n content: string,\n title: string | undefined,\n ssrRoute?: string,\n): string {\n const slotPattern = /<router-slot\\b[^>]*>.*?<\\/router-slot>/s;\n if (!slotPattern.test(html)) return html;\n\n const ssrAttr = ssrRoute ? ` data-ssr-route=\"${ssrRoute}\"` : '';\n html = html.replace(slotPattern, `<router-slot${ssrAttr}>${content}</router-slot>`);\n\n if (title) {\n html = html.replace(/<title>[^<]*<\\/title>/, `<title>${escapeHtml(title)}</title>`);\n }\n\n return html;\n}\n\n/** Read the HTML shell from runtime, with fallback to a default shell. */\nasync function resolveShell(\n runtime: Runtime,\n title: string,\n htmlBase: string,\n): Promise<string> {\n const response = await runtime.query('/index.html');\n if (response.status !== 404) return await response.text();\n return buildHtmlShell(title, htmlBase);\n}\n\n// \u2500\u2500 More path helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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// \u2500\u2500 createEmrouteServer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * Create an emroute server.\n *\n * All paths are Runtime-relative (starting with `/`). Runtime root = appRoot.\n */\nexport async function createEmrouteServer(\n config: EmrouteServerConfig,\n runtime: Runtime,\n): Promise<EmrouteServer> {\n const {\n spa = 'root',\n } = config;\n\n const { html: htmlBase, md: mdBase, app: appBase } = config.basePath ?? DEFAULT_BASE_PATH;\n\n // \u2500\u2500 Route tree (read from runtime) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 let routeTree: RouteNode;\n\n if (config.routeTree) {\n routeTree = config.routeTree;\n } else {\n const manifestResponse = await runtime.query(ROUTES_MANIFEST_PATH);\n if (manifestResponse.status === 404) {\n throw new Error(\n `[emroute] ${ROUTES_MANIFEST_PATH} not found in runtime. ` +\n 'Provide routeTree in config or ensure the runtime produces it.',\n );\n }\n routeTree = await manifestResponse.json();\n }\n\n const moduleLoaders = config.moduleLoaders ?? createModuleLoaders(routeTree, runtime);\n const resolver = new RouteTrie(routeTree);\n\n // \u2500\u2500 Widgets (read from runtime) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 let widgets: WidgetRegistry | undefined = config.widgets;\n let widgetFiles: Record<string, { html?: string; md?: string; css?: string }> = {};\n let discoveredWidgetEntries: WidgetManifestEntry[] = [];\n\n const widgetsResponse = await runtime.query(WIDGETS_MANIFEST_PATH);\n if (widgetsResponse.status !== 404) {\n discoveredWidgetEntries = await widgetsResponse.json();\n if (config.widgets) {\n // Widgets pre-provided (e.g. browser bundle) \u2014 just collect file paths\n widgets = config.widgets;\n for (const entry of discoveredWidgetEntries) {\n if (entry.files) widgetFiles[entry.name] = entry.files;\n }\n } else {\n const imported = await importWidgets(discoveredWidgetEntries, runtime);\n widgets = imported.registry;\n widgetFiles = imported.widgetFiles;\n }\n }\n\n // \u2500\u2500 SSR routers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 let ssrHtmlRouter: SsrHtmlRouter | null = null;\n let ssrMdRouter: SsrMdRouter | null = null;\n\n function buildSsrRouters(): void {\n if (spa === 'only') {\n ssrHtmlRouter = null;\n ssrMdRouter = null;\n return;\n }\n\n ssrHtmlRouter = new SsrHtmlRouter(resolver, {\n fileReader: (path) => runtime.query(path, { as: 'text' }),\n moduleLoaders,\n markdownRenderer: config.markdownRenderer,\n extendContext: config.extendContext,\n widgets,\n widgetFiles,\n });\n\n ssrMdRouter = new SsrMdRouter(resolver, {\n fileReader: (path) => runtime.query(path, { as: 'text' }),\n moduleLoaders,\n extendContext: config.extendContext,\n widgets,\n widgetFiles,\n });\n }\n\n buildSsrRouters();\n\n // \u2500\u2500 HTML shell \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const title = config.title ?? 'emroute';\n let shell = await resolveShell(runtime, title, htmlBase);\n\n // Auto-discover main.css and inject <link> into <head>\n if ((await runtime.query('/main.css')).status !== 404) {\n shell = shell.replace('</head>', ' <link rel=\"stylesheet\" href=\"/main.css\">\\n</head>');\n }\n\n // \u2500\u2500 handleRequest \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 async function handleRequest(req: Request): Promise<Response | null> {\n const url = new URL(req.url);\n const pathname = url.pathname;\n\n const mdPrefix = mdBase + '/';\n const htmlPrefix = htmlBase + '/';\n const appPrefix = appBase + '/';\n\n // SSR Markdown: /md/*\n if (\n ssrMdRouter &&\n (pathname.startsWith(mdPrefix) || pathname === mdBase)\n ) {\n // Normalize trailing slash: /md/about/ \u2192 301 /md/about\n const routePath = pathname === mdBase ? '/' : pathname.slice(mdBase.length);\n if (routePath.length > 1 && routePath.endsWith('/')) {\n const canonical = mdBase + routePath.slice(0, -1) + (url.search || '');\n return Response.redirect(new URL(canonical, url.origin), 301);\n }\n try {\n const routeUrl = new URL(routePath + url.search, url.origin);\n const { content, status, redirect } = await ssrMdRouter.render(routeUrl, req.signal);\n if (redirect) {\n const target = redirect.startsWith('/') ? mdBase + redirect : redirect;\n return Response.redirect(new URL(target, url.origin), status);\n }\n return new Response(rewriteMdLinks(content, mdBase, [mdBase, htmlBase]), {\n status,\n headers: { 'Content-Type': 'text/markdown; charset=utf-8; variant=CommonMark' },\n });\n } catch (e) {\n console.error(`[emroute] Error rendering ${pathname}:`, e);\n return new Response('Internal Server Error', { status: 500 });\n }\n }\n\n // SSR HTML: /html/*\n if (\n ssrHtmlRouter &&\n (pathname.startsWith(htmlPrefix) || pathname === htmlBase)\n ) {\n // Normalize trailing slash: /html/about/ \u2192 301 /html/about\n const routePath = pathname === htmlBase ? '/' : pathname.slice(htmlBase.length);\n if (routePath.length > 1 && routePath.endsWith('/')) {\n const canonical = htmlBase + routePath.slice(0, -1) + (url.search || '');\n return Response.redirect(new URL(canonical, url.origin), 301);\n }\n try {\n const routeUrl = new URL(routePath + url.search, url.origin);\n const result = await ssrHtmlRouter.render(routeUrl, req.signal);\n if (result.redirect) {\n const target = result.redirect.startsWith('/') ? htmlBase + result.redirect : result.redirect;\n return Response.redirect(new URL(target, url.origin), result.status);\n }\n const ssrTitle = result.title ?? title;\n const html = injectSsrContent(shell, result.content, ssrTitle, pathname);\n return new Response(html, {\n status: result.status,\n headers: { 'Content-Type': 'text/html; charset=utf-8' },\n });\n } catch (e) {\n console.error(`[emroute] Error rendering ${pathname}:`, e);\n return new Response('Internal Server Error', { status: 500 });\n }\n }\n\n // /app/* \u2014 serve shell (browser JS takes over via createEmrouteApp)\n if (pathname.startsWith(appPrefix) || pathname === appBase) {\n return new Response(shell, {\n status: 200,\n headers: { 'Content-Type': 'text/html; charset=utf-8' },\n });\n }\n\n // /html/* or /md/* that wasn't handled by SSR (e.g. 'only' mode) \u2014 serve shell\n if (\n pathname.startsWith(htmlPrefix) || pathname === htmlBase ||\n pathname.startsWith(mdPrefix) || pathname === mdBase\n ) {\n return new Response(shell, {\n status: 200,\n headers: { 'Content-Type': 'text/html; charset=utf-8' },\n });\n }\n\n // Static files \u2014 only try runtime for paths with a file extension\n const lastSegment = pathname.split('/').pop() ?? '';\n if (lastSegment.includes('.')) {\n const fileResponse = await runtime.handle(pathname);\n if (fileResponse.status === 200) return fileResponse;\n return null;\n }\n\n // Bare paths \u2014 redirect to /app/* in root/only modes, /html/* otherwise.\n const base = (spa === 'root' || spa === 'only') ? appBase : htmlBase;\n const bare = pathname === '/' ? '' : pathname.slice(1).replace(/\\/$/, '');\n return Response.redirect(new URL(`${base}/${bare}`, url.origin), 302);\n }\n\n // \u2500\u2500 Return \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 return {\n handleRequest,\n get htmlRouter() {\n return ssrHtmlRouter;\n },\n get mdRouter() {\n return ssrMdRouter;\n },\n get routeTree() {\n return routeTree;\n },\n get widgetEntries() {\n return discoveredWidgetEntries;\n },\n get shell() {\n return shell;\n },\n };\n}\n", "/**\n * Fetch Runtime\n *\n * Browser-compatible Runtime that delegates all reads to a remote server\n * via `fetch()`. Used by the thin client in `root` mode \u2014 same\n * `createEmrouteServer` runs in the browser, but the Runtime fetches\n * files from the real server instead of reading from disk.\n *\n * No bundling, no transpiling, no filesystem access.\n * No directory scanning \u2014 the remote server already has manifests.\n */\n\nimport {\n type FetchParams,\n type FetchReturn,\n Runtime,\n type RuntimeConfig,\n} from './abstract.runtime.ts';\n\nexport class FetchRuntime extends Runtime {\n private readonly origin: string;\n\n /**\n * @param origin \u2014 Server origin, e.g. `'http://localhost:4100'` or `location.origin`.\n */\n constructor(origin: string, config: RuntimeConfig = {}) {\n super(config);\n this.origin = origin.endsWith('/') ? origin.slice(0, -1) : origin;\n }\n\n handle(\n resource: FetchParams[0],\n init?: FetchParams[1],\n ): FetchReturn {\n const url = this.toUrl(resource);\n return fetch(url, init);\n }\n\n query(\n resource: FetchParams[0],\n options: FetchParams[1] & { as: 'text' },\n ): Promise<string>;\n query(\n resource: FetchParams[0],\n options?: FetchParams[1],\n ): FetchReturn;\n query(\n resource: FetchParams[0],\n options?: FetchParams[1] & { as?: 'text' },\n ): Promise<Response | string> {\n if (options?.as === 'text') {\n return fetch(this.toUrl(resource)).then((r) => r.text());\n }\n return this.handle(resource, options);\n }\n\n override async loadModule(path: string): Promise<unknown> {\n const url = `${this.origin}${path}`;\n const response = await fetch(url);\n const js = await response.text();\n const blob = new Blob([js], { type: 'application/javascript' });\n return import(URL.createObjectURL(blob));\n }\n\n private toUrl(resource: FetchParams[0]): string {\n if (typeof resource === 'string') return `${this.origin}${resource}`;\n if (resource instanceof URL) return `${this.origin}${resource.pathname}${resource.search}`;\n return `${this.origin}${new URL(resource.url).pathname}`;\n }\n}\n", "/// <reference path=\"../../type/navigation-api.d.ts\" />\n\n/**\n * Emroute App\n *\n * Browser entry point for `/app/` routes. Wraps an EmrouteServer instance\n * (same server, same pipeline) with Navigation API glue that intercepts\n * link clicks, calls `htmlRouter.render()`, and injects the result.\n */\n\nimport type { EmrouteServer } from '../../../server/server-api.type.ts';\nimport { createEmrouteServer } from '../../../server/emroute.server.ts';\nimport { FetchRuntime } from '../../../runtime/fetch.runtime.ts';\nimport { ROUTES_MANIFEST_PATH, WIDGETS_MANIFEST_PATH } from '../../../runtime/abstract.runtime.ts';\nimport type { RouteNode } from '../../type/route-tree.type.ts';\nimport type { NavigateOptions } from '../../type/route.type.ts';\nimport type { WidgetManifestEntry } from '../../type/widget.type.ts';\nimport { assertSafeRedirect, type BasePath, DEFAULT_BASE_PATH } from '../../route/route.core.ts';\nimport { escapeHtml } from '../../util/html.util.ts';\nimport { ComponentElement } from '../../element/component.element.ts';\nimport { MarkdownElement } from '../../element/markdown.element.ts';\nimport { WidgetRegistry } from '../../widget/widget.registry.ts';\n\n/** Options for `createEmrouteApp`. */\nexport interface EmrouteAppOptions {\n basePath?: BasePath;\n}\n\n/** Browser app \u2014 Navigation API wired to an EmrouteServer. */\nexport class EmrouteApp {\n private readonly server: EmrouteServer;\n private readonly appBase: string;\n private slot: Element | null = null;\n private abortController: AbortController | null = null;\n\n constructor(server: EmrouteServer, options?: EmrouteAppOptions) {\n const bp = options?.basePath ?? DEFAULT_BASE_PATH;\n this.server = server;\n this.appBase = bp.app;\n }\n\n async initialize(slotSelector = 'router-slot'): Promise<void> {\n this.slot = document.querySelector(slotSelector);\n\n if (!this.slot) {\n console.error('[EmrouteApp] Slot not found:', slotSelector);\n return;\n }\n\n if (!('navigation' in globalThis)) {\n console.warn('[EmrouteApp] Navigation API not available');\n return;\n }\n\n this.abortController = new AbortController();\n const { signal } = this.abortController;\n\n navigation.addEventListener('navigate', (event) => {\n if (!event.canIntercept) return;\n if (event.hashChange) return;\n if (event.downloadRequest !== null) return;\n\n const url = new URL(event.destination.url);\n if (!this.isAppPath(url.pathname)) return;\n\n event.intercept({\n scroll: 'manual',\n handler: async () => {\n await this.handleNavigation(url, event.signal);\n event.scroll();\n },\n });\n }, { signal });\n\n // SSR adoption \u2014 server already rendered this page, skip re-render\n const ssrRoute = this.slot.getAttribute('data-ssr-route');\n if (ssrRoute && (location.pathname === ssrRoute || location.pathname === ssrRoute + '/')) {\n this.slot.removeAttribute('data-ssr-route');\n return;\n }\n\n // Initial render\n await this.handleNavigation(new URL(location.href), this.abortController.signal);\n }\n\n dispose(): void {\n this.abortController?.abort();\n this.abortController = null;\n this.slot = null;\n }\n\n async navigate(url: string, options: NavigateOptions = {}): Promise<void> {\n try {\n const { finished } = navigation.navigate(url, {\n state: options.state,\n history: options.replace ? 'replace' : 'auto',\n });\n await finished;\n } catch (e) {\n if (e instanceof DOMException && e.name === 'AbortError') return;\n throw e;\n }\n }\n\n private isAppPath(pathname: string): boolean {\n return pathname === this.appBase || pathname.startsWith(this.appBase + '/');\n }\n\n private stripAppBase(pathname: string): string {\n if (pathname === this.appBase) return '/';\n if (pathname.startsWith(this.appBase + '/')) return pathname.slice(this.appBase.length);\n return pathname;\n }\n\n private async handleNavigation(url: URL, signal: AbortSignal): Promise<void> {\n if (!this.slot || !this.server.htmlRouter) return;\n\n const routePath = this.stripAppBase(url.pathname);\n const routeUrl = new URL(routePath + url.search, url.origin);\n\n try {\n const { content, title, redirect } = await this.server.htmlRouter.render(routeUrl, signal);\n\n if (signal.aborted) return;\n\n if (redirect) {\n assertSafeRedirect(redirect);\n const target = redirect.startsWith('/') ? this.appBase + redirect : redirect;\n navigation.navigate(target, { history: 'replace' });\n return;\n }\n\n if (document.startViewTransition) {\n const transition = document.startViewTransition(() => {\n this.slot!.setHTMLUnsafe(content);\n });\n signal.addEventListener('abort', () => transition.skipTransition(), { once: true });\n await transition.updateCallbackDone;\n } else {\n this.slot.setHTMLUnsafe(content);\n }\n\n if (title) document.title = title;\n } catch (error) {\n if (signal.aborted) return;\n console.error('[EmrouteApp] Navigation error:', error);\n if (this.slot) {\n const message = error instanceof Error ? error.message : String(error);\n this.slot.setHTMLUnsafe(`<h1>Error</h1><p>${escapeHtml(message)}</p>`);\n }\n }\n }\n}\n\n/**\n * Create and initialize the browser app.\n *\n * Stored on `globalThis.__emroute_app` for programmatic access.\n */\nexport async function createEmrouteApp(\n server: EmrouteServer,\n options?: EmrouteAppOptions,\n): Promise<EmrouteApp> {\n const g = globalThis as Record<string, unknown>;\n if (g.__emroute_app) {\n console.warn('eMroute: App already initialized.');\n return g.__emroute_app as EmrouteApp;\n }\n const app = new EmrouteApp(server, options);\n await app.initialize();\n g.__emroute_app = app;\n return app;\n}\n\n// \u2500\u2500 Boot \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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/** Options for `bootEmrouteApp`. */\nexport interface BootOptions extends EmrouteAppOptions {\n /** Override the server origin (defaults to `location.origin`). */\n origin?: string;\n}\n\n/**\n * Boot the browser app from runtime manifests.\n *\n * Fetches route tree and widget manifest as JSON, creates lazy module\n * loaders via FetchRuntime, registers widgets for deferred hydration,\n * and wires the Navigation API.\n *\n * Consumer `main.ts` calls this after setting up MarkdownElement renderer,\n * custom elements, etc.\n */\nexport async function bootEmrouteApp(options?: BootOptions): Promise<EmrouteApp> {\n const origin = options?.origin ?? location.origin;\n const runtime = new FetchRuntime(origin);\n\n // Fetch route tree\n const routesResponse = await runtime.handle(ROUTES_MANIFEST_PATH);\n if (!routesResponse.ok) {\n throw new Error(`[emroute] Failed to fetch ${ROUTES_MANIFEST_PATH}: ${routesResponse.status}`);\n }\n const routeTree: RouteNode = await routesResponse.json();\n\n // Fetch widget manifest (optional \u2014 app may have no widgets)\n const widgetsResponse = await runtime.handle(WIDGETS_MANIFEST_PATH);\n const widgetEntries: WidgetManifestEntry[] = widgetsResponse.ok\n ? await widgetsResponse.json()\n : [];\n\n // Build lazy module loaders for all route + widget modules\n const moduleLoaders = buildLazyLoaders(routeTree, widgetEntries, runtime);\n\n // Register widgets eagerly (tag defined immediately, module loads on connectedCallback)\n const widgets = new WidgetRegistry();\n for (const entry of widgetEntries) {\n ComponentElement.registerLazy(entry.name, entry.files, moduleLoaders[entry.modulePath]);\n }\n\n // Create the server (reuses the same createEmrouteServer as SSR)\n const server = await createEmrouteServer({\n routeTree,\n widgets,\n moduleLoaders,\n markdownRenderer: MarkdownElement.getConfiguredRenderer() ?? undefined,\n }, runtime);\n\n return createEmrouteApp(server, options);\n}\n\n/**\n * Walk the route tree and widget entries to build a map of\n * `path \u2192 () => runtime.loadModule(path)` lazy loaders.\n */\nfunction buildLazyLoaders(\n tree: RouteNode,\n widgetEntries: WidgetManifestEntry[],\n runtime: FetchRuntime,\n): Record<string, () => Promise<unknown>> {\n const paths = new Set<string>();\n\n function walk(node: RouteNode): void {\n const modulePath = node.files?.ts ?? node.files?.js;\n if (modulePath) paths.add(modulePath);\n if (node.redirect) paths.add(node.redirect);\n if (node.errorBoundary) paths.add(node.errorBoundary);\n if (node.children) {\n for (const child of Object.values(node.children)) walk(child);\n }\n if (node.dynamic) walk(node.dynamic.child);\n if (node.wildcard) walk(node.wildcard.child);\n }\n\n walk(tree);\n for (const entry of widgetEntries) paths.add(entry.modulePath);\n\n const loaders: Record<string, () => Promise<unknown>> = {};\n for (const path of paths) {\n const absolute = path.startsWith('/') ? path : '/' + path;\n loaders[path] = () => runtime.loadModule(absolute);\n }\n return loaders;\n}\n", "/**\n * WidgetComponent \u2014 embeddable unit within page content.\n *\n * Everything reusable that is not a page is a Widget.\n * Widgets render across all contexts (HTML, Markdown, SPA) and are\n * resolved by name via WidgetRegistry.\n *\n * Pages live in the routes manifest. Widgets live in the registry.\n *\n * Default rendering fallback chains (parallel to PageComponent):\n * - renderHTML: html file \u2192 md file in <mark-down> \u2192 base Component default\n * - renderMarkdown: md file \u2192 ''\n */\n\nimport { Component, type ComponentContext } from './abstract.component.ts';\nimport { escapeHtml, scopeWidgetCss } from '../util/html.util.ts';\n\nexport abstract class WidgetComponent<\n TParams = unknown,\n TData = unknown,\n TContext extends ComponentContext = ComponentContext,\n> extends Component<TParams, TData, TContext> {\n /**\n * Render widget as HTML.\n *\n * Fallback chain:\n * 1. html file content from context\n * 2. md file content wrapped in `<mark-down>`\n * 3. base Component default (markdown\u2192HTML conversion)\n *\n * @example\n * ```ts\n * override renderHTML({ data, params }: this['RenderArgs']) {\n * return `<span>${params.coin}: $${data?.price}</span>`;\n * }\n * ```\n */\n override renderHTML(\n args: this['RenderArgs'],\n ): string {\n const files = args.context.files;\n // @scope needed for SSR Light DOM output; redundant but harmless in SPA Shadow DOM\n const style = files?.css ? `<style>${scopeWidgetCss(files.css, this.name)}</style>\\n` : '';\n\n if (files?.html) {\n return style + files.html;\n }\n\n if (files?.md) {\n return `${style}<mark-down>${escapeHtml(files.md)}</mark-down>`;\n }\n\n if (style) {\n return style + super.renderHTML(args);\n }\n\n return super.renderHTML(args);\n }\n\n /**\n * Render widget as Markdown.\n *\n * Fallback chain:\n * 1. md file content from context\n * 2. empty string\n *\n * @example\n * ```ts\n * override renderMarkdown({ data, params }: this['RenderArgs']) {\n * return `**${params.coin}**: $${data?.price}`;\n * }\n * ```\n */\n override renderMarkdown(\n args: this['RenderArgs'],\n ): string {\n const files = args.context.files;\n\n if (files?.md) {\n return files.md;\n }\n\n return '';\n }\n}\n", "/**\n * Overlay Default CSS\n *\n * Styles for modals, toasts, and popovers. Works for both declarative\n * (commandfor/command + HTML attributes) and programmatic (OverlayService)\n * overlays. Uses CSS custom properties for theming.\n */\n\nexport const overlayCSS: string = /* css */ `\n:root {\n --overlay-backdrop: oklch(0% 0 0 / 0.5);\n --overlay-surface: oklch(100% 0 0);\n --overlay-radius: 8px;\n --overlay-shadow: 0 8px 32px oklch(0% 0 0 / 0.2);\n --overlay-toast-gap: 8px;\n --overlay-toast-duration: 5s;\n --overlay-z: 1000;\n}\n\n/* --- Modal (dialog) --- */\n\ndialog[data-overlay-modal] {\n border: none;\n padding: 0;\n background: var(--overlay-surface);\n border-radius: var(--overlay-radius);\n box-shadow: var(--overlay-shadow);\n max-width: min(90vw, 560px);\n max-height: 85vh;\n overflow: auto;\n opacity: 1;\n translate: 0 0;\n transition:\n opacity 200ms,\n translate 200ms;\n}\n\ndialog[data-overlay-modal][open] {\n transition:\n opacity 200ms,\n translate 200ms,\n display 200ms allow-discrete,\n overlay 200ms allow-discrete;\n\n @starting-style {\n opacity: 0;\n translate: 0 20px;\n }\n}\n\ndialog[data-overlay-modal]::backdrop {\n background: var(--overlay-backdrop);\n opacity: 1;\n transition: opacity 200ms;\n}\n\ndialog[data-overlay-modal][open]::backdrop {\n transition:\n opacity 200ms,\n display 200ms allow-discrete,\n overlay 200ms allow-discrete;\n\n @starting-style {\n opacity: 0;\n }\n}\n\ndialog[data-overlay-modal][data-dismissing] {\n opacity: 0;\n translate: 0 20px;\n}\n\ndialog[data-overlay-modal][data-dismissing]::backdrop {\n opacity: 0;\n}\n\n/* --- Toast container --- */\n\n[data-overlay-toast-container] {\n position: fixed;\n bottom: 16px;\n right: 16px;\n z-index: var(--overlay-z);\n display: flex;\n flex-direction: column;\n gap: var(--overlay-toast-gap);\n pointer-events: none;\n}\n\n/* --- Toast item --- */\n\n[data-overlay-toast] {\n pointer-events: auto;\n background: var(--overlay-surface);\n border-radius: var(--overlay-radius);\n box-shadow: var(--overlay-shadow);\n padding: 12px 16px;\n animation: overlay-toast-auto var(--overlay-toast-duration, 5s) ease-in-out forwards;\n}\n\n/* Manual toast (timeout: 0): no auto-dismiss, entry transition only */\n[data-overlay-toast][data-toast-manual] {\n animation: none;\n opacity: 1;\n translate: 0 0;\n transition:\n opacity 200ms,\n translate 200ms;\n\n @starting-style {\n opacity: 0;\n translate: 20px 0;\n }\n}\n\n/* Dismissed toast: CSS exit animation */\n[data-overlay-toast][data-dismissing] {\n animation: overlay-toast-exit 200ms ease-in forwards;\n}\n\n@keyframes overlay-toast-auto {\n 0% { opacity: 0; translate: 20px 0; }\n 10% { opacity: 1; translate: 0 0; }\n 80% { opacity: 1; translate: 0 0; }\n 100% { opacity: 0; translate: 0 0; display: none; }\n}\n\n@keyframes overlay-toast-exit {\n to { opacity: 0; translate: 20px 0; display: none; }\n}\n\n/* --- Popover --- */\n\n[data-overlay-popover] {\n border: none;\n padding: 0;\n margin: 0;\n background: var(--overlay-surface);\n border-radius: var(--overlay-radius);\n box-shadow: var(--overlay-shadow);\n opacity: 1;\n scale: 1;\n transition:\n opacity 200ms,\n scale 200ms;\n}\n\n[data-overlay-popover]:popover-open {\n position-anchor: auto;\n inset: unset;\n top: anchor(bottom);\n left: anchor(start);\n margin-top: 4px;\n transition:\n opacity 200ms,\n scale 200ms,\n display 200ms allow-discrete,\n overlay 200ms allow-discrete;\n\n @starting-style {\n opacity: 0;\n scale: 0.95;\n }\n}\n\n[data-overlay-popover][data-dismissing] {\n opacity: 0;\n scale: 0.95;\n}\n`;\n", "/**\n * Overlay Service\n *\n * Programmatic API for modals, toasts, and popovers. For simple trigger\n * patterns, use declarative HTML (commandfor/command + popover/dialog)\n * with zero JS. This service covers dynamic content, programmatic\n * triggers, and complex workflows.\n *\n * dismissAll() is DOM-aware: it closes both programmatic overlays\n * managed by this service AND declarative popovers/dialogs found\n * via DOM queries.\n */\n\nimport type { ModalOptions, OverlayService, PopoverOptions, ToastOptions } from './overlay.type.ts';\nimport { overlayCSS } from './overlay.css.ts';\n\nconst ANIMATION_SAFETY_TIMEOUT = 300;\n\n/**\n * Animate an element out by setting `data-dismissing`, waiting for\n * `transitionend`, then calling the provided callback. Includes a\n * safety timeout in case the transition event never fires.\n */\nfunction animateDismiss(el: HTMLElement, onDone: () => void): void {\n el.setAttribute('data-dismissing', '');\n\n let done = false;\n const finish = () => {\n if (done) return;\n done = true;\n onDone();\n };\n\n el.addEventListener('transitionend', finish, { once: true });\n setTimeout(finish, ANIMATION_SAFETY_TIMEOUT);\n}\n\nexport function createOverlayService(): OverlayService {\n let styleInjected = false;\n\n // Modal state\n let dialog: HTMLDialogElement | null = null;\n // Uses `any` because modalResolve is reassigned across multiple modal() calls\n // with different type parameters T. Each call creates a Promise.withResolvers<T>(),\n // so the resolver function signature changes (accepts T | PromiseLike<T | undefined>).\n // Type safety is maintained by closeModal<T>(value?: T) which ensures only valid\n // types are passed to the resolver.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let modalResolve: ((value: any) => void) | null = null;\n let modalOnClose: (() => void) | undefined;\n\n // Toast state\n let toastContainer: HTMLDivElement | null = null;\n\n // Popover state\n let popoverEl: HTMLDivElement | null = null;\n let popoverAnchorObserver: MutationObserver | null = null;\n const supportsAnchor = typeof CSS !== 'undefined' &&\n CSS.supports('anchor-name', '--a');\n\n function injectCSS(): void {\n if (styleInjected) return;\n styleInjected = true;\n const style = document.createElement('style');\n style.textContent = overlayCSS;\n document.head.appendChild(style);\n }\n\n function ensureDialog(): HTMLDialogElement {\n if (dialog) return dialog;\n injectCSS();\n dialog = document.createElement('dialog');\n dialog.setAttribute('data-overlay-modal', '');\n document.body.appendChild(dialog);\n\n dialog.addEventListener('click', (e) => {\n if (e.target === dialog) {\n closeModal(undefined);\n }\n });\n\n return dialog;\n }\n\n function ensureToastContainer(): HTMLDivElement {\n if (toastContainer) return toastContainer;\n injectCSS();\n toastContainer = document.createElement('div');\n toastContainer.setAttribute('data-overlay-toast-container', '');\n document.body.appendChild(toastContainer);\n return toastContainer;\n }\n\n function ensurePopover(): HTMLDivElement {\n if (popoverEl) return popoverEl;\n injectCSS();\n popoverEl = document.createElement('div');\n popoverEl.setAttribute('data-overlay-popover', '');\n popoverEl.setAttribute('popover', '');\n document.body.appendChild(popoverEl);\n return popoverEl;\n }\n\n // --- Modal ---\n\n function modal<T = undefined>(options: ModalOptions<T>): Promise<T | undefined> {\n const d = ensureDialog();\n\n // Clean up any lingering dismiss state from a previous close\n d.removeAttribute('data-dismissing');\n\n // Immediately dismiss popover \u2014 modal takes over the top layer\n hidePopoverImmediate();\n\n // Last wins: close current modal if open\n if (d.open) {\n d.close();\n if (modalResolve) {\n modalResolve(undefined);\n modalResolve = null;\n }\n if (modalOnClose) {\n modalOnClose();\n modalOnClose = undefined;\n }\n }\n\n d.innerHTML = '';\n options.render(d);\n modalOnClose = options.onClose;\n\n const { promise, resolve } = Promise.withResolvers<T | undefined>();\n modalResolve = resolve;\n\n d.showModal();\n\n return promise;\n }\n\n function closeModal<T>(value?: T): void {\n if (!dialog || !dialog.open) return;\n\n const resolve = modalResolve;\n const onClose = modalOnClose;\n const dialogRef = dialog;\n modalResolve = null;\n modalOnClose = undefined;\n\n animateDismiss(dialogRef, () => {\n if (dialogRef && dialogRef.open) {\n dialogRef.close();\n if (resolve) resolve(value);\n if (onClose) onClose();\n }\n });\n }\n\n // --- Toast ---\n\n /** Remove dead toasts (dismissed or animation-finished) from container. */\n function clearDeadToasts(container: HTMLDivElement): void {\n for (const child of [...container.children]) {\n const el = child as HTMLElement;\n if (el.hasAttribute('data-dismissing')) {\n el.remove();\n }\n }\n }\n\n function toast(options: ToastOptions): { dismiss(): void } {\n const container = ensureToastContainer();\n\n // Clean up dead toasts before adding a new one\n clearDeadToasts(container);\n\n const el = document.createElement('div');\n el.setAttribute('data-overlay-toast', '');\n\n const timeout = options.timeout ?? 0;\n if (timeout === 0) {\n el.setAttribute('data-toast-manual', '');\n } else {\n el.style.setProperty('--overlay-toast-duration', `${timeout}ms`);\n }\n\n options.render(el);\n container.appendChild(el);\n\n let dismissed = false;\n const dismiss = () => {\n if (dismissed) return;\n dismissed = true;\n el.setAttribute('data-dismissing', '');\n };\n\n return { dismiss };\n }\n\n // --- Popover ---\n\n function popover(options: PopoverOptions): void {\n const el = ensurePopover();\n\n // Last wins: hide current popover if showing\n cleanupPopoverAnchorObserver();\n try {\n el.hidePopover();\n } catch {\n // Not shown \u2014 ignore\n }\n el.removeAttribute('data-dismissing');\n\n el.innerHTML = '';\n options.render(el);\n\n // Anchor positioning\n if (supportsAnchor) {\n const anchorName = '--overlay-anchor';\n options.anchor.style.setProperty('anchor-name', anchorName);\n el.style.setProperty('position-anchor', anchorName);\n el.style.removeProperty('top');\n el.style.removeProperty('left');\n } else {\n const rect = options.anchor.getBoundingClientRect();\n el.style.top = `${rect.bottom + globalThis.scrollY}px`;\n el.style.left = `${rect.left + globalThis.scrollX}px`;\n el.style.position = 'absolute';\n }\n\n el.showPopover();\n\n // Watch for anchor disconnect\n watchAnchorDisconnect(options.anchor);\n }\n\n function watchAnchorDisconnect(anchor: HTMLElement): void {\n cleanupPopoverAnchorObserver();\n\n const parent = anchor.parentNode;\n if (!parent) {\n closePopover();\n return;\n }\n\n popoverAnchorObserver = new MutationObserver(() => {\n if (!document.contains(anchor)) {\n closePopover();\n }\n });\n\n popoverAnchorObserver.observe(parent, { childList: true });\n }\n\n /** Hide popover instantly without dismiss animation. */\n function hidePopoverImmediate(): void {\n cleanupPopoverAnchorObserver();\n if (!popoverEl) return;\n try {\n popoverEl.hidePopover();\n } catch {\n // Not shown \u2014 ignore\n }\n popoverEl.removeAttribute('data-dismissing');\n }\n\n function cleanupPopoverAnchorObserver(): void {\n if (popoverAnchorObserver) {\n popoverAnchorObserver.disconnect();\n popoverAnchorObserver = null;\n }\n }\n\n function closePopover(): void {\n cleanupPopoverAnchorObserver();\n\n if (!popoverEl) return;\n\n // Check if popover is showing via matches(':popover-open')\n let isOpen: boolean;\n try {\n isOpen = popoverEl.matches(':popover-open');\n } catch {\n // :popover-open may not be supported \u2014 fall back\n isOpen = popoverEl.hasAttribute('popover') && popoverEl.style.display !== 'none';\n }\n\n if (!isOpen) return;\n\n animateDismiss(popoverEl, () => {\n try {\n popoverEl!.hidePopover();\n } catch {\n // Already hidden\n }\n });\n }\n\n // --- Dismiss all ---\n\n function dismissAll(): void {\n // Close programmatic modal\n if (dialog && dialog.open) {\n const resolve = modalResolve;\n const onClose = modalOnClose;\n modalResolve = null;\n modalOnClose = undefined;\n\n dialog.removeAttribute('data-dismissing');\n dialog.close();\n\n if (resolve) resolve(undefined);\n if (onClose) onClose();\n }\n\n // Hide programmatic popover\n hidePopoverImmediate();\n\n // Dismiss all toasts via CSS\n if (toastContainer) {\n for (const child of toastContainer.children) {\n (child as HTMLElement).setAttribute('data-dismissing', '');\n }\n }\n\n // Close declarative popovers found in the DOM\n try {\n for (const el of document.querySelectorAll(':popover-open')) {\n (el as HTMLElement).hidePopover();\n }\n } catch {\n // :popover-open not supported\n }\n\n // Close declarative dialogs found in the DOM (skip our own)\n for (const el of document.querySelectorAll<HTMLDialogElement>('dialog[open]')) {\n if (el !== dialog) el.close();\n }\n }\n\n return {\n modal,\n closeModal,\n toast,\n popover,\n closePopover,\n dismissAll,\n };\n}\n", "/**\n * Built-in Page Title Widget\n *\n * Sets document.title from .page.html and .page.md files without needing\n * a .page.ts component. Renders no visible output.\n *\n * Usage in .page.html:\n * <widget-page-title title=\"About Us\"></widget-page-title>\n */\n\nimport { WidgetComponent } from '../component/widget.component.ts';\n\ninterface PageTitleParams {\n title: string;\n}\n\ninterface PageTitleData {\n title: string;\n}\n\nexport class PageTitleWidget extends WidgetComponent<PageTitleParams, PageTitleData> {\n override readonly name = 'page-title';\n\n override getData(\n args: { params: PageTitleParams; signal?: AbortSignal },\n ): Promise<PageTitleData | null> {\n return Promise.resolve({ title: args.params.title });\n }\n\n override renderHTML(\n args: { data: PageTitleData | null; params: PageTitleParams },\n ): string {\n const title = args.data?.title ?? args.params.title;\n if (title && typeof document !== 'undefined') {\n document.title = title;\n }\n return '';\n }\n\n override renderMarkdown(\n _args: { data: PageTitleData | null; params: PageTitleParams },\n ): string {\n return '';\n }\n\n override validateParams(params: PageTitleParams): string | undefined {\n if (!params.title || typeof params.title !== 'string') {\n return 'page-title widget requires a \"title\" string param';\n }\n return undefined;\n }\n}\n", "/**\n * Built-in Breadcrumb Widget\n *\n * Renders breadcrumb navigation from the current URL path.\n * Uses /html/ prefix for links (content-first routing convention).\n *\n * Usage in .page.html:\n * <widget-breadcrumb></widget-breadcrumb>\n * <widget-breadcrumb separator=\" / \" class=\"my-breadcrumbs\"></widget-breadcrumb>\n *\n * Usage in .page.md:\n * ```widget:breadcrumb\n * {}\n * ```\n */\n\nimport { WidgetComponent } from '../component/widget.component.ts';\nimport { escapeHtml } from '../util/html.util.ts';\nimport type { ComponentContext } from '../component/abstract.component.ts';\n\nconst DEFAULT_HTML_SEPARATOR = ' \\u203A ';\nconst DEFAULT_MD_SEPARATOR = ' > ';\n\ninterface BreadcrumbParams {\n separator?: string;\n class?: string;\n}\n\ninterface BreadcrumbSegment {\n label: string;\n href: string;\n}\n\ninterface BreadcrumbData {\n segments: BreadcrumbSegment[];\n}\n\nexport class BreadcrumbWidget extends WidgetComponent<BreadcrumbParams, BreadcrumbData> {\n override readonly name = 'breadcrumb';\n\n override getData(\n args: { params: BreadcrumbParams; signal?: AbortSignal; context: ComponentContext },\n ): Promise<BreadcrumbData | null> {\n const pathname = args.context.pathname || '/';\n const parts = pathname.split('/').filter(Boolean);\n\n const segments: BreadcrumbSegment[] = [\n { label: 'Home', href: '/' },\n ];\n\n let accumulated = '';\n for (const part of parts) {\n accumulated += '/' + part;\n segments.push({\n label: part.charAt(0).toUpperCase() + part.slice(1).replace(/-/g, ' '),\n href: accumulated,\n });\n }\n\n return Promise.resolve({ segments });\n }\n\n override renderHTML(\n args: { data: BreadcrumbData | null; params: BreadcrumbParams; context: ComponentContext },\n ): string {\n if (!args.data || args.data.segments.length === 0) return '';\n\n const sep = args.params.separator ?? DEFAULT_HTML_SEPARATOR;\n const segments = args.data.segments;\n\n const items = segments.map((seg, i) => {\n const escaped = escapeHtml(seg.label);\n if (i === segments.length - 1) {\n return `<span aria-current=\"page\">${escaped}</span>`;\n }\n return `<a href=\"${escapeHtml(seg.href)}\">${escaped}</a>`;\n });\n\n return `<nav aria-label=\"Breadcrumb\">${items.join(escapeHtml(sep))}</nav>`;\n }\n\n override renderMarkdown(\n args: { data: BreadcrumbData | null; params: BreadcrumbParams; context: ComponentContext },\n ): string {\n if (!args.data || args.data.segments.length === 0) return '';\n\n const sep = args.params.separator ?? DEFAULT_MD_SEPARATOR;\n return args.data.segments\n .map((seg, i, arr) =>\n i === arr.length - 1 ? `**${seg.label}**` : `[${seg.label}](${seg.href})`\n )\n .join(sep);\n }\n}\n", "/**\n * SPA (Browser) Module\n *\n * Everything needed for the browser bundle:\n * - EmrouteApp: Navigation API glue wired to an EmrouteServer\n * - Custom elements for rendering and hydrating SSR islands\n * - Widget registry (built-in widgets are opt-in)\n */\n\nimport { RouterSlot } from '../../element/slot.element.ts';\nimport { MarkdownElement } from '../../element/markdown.element.ts';\nimport { ComponentElement } from '../../element/component.element.ts';\nimport { WidgetRegistry } from '../../widget/widget.registry.ts';\n\nexport { bootEmrouteApp, createEmrouteApp, EmrouteApp, type BootOptions, type EmrouteAppOptions } from './thin-client.ts';\nexport { ComponentElement, MarkdownElement, RouterSlot, WidgetRegistry };\nexport type { SpaMode, WidgetsManifest } from '../../type/widget.type.ts';\n\n// Re-export base classes and types for consumer code (pages, widgets)\nexport { PageComponent } from '../../component/page.component.ts';\nexport { WidgetComponent } from '../../component/widget.component.ts';\nexport {\n Component,\n type ComponentContext,\n type ComponentManifestEntry,\n type ContextProvider,\n type RenderContext,\n} from '../../component/abstract.component.ts';\nexport type {\n MatchedRoute,\n NavigateOptions,\n RouteParams,\n RouterEvent,\n RouterEventListener,\n RouterEventType,\n} from '../../type/route.type.ts';\nexport type { RouteNode } from '../../type/route-tree.type.ts';\nexport type { RouteResolver, ResolvedRoute } from '../../route/route.resolver.ts';\nexport { RouteTrie } from '../../route/route.trie.ts';\nexport type { MarkdownRenderer } from '../../type/markdown.type.ts';\nexport { type BasePath, DEFAULT_BASE_PATH } from '../../route/route.core.ts';\nexport { escapeHtml, scopeWidgetCss } from '../../util/html.util.ts';\nexport type {\n ErrorBoundary,\n RedirectConfig,\n RouteConfig,\n RouteFiles,\n RouteFileType,\n RouteInfo,\n RouterState,\n} from '../../type/route.type.ts';\nexport type { ParsedWidgetBlock, WidgetManifestEntry } from '../../type/widget.type.ts';\nexport { type Logger, setLogger } from '../../type/logger.type.ts';\n\n// Register core custom elements in the browser\nif (globalThis.customElements) {\n if (!customElements.get('router-slot')) customElements.define('router-slot', RouterSlot);\n if (!customElements.get('mark-down')) customElements.define('mark-down', MarkdownElement);\n}\n\n// Overlay API (tree-shakeable - only bundled if imported)\nexport { createOverlayService } from '../../overlay/overlay.service.ts';\nexport type {\n ModalOptions,\n OverlayService,\n PopoverOptions,\n ToastOptions,\n} from '../../overlay/overlay.type.ts';\n\n// Optional: Built-in widgets (tree-shakeable - only bundled if imported)\nexport { PageTitleWidget } from '../../widget/page-title.widget.ts';\nexport { BreadcrumbWidget } from '../../widget/breadcrumb.widget.ts';\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Core HTML utilities for emroute\n */\n\n/** HTML attribute name marking a widget as server-rendered (skip client getData + render). */\nexport const SSR_ATTR = 'ssr';\n\n/** HTML attribute name for lazy-loading widgets via IntersectionObserver. */\nexport const LAZY_ATTR = 'lazy';\n\n/**\n * SSR-compatible ShadowRoot mock.\n * Provides a 1-to-1 subset of the browser ShadowRoot API for server-side rendering.\n */\nclass SsrShadowRoot {\n private _innerHTML = '';\n\n constructor(public readonly host: SsrHTMLElement) {}\n\n get innerHTML(): string {\n return this._innerHTML;\n }\n\n set innerHTML(value: string) {\n this._innerHTML = value;\n }\n\n setHTMLUnsafe(html: string, _options?: Record<string, unknown>): void {\n this._innerHTML = html;\n }\n\n append(..._nodes: (Node | string)[]): void {\n // On the server, append is a no-op \u2014 SSR content is already serialized via innerHTML.\n }\n\n querySelector(_selector: string): Element | null {\n return null;\n }\n\n querySelectorAll(_selector: string): Element[] {\n return [];\n }\n\n get childNodes(): Node[] {\n return [];\n }\n\n get firstChild(): Node | null {\n return null;\n }\n}\n\n/**\n * SSR-compatible HTMLElement mock.\n * Provides a 1-to-1 subset of the browser HTMLElement API for server-side rendering.\n * Methods that require DOM parsing (querySelector, childNodes) return empty results \u2014\n * SSR code should use innerHTML for content, not DOM traversal.\n */\nclass SsrHTMLElement {\n private _innerHTML = '';\n private _shadowRoot: SsrShadowRoot | null = null;\n private _attributes = new Map<string, string>();\n // Accept any CSS property assignment without error\n readonly style = new Proxy({} as CSSStyleDeclaration, {\n set(_target, _prop, _value) {\n return true;\n },\n get(_target, prop) {\n if (typeof prop === 'string') return '';\n return undefined;\n },\n });\n\n get innerHTML(): string {\n return this._innerHTML;\n }\n\n set innerHTML(value: string) {\n this._innerHTML = value;\n }\n\n get shadowRoot(): ShadowRoot | null {\n return this._shadowRoot as unknown as ShadowRoot;\n }\n\n get childNodes(): Node[] {\n return [];\n }\n\n get firstChild(): Node | null {\n return null;\n }\n\n get attributes(): NamedNodeMap {\n const attrs: Attr[] = [];\n for (const [name, value] of this._attributes) {\n attrs.push({ name, value } as Attr);\n }\n return attrs as unknown as NamedNodeMap;\n }\n\n attachShadow(_init: ShadowRootInit): ShadowRoot {\n this._shadowRoot = new SsrShadowRoot(this);\n return this._shadowRoot as unknown as ShadowRoot;\n }\n\n getAttribute(name: string): string | null {\n return this._attributes.get(name) ?? null;\n }\n\n setAttribute(name: string, value: string): void {\n this._attributes.set(name, value);\n }\n\n removeAttribute(name: string): void {\n this._attributes.delete(name);\n }\n\n hasAttribute(name: string): boolean {\n return this._attributes.has(name);\n }\n\n querySelector(_selector: string): Element | null {\n return null;\n }\n\n querySelectorAll(_selector: string): Element[] {\n return [];\n }\n\n append(..._nodes: (Node | string)[]): void {\n // No-op on server \u2014 use innerHTML for content\n }\n\n appendChild(node: Node): Node {\n return node;\n }\n}\n\n/** Server-safe base class: HTMLElement in browser, SSR mock on server. */\nexport const HTMLElementBase = globalThis.HTMLElement ??\n (SsrHTMLElement as unknown as typeof HTMLElement);\n\n/**\n * Escape HTML entities for safe display.\n */\nexport function escapeHtml(text: string): string {\n return text\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;')\n .replaceAll(\"'\", '&#39;')\n .replaceAll('`', '&#96;');\n}\n\n/**\n * Unescape HTML entities back to plain text (server-side, no DOM).\n */\nexport function unescapeHtml(text: string): string {\n return text\n .replaceAll('&#96;', '`')\n .replaceAll('&#39;', \"'\")\n .replaceAll('&quot;', '\"')\n .replaceAll('&gt;', '>')\n .replaceAll('&lt;', '<')\n .replaceAll('&amp;', '&');\n}\n\n/**\n * Wrap CSS in a `@scope` rule scoped to the widget's custom element tag.\n * Used by `WidgetComponent.renderHTML()` for companion CSS files.\n */\nexport function scopeWidgetCss(css: string, widgetName: string): string {\n return `@scope (widget-${widgetName}) {\\n${css}\\n}`;\n}\n\n/**\n * Status code to message mapping.\n */\nexport const STATUS_MESSAGES: Record<number, string> = {\n 401: 'Unauthorized',\n 403: 'Forbidden',\n 404: 'Not Found',\n 500: 'Internal Server Error',\n};\n", "/**\n * Router Slot Element\n *\n * <router-slot> is where page content is rendered.\n * Supports nested routes via parent page containing slot.\n *\n * Usage:\n * ```html\n * <router-slot></router-slot>\n * ```\n *\n * For nested routes, parent page includes:\n * ```typescript\n * export default function render() {\n * return `\n * <header>...</header>\n * <main>\n * <router-slot></router-slot>\n * </main>\n * `;\n * }\n * ```\n */\n\nimport { HTMLElementBase } from '../util/html.util.ts';\n\n/**\n * Router slot web component.\n * Serves as the mounting point for page content.\n */\nexport class RouterSlot extends HTMLElementBase {}\n", "/**\n * Markdown Element \u2014 <mark-down> custom element.\n *\n * Renders markdown content with pluggable renderer.\n * Supports:\n * - Inline content: <mark-down># Title</mark-down>\n * - Source attribute: <mark-down src=\"/path/to.md\"></mark-down>\n */\n\nimport { escapeHtml, HTMLElementBase } from '../util/html.util.ts';\nimport type { MarkdownRenderer } from '../type/markdown.type.ts';\n\nexport class MarkdownElement extends HTMLElementBase {\n private static renderer: MarkdownRenderer | null = null;\n private static rendererInitPromise: Promise<void> | null = null;\n private abortController: AbortController | null = null;\n\n /**\n * Set the markdown renderer.\n * Must be called before any <mark-down> elements are connected.\n *\n * @example\n * ```ts\n * import { createEmkoRenderer } from './emko.renderer.ts';\n * MarkdownElement.setRenderer(await createEmkoRenderer());\n * ```\n */\n static setRenderer(renderer: MarkdownRenderer): void {\n MarkdownElement.renderer = renderer;\n MarkdownElement.rendererInitPromise = renderer.init ? renderer.init() : null;\n }\n\n /** Get the current renderer (if set). Used by bootEmrouteApp to pass through to createEmrouteServer. */\n static getConfiguredRenderer(): MarkdownRenderer | null {\n return MarkdownElement.renderer;\n }\n\n /**\n * Get the current renderer, waiting for init if needed.\n */\n private static async getRenderer(): Promise<MarkdownRenderer> {\n const renderer = MarkdownElement.renderer;\n if (!renderer) {\n throw new Error(\n 'No markdown renderer configured. Call MarkdownElement.setRenderer() before using <mark-down> elements.',\n );\n }\n\n if (MarkdownElement.rendererInitPromise) {\n await MarkdownElement.rendererInitPromise;\n }\n\n return renderer;\n }\n\n async connectedCallback(): Promise<void> {\n this.abortController = new AbortController();\n await this.loadContent();\n }\n\n disconnectedCallback(): void {\n this.abortController?.abort();\n this.abortController = null;\n }\n\n private async loadContent(): Promise<void> {\n const src = this.getAttribute('src');\n const inlineContent = this.textContent?.trim();\n\n if (src) {\n await this.loadFromSrc(src);\n } else if (inlineContent) {\n await this.renderContent(inlineContent);\n } else {\n this.innerHTML = '';\n }\n }\n\n private async loadFromSrc(src: string): Promise<void> {\n const signal = this.abortController?.signal;\n\n try {\n const response = await fetch(src, signal ? { signal } : {});\n\n if (!response.ok) {\n throw new Error(`Failed to fetch ${src}: ${response.status}`);\n }\n\n const markdown = await response.text();\n await this.renderContent(markdown);\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n return;\n }\n this.showError(error);\n }\n }\n\n private async renderContent(markdown: string): Promise<void> {\n try {\n const renderer = await MarkdownElement.getRenderer();\n this.innerHTML = renderer.render(markdown);\n } catch (error) {\n this.showError(error);\n }\n }\n\n private showError(error: unknown): void {\n const message = error instanceof Error ? error.message : String(error);\n this.innerHTML = `<div>Markdown Error: ${escapeHtml(message)}</div>`;\n }\n}\n", "/**\n * Widget Element - Browser Custom Element\n *\n * Renders Widget instances in the browser as `widget-{name}` elements.\n * Handles:\n * - SSR hydration (ssr attribute)\n * - Client-side data fetching with AbortSignal\n * - Companion file loading (html, md, css) with caching\n * - Loading/error states\n */\n\nimport type {\n Component,\n ComponentContext,\n ContextProvider,\n} from '../component/abstract.component.ts';\nimport { HTMLElementBase, LAZY_ATTR, SSR_ATTR } from '../util/html.util.ts';\n\ntype ComponentState = 'idle' | 'loading' | 'ready' | 'error';\n\n/** Strip keys with undefined values \u2014 returns the filtered object, or undefined if all values are undefined. */\nfunction filterUndefined<T extends Record<string, unknown>>(obj: T): { [K in keyof T as T[K] extends undefined ? never : K]: NonNullable<T[K]> } | undefined {\n const result: Record<string, unknown> = {};\n let hasValue = false;\n for (const [k, v] of Object.entries(obj)) {\n if (v !== undefined) { result[k] = v; hasValue = true; }\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return hasValue ? result as any : undefined;\n}\n\ntype WidgetFiles = { html?: string; md?: string; css?: string };\n\n/**\n * Custom element that renders a Component in the browser.\n */\nexport class ComponentElement<TParams, TData> extends HTMLElementBase {\n /** Shared file content cache \u2014 deduplicates fetches across all widget instances. */\n private static fileCache = new Map<string, Promise<string | undefined>>();\n\n /** Lazy module loaders keyed by tag name \u2014 set by registerLazy(). */\n private static lazyLoaders = new Map<string, () => Promise<unknown>>();\n\n /** Cached module promises for lazy-loaded widgets \u2014 avoids re-fetching. */\n private static lazyModules = new Map<string, Promise<unknown>>();\n\n /** App-level context provider set once during router initialization. */\n private static extendContext: ContextProvider | undefined;\n\n /** Register (or clear) the context provider that enriches every widget's ComponentContext. */\n static setContextProvider(provider: ContextProvider | undefined): void {\n ComponentElement.extendContext = provider;\n }\n\n private component: Component<TParams, TData>;\n private effectiveFiles?: WidgetFiles | undefined;\n private params: TParams | null = null;\n private data: TData | null = null;\n private context!: ComponentContext;\n private state: ComponentState = 'idle';\n private errorMessage = '';\n private deferred: PromiseWithResolvers<void> | null = null;\n private abortController: AbortController | null = null;\n private intersectionObserver: IntersectionObserver | null = null;\n\n /** Promise that resolves with fetched data (available after loadData starts) */\n dataPromise: Promise<TData | null> | null = null;\n\n constructor(component: Component<TParams, TData>, files?: WidgetFiles) {\n super();\n this.component = component;\n this.effectiveFiles = files;\n // Attach shadow root if not already present (Declarative Shadow DOM creates it from <template shadowrootmode=\"open\">)\n // This enables progressive enhancement: SSR with DSD works without JS, then hydrates when JS loads\n if (!this.shadowRoot) {\n this.attachShadow({ mode: 'open' });\n }\n }\n\n /**\n * Register a widget as a custom element: `widget-{name}`.\n * Creates a fresh widget instance per DOM element (per-element state).\n * Optional `files` parameter provides discovered file paths without mutating\n * the component instance.\n */\n static register<TP, TD>(\n component: Component<TP, TD>,\n files?: WidgetFiles,\n ): void {\n const tagName = `widget-${component.name}`;\n\n if (!globalThis.customElements || customElements.get(tagName)) {\n return;\n }\n\n const WidgetClass = component.constructor as new () => Component<TP, TD>;\n\n const BoundElement = class extends ComponentElement<TP, TD> {\n constructor() {\n super(new WidgetClass(), files);\n }\n };\n\n customElements.define(tagName, BoundElement);\n }\n\n /**\n * Register a widget class (not instance) as a custom element: `widget-{name}`.\n * Used for manifest-based registration where classes are loaded dynamically.\n */\n static registerClass<TP, TD>(\n WidgetClass: new () => Component<TP, TD>,\n name: string,\n files?: WidgetFiles,\n ): void {\n const tagName = `widget-${name}`;\n\n if (!globalThis.customElements || customElements.get(tagName)) {\n return;\n }\n\n const BoundElement = class extends ComponentElement<TP, TD> {\n constructor() {\n super(new WidgetClass(), files);\n }\n };\n\n customElements.define(tagName, BoundElement);\n }\n\n /**\n * Register a widget lazily: define the custom element immediately (so SSR\n * content via Declarative Shadow DOM is adopted), but defer loading the\n * module until connectedCallback fires. Once loaded, the real component\n * replaces the placeholder and hydration proceeds normally.\n */\n static registerLazy(\n name: string,\n files: WidgetFiles | undefined,\n loader: () => Promise<unknown>,\n ): void {\n const tagName = `widget-${name}`;\n if (!globalThis.customElements || customElements.get(tagName)) return;\n\n ComponentElement.lazyLoaders.set(tagName, loader);\n\n // Placeholder component \u2014 replaced by the real one once the module loads.\n // Cast needed because Component is abstract; the real module replaces this.\n const placeholder = {\n name,\n getData: () => Promise.resolve(null),\n renderHTML: () => '',\n renderMarkdown: () => '',\n renderError: () => '',\n renderMarkdownError: () => '',\n } as unknown as Component<unknown, unknown>;\n\n const BoundElement = class extends ComponentElement<unknown, unknown> {\n constructor() {\n super(placeholder, files);\n }\n };\n\n customElements.define(tagName, BoundElement);\n }\n\n /**\n * Promise that resolves when component is ready (data loaded and rendered).\n * Used by router to wait for async components.\n */\n get ready(): Promise<void> {\n if (this.state === 'ready') {\n return Promise.resolve();\n }\n this.deferred ??= Promise.withResolvers<void>();\n return this.deferred.promise;\n }\n\n async connectedCallback(): Promise<void> {\n // Lazy module loading \u2014 resolve actual component before proceeding\n const tagName = this.tagName.toLowerCase();\n const lazyLoader = ComponentElement.lazyLoaders.get(tagName);\n if (lazyLoader) {\n try {\n let modulePromise = ComponentElement.lazyModules.get(tagName);\n if (!modulePromise) {\n modulePromise = lazyLoader();\n ComponentElement.lazyModules.set(tagName, modulePromise);\n }\n const mod = await modulePromise as Record<string, unknown>;\n for (const exp of Object.values(mod)) {\n if (exp && typeof exp === 'object' && 'getData' in exp) {\n const WidgetClass = exp.constructor as new () => Component<TParams, TData>;\n this.component = new WidgetClass();\n break;\n }\n if (typeof exp === 'function' && (exp as { prototype?: { getData?: unknown } }).prototype?.getData) {\n this.component = new (exp as new () => Component<TParams, TData>)();\n break;\n }\n }\n } catch {\n // Module failed to load (e.g. raw .ts served without transpilation).\n // SSR content is already visible \u2014 skip hydration gracefully.\n if (this.hasAttribute(SSR_ATTR)) {\n this.removeAttribute(SSR_ATTR);\n this.signalReady();\n return;\n }\n }\n }\n\n this.component.element = this;\n this.style.contentVisibility = 'auto';\n this.abortController = new AbortController();\n const signal = this.abortController.signal;\n\n // Parse params from element attributes\n const params: Record<string, unknown> = {};\n for (const attr of this.attributes) {\n if (attr.name === SSR_ATTR || attr.name === LAZY_ATTR) continue;\n const key = attr.name.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n try {\n params[key] = JSON.parse(attr.value);\n } catch {\n params[key] = attr.value;\n }\n }\n this.params = params as TParams;\n\n // Validate params\n if (this.component.validateParams && this.params !== null) {\n const error = this.component.validateParams(this.params);\n if (error) {\n this.setError(error);\n return;\n }\n }\n\n // Load companion files (html, md, css) if declared\n const files = await this.loadFiles();\n if (signal.aborted) return;\n\n const currentUrl = globalThis.location ? new URL(location.href) : new URL('http://localhost/');\n const filteredFiles = filterUndefined(files);\n const base: ComponentContext = {\n url: currentUrl,\n pathname: currentUrl.pathname,\n searchParams: currentUrl.searchParams,\n params: this.params ?? {},\n ...(filteredFiles ? { files: filteredFiles } : {}),\n };\n this.context = ComponentElement.extendContext ? ComponentElement.extendContext(base) : base;\n\n // Hydrate from SSR: adopt content from Declarative Shadow DOM\n if (this.hasAttribute(SSR_ATTR)) {\n this.removeAttribute(SSR_ATTR);\n\n // Read SSR data from light DOM (JSON text placed alongside shadow root)\n const lightText = this.textContent?.trim();\n if (lightText) {\n try {\n this.data = JSON.parse(lightText);\n } catch {\n // Not valid JSON \u2014 proceed with data: null\n }\n }\n // Clear light DOM content (JSON text)\n this.textContent = '';\n\n this.state = 'ready';\n\n // Call hydrate() hook to attach event listeners\n if (this.component.hydrate) {\n const args = { data: this.data, params: this.params!, context: this.context };\n queueMicrotask(() => {\n this.component.hydrate!(args);\n });\n }\n\n this.signalReady();\n return;\n }\n\n // Lazy: defer loadData until element is visible\n if (this.hasAttribute(LAZY_ATTR)) {\n this.intersectionObserver = new IntersectionObserver(([entry]) => {\n if (entry.isIntersecting) {\n this.intersectionObserver?.disconnect();\n this.intersectionObserver = null;\n this.loadData();\n }\n });\n this.intersectionObserver.observe(this);\n return;\n }\n\n await this.loadData();\n }\n\n disconnectedCallback(): void {\n this.component.destroy?.();\n this.component.element = undefined;\n this.intersectionObserver?.disconnect();\n this.intersectionObserver = null;\n this.abortController?.abort();\n this.abortController = null;\n this.state = 'idle';\n this.data = null;\n this.context = undefined!;\n this.dataPromise = null;\n this.errorMessage = '';\n this.signalReady();\n this.deferred = null;\n }\n\n /**\n * Reload component data. Aborts any in-flight request first.\n */\n async reload(): Promise<void> {\n if (this.params === null) return;\n\n // Abort previous and create fresh controller\n this.abortController?.abort();\n this.abortController = new AbortController();\n\n await this.loadData();\n }\n\n /**\n * Fetch a single file by path, with caching.\n * Absolute URLs (http/https) pass through; relative paths get '/' prefix.\n */\n private static loadFile(path: string): Promise<string | undefined> {\n const cached = ComponentElement.fileCache.get(path);\n if (cached) return cached;\n\n const url = path.startsWith('http://') || path.startsWith('https://')\n ? path\n : (path.startsWith('/') ? path : '/' + path);\n\n const promise = fetch(url).then(\n (res) => res.ok ? res.text() : undefined,\n () => undefined,\n );\n\n ComponentElement.fileCache.set(path, promise);\n return promise;\n }\n\n /**\n * Load all companion files for this widget instance.\n * Uses effectiveFiles (from registration) falling back to component.files.\n */\n private async loadFiles(): Promise<{ html?: string; md?: string; css?: string }> {\n const filePaths = this.effectiveFiles ?? this.component.files;\n if (!filePaths) return {};\n\n const [html, md, css] = await Promise.all([\n filePaths.html ? ComponentElement.loadFile(filePaths.html) : undefined,\n filePaths.md ? ComponentElement.loadFile(filePaths.md) : undefined,\n filePaths.css ? ComponentElement.loadFile(filePaths.css) : undefined,\n ]);\n\n return filterUndefined({ html, md, css }) ?? {};\n }\n\n private async loadData(): Promise<void> {\n if (this.params === null) return;\n\n const signal = this.abortController?.signal;\n\n this.state = 'loading';\n this.render();\n\n try {\n const promise = this.component.getData({\n params: this.params,\n ...(signal ? { signal } : {}),\n context: this.context,\n });\n this.dataPromise = promise;\n this.data = await promise;\n\n // Check abort after await \u2014 don't touch DOM if disconnected\n if (signal?.aborted) return;\n\n this.state = 'ready';\n } catch (e) {\n if (e instanceof DOMException && e.name === 'AbortError') return;\n if (signal?.aborted) return;\n\n this.setError(e instanceof Error ? e.message : String(e));\n return;\n }\n\n this.render();\n this.signalReady();\n }\n\n private setError(message: string): void {\n this.state = 'error';\n this.errorMessage = message;\n this.render();\n this.signalReady(); // Ready even on error (completed loading)\n }\n\n private signalReady(): void {\n this.deferred?.resolve();\n this.deferred = null;\n }\n\n private render(): void {\n if (this.params === null) {\n this.shadowRoot!.setHTMLUnsafe('');\n return;\n }\n\n if (this.state === 'error') {\n this.shadowRoot!.setHTMLUnsafe(this.component.renderError({\n error: new Error(this.errorMessage),\n params: this.params,\n }));\n return;\n }\n\n this.shadowRoot!.setHTMLUnsafe(this.component.renderHTML({\n data: this.state === 'ready' ? this.data : null,\n params: this.params,\n context: this.context,\n }));\n\n // Call hydrate() after rendering to attach event listeners\n if (this.state === 'ready' && this.component.hydrate) {\n const args = { data: this.data, params: this.params!, context: this.context };\n queueMicrotask(() => {\n this.component.hydrate!(args);\n });\n }\n }\n}\n", "/**\n * Widget Registry\n *\n * Canonical registry where all widgets live. Used by all renderers:\n * - SSR HTML: resolves widgets by name, calls getData() + renderHTML()\n * - SSR Markdown: resolves widgets by name, calls getData() + renderMarkdown()\n * - SPA: registers custom elements for each widget\n *\n * Pages are NOT in this registry \u2014 they live in the routes manifest.\n */\n\nimport type { WidgetComponent } from '../component/widget.component.ts';\nimport type { WidgetManifestEntry, WidgetsManifest } from '../type/widget.type.ts';\n\nexport class WidgetRegistry {\n private widgets = new Map<string, WidgetComponent>();\n\n /** Register a widget by its name. */\n add(widget: WidgetComponent): void {\n this.widgets.set(widget.name, widget);\n }\n\n /** Look up a widget by name. */\n get(name: string): WidgetComponent | undefined {\n return this.widgets.get(name);\n }\n\n /** Iterate all registered widgets. */\n [Symbol.iterator](): IterableIterator<WidgetComponent> {\n return this.widgets.values();\n }\n\n /** Emit a WidgetsManifest from registered widgets. */\n toManifest(): WidgetsManifest {\n const widgets: WidgetManifestEntry[] = [];\n const moduleLoaders: Record<string, () => Promise<unknown>> = {};\n\n for (const [name, widget] of this.widgets) {\n const entry: WidgetManifestEntry = {\n name,\n modulePath: name,\n tagName: `widget-${name}`,\n ...(widget.files ? { files: widget.files } : {}),\n };\n widgets.push(entry);\n moduleLoaders[name] = () => Promise.resolve({ default: widget.constructor });\n }\n\n return { widgets, moduleLoaders };\n }\n}\n", "/**\n * Route Core\n *\n * Shared routing logic used by all renderers:\n * - Route matching (delegates to RouteResolver)\n * - Module loading and caching\n * - Event emission\n * - URL normalization\n * - BasePath stripping\n */\n\nimport type {\n MatchedRoute,\n RouteConfig,\n RouteInfo,\n RouteParams,\n RouterEvent,\n RouterEventListener,\n} from '../type/route.type.ts';\nimport type { ComponentContext, ContextProvider, FileContents } from '../component/abstract.component.ts';\nimport type { RouteResolver, ResolvedRoute } from './route.resolver.ts';\n\n/** Base paths for the two SSR rendering endpoints. */\nexport interface BasePath {\n /** Base path for SSR HTML rendering (default: '/html') */\n html: string;\n /** Base path for SSR Markdown rendering (default: '/md') */\n md: string;\n /** Base path for PWA/SPA rendering (default: '/app') */\n app: string;\n}\n\n/** Default base paths \u2014 backward compatible with existing /html/ and /md/ prefixes. */\nexport const DEFAULT_BASE_PATH: BasePath = { html: '/html', md: '/md', app: '/app' };\n\nconst BLOCKED_PROTOCOLS = /^(javascript|data|vbscript):/i;\n\n/** Throw if a redirect URL uses a dangerous protocol. */\nexport function assertSafeRedirect(url: string): void {\n if (BLOCKED_PROTOCOLS.test(url.trim())) {\n throw new Error(`Unsafe redirect URL blocked: ${url}`);\n }\n}\n\n/** Default root route \u2014 renders a slot for child routes. */\nexport const DEFAULT_ROOT_ROUTE: RouteConfig = {\n pattern: '/',\n type: 'page',\n modulePath: '__default_root__',\n};\n\n/** Synthesize a RouteConfig from a ResolvedRoute (bridge for renderer compatibility). */\nfunction toRouteConfig(resolved: ResolvedRoute): RouteConfig {\n const node = resolved.node;\n return {\n pattern: resolved.pattern,\n type: node.redirect ? 'redirect' : 'page',\n modulePath: node.redirect ?? node.files?.ts ?? node.files?.js ?? node.files?.html ?? node.files?.md ?? '',\n ...(node.files ? { files: node.files } : {}),\n };\n}\n\n/** Options for RouteCore */\nexport interface RouteCoreOptions {\n /**\n * Read a companion file (.html, .md, .css) by path \u2014 returns its text content.\n * SSR: `(path) => runtime.query(path, { as: 'text' })`.\n * SPA default: `fetch(path, { headers: { Accept: 'text/plain' } }).then(r => r.text())`.\n */\n fileReader?: (path: string) => Promise<string>;\n /** Enriches every ComponentContext with app-level services before it reaches components. */\n extendContext?: ContextProvider;\n /** Module loaders keyed by path \u2014 server provides these for SSR imports. */\n moduleLoaders?: Record<string, () => Promise<unknown>>;\n}\n\n/**\n * Core router functionality shared across all rendering contexts.\n */\nexport class RouteCore {\n private readonly resolver: RouteResolver;\n /** Registered context provider (if any). Exposed so renderers can apply it to inline contexts. */\n readonly contextProvider: ContextProvider | undefined;\n private listeners: Set<RouterEventListener> = new Set();\n private moduleCache: Map<string, unknown> = new Map();\n private widgetFileCache: Map<string, string> = new Map();\n private moduleLoaders: Record<string, () => Promise<unknown>>;\n currentRoute: MatchedRoute | null = null;\n private readFile: (path: string) => Promise<string>;\n\n constructor(resolver: RouteResolver, options: RouteCoreOptions = {}) {\n this.resolver = resolver;\n this.readFile = options.fileReader ??\n ((path) => fetch(path, { headers: { Accept: 'text/plain' } }).then((r) => r.text()));\n this.contextProvider = options.extendContext;\n this.moduleLoaders = options.moduleLoaders ?? {};\n }\n\n /**\n * Get current route parameters.\n */\n getParams(): RouteParams {\n return this.currentRoute?.params ?? {};\n }\n\n /**\n * Add event listener for router events.\n */\n addEventListener(listener: RouterEventListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n /**\n * Emit router event to listeners.\n */\n emit(event: RouterEvent): void {\n for (const listener of this.listeners) {\n try {\n listener(event);\n } catch (e) {\n console.error('[Router] Event listener error:', e);\n }\n }\n }\n\n /**\n * Match a URL to a route.\n * Falls back to the default root route for '/'.\n */\n match(url: URL): MatchedRoute | undefined {\n const pathname = url.pathname;\n\n const resolved = this.resolver.match(pathname);\n if (resolved) {\n return {\n route: toRouteConfig(resolved),\n params: resolved.params,\n };\n }\n\n if (pathname === '/' || pathname === '') {\n return {\n route: DEFAULT_ROOT_ROUTE,\n params: {},\n };\n }\n\n return undefined;\n }\n\n /** Get status-specific page (404, 401, 403). */\n getStatusPage(status: number): RouteConfig | undefined {\n const node = this.resolver.findRoute(`/${status}`);\n if (!node) return undefined;\n return {\n pattern: `/${status}`,\n type: 'page',\n modulePath: node.files?.ts ?? node.files?.js ?? node.files?.html ?? node.files?.md ?? '',\n ...(node.files ? { files: node.files } : {}),\n };\n }\n\n /** Get global error handler (root errorBoundary). */\n getErrorHandler(): RouteConfig | undefined {\n const modulePath = this.resolver.findErrorBoundary('/');\n if (!modulePath) return undefined;\n return { pattern: '/', type: 'error', modulePath };\n }\n\n /**\n * Find error boundary for a given pathname.\n * Note: pattern is the input pathname, not the boundary's own pattern.\n * Callers should only rely on modulePath.\n */\n findErrorBoundary(pathname: string): { pattern: string; modulePath: string } | undefined {\n const modulePath = this.resolver.findErrorBoundary(pathname);\n if (!modulePath) return undefined;\n return { pattern: pathname, modulePath };\n }\n\n /**\n * Find a route by its exact pattern.\n * Used for building route hierarchy.\n */\n findRoute(pattern: string): RouteConfig | undefined {\n const node = this.resolver.findRoute(pattern);\n if (!node) return undefined;\n return {\n pattern,\n type: node.redirect ? 'redirect' : 'page',\n modulePath: node.redirect ?? node.files?.ts ?? node.files?.js ?? node.files?.html ?? node.files?.md ?? '',\n ...(node.files ? { files: node.files } : {}),\n };\n }\n\n /**\n * Build route hierarchy from a pattern.\n * Patterns are always unprefixed (no basePath).\n *\n * e.g., '/projects/:id/tasks'\n * \u2192 ['/', '/projects', '/projects/:id', '/projects/:id/tasks']\n */\n buildRouteHierarchy(pattern: string): string[] {\n if (pattern === '/') {\n return ['/'];\n }\n\n const segments = pattern.split('/').filter(Boolean);\n\n const hierarchy: string[] = ['/'];\n let current = '';\n for (const segment of segments) {\n current += '/' + segment;\n hierarchy.push(current);\n }\n\n return hierarchy;\n }\n\n /**\n * Normalize URL by removing trailing slashes (except bare '/').\n */\n normalizeUrl(url: string): string {\n if (url.length > 1 && url.endsWith('/')) {\n return url.slice(0, -1);\n }\n return url;\n }\n\n /**\n * Convert relative path to absolute path.\n */\n toAbsolutePath(path: string): string {\n return path.startsWith('/') ? path : '/' + path;\n }\n\n /**\n * Load a module with caching.\n * Uses pre-bundled loaders when available, falls back to dynamic import.\n */\n async loadModule<T>(modulePath: string): Promise<T> {\n if (this.moduleCache.has(modulePath)) {\n return this.moduleCache.get(modulePath) as T;\n }\n\n let module: unknown;\n const loader = this.moduleLoaders[modulePath];\n if (loader) {\n module = await loader();\n } else {\n const absolutePath = this.toAbsolutePath(modulePath);\n module = await import(absolutePath);\n }\n\n this.moduleCache.set(modulePath, module);\n return module as T;\n }\n\n /**\n * Load widget file contents with caching.\n */\n async loadWidgetFiles(\n widgetFiles: { html?: string; md?: string; css?: string },\n ): Promise<{ html?: string; md?: string; css?: string }> {\n const load = async (path: string): Promise<string | undefined> => {\n const absPath = this.toAbsolutePath(path);\n const cached = this.widgetFileCache.get(absPath);\n if (cached !== undefined) return cached;\n\n try {\n const content = await this.readFile(absPath);\n this.widgetFileCache.set(absPath, content);\n return content;\n } catch (e) {\n console.warn(\n `[RouteCore] Failed to load widget file ${path}:`,\n e instanceof Error ? e.message : e,\n );\n return undefined;\n }\n };\n\n const [html, md, css] = await Promise.all([\n widgetFiles.html ? load(widgetFiles.html) : undefined,\n widgetFiles.md ? load(widgetFiles.md) : undefined,\n widgetFiles.css ? load(widgetFiles.css) : undefined,\n ]);\n\n const result: { html?: string; md?: string; css?: string } = {};\n if (html != null) result.html = html;\n if (md != null) result.md = md;\n if (css != null) result.css = css;\n return result;\n }\n\n /**\n * Build a RouteInfo from a matched route and the resolved URL pathname.\n * Called once per navigation; the result is reused across the route hierarchy.\n */\n toRouteInfo(matched: MatchedRoute, url: URL): RouteInfo {\n return {\n url,\n params: matched.params,\n };\n }\n\n /**\n * Get inlined `__files` from a cached module (merged module pattern).\n * Returns undefined if the module isn't cached or has no __files.\n */\n getModuleFiles(modulePath: string): { html?: string; md?: string; css?: string } | undefined {\n const cached = this.moduleCache.get(modulePath);\n if (!cached || typeof cached !== 'object') return undefined;\n const files = (cached as Record<string, unknown>).__files;\n if (!files || typeof files !== 'object') return undefined;\n return files as { html?: string; md?: string; css?: string };\n }\n\n /**\n * Build a ComponentContext by extending RouteInfo with loaded file contents.\n *\n * When the route module is a merged module (contains `__files`), uses\n * inlined content directly. Otherwise falls back to reading companion files.\n */\n async buildComponentContext(\n routeInfo: RouteInfo,\n route: RouteConfig,\n signal?: AbortSignal,\n isLeaf?: boolean,\n ): Promise<ComponentContext> {\n const rf = route.files;\n const modulePath = rf?.ts ?? rf?.js;\n\n // Try inlined __files from merged module (already cached by loadRouteContent)\n const inlined = modulePath ? this.getModuleFiles(modulePath) : undefined;\n\n let html: string | undefined;\n let md: string | undefined;\n let css: string | undefined;\n\n if (inlined) {\n html = inlined.html;\n md = inlined.md;\n css = inlined.css;\n } else {\n const fetchFile = (filePath: string): Promise<string> =>\n this.readFile(this.toAbsolutePath(filePath));\n [html, md, css] = await Promise.all([\n rf?.html ? fetchFile(rf.html) : undefined,\n rf?.md ? fetchFile(rf.md) : undefined,\n rf?.css ? fetchFile(rf.css) : undefined,\n ]);\n }\n\n const files: FileContents = {};\n if (html != null) files.html = html;\n if (md != null) files.md = md;\n if (css != null) files.css = css;\n\n const base: ComponentContext = {\n ...routeInfo,\n pathname: routeInfo.url.pathname,\n searchParams: routeInfo.url.searchParams,\n files,\n ...(signal ? { signal } : {}),\n ...(isLeaf != null ? { isLeaf } : {}),\n };\n return this.contextProvider ? this.contextProvider(base) : base;\n }\n}\n", "/**\n * Route Trie\n *\n * Segment-based trie implementing RouteResolver for O(depth) route matching.\n *\n * Each URL segment maps to a trie node. Nodes are tried in order:\n * static \u2192 dynamic (:param) \u2192 wildcard (:rest*). Backtracking handles\n * cases where a dynamic path leads to a dead end but a wildcard at an\n * ancestor would match.\n *\n * Static segment matching is case-sensitive, per RFC 3986.\n *\n * Accepts a RouteNode tree (the JSON-serializable manifest from Runtime)\n * and converts it to an internal trie with Map-based static children for\n * O(1) segment lookup.\n */\n\nimport type { RouteNode } from '../type/route-tree.type.ts';\nimport type { RouteResolver, ResolvedRoute } from './route.resolver.ts';\n\n/** Internal trie node with Map for O(1) static child lookup. */\ninterface TrieNode {\n /** RouteNode when this node is a terminal route. */\n route?: RouteNode;\n /** Reconstructed pattern for this node (e.g. \"/projects/:id\"). */\n pattern?: string;\n /** Error boundary module path scoped to this prefix. */\n errorBoundary?: string;\n /** Static children keyed by exact segment. */\n static: Map<string, TrieNode>;\n /** Dynamic child for single-segment params (:param). */\n dynamic?: { param: string; node: TrieNode };\n /** Wildcard child for catch-all params (:rest*). */\n wildcard?: { param: string; node: TrieNode };\n}\n\nfunction createNode(): TrieNode {\n return { static: new Map() };\n}\n\n/** Try decodeURIComponent, return the original segment on malformed input. */\nfunction safeDecode(segment: string): string {\n try {\n return decodeURIComponent(segment);\n } catch {\n return segment;\n }\n}\n\n/**\n * Split a normalized pathname into segments.\n * Assumes leading slash, no trailing slash. Must NOT be called with '/'.\n */\nfunction splitSegments(pathname: string): string[] {\n return pathname.substring(1).split('/');\n}\n\n/**\n * Convert a RouteNode tree into a TrieNode tree.\n * Recursively walks the RouteNode, converting Record children to Map\n * and reconstructing URL patterns at each node.\n */\nfunction convertNode(source: RouteNode, pattern: string): TrieNode {\n const node = createNode();\n\n // Terminal route (has files or redirect)\n if (source.files || source.redirect) {\n node.route = source;\n node.pattern = pattern;\n }\n\n // Error boundary\n if (source.errorBoundary) {\n node.errorBoundary = source.errorBoundary;\n }\n\n // Static children\n if (source.children) {\n for (const [segment, child] of Object.entries(source.children)) {\n const childPattern = pattern === '/' ? `/${segment}` : `${pattern}/${segment}`;\n node.static.set(segment, convertNode(child, childPattern));\n }\n }\n\n // Dynamic child\n if (source.dynamic) {\n const { param, child } = source.dynamic;\n const childPattern = pattern === '/' ? `/:${param}` : `${pattern}/:${param}`;\n node.dynamic = { param, node: convertNode(child, childPattern) };\n }\n\n // Wildcard child\n if (source.wildcard) {\n const { param, child } = source.wildcard;\n const childPattern = pattern === '/' ? `/:${param}*` : `${pattern}/:${param}*`;\n node.wildcard = { param, node: convertNode(child, childPattern) };\n }\n\n return node;\n}\n\n/**\n * Trie-based route resolver.\n *\n * Implements RouteResolver with O(depth) matching by walking the trie.\n * Constructed from a RouteNode tree (produced by Runtime.scanRoutes).\n */\nexport class RouteTrie implements RouteResolver {\n private readonly root: TrieNode;\n\n constructor(tree: RouteNode) {\n this.root = convertNode(tree, '/');\n }\n\n match(pathname: string): ResolvedRoute | undefined {\n // Normalize: strip trailing slash (except bare '/')\n if (pathname.length > 1 && pathname.endsWith('/')) {\n pathname = pathname.slice(0, -1);\n }\n\n if (!pathname.startsWith('/')) {\n pathname = '/' + pathname;\n }\n\n if (pathname === '/') {\n if (this.root.route) {\n return { node: this.root.route, pattern: '/', params: {} };\n }\n return undefined;\n }\n\n const segments = splitSegments(pathname);\n return this.walk(this.root, segments, 0, {});\n }\n\n findErrorBoundary(pathname: string): string | undefined {\n if (pathname.length > 1 && pathname.endsWith('/')) {\n pathname = pathname.slice(0, -1);\n }\n if (!pathname.startsWith('/')) {\n pathname = '/' + pathname;\n }\n\n if (pathname === '/') return this.root.errorBoundary;\n\n const segments = splitSegments(pathname);\n return this.walkForBoundary(this.root, segments, 0, this.root.errorBoundary);\n }\n\n findRoute(pattern: string): RouteNode | undefined {\n if (pattern === '/') {\n return this.root.route;\n }\n\n const segments = splitSegments(pattern);\n let node = this.root;\n\n for (const segment of segments) {\n let child: TrieNode | undefined;\n\n if (segment.startsWith(':') && segment.endsWith('*')) {\n child = node.wildcard?.node;\n } else if (segment.startsWith(':')) {\n child = node.dynamic?.node;\n } else {\n child = node.static.get(segment);\n }\n\n if (!child) return undefined;\n node = child;\n }\n\n return node.route;\n }\n\n // \u2500\u2500 Private matching \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 private walk(\n node: TrieNode,\n segments: string[],\n index: number,\n params: Record<string, string>,\n ): ResolvedRoute | undefined {\n if (index === segments.length) {\n if (node.route) {\n return { node: node.route, pattern: node.pattern!, params: { ...params } };\n }\n if (node.wildcard?.node.route) {\n return {\n node: node.wildcard.node.route,\n pattern: node.wildcard.node.pattern!,\n params: { ...params, [node.wildcard.param]: '' },\n };\n }\n return undefined;\n }\n\n const segment = segments[index];\n\n // 1. Try static child\n const staticChild = node.static.get(segment);\n if (staticChild) {\n const result = this.walk(staticChild, segments, index + 1, params);\n if (result) return result;\n }\n\n // 2. Try dynamic child (single segment)\n if (node.dynamic) {\n const { param, node: dynamicNode } = node.dynamic;\n params[param] = safeDecode(segment);\n const result = this.walk(dynamicNode, segments, index + 1, params);\n if (result) return result;\n delete params[param];\n }\n\n // 3. Try wildcard (consumes all remaining segments)\n if (node.wildcard?.node.route) {\n const { param, node: wildcardNode } = node.wildcard;\n let rest = safeDecode(segments[index]);\n for (let i = index + 1; i < segments.length; i++) {\n rest += '/' + safeDecode(segments[i]);\n }\n return {\n node: wildcardNode.route!,\n pattern: wildcardNode.pattern!,\n params: { ...params, [param]: rest },\n };\n }\n\n return undefined;\n }\n\n /**\n * Walk for error boundary. Follows the same priority as match\n * (static \u2192 dynamic \u2192 wildcard) without backtracking across branches.\n * Returns the deepest error boundary module path found along the path.\n */\n private walkForBoundary(\n node: TrieNode,\n segments: string[],\n index: number,\n deepest: string | undefined,\n ): string | undefined {\n if (index === segments.length) {\n return node.errorBoundary ?? deepest;\n }\n\n const segment = segments[index];\n\n const staticChild = node.static.get(segment);\n if (staticChild) {\n return this.walkForBoundary(staticChild, segments, index + 1, staticChild.errorBoundary ?? deepest);\n }\n\n if (node.dynamic) {\n return this.walkForBoundary(node.dynamic.node, segments, index + 1, node.dynamic.node.errorBoundary ?? deepest);\n }\n\n if (node.wildcard) {\n return node.wildcard.node.errorBoundary ?? deepest;\n }\n\n return deepest;\n }\n}\n", "/**\n * Logger Interface\n *\n * Minimal pluggable logger for surfacing errors from silent catch blocks.\n * Structurally compatible with hardkore's StructuredLogger \u2014 any instance\n * of that class satisfies this interface without an explicit dependency.\n *\n * Default: no-op (silent degradation). Call setLogger() at startup to wire in.\n */\nexport interface Logger {\n error(msg: string, error?: Error): void;\n warn(msg: string): void;\n}\n\nconst noop = () => {};\n\n/** Module-level logger. Always callable \u2014 defaults to no-op. */\nexport const logger: Logger = { error: noop, warn: noop };\n\n/** Replace the logger implementation. Call once at startup. */\nexport function setLogger(impl: Logger): void {\n logger.error = impl.error.bind(impl);\n logger.warn = impl.warn.bind(impl);\n}\n", "/**\n * Widget Resolve Utilities\n *\n * Server-side resolution of <widget-*> tags in HTML.\n * Calls getData() + renderHTML() on widgets and injects SSR hydration data.\n */\n\nimport type { Component, ComponentContext, ContextProvider } from '../component/abstract.component.ts';\nimport { logger } from '../type/logger.type.ts';\nimport type { RouteInfo } from '../type/route.type.ts';\nimport { LAZY_ATTR, SSR_ATTR } from './html.util.ts';\n\n/** Maximum nesting depth for widgets to prevent infinite loops */\nexport const MAX_WIDGET_DEPTH = 10;\n\n/**\n * Recursively resolve widgets in content with depth limit.\n *\n * Generic utility used by both HTML and Markdown widget resolution.\n * Each depth level processes all widgets concurrently, then recurses\n * into each rendered result to resolve nested widgets.\n *\n * @param content - Content containing widgets\n * @param parse - Find widgets in content\n * @param resolve - Resolve a single widget to rendered output\n * @param replace - Replace widgets with resolved content\n * @param depth - Current recursion depth (internal)\n * @returns Content with all widgets recursively resolved\n */\nexport async function resolveRecursively<T>(\n content: string,\n parse: (content: string) => T[],\n resolve: (widget: T) => Promise<string>,\n replace: (content: string, replacements: Map<T, string>) => string,\n depth = 0,\n): Promise<string> {\n if (depth >= MAX_WIDGET_DEPTH) {\n logger.warn(\n `Widget nesting depth limit reached (${MAX_WIDGET_DEPTH}). ` +\n 'Possible circular dependency or excessive nesting.',\n );\n return content;\n }\n\n const widgets = parse(content);\n if (widgets.length === 0) return content;\n\n const replacements = new Map<T, string>();\n await Promise.all(\n widgets.map(async (widget) => {\n let rendered = await resolve(widget);\n\n // Recursively resolve any nested widgets in the rendered output\n rendered = await resolveRecursively(rendered, parse, resolve, replace, depth + 1);\n\n replacements.set(widget, rendered);\n }),\n );\n\n return replace(content, replacements);\n}\n\n/**\n * Resolve <widget-*> tags in HTML by calling getData() + renderHTML()\n * via the widget registry. Injects rendered content and boolean ssr attribute.\n *\n * Supports nested widgets: if a widget's renderHTML() returns HTML containing\n * other <widget-*> tags, those will be resolved recursively up to MAX_WIDGET_DEPTH.\n *\n * Before: <widget-crypto-price coin=\"bitcoin\"></widget-crypto-price>\n * After: <widget-crypto-price coin=\"bitcoin\" ssr><template shadowrootmode=\"open\"><span>$42,000</span></template></widget-crypto-price>\n *\n * When a widget has `exposeSsrData = true`, the getData() result is serialized\n * as JSON text in the light DOM (alongside the shadow root template):\n * After: <widget-crypto-price coin=\"bitcoin\" ssr><template shadowrootmode=\"open\"><span>$42,000</span></template>{\"price\":42000}</widget-crypto-price>\n */\nexport function resolveWidgetTags(\n html: string,\n registry: { get(name: string): Component | undefined },\n routeInfo: RouteInfo,\n loadFiles?: (\n widgetName: string,\n declaredFiles?: { html?: string; md?: string; css?: string },\n ) => Promise<{ html?: string; md?: string; css?: string }>,\n contextProvider?: ContextProvider,\n): Promise<string> {\n const tagPattern =\n /<widget-(?<name>[a-z][a-z0-9-]*)(?<attrs>\\s[^>]*)?>(?<content>.*?)<\\/widget-\\k<name>>/gis;\n\n // Wrapping info stored per-match so replace() can apply it after recursion\n const wrappers = new Map<RegExpExecArray, { tagName: string; attrs: string; ssrData: string }>();\n\n // Matches standalone ssr attribute (boolean or with value), not as substring of another value\n const ssrAttrPattern = new RegExp(`\\\\s${SSR_ATTR}(?:\\\\s|=|$)`);\n\n // Parse: find unprocessed widget tags\n const parse = (content: string) => {\n const matches = content.matchAll(tagPattern).toArray();\n return matches.filter((match) => {\n const attrsString = match.groups!.attrs || '';\n return !ssrAttrPattern.test(attrsString);\n });\n };\n\n // Resolve: render a single widget's inner content (no outer tag wrapping \u2014 that's in replace)\n const resolve = async (match: RegExpExecArray): Promise<string> => {\n const widgetName = match.groups!.name;\n const attrsString = match.groups!.attrs?.trim() ?? '';\n const widget = registry.get(widgetName);\n\n if (!widget) return match[0]; // no widget found \u2014 leave original tag as-is\n\n const params = parseAttrsToParams(attrsString);\n\n try {\n let files: { html?: string; md?: string; css?: string } | undefined;\n if (loadFiles) {\n files = await loadFiles(widgetName, widget.files);\n }\n\n const baseContext: ComponentContext = {\n ...routeInfo,\n pathname: routeInfo.url.pathname,\n searchParams: routeInfo.url.searchParams,\n ...(files ? { files } : {}),\n };\n const context: ComponentContext = contextProvider ? contextProvider(baseContext) : baseContext;\n\n const data = await widget.getData({ params, context });\n const rendered = widget.renderHTML({ data, params, context });\n\n // Store wrapping info \u2014 applied in replace() after recursion resolves nested widgets\n wrappers.set(match, {\n tagName: `widget-${widgetName}`,\n attrs: attrsString ? ` ${attrsString}` : '',\n ssrData: widget.exposeSsrData ? escapeAttr(JSON.stringify(data)) : '',\n });\n\n return rendered;\n } catch (e) {\n logger.error(\n `[SSR HTML] Widget \"${widgetName}\" render failed`,\n e instanceof Error ? e : undefined,\n );\n return match[0]; // render failed \u2014 leave original tag as-is\n }\n };\n\n // Replace: wrap resolved content in outer tag + DSD template, then substitute by index\n const replace = (content: string, replacements: Map<RegExpExecArray, string>) => {\n let result = content;\n const entries = [...replacements.entries()].sort((a, b) => b[0].index! - a[0].index!);\n for (const [match, innerHtml] of entries) {\n const start = match.index!;\n const end = start + match[0].length;\n const wrap = wrappers.get(match);\n const lightDomData = wrap?.ssrData ? wrap.ssrData : '';\n const replacement = wrap\n ? `<${wrap.tagName}${wrap.attrs} ${SSR_ATTR}><template shadowrootmode=\"open\">${innerHtml}</template>${lightDomData}</${wrap.tagName}>`\n : innerHtml; // no wrapper = unresolved widget, innerHtml is the original tag\n result = result.slice(0, start) + replacement + result.slice(end);\n }\n return result;\n };\n\n return resolveRecursively(html, parse, resolve, replace);\n}\n\n/** Parse HTML attribute string into params object (kebab\u2192camelCase, JSON.parse with string fallback). */\nexport function parseAttrsToParams(attrsString: string): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n if (!attrsString) return params;\n\n const attrPattern =\n /(?<attr>[a-z][a-z0-9-]*)(?:=\"(?<dq>[^\"]*)\"|='(?<sq>[^']*)'|=(?<uq>[^\\s>]+))?/gi;\n for (const match of attrsString.matchAll(attrPattern)) {\n const { attr: attrName, dq, sq, uq } = match.groups!;\n if (attrName === SSR_ATTR || attrName === LAZY_ATTR) continue;\n const key = attrName.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n const rawValue = dq ?? sq ?? uq;\n if (rawValue === undefined) {\n params[key] = '';\n continue;\n }\n const raw = rawValue.replaceAll('&amp;', '&').replaceAll('&#39;', \"'\").replaceAll(\n '&quot;',\n '\"',\n );\n try {\n params[key] = JSON.parse(raw);\n } catch {\n params[key] = raw;\n }\n }\n\n return params;\n}\n\n/** Escape a value for use in a single-quoted HTML attribute. */\nfunction escapeAttr(value: string): string {\n return value.replaceAll('&', '&amp;').replaceAll(\"'\", '&#39;');\n}\n", "/**\n * Unified Component Architecture\n *\n * Everything is a Component: pages and widgets.\n * Components render differently based on context:\n * - /md/* \u2192 Markdown (LLMs, text clients)\n * - /html/* \u2192 Pre-rendered HTML (SSR)\n * - SPA \u2192 Hydrated custom elements\n *\n * Precedence (like .ts/.html/.md):\n * - renderHTML() if defined \u2192 full HTML control\n * - renderMarkdown() \u2192 converted to HTML via markdown renderer\n */\n\nimport type { RouteInfo } from '../type/route.type.ts';\nimport { escapeHtml } from '../util/html.util.ts';\n\n/**\n * Context passed to components during rendering.\n * Extends RouteInfo (pathname, pattern, params)\n * with pre-loaded file content and an abort signal.\n *\n * Consumers can extend this interface via module augmentation\n * to add app-level services (RPC clients, auth, feature flags, etc.).\n */\n/** Shape of companion file contents (html, md, css). Used by generated `.page.files.g.ts` modules. */\nexport type FileContents = { html?: string; md?: string; css?: string };\n\nexport interface ComponentContext extends RouteInfo {\n /** @deprecated Use context.url.pathname */\n readonly pathname: string;\n /** @deprecated Use context.url.searchParams */\n readonly searchParams: URLSearchParams;\n readonly files?: Readonly<FileContents>;\n readonly signal?: AbortSignal;\n /** True when this component is the leaf (matched) route, false when rendered as a layout parent. */\n readonly isLeaf?: boolean;\n}\n\n/**\n * Callback that enriches the base ComponentContext with app-level services.\n * Registered once at router creation; called for every context construction.\n *\n * **1. Register** \u2014 always spread `base` to preserve routing/file/signal data:\n * ```ts\n * createSpaHtmlRouter(manifest, {\n * extendContext: (base) => ({ ...base, rpc: myRpcClient }),\n * });\n * ```\n *\n * **2. Access** \u2014 expose custom properties to components via module augmentation:\n * ```ts\n * declare module '@emkodev/emroute' {\n * interface ComponentContext { rpc: RpcClient; }\n * }\n * ```\n * or per-component via the third generic:\n * ```ts\n * class MyPage extends PageComponent<Params, Data, AppContext> {}\n * ```\n */\nexport type ContextProvider = (base: ComponentContext) => ComponentContext;\n\n/**\n * Render context determines how components are rendered.\n */\nexport type RenderContext = 'markdown' | 'html' | 'spa';\n\n/**\n * Abstract base class for all components.\n *\n * Subclasses must implement:\n * - name: unique identifier for custom element tag\n * - getData(): fetch/compute data\n * - renderMarkdown(): render as markdown\n *\n * Optional override:\n * - renderHTML(): custom HTML rendering (defaults to markdown\u2192HTML conversion)\n * - validateParams(): params validation\n *\n * @typeParam TContext \u2014 custom context shape; defaults to ComponentContext.\n * Use with `extendContext` on the router to inject app-level services.\n * See {@link ContextProvider} for details.\n */\nexport abstract class Component<\n TParams = unknown,\n TData = unknown,\n TContext extends ComponentContext = ComponentContext,\n> {\n /** Type carrier for getData args \u2014 use as `this['DataArgs']` in overrides. */\n declare readonly DataArgs: {\n params: TParams;\n signal?: AbortSignal;\n context: TContext;\n };\n\n /** Type carrier for render args \u2014 use as `this['RenderArgs']` in overrides. */\n declare readonly RenderArgs: {\n data: TData | null;\n params: TParams;\n context: TContext;\n };\n\n /** Unique name in kebab-case. Used for custom element: `<widget-{name}>` */\n abstract readonly name: string;\n\n /** Host element reference, set by ComponentElement in the browser. */\n element?: HTMLElement | undefined;\n\n /** Associated file paths for pre-loaded content (html, md, css). */\n readonly files?: { html?: string; md?: string; css?: string };\n\n /**\n * When true, SSR serializes the getData() result into the element's\n * light DOM so the client can access it immediately in hydrate()\n * without re-fetching.\n *\n * Default is false \u2014 hydrate() receives `data: null`. Most widgets\n * don't need this because the rendered Shadow DOM already contains\n * the visual representation of the data.\n *\n * If you find yourself parsing the shadow DOM in hydrate() trying to\n * reconstruct the original data object, set this to true instead.\n * The server-fetched data will be available as `args.data` in hydrate().\n */\n readonly exposeSsrData?: boolean;\n\n /**\n * Fetch or compute data based on params.\n * Called server-side for SSR, client-side for SPA.\n *\n * @example\n * ```ts\n * override async getData({ params, signal }: this['DataArgs']) {\n * const res = await fetch(`/api/${params.id}`, { signal });\n * return res.json();\n * }\n * ```\n */\n abstract getData(args: this['DataArgs']): Promise<TData | null>;\n\n /**\n * Render as markdown.\n * This is the canonical content representation.\n *\n * @example\n * ```ts\n * override renderMarkdown({ data }: this['RenderArgs']) {\n * return `# ${data?.title}`;\n * }\n * ```\n */\n abstract renderMarkdown(args: this['RenderArgs']): string;\n\n /**\n * Render as HTML for browser context.\n *\n * Default implementation converts renderMarkdown() output to HTML.\n * Override for custom HTML rendering with rich styling/interactivity.\n */\n renderHTML(args: this['RenderArgs']): string {\n if (args.data === null) {\n return `<div data-component=\"${this.name}\">Loading...</div>`;\n }\n // Default: wrap markdown in a container\n // The actual markdown\u2192HTML conversion happens at render time\n const markdown = this.renderMarkdown({\n data: args.data,\n params: args.params,\n context: args.context,\n });\n return `<div data-component=\"${this.name}\" data-markdown>${escapeHtml(markdown)}</div>`;\n }\n\n /**\n * Hydration hook called after SSR content is adopted or after SPA rendering.\n * Use to attach event listeners to existing DOM without re-rendering.\n *\n * @example\n * ```ts\n * override hydrate({ data, params, context }: this['RenderArgs']) {\n * const button = this.element?.querySelector('button');\n * button?.addEventListener('click', () => this.deleteItem(data.id));\n * }\n * ```\n */\n hydrate?(args: this['RenderArgs']): void;\n\n /**\n * Cleanup hook called when the component is removed from the DOM.\n * Use for clearing timers, removing event listeners, unmounting\n * third-party renderers, closing connections, etc.\n *\n * Intentionally synchronous (called from disconnectedCallback). You can\n * fire async cleanup here, but it will not be awaited.\n */\n destroy?(): void;\n\n /**\n * Validate params.\n * @returns Error message if invalid, undefined if valid.\n */\n validateParams?(params: TParams): string | undefined;\n\n /**\n * Render error state.\n */\n renderError(args: { error: unknown; params: TParams }): string {\n const msg = args.error instanceof Error ? args.error.message : String(args.error);\n return `<div data-component=\"${this.name}\">Error: ${escapeHtml(msg)}</div>`;\n }\n\n /**\n * Render error as markdown.\n */\n renderMarkdownError(error: unknown): string {\n const msg = error instanceof Error ? error.message : String(error);\n return `> **Error** (\\`${this.name}\\`): ${msg}`;\n }\n}\n\n/**\n * Component manifest entry for code generation.\n */\nexport interface ComponentManifestEntry {\n name: string;\n modulePath: string;\n tagName: string;\n type: 'page' | 'widget';\n pattern?: string;\n}\n", "/**\n * Page Component\n *\n * Page component \u2014 params come from URL, context carries file content.\n *\n * Default implementations follow the fallback table:\n * - renderHTML: html file \u2192 md via <mark-down> \u2192 <router-slot /> (non-leaf only)\n * - renderMarkdown: md file \u2192 ```router-slot\\n``` (non-leaf only)\n * - getData: no-op (returns null)\n */\n\nimport { Component, type ComponentContext } from './abstract.component.ts';\nimport { escapeHtml } from '../util/html.util.ts';\n\nexport class PageComponent<\n TParams extends Record<string, string> = Record<string, string>,\n TData = unknown,\n TContext extends ComponentContext = ComponentContext,\n> extends Component<TParams, TData, TContext> {\n override readonly name: string = 'page';\n\n /** Route pattern this page handles (optional \u2014 set by subclasses) */\n readonly pattern?: string;\n\n /**\n * Fetch or compute page data. Override in subclasses.\n * Default: returns null (no data needed).\n *\n * @example\n * ```ts\n * override getData({ params, context }: this['DataArgs']) {\n * return fetch(`/api/${params.id}`, { signal: context?.signal });\n * }\n * ```\n */\n override getData(\n _args: this['DataArgs'],\n ): Promise<TData | null> {\n return Promise.resolve(null);\n }\n\n /**\n * Render page as HTML.\n *\n * Fallback chain:\n * 1. html file content from context\n * 2. md file content wrapped in `<mark-down>`\n * 3. `<router-slot />` (bare slot for child routes)\n *\n * @example\n * ```ts\n * override renderHTML({ data, params, context }: this['RenderArgs']) {\n * return `<h1>${params.id}</h1><p>${context?.files?.html ?? ''}</p>`;\n * }\n * ```\n */\n override renderHTML(\n args: this['RenderArgs'],\n ): string {\n const files = args.context.files;\n const style = files?.css ? `<style>${files.css}</style>\\n` : '';\n\n if (files?.html) {\n let html = style + files.html;\n if (files.md && html.includes('<mark-down></mark-down>')) {\n html = html.replace(\n '<mark-down></mark-down>',\n `<mark-down>${escapeHtml(files.md)}</mark-down>`,\n );\n }\n return html;\n }\n\n if (files?.md) {\n // HOTFIX: skip external <router-slot> when markdown already defines one\n // via ```router-slot fenced block. Without this, SPA mode produces two\n // slots with the same pattern \u2014 one inside <mark-down> (from the fenced\n // block) and one outside (from this suffix). SSR strips empty duplicates\n // via stripSlots, but SPA has no equivalent cleanup.\n // See: issues/pending/spa-duplicate-router-slot.issue.md\n const hasSlot = files.md.includes('```router-slot');\n const slot = args.context.isLeaf || hasSlot ? '' : '\\n<router-slot></router-slot>';\n return `${style}<mark-down>${escapeHtml(files.md)}</mark-down>${slot}`;\n }\n\n return args.context.isLeaf ? '' : '<router-slot></router-slot>';\n }\n\n /**\n * Render page as Markdown.\n *\n * Fallback chain:\n * 1. md file content from context\n * 2. `` ```router-slot\\n``` `` (slot placeholder in markdown \u2014 newline required)\n *\n * @example\n * ```ts\n * override renderMarkdown({ data, params, context }: this['RenderArgs']) {\n * return `# ${params.id}\\n\\n${context?.files?.md ?? ''}`;\n * }\n * ```\n */\n override renderMarkdown(\n args: this['RenderArgs'],\n ): string {\n const files = args.context.files;\n\n if (files?.md) {\n return files.md;\n }\n\n return args.context.isLeaf ? '' : '```router-slot\\n```';\n }\n\n /**\n * Page title. Override in subclasses.\n * Default: undefined (no title).\n *\n * @example\n * ```ts\n * override getTitle({ data, params }: this['RenderArgs']) {\n * return `Project ${params.id}`;\n * }\n * ```\n */\n getTitle(\n _args: this['RenderArgs'],\n ): string | undefined {\n return undefined;\n }\n}\n\n/** Shared default instance used by renderers when no custom .page.ts exists. */\nexport default new PageComponent();\n", "/**\n * SSR Renderer Base\n *\n * Abstract base class for server-side renderers.\n * Provides the shared render() pipeline; subclasses supply format-specific rendering.\n */\n\nimport type {\n MatchedRoute,\n RouteConfig,\n RouteInfo,\n} from '../../type/route.type.ts';\nimport { logger } from '../../type/logger.type.ts';\nimport type { ComponentContext } from '../../component/abstract.component.ts';\nimport defaultPageComponent, { type PageComponent } from '../../component/page.component.ts';\nimport {\n assertSafeRedirect,\n DEFAULT_ROOT_ROUTE,\n RouteCore,\n type RouteCoreOptions,\n} from '../../route/route.core.ts';\nimport type { RouteResolver } from '../../route/route.resolver.ts';\nimport type { WidgetRegistry } from '../../widget/widget.registry.ts';\n\n/** Base options for SSR renderers */\nexport interface SsrRendererOptions extends RouteCoreOptions {\n /** Widget registry for server-side widget rendering */\n widgets?: WidgetRegistry;\n /** Widget companion file paths, keyed by widget name */\n widgetFiles?: Record<string, { html?: string; md?: string; css?: string }>;\n}\n\n/**\n * Abstract SSR renderer with shared routing pipeline.\n */\nexport abstract class SsrRenderer {\n protected core: RouteCore;\n protected widgets: WidgetRegistry | null;\n protected widgetFiles: Record<string, { html?: string; md?: string; css?: string }>;\n protected abstract readonly label: string;\n\n constructor(resolver: RouteResolver, options: SsrRendererOptions = {}) {\n this.core = new RouteCore(resolver, options);\n this.widgets = options.widgets ?? null;\n this.widgetFiles = options.widgetFiles ?? {};\n }\n\n /**\n * Render a URL to a content string.\n */\n async render(\n url: URL,\n signal?: AbortSignal,\n ): Promise<{ content: string; status: number; title?: string; redirect?: string }> {\n const matched = this.core.match(url);\n\n if (!matched) {\n const statusPage = this.core.getStatusPage(404);\n if (statusPage) {\n try {\n const ri: RouteInfo = { url, params: {} };\n const result = await this.renderRouteContent(ri, statusPage, undefined, signal);\n return { content: this.stripSlots(result.content), status: 404, ...(result.title != null ? { title: result.title } : {}) };\n } catch (e) {\n logger.error(\n `[${this.label}] Failed to render 404 status page for ${url.pathname}`,\n e instanceof Error ? e : undefined,\n );\n }\n }\n return { content: this.renderStatusPage(404, url), status: 404 };\n }\n\n // Handle redirect\n if (matched.route.type === 'redirect') {\n const module = await this.core.loadModule<{ default: { to: string; status?: number } }>(\n matched.route.modulePath,\n );\n const redirectConfig = module.default;\n assertSafeRedirect(redirectConfig.to);\n return {\n content: this.renderRedirect(redirectConfig.to),\n status: redirectConfig.status ?? 301,\n redirect: redirectConfig.to,\n };\n }\n\n const routeInfo = this.core.toRouteInfo(matched, url);\n\n try {\n const { content, title } = await this.renderPage(routeInfo, matched, signal);\n return { content, status: 200, ...(title != null ? { title } : {}) };\n } catch (error) {\n if (error instanceof Response) {\n const statusPage = this.core.getStatusPage(error.status);\n if (statusPage) {\n try {\n const ri: RouteInfo = { url, params: {} };\n const result = await this.renderRouteContent(ri, statusPage, undefined, signal);\n return {\n content: this.stripSlots(result.content),\n status: error.status,\n ...(result.title != null ? { title: result.title } : {}),\n };\n } catch (e) {\n logger.error(\n `[${this.label}] Failed to render ${error.status} status page for ${url.pathname}`,\n e instanceof Error ? e : undefined,\n );\n }\n }\n return { content: this.renderStatusPage(error.status, url), status: error.status };\n }\n logger.error(\n `[${this.label}] Error rendering ${url.pathname}:`,\n error instanceof Error ? error : undefined,\n );\n\n const boundary = this.core.findErrorBoundary(url.pathname);\n if (boundary) {\n const result = await this.tryRenderErrorModule(boundary.modulePath, url, 'boundary');\n if (result) return result;\n }\n\n const errorHandler = this.core.getErrorHandler();\n if (errorHandler) {\n const result = await this.tryRenderErrorModule(errorHandler.modulePath, url, 'handler');\n if (result) return result;\n }\n\n return { content: this.renderErrorPage(error, url), status: 500 };\n }\n }\n\n /**\n * Render a matched page by composing the route hierarchy.\n */\n protected async renderPage(\n routeInfo: RouteInfo,\n matched: MatchedRoute,\n signal?: AbortSignal,\n ): Promise<{ content: string; title?: string }> {\n const hierarchy = this.core.buildRouteHierarchy(matched.route.pattern);\n\n // Resolve routes for each hierarchy segment (skip missing / duplicate wildcard)\n const segments: { route: RouteConfig; isLeaf: boolean }[] = [];\n for (let i = 0; i < hierarchy.length; i++) {\n const routePattern = hierarchy[i];\n let route = this.core.findRoute(routePattern);\n\n if (!route && routePattern === '/') {\n route = DEFAULT_ROOT_ROUTE;\n }\n\n if (!route) continue;\n if (route === matched.route && routePattern !== matched.route.pattern) continue;\n\n segments.push({ route, isLeaf: i === hierarchy.length - 1 });\n }\n\n // Fire all renderRouteContent calls in parallel\n const results = await Promise.all(\n segments.map(({ route, isLeaf }) =>\n this.renderRouteContent(routeInfo, route, isLeaf, signal),\n ),\n );\n\n // Sequential slot injection\n let result = '';\n let pageTitle: string | undefined;\n let lastRenderedPattern = '';\n\n for (let i = 0; i < segments.length; i++) {\n const { content, title } = results[i];\n\n if (title) {\n pageTitle = title;\n }\n\n if (result === '') {\n result = content;\n } else {\n const injected = this.injectSlot(result, content, lastRenderedPattern);\n if (injected === result) {\n logger.warn(\n `[${this.label}] Route \"${lastRenderedPattern}\" has no <router-slot> ` +\n `for child route \"${hierarchy[i]}\" to render into. ` +\n `Add <router-slot></router-slot> to the parent template.`,\n );\n }\n result = injected;\n }\n\n lastRenderedPattern = segments[i].route.pattern;\n }\n\n result = this.stripSlots(result);\n\n return { content: result, ...(pageTitle != null ? { title: pageTitle } : {}) };\n }\n\n protected abstract renderRouteContent(\n routeInfo: RouteInfo,\n route: RouteConfig,\n isLeaf?: boolean,\n signal?: AbortSignal,\n ): Promise<{ content: string; title?: string }>;\n\n /** Load component, build context, get data, render content, get title. */\n protected async loadRouteContent(\n routeInfo: RouteInfo,\n route: RouteConfig,\n isLeaf?: boolean,\n signal?: AbortSignal,\n ): Promise<{ content: string; title?: string }> {\n const files = route.files ?? {};\n\n const tsModule = files.ts ?? files.js;\n const component: PageComponent = tsModule\n ? (await this.core.loadModule<{ default: PageComponent }>(tsModule)).default\n : defaultPageComponent;\n\n const context = await this.core.buildComponentContext(routeInfo, route, signal, isLeaf);\n const data = await component.getData({ params: routeInfo.params, ...(signal ? { signal } : {}), context });\n const content = this.renderContent(component, { data, params: routeInfo.params, context });\n const title = component.getTitle({ data, params: routeInfo.params, context });\n\n return { content, ...(title != null ? { title } : {}) };\n }\n\n /** Render a component to the output format (HTML or Markdown). */\n protected abstract renderContent(\n component: PageComponent,\n args: PageComponent['RenderArgs'],\n ): string;\n\n /** Render a component for error boundary/handler with minimal context. */\n protected renderComponent(\n component: PageComponent,\n data: unknown,\n context: ComponentContext,\n ): string {\n return this.renderContent(component, { data, params: {}, context });\n }\n\n private static readonly EMPTY_URL = new URL('http://error');\n\n /** Try to load and render an error boundary or handler module. Returns null on failure. */\n private async tryRenderErrorModule(\n modulePath: string,\n url: URL,\n kind: 'boundary' | 'handler',\n ): Promise<{ content: string; status: number } | null> {\n try {\n const module = await this.core.loadModule<{ default: PageComponent }>(modulePath);\n const component = module.default;\n const minCtx: ComponentContext = {\n url: SsrRenderer.EMPTY_URL,\n params: {},\n pathname: '',\n searchParams: new URLSearchParams(),\n };\n const data = await component.getData({ params: {}, context: minCtx });\n const content = this.renderComponent(component, data, minCtx);\n return { content, status: 500 };\n } catch (e) {\n logger.error(\n `[${this.label}] Error ${kind} failed for ${url.pathname}`,\n e instanceof Error ? e : undefined,\n );\n return null;\n }\n }\n\n protected abstract renderRedirect(to: string): string;\n\n protected abstract renderStatusPage(status: number, url: URL): string;\n\n protected abstract renderErrorPage(error: unknown, url: URL): string;\n\n /** Inject child content into the slot owned by parentPattern. */\n protected abstract injectSlot(parent: string, child: string, parentPattern: string): string;\n\n /** Strip all unconsumed slot placeholders from the final result. */\n protected abstract stripSlots(result: string): string;\n}\n", "/**\n * SSR HTML Renderer\n *\n * Server-side HTML rendering.\n * Generates complete HTML strings without DOM manipulation.\n * Expands <mark-down> tags server-side when a markdown renderer is provided.\n */\n\nimport type { RouteConfig, RouteInfo } from '../../type/route.type.ts';\nimport type { RouteResolver } from '../../route/route.resolver.ts';\nimport type { MarkdownRenderer } from '../../type/markdown.type.ts';\nimport type { PageComponent } from '../../component/page.component.ts';\nimport { DEFAULT_ROOT_ROUTE } from '../../route/route.core.ts';\nimport { escapeHtml, STATUS_MESSAGES, unescapeHtml } from '../../util/html.util.ts';\nimport { resolveWidgetTags } from '../../util/widget-resolve.util.ts';\nimport { SsrRenderer, type SsrRendererOptions } from './ssr.renderer.ts';\n\n/** Options for SSR HTML Router */\nexport interface SsrHtmlRouterOptions extends SsrRendererOptions {\n /** Markdown renderer for server-side <mark-down> expansion */\n markdownRenderer?: MarkdownRenderer;\n}\n\n/**\n * SSR HTML Router for server-side rendering.\n */\nexport class SsrHtmlRouter extends SsrRenderer {\n protected override readonly label = 'SSR HTML';\n private markdownRenderer: MarkdownRenderer | null;\n private markdownReady: Promise<void> | null = null;\n\n constructor(resolver: RouteResolver, options: SsrHtmlRouterOptions = {}) {\n super(resolver, options);\n this.markdownRenderer = options.markdownRenderer ?? null;\n\n if (this.markdownRenderer?.init) {\n this.markdownReady = this.markdownRenderer.init();\n }\n }\n\n protected override injectSlot(parent: string, child: string, parentPattern: string): string {\n const escaped = parentPattern.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n return parent.replace(\n new RegExp(`<router-slot\\\\b[^>]*\\\\bpattern=\"${escaped}\"[^>]*></router-slot>`),\n child,\n );\n }\n\n protected override stripSlots(result: string): string {\n return result.replace(/<router-slot[^>]*><\\/router-slot>/g, '');\n }\n\n /**\n * Render a single route's content.\n */\n protected override async renderRouteContent(\n routeInfo: RouteInfo,\n route: RouteConfig,\n isLeaf?: boolean,\n signal?: AbortSignal,\n ): Promise<{ content: string; title?: string }> {\n if (route.modulePath === DEFAULT_ROOT_ROUTE.modulePath) {\n return { content: `<router-slot pattern=\"${route.pattern}\"></router-slot>` };\n }\n\n const { content: rawContent, title } = await this.loadRouteContent(routeInfo, route, isLeaf, signal);\n let content = rawContent;\n\n // Expand <mark-down> tags server-side\n content = await this.expandMarkdown(content);\n\n // Attribute bare <router-slot> tags with this route's pattern (before widget\n // resolution so widget-internal slots inside <template> are not affected)\n content = this.attributeSlots(content, route.pattern);\n\n // Resolve <widget-*> tags: call getData() + renderHTML(), inject ssr attribute\n if (this.widgets) {\n content = await resolveWidgetTags(\n content,\n this.widgets,\n routeInfo,\n (name, declared) => {\n const files = this.widgetFiles[name] ?? declared;\n return files ? this.core.loadWidgetFiles(files) : Promise.resolve({});\n },\n this.core.contextProvider,\n );\n }\n\n return { content, ...(title != null ? { title } : {}) };\n }\n\n protected override renderContent(\n component: PageComponent,\n args: PageComponent['RenderArgs'],\n ): string {\n return component.renderHTML(args);\n }\n\n protected override renderRedirect(to: string): string {\n return `<meta http-equiv=\"refresh\" content=\"0;url=${escapeHtml(to)}\">`;\n }\n\n protected override renderStatusPage(status: number, url: URL): string {\n return `\n <h1>${STATUS_MESSAGES[status] ?? 'Error'}</h1>\n <p>Path: ${escapeHtml(url.pathname)}</p>\n `;\n }\n\n protected override renderErrorPage(error: unknown, url: URL): string {\n const message = error instanceof Error ? error.message : String(error);\n return `\n <h1>Error</h1>\n <p>Path: ${escapeHtml(url.pathname)}</p>\n <p>${escapeHtml(message)}</p>\n `;\n }\n\n /** Add pattern attribute to bare <router-slot> tags. */\n private attributeSlots(content: string, routePattern: string): string {\n return content.replace(\n /<router-slot(?![^>]*\\bpattern=)([^>]*)><\\/router-slot>/g,\n `<router-slot pattern=\"${routePattern}\"$1></router-slot>`,\n );\n }\n\n /**\n * Expand <mark-down> tags by rendering markdown to HTML server-side.\n * Leaves content unchanged if no markdown renderer is configured.\n */\n private async expandMarkdown(content: string): Promise<string> {\n if (!this.markdownRenderer) return content;\n if (!content.includes('<mark-down>')) return content;\n\n if (this.markdownReady) {\n await this.markdownReady;\n }\n\n const renderer = this.markdownRenderer;\n\n // Match <mark-down>escaped content</mark-down>\n const pattern = /<mark-down>([\\s\\S]*?)<\\/mark-down>/g;\n\n return content.replace(pattern, (_match, escaped: string) => {\n const markdown = unescapeHtml(escaped);\n const rendered = renderer.render(markdown);\n return rendered;\n });\n }\n}\n\n/**\n * Create SSR HTML router.\n */\nexport function createSsrHtmlRouter(\n resolver: RouteResolver,\n options?: SsrHtmlRouterOptions,\n): SsrHtmlRouter {\n return new SsrHtmlRouter(resolver, options);\n}\n", "/**\n * Widget Parser\n *\n * Parses fenced widget blocks from markdown content.\n *\n * Syntax:\n * ```widget:widget-name\n * {\"key\": \"value\"}\n * ```\n */\n\nimport type { ParsedWidgetBlock } from '../type/widget.type.ts';\n\n/**\n * Pattern to match widget fenced code blocks.\n * Captures: widget name, params content\n */\nconst WIDGET_PATTERN = /```widget:(?<name>[a-z][a-z0-9-]*)\\n(?<params>.*?)```/gs;\n\n/**\n * Parse all widget blocks from markdown content.\n *\n * @param markdown - Markdown content to parse\n * @returns Array of parsed widget blocks with positions\n */\nexport function parseWidgetBlocks(markdown: string): ParsedWidgetBlock[] {\n const blocks: ParsedWidgetBlock[] = [];\n\n for (const match of markdown.matchAll(WIDGET_PATTERN)) {\n const fullMatch = match[0];\n const { name: widgetName, params: paramsRaw } = match.groups!;\n const paramsJson = paramsRaw.trim();\n const startIndex = match.index;\n\n const block: ParsedWidgetBlock = {\n fullMatch,\n widgetName,\n params: null,\n startIndex,\n endIndex: startIndex + fullMatch.length,\n };\n\n // Parse JSON params if present\n if (paramsJson) {\n try {\n const parsed = JSON.parse(paramsJson);\n if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {\n block.params = parsed;\n } else {\n block.parseError = 'Params must be a JSON object';\n }\n } catch (e) {\n block.parseError = `Invalid JSON: ${e instanceof Error ? e.message : String(e)}`;\n }\n } else {\n // Empty params is valid - use empty object\n block.params = {};\n }\n\n blocks.push(block);\n }\n\n return blocks;\n}\n\n/**\n * Replace widget blocks in markdown with rendered content.\n *\n * @param markdown - Original markdown content\n * @param replacements - Map of parsed blocks to replacement strings\n * @returns Markdown with widget blocks replaced\n */\nexport function replaceWidgetBlocks(\n markdown: string,\n replacements: Map<ParsedWidgetBlock, string>,\n): string {\n // Sort blocks by position descending to replace from end first\n // This preserves indices during replacement\n const sortedBlocks = [...replacements.entries()].sort(\n ([a], [b]) => b.startIndex - a.startIndex,\n );\n\n let result = markdown;\n for (const [block, replacement] of sortedBlocks) {\n result = result.slice(0, block.startIndex) + replacement + result.slice(block.endIndex);\n }\n\n return result;\n}\n", "/**\n * SSR Markdown Renderer\n *\n * Server-side Markdown rendering.\n * Generates Markdown strings for LLM consumption, text clients, curl.\n */\n\nimport type { RouteConfig, RouteInfo } from '../../type/route.type.ts';\nimport type { ComponentContext } from '../../component/abstract.component.ts';\nimport type { RouteResolver } from '../../route/route.resolver.ts';\nimport type { PageComponent } from '../../component/page.component.ts';\nimport { DEFAULT_ROOT_ROUTE } from '../../route/route.core.ts';\nimport { STATUS_MESSAGES } from '../../util/html.util.ts';\nimport { resolveRecursively } from '../../util/widget-resolve.util.ts';\nimport { parseWidgetBlocks, replaceWidgetBlocks } from '../../widget/widget.parser.ts';\nimport { SsrRenderer, type SsrRendererOptions } from './ssr.renderer.ts';\n\nconst BARE_SLOT_BLOCK = '```router-slot\\n```';\n\nfunction routerSlotBlock(pattern: string): string {\n return `\\`\\`\\`router-slot\\n{\"pattern\":\"${pattern}\"}\\n\\`\\`\\``;\n}\n\n/** Options for SSR Markdown Router */\nexport type SsrMdRouterOptions = SsrRendererOptions;\n\n/**\n * SSR Markdown Router for server-side markdown rendering.\n */\nexport class SsrMdRouter extends SsrRenderer {\n protected override readonly label = 'SSR MD';\n\n constructor(resolver: RouteResolver, options: SsrMdRouterOptions = {}) {\n super(resolver, options);\n }\n\n protected override injectSlot(parent: string, child: string, parentPattern: string): string {\n return parent.replace(routerSlotBlock(parentPattern), child);\n }\n\n protected override stripSlots(result: string): string {\n return result\n .replace(/```router-slot\\n(?:\\{[^}]*\\}\\n)?```/g, '')\n .trim();\n }\n\n /**\n * Render a single route's content to Markdown.\n */\n protected override async renderRouteContent(\n routeInfo: RouteInfo,\n route: RouteConfig,\n isLeaf?: boolean,\n signal?: AbortSignal,\n ): Promise<{ content: string; title?: string }> {\n if (route.modulePath === DEFAULT_ROOT_ROUTE.modulePath) {\n return { content: routerSlotBlock(route.pattern) };\n }\n\n const { content: rawContent, title } = await this.loadRouteContent(routeInfo, route, isLeaf, signal);\n let content = rawContent;\n\n // Attribute bare router-slot blocks with this route's pattern\n // (before widget resolution so widget-internal blocks are not affected)\n content = content.replaceAll(BARE_SLOT_BLOCK, routerSlotBlock(route.pattern));\n\n // Resolve fenced widget blocks: call getData() + renderMarkdown()\n if (this.widgets) {\n content = await this.resolveWidgets(content, routeInfo);\n }\n\n return { content, ...(title != null ? { title } : {}) };\n }\n\n protected override renderContent(\n component: PageComponent,\n args: PageComponent['RenderArgs'],\n ): string {\n return component.renderMarkdown(args);\n }\n\n protected override renderRedirect(to: string): string {\n return `Redirect to: ${to}`;\n }\n\n protected override renderStatusPage(status: number, url: URL): string {\n return `# ${STATUS_MESSAGES[status] ?? 'Error'}\\n\\nPath: \\`${url.pathname}\\``;\n }\n\n protected override renderErrorPage(_error: unknown, url: URL): string {\n return `# Internal Server Error\\n\\nPath: \\`${url.pathname}\\``;\n }\n\n /**\n * Resolve fenced widget blocks in markdown content.\n * Replaces ```widget:name blocks with rendered markdown output.\n */\n private resolveWidgets(\n content: string,\n routeInfo: RouteInfo,\n ): Promise<string> {\n return resolveRecursively(\n content,\n parseWidgetBlocks,\n async (block) => {\n if (block.parseError || !block.params) {\n return `> **Error** (\\`${block.widgetName}\\`): ${block.parseError}`;\n }\n\n const widget = this.widgets!.get(block.widgetName);\n if (!widget) {\n return `> **Error**: Unknown widget \\`${block.widgetName}\\``;\n }\n\n try {\n let files: { html?: string; md?: string } | undefined;\n const filePaths = this.widgetFiles[block.widgetName] ?? widget.files;\n if (filePaths) {\n files = await this.core.loadWidgetFiles(filePaths);\n }\n\n const baseContext: ComponentContext = {\n ...routeInfo,\n pathname: routeInfo.url.pathname,\n searchParams: routeInfo.url.searchParams,\n ...(files ? { files } : {}),\n };\n const context: ComponentContext = this.core.contextProvider\n ? this.core.contextProvider(baseContext)\n : baseContext;\n const data = await widget.getData({ params: block.params, context });\n return widget.renderMarkdown({ data, params: block.params, context });\n } catch (e) {\n return widget.renderMarkdownError(e);\n }\n },\n replaceWidgetBlocks,\n );\n }\n}\n\n/**\n * Create SSR Markdown router.\n */\nexport function createSsrMdRouter(\n resolver: RouteResolver,\n options?: SsrMdRouterOptions,\n): SsrMdRouter {\n return new SsrMdRouter(resolver, options);\n}\n", "/**\n * Markdown Link Rewriting\n *\n * Rewrites internal absolute links in markdown to include a base path prefix.\n * Skips fenced code blocks and links already under a known base path.\n */\n\n/** Rewrite internal absolute links in markdown to include the base path prefix. */\nexport function rewriteMdLinks(markdown: string, base: string, skipPrefixes: string[]): string {\n const prefix = base + '/';\n // Negative lookahead: skip links already under a known base path\n const skip = skipPrefixes.map((p) => p.slice(1) + '/').join('|');\n const inlineRe = new RegExp(`\\\\]\\\\(\\\\/(?!${skip})`, 'g');\n const refRe = new RegExp(`^(\\\\[[^\\\\]]+\\\\]:\\\\s+)\\\\/(?!${skip})`, 'g');\n\n const lines = markdown.split('\\n');\n let inCodeBlock = false;\n\n for (let i = 0; i < lines.length; i++) {\n if (lines[i].startsWith('```')) {\n inCodeBlock = !inCodeBlock;\n continue;\n }\n if (inCodeBlock) continue;\n\n lines[i] = lines[i].replaceAll(inlineRe, `](${prefix}`);\n lines[i] = lines[i].replaceAll(refRe, `$1${prefix}`);\n }\n\n return lines.join('\\n');\n}\n", "/**\n * Route Tree Utilities\n *\n * Pure functions for building a RouteNode tree from filesystem paths.\n */\n\nimport type { RouteNode } from '../type/route-tree.type.ts';\n\n/**\n * Resolve the target node for a page or redirect file based on its name.\n *\n * - \"index\" at root \u2192 the node itself (root route)\n * - \"index\" in a subdirectory \u2192 wildcard catch-all on the node\n * - \"[param]\" \u2192 dynamic child\n * - anything else \u2192 static child\n */\nexport function resolveTargetNode(node: RouteNode, name: string, isRoot: boolean): RouteNode {\n if (name === 'index') {\n if (isRoot) return node;\n // Non-root index \u2192 wildcard catch-all\n node.wildcard ??= { param: 'rest', child: {} };\n return node.wildcard.child;\n }\n\n if (name.startsWith('[') && name.endsWith(']')) {\n const param = name.slice(1, -1);\n node.dynamic ??= { param, child: {} };\n return node.dynamic.child;\n }\n\n // Static segment\n node.children ??= {};\n node.children[name] ??= {};\n return node.children[name];\n}\n", "import type { RouteNode, RouteFiles } from '../src/type/route-tree.type.ts';\nimport { resolveTargetNode } from '../src/route/route-tree.util.ts';\nimport type { WidgetManifestEntry } from '../src/type/widget.type.ts';\nimport type { ElementManifestEntry } from '../src/type/element.type.ts';\n\nexport const CONTENT_TYPES: Map<string, string> = new Map<string, string>([\n ['.html', 'text/html; charset=utf-8'],\n ['.css', 'text/css; charset=utf-8'],\n ['.js', 'application/javascript; charset=utf-8'],\n ['.mjs', 'application/javascript; charset=utf-8'],\n ['.ts', 'text/typescript; charset=utf-8'],\n ['.json', 'application/json; charset=utf-8'],\n ['.md', 'text/plain; charset=utf-8'],\n ['.txt', 'text/plain; charset=utf-8'],\n ['.wasm', 'application/wasm'],\n ['.map', 'application/json; charset=utf-8'],\n ['.png', 'image/png'],\n ['.jpg', 'image/jpeg'],\n ['.jpeg', 'image/jpeg'],\n ['.gif', 'image/gif'],\n ['.svg', 'image/svg+xml'],\n ['.ico', 'image/x-icon'],\n ['.webp', 'image/webp'],\n ['.avif', 'image/avif'],\n ['.woff', 'font/woff'],\n ['.woff2', 'font/woff2'],\n ['.ttf', 'font/ttf'],\n]);\n\nexport type FetchParams = Parameters<typeof fetch>;\nexport type FetchReturn = ReturnType<typeof fetch>;\n\nexport const DEFAULT_ROUTES_DIR = '/routes';\nexport const DEFAULT_WIDGETS_DIR = '/widgets';\nexport const DEFAULT_ELEMENTS_DIR = '/elements';\nexport const ROUTES_MANIFEST_PATH = '/routes.manifest.json';\nexport const WIDGETS_MANIFEST_PATH = '/widgets.manifest.json';\nexport const ELEMENTS_MANIFEST_PATH = '/elements.manifest.json';\n\nexport interface RuntimeConfig {\n routesDir?: string;\n widgetsDir?: string;\n elementsDir?: string;\n}\n\n/**\n * Abstract resource provider. Speaks Request/Response (ADR-1).\n *\n * Three access patterns:\n * - `handle()` \u2014 raw passthrough, server forwards browser requests as-is.\n * - `query()` \u2014 read. Returns Response, or string when `{ as: \"text\" }`.\n * - `command()` \u2014 write (PUT by default, override with `{ method }` in options).\n *\n * Includes manifest resolution: when `query(ROUTES_MANIFEST_PATH)` or\n * `query(WIDGETS_MANIFEST_PATH)` returns 404, the runtime scans the\n * configured directories and caches the result.\n */\nexport abstract class Runtime {\n constructor(readonly config: RuntimeConfig = {}) {\n this.config = config;\n }\n /** Concrete runtimes implement this. Accepts the same args as `fetch()`. */\n abstract handle(resource: FetchParams[0], init?: FetchParams[1]): FetchReturn;\n\n /**\n * Read with `{ as: \"text\" }` \u2014 skip metadata, return contents only.\n * Semantically equivalent to `Accept: text/plain`; `as` exists for type safety.\n */\n abstract query(\n resource: FetchParams[0],\n options: FetchParams[1] & { as: 'text' },\n ): Promise<string>;\n /** Read \u2014 returns full Response with headers, status, body. */\n abstract query(\n resource: FetchParams[0],\n options?: FetchParams[1],\n ): FetchReturn;\n\n /** Write. Defaults to PUT; pass `{ method: \"DELETE\" }` etc. to override. */\n command(resource: FetchParams[0], options?: FetchParams[1]): FetchReturn {\n const path = typeof resource === 'string'\n ? resource\n : new URL(resource instanceof Request ? resource.url : resource.toString()).pathname;\n const result = this.handle(resource, { method: 'PUT', ...options });\n const routesDir = this.config.routesDir ?? DEFAULT_ROUTES_DIR;\n if (path.startsWith(routesDir + '/')) {\n return result.then(async (res) => {\n await this.mergeRouteIntoManifest(path, routesDir);\n return res;\n });\n }\n return result;\n }\n\n /**\n * Parse a single route file path and merge it into the stored manifest.\n * Avoids a full directory rescan \u2014 just reads the current manifest,\n * inserts the new entry, and writes it back.\n */\n private async mergeRouteIntoManifest(\n filePath: string,\n routesDir: string,\n ): Promise<void> {\n const relativePath = filePath.slice(routesDir.length + 1);\n const parts = relativePath.split('/');\n const filename = parts[parts.length - 1];\n const dirSegments = parts.slice(0, -1);\n\n const match = filename.match(/^(.+?)\\.(page|error|redirect)\\.(ts|js|html|md|css)$/);\n if (!match) return;\n\n const [, name, kind, ext] = match;\n\n // Read current manifest (or start fresh)\n const response = await this.handle(ROUTES_MANIFEST_PATH);\n const tree: RouteNode = response.status === 404\n ? {}\n : await response.json();\n\n // Walk to the parent node\n let node = tree;\n for (const dir of dirSegments) {\n if (dir.startsWith('[') && dir.endsWith(']')) {\n const param = dir.slice(1, -1);\n node.dynamic ??= { param, child: {} };\n node = node.dynamic.child;\n } else {\n node.children ??= {};\n node.children[dir] ??= {};\n node = node.children[dir];\n }\n }\n\n // Place the file\n if (kind === 'error') {\n node.errorBoundary = filePath;\n } else {\n const target = resolveTargetNode(node, name, dirSegments.length === 0);\n if (kind === 'redirect') {\n target.redirect = filePath;\n } else {\n target.files ??= {};\n target.files[ext as keyof RouteFiles] = filePath;\n }\n }\n\n // Write updated manifest back\n this.routesManifestCache = null;\n await this.handle(ROUTES_MANIFEST_PATH, {\n method: 'PUT',\n body: JSON.stringify(tree),\n });\n }\n\n /**\n * Dynamically import a module from this runtime's storage.\n * Used by the server for SSR imports of `.page.ts` and `.widget.ts` files.\n */\n loadModule(_path: string): Promise<unknown> {\n throw new Error(`loadModule not implemented for ${this.constructor.name}`);\n }\n\n /**\n * Transpile TypeScript source to JavaScript.\n * Used by the build step to produce browser-loadable .js modules.\n */\n transpile(_source: string): Promise<string> {\n throw new Error(`transpile not implemented for ${this.constructor.name}`);\n }\n\n // \u2500\u2500 Manifest resolution \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 private routesManifestCache: Response | null = null;\n private widgetsManifestCache: Response | null = null;\n private elementsManifestCache: Response | null = null;\n\n /** Clear cached manifests so the next query triggers a fresh scan. */\n invalidateManifests(): void {\n this.routesManifestCache = null;\n this.widgetsManifestCache = null;\n this.elementsManifestCache = null;\n }\n\n /**\n * Resolve the routes manifest. Called when the concrete runtime returns\n * 404 for ROUTES_MANIFEST_PATH. Scans `config.routesDir` (or default).\n */\n async resolveRoutesManifest(): Promise<Response> {\n if (this.routesManifestCache) return this.routesManifestCache.clone();\n\n const routesDir = this.config.routesDir ?? DEFAULT_ROUTES_DIR;\n\n // Check if directory exists by querying it\n const dirResponse = await this.query(routesDir + '/');\n if (dirResponse.status === 404) {\n return new Response('Not Found', { status: 404 });\n }\n\n const tree = await this.scanRoutes(routesDir);\n\n this.routesManifestCache = Response.json(tree);\n return this.routesManifestCache.clone();\n }\n\n /**\n * Resolve the widgets manifest. Called when the concrete runtime returns\n * 404 for WIDGETS_MANIFEST_PATH. Scans `config.widgetsDir` (or default).\n */\n async resolveWidgetsManifest(): Promise<Response> {\n if (this.widgetsManifestCache) return this.widgetsManifestCache.clone();\n\n const widgetsDir = this.config.widgetsDir ?? DEFAULT_WIDGETS_DIR;\n\n const dirResponse = await this.query(widgetsDir + '/');\n if (dirResponse.status === 404) {\n return new Response('Not Found', { status: 404 });\n }\n\n const entries = await this.scanWidgets(widgetsDir, widgetsDir.replace(/^\\//, ''));\n this.widgetsManifestCache = Response.json(entries);\n return this.widgetsManifestCache.clone();\n }\n\n /**\n * Resolve the elements manifest. Called when the concrete runtime returns\n * 404 for ELEMENTS_MANIFEST_PATH. Scans `config.elementsDir` (or default).\n */\n async resolveElementsManifest(): Promise<Response> {\n if (this.elementsManifestCache) return this.elementsManifestCache.clone();\n\n const elementsDir = this.config.elementsDir ?? DEFAULT_ELEMENTS_DIR;\n\n const dirResponse = await this.query(elementsDir + '/');\n if (dirResponse.status === 404) {\n return new Response('Not Found', { status: 404 });\n }\n\n const entries = await this.scanElements(elementsDir, elementsDir.replace(/^\\//, ''));\n this.elementsManifestCache = Response.json(entries);\n return this.elementsManifestCache.clone();\n }\n\n // \u2500\u2500 Scanning \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 protected async *walkDirectory(dir: string): AsyncGenerator<string> {\n const trailingDir = dir.endsWith('/') ? dir : dir + '/';\n const response = await this.query(trailingDir);\n const entries: string[] = await response.json();\n\n for (const entry of entries) {\n const path = `${trailingDir}${entry}`;\n if (entry.endsWith('/')) {\n yield* this.walkDirectory(path);\n } else {\n yield path;\n }\n }\n }\n\n /**\n * Scan a routes directory and build a RouteNode tree.\n * The filesystem structure maps directly to the tree \u2014 no intermediate array.\n */\n protected async scanRoutes(routesDir: string): Promise<RouteNode> {\n const root: RouteNode = {};\n\n const allFiles: string[] = [];\n for await (const file of this.walkDirectory(routesDir)) {\n allFiles.push(file);\n }\n\n for (const filePath of allFiles) {\n const relativePath = filePath.replace(`${routesDir}/`, '');\n const parts = relativePath.split('/');\n const filename = parts[parts.length - 1];\n const dirSegments = parts.slice(0, -1);\n\n // Parse filename: name.kind.ext (e.g. \"about.page.ts\", \"[id].page.html\", \"index.error.ts\")\n const match = filename.match(/^(.+?)\\.(page|error|redirect)\\.(ts|js|html|md|css)$/);\n if (!match) continue;\n\n const [, name, kind, ext] = match;\n\n // Walk directory segments to reach the parent node\n let node = root;\n for (const dir of dirSegments) {\n if (dir.startsWith('[') && dir.endsWith(']')) {\n const param = dir.slice(1, -1);\n node.dynamic ??= { param, child: {} };\n node = node.dynamic.child;\n } else {\n node.children ??= {};\n node.children[dir] ??= {};\n node = node.children[dir];\n }\n }\n\n // Place the file on the correct node\n if (kind === 'error') {\n // Error boundary scopes to the directory it's in.\n // Root index.error.ts \u2192 root.errorBoundary (global handler).\n // projects/projects.error.ts \u2192 projects node errorBoundary.\n node.errorBoundary = filePath;\n continue;\n }\n\n // For page and redirect files, the name determines the final node\n const target = resolveTargetNode(node, name, dirSegments.length === 0);\n\n if (kind === 'redirect') {\n target.redirect = filePath;\n } else {\n // kind === 'page'\n target.files ??= {};\n target.files[ext as keyof RouteFiles] = filePath;\n }\n }\n\n return root;\n }\n\n protected async scanWidgets(\n widgetsDir: string,\n pathPrefix?: string,\n ): Promise<WidgetManifestEntry[]> {\n const COMPANION_EXTENSIONS = ['html', 'md', 'css'] as const;\n const entries: WidgetManifestEntry[] = [];\n\n const trailingDir = widgetsDir.endsWith('/') ? widgetsDir : widgetsDir + '/';\n const response = await this.query(trailingDir);\n const listing: string[] = await response.json();\n\n for (const item of listing) {\n if (!item.endsWith('/')) continue;\n\n const name = item.slice(0, -1);\n\n // Try .widget.ts first, then .widget.js\n let moduleFile = `${name}.widget.ts`;\n let modulePath = `${trailingDir}${name}/${moduleFile}`;\n if ((await this.query(modulePath)).status === 404) {\n moduleFile = `${name}.widget.js`;\n modulePath = `${trailingDir}${name}/${moduleFile}`;\n if ((await this.query(modulePath)).status === 404) continue;\n }\n\n const prefix = pathPrefix ? `${pathPrefix}/` : '';\n const entry: WidgetManifestEntry = {\n name,\n modulePath: `${prefix}${name}/${moduleFile}`,\n tagName: `widget-${name}`,\n };\n\n const files: { html?: string; md?: string; css?: string } = {};\n let hasFiles = false;\n for (const ext of COMPANION_EXTENSIONS) {\n const companionFile = `${name}.widget.${ext}`;\n const companionPath = `${trailingDir}${name}/${companionFile}`;\n if ((await this.query(companionPath)).status !== 404) {\n files[ext] = `${prefix}${name}/${companionFile}`;\n hasFiles = true;\n }\n }\n\n if (hasFiles) entry.files = files;\n entries.push(entry);\n }\n\n entries.sort((a, b) => a.name.localeCompare(b.name));\n return entries;\n }\n\n protected async scanElements(\n elementsDir: string,\n pathPrefix?: string,\n ): Promise<ElementManifestEntry[]> {\n const entries: ElementManifestEntry[] = [];\n\n const trailingDir = elementsDir.endsWith('/') ? elementsDir : elementsDir + '/';\n const response = await this.query(trailingDir);\n const listing: string[] = await response.json();\n\n for (const item of listing) {\n if (!item.endsWith('/')) continue;\n\n const name = item.slice(0, -1);\n\n // Custom element names must contain a hyphen (web spec requirement)\n if (!name.includes('-')) {\n console.warn(`[emroute] Skipping element \"${name}\": custom element names must contain a hyphen (e.g. \"my-element\")`);\n continue;\n }\n\n // Try .element.ts first, then .element.js\n let moduleFile = `${name}.element.ts`;\n let modulePath = `${trailingDir}${name}/${moduleFile}`;\n if ((await this.query(modulePath)).status === 404) {\n moduleFile = `${name}.element.js`;\n modulePath = `${trailingDir}${name}/${moduleFile}`;\n if ((await this.query(modulePath)).status === 404) continue;\n }\n\n const prefix = pathPrefix ? `${pathPrefix}/` : '';\n entries.push({\n name,\n modulePath: `${prefix}${name}/${moduleFile}`,\n tagName: name,\n });\n }\n\n entries.sort((a, b) => a.name.localeCompare(b.name));\n return entries;\n }\n}\n", "/**\n * Emroute Server\n *\n * Runtime-agnostic server that handles SSR rendering, manifest resolution,\n * static file serving, and route matching. Works with any Runtime implementation.\n *\n * Usage (standalone):\n * ```ts\n * import { createEmrouteServer } from '@emkodev/emroute/server';\n * import { BunFsRuntime } from '@emkodev/emroute/runtime/bun/fs';\n *\n * const runtime = new BunFsRuntime('.', { routesDir: '/routes' });\n * const emroute = await createEmrouteServer({ spa: 'root' }, runtime);\n *\n * Bun.serve({ fetch: (req) => emroute.handleRequest(req) ?? new Response('Not Found', { status: 404 }) });\n * ```\n *\n * Usage (composable):\n * ```ts\n * const emroute = await createEmrouteServer(config, runtime);\n *\n * Bun.serve({ async fetch(req) {\n * if (isApiRoute(req)) return handleApi(req);\n * const response = await emroute.handleRequest(req);\n * if (response) return response;\n * return new Response('Not Found', { status: 404 });\n * }});\n * ```\n */\n\nimport { DEFAULT_BASE_PATH } from '../src/route/route.core.ts';\nimport { RouteTrie } from '../src/route/route.trie.ts';\nimport { SsrHtmlRouter } from '../src/renderer/ssr/html.renderer.ts';\nimport { SsrMdRouter } from '../src/renderer/ssr/md.renderer.ts';\nimport type { RouteNode } from '../src/type/route-tree.type.ts';\nimport type { WidgetManifestEntry } from '../src/type/widget.type.ts';\nimport type { ElementManifestEntry } from '../src/type/element.type.ts';\nimport { WidgetRegistry } from '../src/widget/widget.registry.ts';\nimport type { WidgetComponent } from '../src/component/widget.component.ts';\nimport { escapeHtml } from '../src/util/html.util.ts';\nimport { rewriteMdLinks } from '../src/util/md.util.ts';\nimport {\n ROUTES_MANIFEST_PATH,\n Runtime,\n WIDGETS_MANIFEST_PATH,\n ELEMENTS_MANIFEST_PATH,\n} from '../runtime/abstract.runtime.ts';\nimport type { EmrouteServer, EmrouteServerConfig } from './server-api.type.ts';\n\n// \u2500\u2500 Module loaders \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * Collect all .ts module paths from a RouteNode tree and create loaders.\n * Uses `runtime.loadModule()` \u2014 each runtime decides how to load modules\n * (filesystem import, SQLite transpile + blob URL, etc.).\n */\nfunction createModuleLoaders(\n tree: RouteNode,\n runtime: Runtime,\n): Record<string, () => Promise<unknown>> {\n const paths = new Set<string>();\n\n function walk(node: RouteNode): void {\n const modulePath = node.files?.ts ?? node.files?.js;\n if (modulePath) paths.add(modulePath);\n if (node.redirect) paths.add(node.redirect);\n if (node.errorBoundary) paths.add(node.errorBoundary);\n\n if (node.children) {\n for (const child of Object.values(node.children)) walk(child);\n }\n if (node.dynamic) walk(node.dynamic.child);\n if (node.wildcard) walk(node.wildcard.child);\n }\n\n walk(tree);\n\n const loaders: Record<string, () => Promise<unknown>> = {};\n for (const path of paths) {\n loaders[path] = () => runtime.loadModule(path);\n }\n return loaders;\n}\n\n// \u2500\u2500 Widget helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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/** Find a WidgetComponent export from a module. */\nfunction extractWidgetExport(\n mod: Record<string, unknown>,\n): WidgetComponent | null {\n for (const value of Object.values(mod)) {\n if (!value) continue;\n if (typeof value === 'object' && 'getData' in value) {\n return value as WidgetComponent;\n }\n if (typeof value === 'function' && value.prototype?.getData) {\n return new (value as new () => WidgetComponent)();\n }\n }\n return null;\n}\n\n/** Import widget modules for SSR via runtime.loadModule(). */\nasync function importWidgets(\n entries: WidgetManifestEntry[],\n runtime: Runtime,\n manual?: WidgetRegistry,\n): Promise<{\n registry: WidgetRegistry;\n widgetFiles: Record<string, { html?: string; md?: string; css?: string }>;\n}> {\n const registry = new WidgetRegistry();\n const widgetFiles: Record<string, { html?: string; md?: string; css?: string }> = {};\n\n for (const entry of entries) {\n try {\n const runtimePath = entry.modulePath.startsWith('/')\n ? entry.modulePath\n : `/${entry.modulePath}`;\n\n const mod = await runtime.loadModule(runtimePath) as Record<string, unknown>;\n const instance = extractWidgetExport(mod);\n if (!instance) continue;\n registry.add(instance);\n\n // Prefer inlined __files from merged module over manifest paths\n const inlined = mod.__files;\n if (inlined && typeof inlined === 'object') {\n widgetFiles[entry.name] = inlined as { html?: string; md?: string; css?: string };\n } else if (entry.files) {\n widgetFiles[entry.name] = entry.files;\n }\n } catch (e) {\n console.error(`[emroute] Failed to load widget ${entry.modulePath}:`, e);\n if (entry.files) widgetFiles[entry.name] = entry.files;\n }\n }\n\n if (manual) {\n for (const widget of manual) {\n registry.add(widget);\n }\n }\n\n return { registry, widgetFiles };\n}\n\n// \u2500\u2500 HTML shell \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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/** Build a default HTML shell. */\nfunction buildHtmlShell(title: string, htmlBase: string): string {\n const baseTag = htmlBase ? `\\n <base href=\"${escapeHtml(htmlBase)}/\">` : '';\n return `<!DOCTYPE html>\n<html>\n<head>${baseTag}\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <title>${escapeHtml(title)}</title>\n <style>@view-transition { navigation: auto; } router-slot { display: contents; }</style>\n</head>\n<body>\n <router-slot></router-slot>\n</body>\n</html>`;\n}\n\n/** Inject SSR-rendered content into an HTML shell. */\nfunction injectSsrContent(\n html: string,\n content: string,\n title: string | undefined,\n ssrRoute?: string,\n): string {\n const slotPattern = /<router-slot\\b[^>]*>.*?<\\/router-slot>/s;\n if (!slotPattern.test(html)) return html;\n\n const ssrAttr = ssrRoute ? ` data-ssr-route=\"${ssrRoute}\"` : '';\n html = html.replace(slotPattern, `<router-slot${ssrAttr}>${content}</router-slot>`);\n\n if (title) {\n html = html.replace(/<title>[^<]*<\\/title>/, `<title>${escapeHtml(title)}</title>`);\n }\n\n return html;\n}\n\n/** Read the HTML shell from runtime, with fallback to a default shell. */\nasync function resolveShell(\n runtime: Runtime,\n title: string,\n htmlBase: string,\n): Promise<string> {\n const response = await runtime.query('/index.html');\n if (response.status !== 404) return await response.text();\n return buildHtmlShell(title, htmlBase);\n}\n\n// \u2500\u2500 More path helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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// \u2500\u2500 createEmrouteServer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 * Create an emroute server.\n *\n * All paths are Runtime-relative (starting with `/`). Runtime root = appRoot.\n */\nexport async function createEmrouteServer(\n config: EmrouteServerConfig,\n runtime: Runtime,\n): Promise<EmrouteServer> {\n const {\n spa = 'root',\n } = config;\n\n const { html: htmlBase, md: mdBase, app: appBase } = config.basePath ?? DEFAULT_BASE_PATH;\n\n // \u2500\u2500 Route tree (read from runtime) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 let routeTree: RouteNode;\n\n if (config.routeTree) {\n routeTree = config.routeTree;\n } else {\n const manifestResponse = await runtime.query(ROUTES_MANIFEST_PATH);\n if (manifestResponse.status === 404) {\n throw new Error(\n `[emroute] ${ROUTES_MANIFEST_PATH} not found in runtime. ` +\n 'Provide routeTree in config or ensure the runtime produces it.',\n );\n }\n routeTree = await manifestResponse.json();\n }\n\n const moduleLoaders = config.moduleLoaders ?? createModuleLoaders(routeTree, runtime);\n const resolver = new RouteTrie(routeTree);\n\n // \u2500\u2500 Widgets (read from runtime) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 let widgets: WidgetRegistry | undefined = config.widgets;\n let widgetFiles: Record<string, { html?: string; md?: string; css?: string }> = {};\n let discoveredWidgetEntries: WidgetManifestEntry[] = [];\n\n const widgetsResponse = await runtime.query(WIDGETS_MANIFEST_PATH);\n if (widgetsResponse.status !== 404) {\n discoveredWidgetEntries = await widgetsResponse.json();\n if (config.widgets) {\n // Widgets pre-provided (e.g. browser bundle) \u2014 just collect file paths\n widgets = config.widgets;\n for (const entry of discoveredWidgetEntries) {\n if (entry.files) widgetFiles[entry.name] = entry.files;\n }\n } else {\n const imported = await importWidgets(discoveredWidgetEntries, runtime);\n widgets = imported.registry;\n widgetFiles = imported.widgetFiles;\n }\n }\n\n // \u2500\u2500 Elements (read from runtime) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 let discoveredElementEntries: ElementManifestEntry[] = [];\n const elementsResponse = await runtime.query(ELEMENTS_MANIFEST_PATH);\n if (elementsResponse.status !== 404) {\n discoveredElementEntries = await elementsResponse.json();\n }\n\n // \u2500\u2500 SSR routers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 let ssrHtmlRouter: SsrHtmlRouter | null = null;\n let ssrMdRouter: SsrMdRouter | null = null;\n\n function buildSsrRouters(): void {\n if (spa === 'only') {\n ssrHtmlRouter = null;\n ssrMdRouter = null;\n return;\n }\n\n ssrHtmlRouter = new SsrHtmlRouter(resolver, {\n fileReader: (path) => runtime.query(path, { as: 'text' }),\n moduleLoaders,\n ...(config.markdownRenderer ? { markdownRenderer: config.markdownRenderer } : {}),\n ...(config.extendContext ? { extendContext: config.extendContext } : {}),\n ...(widgets ? { widgets } : {}),\n widgetFiles,\n });\n\n ssrMdRouter = new SsrMdRouter(resolver, {\n fileReader: (path) => runtime.query(path, { as: 'text' }),\n moduleLoaders,\n ...(config.extendContext ? { extendContext: config.extendContext } : {}),\n ...(widgets ? { widgets } : {}),\n widgetFiles,\n });\n }\n\n buildSsrRouters();\n\n // \u2500\u2500 HTML shell \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 const title = config.title ?? 'emroute';\n const shellBase = (spa === 'root' || spa === 'only') ? appBase : htmlBase;\n let shell = await resolveShell(runtime, title, shellBase);\n\n // Auto-discover main.css and inject <link> into <head>\n if ((await runtime.query('/main.css')).status !== 404) {\n shell = shell.replace('</head>', ' <link rel=\"stylesheet\" href=\"/main.css\">\\n</head>');\n }\n\n // \u2500\u2500 handleRequest \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 async function handleRequest(req: Request): Promise<Response | null> {\n const url = new URL(req.url);\n const pathname = url.pathname;\n\n const mdPrefix = mdBase + '/';\n const htmlPrefix = htmlBase + '/';\n const appPrefix = appBase + '/';\n\n // SSR Markdown: /md/*\n if (\n ssrMdRouter &&\n (pathname.startsWith(mdPrefix) || pathname === mdBase)\n ) {\n // Normalize trailing slash: /md/about/ \u2192 301 /md/about\n const routePath = pathname === mdBase ? '/' : pathname.slice(mdBase.length);\n if (routePath.length > 1 && routePath.endsWith('/')) {\n const canonical = mdBase + routePath.slice(0, -1) + (url.search || '');\n return Response.redirect(new URL(canonical, url.origin), 301);\n }\n try {\n const routeUrl = new URL(routePath + url.search, url.origin);\n const { content, status, redirect } = await ssrMdRouter.render(routeUrl, req.signal);\n if (redirect) {\n const target = redirect.startsWith('/') ? mdBase + redirect : redirect;\n return Response.redirect(new URL(target, url.origin), status);\n }\n return new Response(rewriteMdLinks(content, mdBase, [mdBase, htmlBase]), {\n status,\n headers: { 'Content-Type': 'text/markdown; charset=utf-8; variant=CommonMark' },\n });\n } catch (e) {\n console.error(`[emroute] Error rendering ${pathname}:`, e);\n return new Response('Internal Server Error', { status: 500 });\n }\n }\n\n // SSR HTML: /html/*\n if (\n ssrHtmlRouter &&\n (pathname.startsWith(htmlPrefix) || pathname === htmlBase)\n ) {\n // Normalize trailing slash: /html/about/ \u2192 301 /html/about\n const routePath = pathname === htmlBase ? '/' : pathname.slice(htmlBase.length);\n if (routePath.length > 1 && routePath.endsWith('/')) {\n const canonical = htmlBase + routePath.slice(0, -1) + (url.search || '');\n return Response.redirect(new URL(canonical, url.origin), 301);\n }\n try {\n const routeUrl = new URL(routePath + url.search, url.origin);\n const result = await ssrHtmlRouter.render(routeUrl, req.signal);\n if (result.redirect) {\n const target = result.redirect.startsWith('/') ? htmlBase + result.redirect : result.redirect;\n return Response.redirect(new URL(target, url.origin), result.status);\n }\n const ssrTitle = result.title ?? title;\n const html = injectSsrContent(shell, result.content, ssrTitle, pathname);\n return new Response(html, {\n status: result.status,\n headers: { 'Content-Type': 'text/html; charset=utf-8' },\n });\n } catch (e) {\n console.error(`[emroute] Error rendering ${pathname}:`, e);\n return new Response('Internal Server Error', { status: 500 });\n }\n }\n\n // /app/* \u2014 serve shell (browser JS takes over via createEmrouteApp)\n if (pathname.startsWith(appPrefix) || pathname === appBase) {\n return new Response(shell, {\n status: 200,\n headers: { 'Content-Type': 'text/html; charset=utf-8' },\n });\n }\n\n // /html/* or /md/* that wasn't handled by SSR (e.g. 'only' mode) \u2014 serve shell\n if (\n pathname.startsWith(htmlPrefix) || pathname === htmlBase ||\n pathname.startsWith(mdPrefix) || pathname === mdBase\n ) {\n return new Response(shell, {\n status: 200,\n headers: { 'Content-Type': 'text/html; charset=utf-8' },\n });\n }\n\n // Static files \u2014 only try runtime for paths with a file extension\n const lastSegment = pathname.split('/').pop() ?? '';\n if (lastSegment.includes('.')) {\n const fileResponse = await runtime.handle(pathname);\n if (fileResponse.status === 200) return fileResponse;\n return null;\n }\n\n // Bare paths \u2014 redirect to /app/* in root/only modes, /html/* otherwise.\n const base = (spa === 'root' || spa === 'only') ? appBase : htmlBase;\n const bare = pathname === '/' ? '' : pathname.slice(1).replace(/\\/$/, '');\n return Response.redirect(new URL(`${base}/${bare}`, url.origin), 302);\n }\n\n // \u2500\u2500 Return \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 return {\n handleRequest,\n get htmlRouter() {\n return ssrHtmlRouter;\n },\n get mdRouter() {\n return ssrMdRouter;\n },\n get routeTree() {\n return routeTree;\n },\n get widgetEntries() {\n return discoveredWidgetEntries;\n },\n get elementEntries() {\n return discoveredElementEntries;\n },\n get shell() {\n return shell;\n },\n };\n}\n", "/**\n * Fetch Runtime\n *\n * Browser-compatible Runtime that delegates all reads to a remote server\n * via `fetch()`. Used by the thin client in `root` mode \u2014 same\n * `createEmrouteServer` runs in the browser, but the Runtime fetches\n * files from the real server instead of reading from disk.\n *\n * No bundling, no transpiling, no filesystem access.\n * No directory scanning \u2014 the remote server already has manifests.\n */\n\nimport {\n type FetchParams,\n type FetchReturn,\n Runtime,\n type RuntimeConfig,\n} from './abstract.runtime.ts';\n\nexport class FetchRuntime extends Runtime {\n private readonly origin: string;\n\n /**\n * @param origin \u2014 Server origin, e.g. `'http://localhost:4100'` or `location.origin`.\n */\n constructor(origin: string, config: RuntimeConfig = {}) {\n super(config);\n this.origin = origin.endsWith('/') ? origin.slice(0, -1) : origin;\n }\n\n handle(\n resource: FetchParams[0],\n init?: FetchParams[1],\n ): FetchReturn {\n const url = this.toUrl(resource);\n return fetch(url, init);\n }\n\n query(\n resource: FetchParams[0],\n options: FetchParams[1] & { as: 'text' },\n ): Promise<string>;\n query(\n resource: FetchParams[0],\n options?: FetchParams[1],\n ): FetchReturn;\n query(\n resource: FetchParams[0],\n options?: FetchParams[1] & { as?: 'text' },\n ): Promise<Response | string> {\n if (options?.as === 'text') {\n return fetch(this.toUrl(resource)).then((r) => r.text());\n }\n return this.handle(resource, options);\n }\n\n override async loadModule(path: string): Promise<unknown> {\n const url = `${this.origin}${path}`;\n const response = await fetch(url);\n const js = await response.text();\n const blob = new Blob([js], { type: 'application/javascript' });\n return import(URL.createObjectURL(blob));\n }\n\n private toUrl(resource: FetchParams[0]): string {\n if (typeof resource === 'string') return `${this.origin}${resource}`;\n if (resource instanceof URL) return `${this.origin}${resource.pathname}${resource.search}`;\n return `${this.origin}${new URL(resource.url).pathname}`;\n }\n}\n", "/// <reference path=\"../../type/navigation-api.d.ts\" />\n\n/**\n * Emroute App\n *\n * Browser entry point for `/app/` routes. Wraps an EmrouteServer instance\n * (same server, same pipeline) with Navigation API glue that intercepts\n * link clicks, calls `htmlRouter.render()`, and injects the result.\n */\n\nimport type { EmrouteServer } from '../../../server/server-api.type.ts';\nimport { createEmrouteServer } from '../../../server/emroute.server.ts';\nimport { FetchRuntime } from '../../../runtime/fetch.runtime.ts';\nimport { ROUTES_MANIFEST_PATH, WIDGETS_MANIFEST_PATH, ELEMENTS_MANIFEST_PATH } from '../../../runtime/abstract.runtime.ts';\nimport type { RouteNode } from '../../type/route-tree.type.ts';\nimport type { NavigateOptions } from '../../type/route.type.ts';\nimport type { WidgetManifestEntry } from '../../type/widget.type.ts';\nimport type { ElementManifestEntry } from '../../type/element.type.ts';\nimport { assertSafeRedirect, type BasePath, DEFAULT_BASE_PATH } from '../../route/route.core.ts';\nimport { escapeHtml } from '../../util/html.util.ts';\nimport { ComponentElement } from '../../element/component.element.ts';\nimport { MarkdownElement } from '../../element/markdown.element.ts';\nimport { WidgetRegistry } from '../../widget/widget.registry.ts';\n\n/** Options for `createEmrouteApp`. */\nexport interface EmrouteAppOptions {\n basePath?: BasePath;\n}\n\n/** Browser app \u2014 Navigation API wired to an EmrouteServer. */\nexport class EmrouteApp {\n private readonly server: EmrouteServer;\n private readonly appBase: string;\n private slot: Element | null = null;\n private abortController: AbortController | null = null;\n\n constructor(server: EmrouteServer, options?: EmrouteAppOptions) {\n const bp = options?.basePath ?? DEFAULT_BASE_PATH;\n this.server = server;\n this.appBase = bp.app;\n }\n\n async initialize(slotSelector = 'router-slot'): Promise<void> {\n this.slot = document.querySelector(slotSelector);\n\n if (!this.slot) {\n console.error('[EmrouteApp] Slot not found:', slotSelector);\n return;\n }\n\n if (!('navigation' in globalThis)) {\n console.warn('[EmrouteApp] Navigation API not available');\n return;\n }\n\n this.abortController = new AbortController();\n const { signal } = this.abortController;\n\n navigation.addEventListener('navigate', (event) => {\n if (!event.canIntercept) return;\n if (event.hashChange) return;\n if (event.downloadRequest !== null) return;\n\n const url = new URL(event.destination.url);\n if (!this.isAppPath(url.pathname)) return;\n\n event.intercept({\n scroll: 'manual',\n handler: async () => {\n await this.handleNavigation(url, event.signal);\n event.scroll();\n },\n });\n }, { signal });\n\n // SSR adoption \u2014 server already rendered this page, skip re-render\n const ssrRoute = this.slot.getAttribute('data-ssr-route');\n if (ssrRoute && (location.pathname === ssrRoute || location.pathname === ssrRoute + '/')) {\n this.slot.removeAttribute('data-ssr-route');\n return;\n }\n\n // Initial render\n await this.handleNavigation(new URL(location.href), this.abortController.signal);\n }\n\n dispose(): void {\n this.abortController?.abort();\n this.abortController = null;\n this.slot = null;\n }\n\n async navigate(url: string, options: NavigateOptions = {}): Promise<void> {\n try {\n const { finished } = navigation.navigate(url, {\n state: options.state,\n history: options.replace ? 'replace' : 'auto',\n });\n await finished;\n } catch (e) {\n if (e instanceof DOMException && e.name === 'AbortError') return;\n throw e;\n }\n }\n\n private isAppPath(pathname: string): boolean {\n return pathname === this.appBase || pathname.startsWith(this.appBase + '/');\n }\n\n private stripAppBase(pathname: string): string {\n if (pathname === this.appBase) return '/';\n if (pathname.startsWith(this.appBase + '/')) return pathname.slice(this.appBase.length);\n return pathname;\n }\n\n private async handleNavigation(url: URL, signal: AbortSignal): Promise<void> {\n if (!this.slot || !this.server.htmlRouter) return;\n\n const routePath = this.stripAppBase(url.pathname);\n const routeUrl = new URL(routePath + url.search, url.origin);\n\n try {\n const { content, title, redirect } = await this.server.htmlRouter.render(routeUrl, signal);\n\n if (signal.aborted) return;\n\n if (redirect) {\n assertSafeRedirect(redirect);\n const target = redirect.startsWith('/') ? this.appBase + redirect : redirect;\n navigation.navigate(target, { history: 'replace' });\n return;\n }\n\n if (document.startViewTransition) {\n const transition = document.startViewTransition(() => {\n this.slot!.setHTMLUnsafe(content);\n });\n signal.addEventListener('abort', () => transition.skipTransition(), { once: true });\n await transition.updateCallbackDone;\n } else {\n this.slot.setHTMLUnsafe(content);\n }\n\n if (title) document.title = title;\n } catch (error) {\n if (signal.aborted) return;\n console.error('[EmrouteApp] Navigation error:', error);\n if (this.slot) {\n const message = error instanceof Error ? error.message : String(error);\n this.slot.setHTMLUnsafe(`<h1>Error</h1><p>${escapeHtml(message)}</p>`);\n }\n }\n }\n}\n\n/**\n * Create and initialize the browser app.\n *\n * Stored on `globalThis.__emroute_app` for programmatic access.\n */\nexport async function createEmrouteApp(\n server: EmrouteServer,\n options?: EmrouteAppOptions,\n): Promise<EmrouteApp> {\n const g = globalThis as Record<string, unknown>;\n if (g.__emroute_app) {\n console.warn('eMroute: App already initialized.');\n return g.__emroute_app as EmrouteApp;\n }\n const app = new EmrouteApp(server, options);\n await app.initialize();\n g.__emroute_app = app;\n return app;\n}\n\n// \u2500\u2500 Boot \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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/** Options for `bootEmrouteApp`. */\nexport interface BootOptions extends EmrouteAppOptions {\n /** Override the server origin (defaults to `location.origin`). */\n origin?: string;\n}\n\n/**\n * Boot the browser app from runtime manifests.\n *\n * Fetches route tree and widget manifest as JSON, creates lazy module\n * loaders via FetchRuntime, registers widgets for deferred hydration,\n * and wires the Navigation API.\n *\n * Consumer `main.ts` calls this after setting up MarkdownElement renderer,\n * custom elements, etc.\n */\nexport async function bootEmrouteApp(options?: BootOptions): Promise<EmrouteApp> {\n const origin = options?.origin ?? location.origin;\n const runtime = new FetchRuntime(origin);\n\n // Fetch route tree\n const routesResponse = await runtime.handle(ROUTES_MANIFEST_PATH);\n if (!routesResponse.ok) {\n throw new Error(`[emroute] Failed to fetch ${ROUTES_MANIFEST_PATH}: ${routesResponse.status}`);\n }\n const routeTree: RouteNode = await routesResponse.json();\n\n // Fetch widget manifest (optional \u2014 app may have no widgets)\n const widgetsResponse = await runtime.handle(WIDGETS_MANIFEST_PATH);\n const widgetEntries: WidgetManifestEntry[] = widgetsResponse.ok\n ? await widgetsResponse.json()\n : [];\n\n // Fetch element manifest (optional \u2014 app may have no custom elements)\n const elementsResponse = await runtime.handle(ELEMENTS_MANIFEST_PATH);\n const elementEntries: ElementManifestEntry[] = elementsResponse.ok\n ? await elementsResponse.json()\n : [];\n\n // Build lazy module loaders for all route + widget + element modules\n const moduleLoaders = buildLazyLoaders(routeTree, widgetEntries, elementEntries, runtime);\n\n // Register widgets eagerly (tag defined immediately, module loads on connectedCallback)\n const widgets = new WidgetRegistry();\n for (const entry of widgetEntries) {\n ComponentElement.registerLazy(entry.name, entry.files, moduleLoaders[entry.modulePath]);\n }\n\n // Register custom elements \u2014 import all modules, define when loaded\n for (const entry of elementEntries) {\n const loader = moduleLoaders[entry.modulePath];\n if (loader) {\n loader().then((mod) => {\n const cls = (mod as Record<string, unknown>).default;\n if (typeof cls === 'function' && !customElements.get(entry.tagName)) {\n customElements.define(entry.tagName, cls as CustomElementConstructor);\n }\n }).catch((e) => {\n console.error(`[emroute] Failed to load element ${entry.tagName}:`, e);\n });\n }\n }\n\n // Create the server (reuses the same createEmrouteServer as SSR)\n const mdRenderer = MarkdownElement.getConfiguredRenderer();\n const server = await createEmrouteServer({\n routeTree,\n widgets,\n moduleLoaders,\n ...(mdRenderer ? { markdownRenderer: mdRenderer } : {}),\n }, runtime);\n\n return createEmrouteApp(server, options);\n}\n\n/**\n * Walk the route tree, widget entries, and element entries to build a map of\n * `path \u2192 () => runtime.loadModule(path)` lazy loaders.\n */\nfunction buildLazyLoaders(\n tree: RouteNode,\n widgetEntries: WidgetManifestEntry[],\n elementEntries: ElementManifestEntry[],\n runtime: FetchRuntime,\n): Record<string, () => Promise<unknown>> {\n const paths = new Set<string>();\n\n function walk(node: RouteNode): void {\n const modulePath = node.files?.ts ?? node.files?.js;\n if (modulePath) paths.add(modulePath);\n if (node.redirect) paths.add(node.redirect);\n if (node.errorBoundary) paths.add(node.errorBoundary);\n if (node.children) {\n for (const child of Object.values(node.children)) walk(child);\n }\n if (node.dynamic) walk(node.dynamic.child);\n if (node.wildcard) walk(node.wildcard.child);\n }\n\n walk(tree);\n for (const entry of widgetEntries) paths.add(entry.modulePath);\n for (const entry of elementEntries) paths.add(entry.modulePath);\n\n const loaders: Record<string, () => Promise<unknown>> = {};\n for (const path of paths) {\n const absolute = path.startsWith('/') ? path : '/' + path;\n loaders[path] = () => runtime.loadModule(absolute);\n }\n return loaders;\n}\n", "/**\n * WidgetComponent \u2014 embeddable unit within page content.\n *\n * Everything reusable that is not a page is a Widget.\n * Widgets render across all contexts (HTML, Markdown, SPA) and are\n * resolved by name via WidgetRegistry.\n *\n * Pages live in the routes manifest. Widgets live in the registry.\n *\n * Default rendering fallback chains (parallel to PageComponent):\n * - renderHTML: html file \u2192 md file in <mark-down> \u2192 base Component default\n * - renderMarkdown: md file \u2192 ''\n */\n\nimport { Component, type ComponentContext } from './abstract.component.ts';\nimport { escapeHtml, scopeWidgetCss } from '../util/html.util.ts';\n\nexport abstract class WidgetComponent<\n TParams = unknown,\n TData = unknown,\n TContext extends ComponentContext = ComponentContext,\n> extends Component<TParams, TData, TContext> {\n /**\n * Render widget as HTML.\n *\n * Fallback chain:\n * 1. html file content from context\n * 2. md file content wrapped in `<mark-down>`\n * 3. base Component default (markdown\u2192HTML conversion)\n *\n * @example\n * ```ts\n * override renderHTML({ data, params }: this['RenderArgs']) {\n * return `<span>${params.coin}: $${data?.price}</span>`;\n * }\n * ```\n */\n override renderHTML(\n args: this['RenderArgs'],\n ): string {\n const files = args.context.files;\n // @scope needed for SSR Light DOM output; redundant but harmless in SPA Shadow DOM\n const style = files?.css ? `<style>${scopeWidgetCss(files.css, this.name)}</style>\\n` : '';\n\n if (files?.html) {\n return style + files.html;\n }\n\n if (files?.md) {\n return `${style}<mark-down>${escapeHtml(files.md)}</mark-down>`;\n }\n\n if (style) {\n return style + super.renderHTML(args);\n }\n\n return super.renderHTML(args);\n }\n\n /**\n * Render widget as Markdown.\n *\n * Fallback chain:\n * 1. md file content from context\n * 2. empty string\n *\n * @example\n * ```ts\n * override renderMarkdown({ data, params }: this['RenderArgs']) {\n * return `**${params.coin}**: $${data?.price}`;\n * }\n * ```\n */\n override renderMarkdown(\n args: this['RenderArgs'],\n ): string {\n const files = args.context.files;\n\n if (files?.md) {\n return files.md;\n }\n\n return '';\n }\n}\n", "/**\n * Overlay Default CSS\n *\n * Styles for modals, toasts, and popovers. Works for both declarative\n * (commandfor/command + HTML attributes) and programmatic (OverlayService)\n * overlays. Uses CSS custom properties for theming.\n */\n\nexport const overlayCSS: string = /* css */ `\n:root {\n --overlay-backdrop: oklch(0% 0 0 / 0.5);\n --overlay-surface: oklch(100% 0 0);\n --overlay-radius: 8px;\n --overlay-shadow: 0 8px 32px oklch(0% 0 0 / 0.2);\n --overlay-toast-gap: 8px;\n --overlay-toast-duration: 5s;\n --overlay-z: 1000;\n}\n\n/* --- Modal (dialog) --- */\n\ndialog[data-overlay-modal] {\n border: none;\n padding: 0;\n background: var(--overlay-surface);\n border-radius: var(--overlay-radius);\n box-shadow: var(--overlay-shadow);\n max-width: min(90vw, 560px);\n max-height: 85vh;\n overflow: auto;\n opacity: 1;\n translate: 0 0;\n transition:\n opacity 200ms,\n translate 200ms;\n}\n\ndialog[data-overlay-modal][open] {\n transition:\n opacity 200ms,\n translate 200ms,\n display 200ms allow-discrete,\n overlay 200ms allow-discrete;\n\n @starting-style {\n opacity: 0;\n translate: 0 20px;\n }\n}\n\ndialog[data-overlay-modal]::backdrop {\n background: var(--overlay-backdrop);\n opacity: 1;\n transition: opacity 200ms;\n}\n\ndialog[data-overlay-modal][open]::backdrop {\n transition:\n opacity 200ms,\n display 200ms allow-discrete,\n overlay 200ms allow-discrete;\n\n @starting-style {\n opacity: 0;\n }\n}\n\ndialog[data-overlay-modal][data-dismissing] {\n opacity: 0;\n translate: 0 20px;\n}\n\ndialog[data-overlay-modal][data-dismissing]::backdrop {\n opacity: 0;\n}\n\n/* --- Toast container --- */\n\n[data-overlay-toast-container] {\n position: fixed;\n bottom: 16px;\n right: 16px;\n z-index: var(--overlay-z);\n display: flex;\n flex-direction: column;\n gap: var(--overlay-toast-gap);\n pointer-events: none;\n}\n\n/* --- Toast item --- */\n\n[data-overlay-toast] {\n pointer-events: auto;\n background: var(--overlay-surface);\n border-radius: var(--overlay-radius);\n box-shadow: var(--overlay-shadow);\n padding: 12px 16px;\n animation: overlay-toast-auto var(--overlay-toast-duration, 5s) ease-in-out forwards;\n}\n\n/* Manual toast (timeout: 0): no auto-dismiss, entry transition only */\n[data-overlay-toast][data-toast-manual] {\n animation: none;\n opacity: 1;\n translate: 0 0;\n transition:\n opacity 200ms,\n translate 200ms;\n\n @starting-style {\n opacity: 0;\n translate: 20px 0;\n }\n}\n\n/* Dismissed toast: CSS exit animation */\n[data-overlay-toast][data-dismissing] {\n animation: overlay-toast-exit 200ms ease-in forwards;\n}\n\n@keyframes overlay-toast-auto {\n 0% { opacity: 0; translate: 20px 0; }\n 10% { opacity: 1; translate: 0 0; }\n 80% { opacity: 1; translate: 0 0; }\n 100% { opacity: 0; translate: 0 0; display: none; }\n}\n\n@keyframes overlay-toast-exit {\n to { opacity: 0; translate: 20px 0; display: none; }\n}\n\n/* --- Popover --- */\n\n[data-overlay-popover] {\n border: none;\n padding: 0;\n margin: 0;\n background: var(--overlay-surface);\n border-radius: var(--overlay-radius);\n box-shadow: var(--overlay-shadow);\n opacity: 1;\n scale: 1;\n transition:\n opacity 200ms,\n scale 200ms;\n}\n\n[data-overlay-popover]:popover-open {\n position-anchor: auto;\n inset: unset;\n top: anchor(bottom);\n left: anchor(start);\n margin-top: 4px;\n transition:\n opacity 200ms,\n scale 200ms,\n display 200ms allow-discrete,\n overlay 200ms allow-discrete;\n\n @starting-style {\n opacity: 0;\n scale: 0.95;\n }\n}\n\n[data-overlay-popover][data-dismissing] {\n opacity: 0;\n scale: 0.95;\n}\n`;\n", "/**\n * Overlay Service\n *\n * Programmatic API for modals, toasts, and popovers. For simple trigger\n * patterns, use declarative HTML (commandfor/command + popover/dialog)\n * with zero JS. This service covers dynamic content, programmatic\n * triggers, and complex workflows.\n *\n * dismissAll() is DOM-aware: it closes both programmatic overlays\n * managed by this service AND declarative popovers/dialogs found\n * via DOM queries.\n */\n\nimport type { ModalOptions, OverlayService, PopoverOptions, ToastOptions } from './overlay.type.ts';\nimport { overlayCSS } from './overlay.css.ts';\n\nconst ANIMATION_SAFETY_TIMEOUT = 300;\n\n/**\n * Animate an element out by setting `data-dismissing`, waiting for\n * `transitionend`, then calling the provided callback. Includes a\n * safety timeout in case the transition event never fires.\n */\nfunction animateDismiss(el: HTMLElement, onDone: () => void): void {\n el.setAttribute('data-dismissing', '');\n\n let done = false;\n const finish = () => {\n if (done) return;\n done = true;\n onDone();\n };\n\n el.addEventListener('transitionend', finish, { once: true });\n setTimeout(finish, ANIMATION_SAFETY_TIMEOUT);\n}\n\nexport function createOverlayService(): OverlayService {\n let styleInjected = false;\n\n // Modal state\n let dialog: HTMLDialogElement | null = null;\n // Uses `any` because modalResolve is reassigned across multiple modal() calls\n // with different type parameters T. Each call creates a Promise.withResolvers<T>(),\n // so the resolver function signature changes (accepts T | PromiseLike<T | undefined>).\n // Type safety is maintained by closeModal<T>(value?: T) which ensures only valid\n // types are passed to the resolver.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let modalResolve: ((value: any) => void) | null = null;\n let modalOnClose: (() => void) | undefined;\n\n // Toast state\n let toastContainer: HTMLDivElement | null = null;\n\n // Popover state\n let popoverEl: HTMLDivElement | null = null;\n let popoverAnchorObserver: MutationObserver | null = null;\n const supportsAnchor = typeof CSS !== 'undefined' &&\n CSS.supports('anchor-name', '--a');\n\n function injectCSS(): void {\n if (styleInjected) return;\n styleInjected = true;\n const style = document.createElement('style');\n style.textContent = overlayCSS;\n document.head.appendChild(style);\n }\n\n function ensureDialog(): HTMLDialogElement {\n if (dialog) return dialog;\n injectCSS();\n dialog = document.createElement('dialog');\n dialog.setAttribute('data-overlay-modal', '');\n document.body.appendChild(dialog);\n\n dialog.addEventListener('click', (e) => {\n if (e.target === dialog) {\n closeModal(undefined);\n }\n });\n\n return dialog;\n }\n\n function ensureToastContainer(): HTMLDivElement {\n if (toastContainer) return toastContainer;\n injectCSS();\n toastContainer = document.createElement('div');\n toastContainer.setAttribute('data-overlay-toast-container', '');\n document.body.appendChild(toastContainer);\n return toastContainer;\n }\n\n function ensurePopover(): HTMLDivElement {\n if (popoverEl) return popoverEl;\n injectCSS();\n popoverEl = document.createElement('div');\n popoverEl.setAttribute('data-overlay-popover', '');\n popoverEl.setAttribute('popover', '');\n document.body.appendChild(popoverEl);\n return popoverEl;\n }\n\n // --- Modal ---\n\n function modal<T = undefined>(options: ModalOptions<T>): Promise<T | undefined> {\n const d = ensureDialog();\n\n // Clean up any lingering dismiss state from a previous close\n d.removeAttribute('data-dismissing');\n\n // Immediately dismiss popover \u2014 modal takes over the top layer\n hidePopoverImmediate();\n\n // Last wins: close current modal if open\n if (d.open) {\n d.close();\n if (modalResolve) {\n modalResolve(undefined);\n modalResolve = null;\n }\n if (modalOnClose) {\n modalOnClose();\n modalOnClose = undefined;\n }\n }\n\n d.innerHTML = '';\n options.render(d);\n modalOnClose = options.onClose;\n\n const { promise, resolve } = Promise.withResolvers<T | undefined>();\n modalResolve = resolve;\n\n d.showModal();\n\n return promise;\n }\n\n function closeModal<T>(value?: T): void {\n if (!dialog || !dialog.open) return;\n\n const resolve = modalResolve;\n const onClose = modalOnClose;\n const dialogRef = dialog;\n modalResolve = null;\n modalOnClose = undefined;\n\n animateDismiss(dialogRef, () => {\n if (dialogRef && dialogRef.open) {\n dialogRef.close();\n if (resolve) resolve(value);\n if (onClose) onClose();\n }\n });\n }\n\n // --- Toast ---\n\n /** Remove dead toasts (dismissed or animation-finished) from container. */\n function clearDeadToasts(container: HTMLDivElement): void {\n for (const child of [...container.children]) {\n const el = child as HTMLElement;\n if (el.hasAttribute('data-dismissing')) {\n el.remove();\n }\n }\n }\n\n function toast(options: ToastOptions): { dismiss(): void } {\n const container = ensureToastContainer();\n\n // Clean up dead toasts before adding a new one\n clearDeadToasts(container);\n\n const el = document.createElement('div');\n el.setAttribute('data-overlay-toast', '');\n\n const timeout = options.timeout ?? 0;\n if (timeout === 0) {\n el.setAttribute('data-toast-manual', '');\n } else {\n el.style.setProperty('--overlay-toast-duration', `${timeout}ms`);\n }\n\n options.render(el);\n container.appendChild(el);\n\n let dismissed = false;\n const dismiss = () => {\n if (dismissed) return;\n dismissed = true;\n el.setAttribute('data-dismissing', '');\n };\n\n return { dismiss };\n }\n\n // --- Popover ---\n\n function popover(options: PopoverOptions): void {\n const el = ensurePopover();\n\n // Last wins: hide current popover if showing\n cleanupPopoverAnchorObserver();\n try {\n el.hidePopover();\n } catch {\n // Not shown \u2014 ignore\n }\n el.removeAttribute('data-dismissing');\n\n el.innerHTML = '';\n options.render(el);\n\n // Anchor positioning\n if (supportsAnchor) {\n const anchorName = '--overlay-anchor';\n options.anchor.style.setProperty('anchor-name', anchorName);\n el.style.setProperty('position-anchor', anchorName);\n el.style.removeProperty('top');\n el.style.removeProperty('left');\n } else {\n const rect = options.anchor.getBoundingClientRect();\n el.style.top = `${rect.bottom + globalThis.scrollY}px`;\n el.style.left = `${rect.left + globalThis.scrollX}px`;\n el.style.position = 'absolute';\n }\n\n el.showPopover();\n\n // Watch for anchor disconnect\n watchAnchorDisconnect(options.anchor);\n }\n\n function watchAnchorDisconnect(anchor: HTMLElement): void {\n cleanupPopoverAnchorObserver();\n\n const parent = anchor.parentNode;\n if (!parent) {\n closePopover();\n return;\n }\n\n popoverAnchorObserver = new MutationObserver(() => {\n if (!document.contains(anchor)) {\n closePopover();\n }\n });\n\n popoverAnchorObserver.observe(parent, { childList: true });\n }\n\n /** Hide popover instantly without dismiss animation. */\n function hidePopoverImmediate(): void {\n cleanupPopoverAnchorObserver();\n if (!popoverEl) return;\n try {\n popoverEl.hidePopover();\n } catch {\n // Not shown \u2014 ignore\n }\n popoverEl.removeAttribute('data-dismissing');\n }\n\n function cleanupPopoverAnchorObserver(): void {\n if (popoverAnchorObserver) {\n popoverAnchorObserver.disconnect();\n popoverAnchorObserver = null;\n }\n }\n\n function closePopover(): void {\n cleanupPopoverAnchorObserver();\n\n if (!popoverEl) return;\n\n // Check if popover is showing via matches(':popover-open')\n let isOpen: boolean;\n try {\n isOpen = popoverEl.matches(':popover-open');\n } catch {\n // :popover-open may not be supported \u2014 fall back\n isOpen = popoverEl.hasAttribute('popover') && popoverEl.style.display !== 'none';\n }\n\n if (!isOpen) return;\n\n animateDismiss(popoverEl, () => {\n try {\n popoverEl!.hidePopover();\n } catch {\n // Already hidden\n }\n });\n }\n\n // --- Dismiss all ---\n\n function dismissAll(): void {\n // Close programmatic modal\n if (dialog && dialog.open) {\n const resolve = modalResolve;\n const onClose = modalOnClose;\n modalResolve = null;\n modalOnClose = undefined;\n\n dialog.removeAttribute('data-dismissing');\n dialog.close();\n\n if (resolve) resolve(undefined);\n if (onClose) onClose();\n }\n\n // Hide programmatic popover\n hidePopoverImmediate();\n\n // Dismiss all toasts via CSS\n if (toastContainer) {\n for (const child of toastContainer.children) {\n (child as HTMLElement).setAttribute('data-dismissing', '');\n }\n }\n\n // Close declarative popovers found in the DOM\n try {\n for (const el of document.querySelectorAll(':popover-open')) {\n (el as HTMLElement).hidePopover();\n }\n } catch {\n // :popover-open not supported\n }\n\n // Close declarative dialogs found in the DOM (skip our own)\n for (const el of document.querySelectorAll<HTMLDialogElement>('dialog[open]')) {\n if (el !== dialog) el.close();\n }\n }\n\n return {\n modal,\n closeModal,\n toast,\n popover,\n closePopover,\n dismissAll,\n };\n}\n", "/**\n * Built-in Page Title Widget\n *\n * Sets document.title from .page.html and .page.md files without needing\n * a .page.ts component. Renders no visible output.\n *\n * Usage in .page.html:\n * <widget-page-title title=\"About Us\"></widget-page-title>\n */\n\nimport { WidgetComponent } from '../component/widget.component.ts';\n\ninterface PageTitleParams {\n title: string;\n}\n\ninterface PageTitleData {\n title: string;\n}\n\nexport class PageTitleWidget extends WidgetComponent<PageTitleParams, PageTitleData> {\n override readonly name = 'page-title';\n\n override getData(\n args: { params: PageTitleParams; signal?: AbortSignal },\n ): Promise<PageTitleData | null> {\n return Promise.resolve({ title: args.params.title });\n }\n\n override renderHTML(\n args: { data: PageTitleData | null; params: PageTitleParams },\n ): string {\n const title = args.data?.title ?? args.params.title;\n if (title && typeof document !== 'undefined') {\n document.title = title;\n }\n return '';\n }\n\n override renderMarkdown(\n _args: { data: PageTitleData | null; params: PageTitleParams },\n ): string {\n return '';\n }\n\n override validateParams(params: PageTitleParams): string | undefined {\n if (!params.title || typeof params.title !== 'string') {\n return 'page-title widget requires a \"title\" string param';\n }\n return undefined;\n }\n}\n", "/**\n * Built-in Breadcrumb Widget\n *\n * Renders breadcrumb navigation from the current URL path.\n * Uses /html/ prefix for links (content-first routing convention).\n *\n * Usage in .page.html:\n * <widget-breadcrumb></widget-breadcrumb>\n * <widget-breadcrumb separator=\" / \" class=\"my-breadcrumbs\"></widget-breadcrumb>\n *\n * Usage in .page.md:\n * ```widget:breadcrumb\n * {}\n * ```\n */\n\nimport { WidgetComponent } from '../component/widget.component.ts';\nimport { escapeHtml } from '../util/html.util.ts';\nimport type { ComponentContext } from '../component/abstract.component.ts';\n\nconst DEFAULT_HTML_SEPARATOR = ' \\u203A ';\nconst DEFAULT_MD_SEPARATOR = ' > ';\n\ninterface BreadcrumbParams {\n separator?: string;\n class?: string;\n}\n\ninterface BreadcrumbSegment {\n label: string;\n href: string;\n}\n\ninterface BreadcrumbData {\n segments: BreadcrumbSegment[];\n}\n\nexport class BreadcrumbWidget extends WidgetComponent<BreadcrumbParams, BreadcrumbData> {\n override readonly name = 'breadcrumb';\n\n override getData(\n args: { params: BreadcrumbParams; signal?: AbortSignal; context: ComponentContext },\n ): Promise<BreadcrumbData | null> {\n const pathname = args.context.pathname || '/';\n const parts = pathname.split('/').filter(Boolean);\n\n const segments: BreadcrumbSegment[] = [\n { label: 'Home', href: '/' },\n ];\n\n let accumulated = '';\n for (const part of parts) {\n accumulated += '/' + part;\n segments.push({\n label: part.charAt(0).toUpperCase() + part.slice(1).replace(/-/g, ' '),\n href: accumulated,\n });\n }\n\n return Promise.resolve({ segments });\n }\n\n override renderHTML(\n args: { data: BreadcrumbData | null; params: BreadcrumbParams; context: ComponentContext },\n ): string {\n if (!args.data || args.data.segments.length === 0) return '';\n\n const sep = args.params.separator ?? DEFAULT_HTML_SEPARATOR;\n const segments = args.data.segments;\n\n const items = segments.map((seg, i) => {\n const escaped = escapeHtml(seg.label);\n if (i === segments.length - 1) {\n return `<span aria-current=\"page\">${escaped}</span>`;\n }\n return `<a href=\"${escapeHtml(seg.href)}\">${escaped}</a>`;\n });\n\n return `<nav aria-label=\"Breadcrumb\">${items.join(escapeHtml(sep))}</nav>`;\n }\n\n override renderMarkdown(\n args: { data: BreadcrumbData | null; params: BreadcrumbParams; context: ComponentContext },\n ): string {\n if (!args.data || args.data.segments.length === 0) return '';\n\n const sep = args.params.separator ?? DEFAULT_MD_SEPARATOR;\n return args.data.segments\n .map((seg, i, arr) =>\n i === arr.length - 1 ? `**${seg.label}**` : `[${seg.label}](${seg.href})`\n )\n .join(sep);\n }\n}\n", "/**\n * SPA (Browser) Module\n *\n * Everything needed for the browser bundle:\n * - EmrouteApp: Navigation API glue wired to an EmrouteServer\n * - Custom elements for rendering and hydrating SSR islands\n * - Widget registry (built-in widgets are opt-in)\n */\n\nimport { RouterSlot } from '../../element/slot.element.ts';\nimport { MarkdownElement } from '../../element/markdown.element.ts';\nimport { ComponentElement } from '../../element/component.element.ts';\nimport { WidgetRegistry } from '../../widget/widget.registry.ts';\n\nexport { bootEmrouteApp, createEmrouteApp, EmrouteApp, type BootOptions, type EmrouteAppOptions } from './thin-client.ts';\nexport { ComponentElement, MarkdownElement, RouterSlot, WidgetRegistry };\nexport type { SpaMode, WidgetsManifest } from '../../type/widget.type.ts';\n\n// Re-export base classes and types for consumer code (pages, widgets)\nexport { PageComponent } from '../../component/page.component.ts';\nexport { WidgetComponent } from '../../component/widget.component.ts';\nexport {\n Component,\n type ComponentContext,\n type ComponentManifestEntry,\n type ContextProvider,\n type RenderContext,\n} from '../../component/abstract.component.ts';\nexport type {\n MatchedRoute,\n NavigateOptions,\n RouteParams,\n RouterEvent,\n RouterEventListener,\n RouterEventType,\n} from '../../type/route.type.ts';\nexport type { RouteNode } from '../../type/route-tree.type.ts';\nexport type { RouteResolver, ResolvedRoute } from '../../route/route.resolver.ts';\nexport { RouteTrie } from '../../route/route.trie.ts';\nexport type { MarkdownRenderer } from '../../type/markdown.type.ts';\nexport { type BasePath, DEFAULT_BASE_PATH } from '../../route/route.core.ts';\nexport { escapeHtml, scopeWidgetCss } from '../../util/html.util.ts';\nexport type {\n ErrorBoundary,\n RedirectConfig,\n RouteConfig,\n RouteFiles,\n RouteFileType,\n RouteInfo,\n RouterState,\n} from '../../type/route.type.ts';\nexport type { ParsedWidgetBlock, WidgetManifestEntry } from '../../type/widget.type.ts';\nexport { type Logger, setLogger } from '../../type/logger.type.ts';\n\n// Register core custom elements in the browser\nif (globalThis.customElements) {\n if (!customElements.get('router-slot')) customElements.define('router-slot', RouterSlot);\n if (!customElements.get('mark-down')) customElements.define('mark-down', MarkdownElement);\n}\n\n// Overlay API (tree-shakeable - only bundled if imported)\nexport { createOverlayService } from '../../overlay/overlay.service.ts';\nexport type {\n ModalOptions,\n OverlayService,\n PopoverOptions,\n ToastOptions,\n} from '../../overlay/overlay.type.ts';\n\n// Optional: Built-in widgets (tree-shakeable - only bundled if imported)\nexport { PageTitleWidget } from '../../widget/page-title.widget.ts';\nexport { BreadcrumbWidget } from '../../widget/breadcrumb.widget.ts';\n"],
5
+ "mappings": ";AAKO,IAAM,WAAW;AAGjB,IAAM,YAAY;AAMzB,IAAM,gBAAN,MAAmB;EAGW;EAFpB,aAAa;EAErB,YAA4B,MAAoB;AAApB,SAAA,OAAA;EAAuB;EAEnD,IAAI,YAAS;AACX,WAAO,KAAK;EACd;EAEA,IAAI,UAAU,OAAa;AACzB,SAAK,aAAa;EACpB;EAEA,cAAc,MAAc,UAAkC;AAC5D,SAAK,aAAa;EACpB;EAEA,UAAU,QAAyB;EAEnC;EAEA,cAAc,WAAiB;AAC7B,WAAO;EACT;EAEA,iBAAiB,WAAiB;AAChC,WAAO,CAAA;EACT;EAEA,IAAI,aAAU;AACZ,WAAO,CAAA;EACT;EAEA,IAAI,aAAU;AACZ,WAAO;EACT;;AASF,IAAM,iBAAN,MAAoB;EACV,aAAa;EACb,cAAoC;EACpC,cAAc,oBAAI,IAAG;;EAEpB,QAAQ,IAAI,MAAM,CAAA,GAA2B;IACpD,IAAI,SAAS,OAAO,QAAM;AACxB,aAAO;IACT;IACA,IAAI,SAAS,MAAI;AACf,UAAI,OAAO,SAAS;AAAU,eAAO;AACrC,aAAO;IACT;GACD;EAED,IAAI,YAAS;AACX,WAAO,KAAK;EACd;EAEA,IAAI,UAAU,OAAa;AACzB,SAAK,aAAa;EACpB;EAEA,IAAI,aAAU;AACZ,WAAO,KAAK;EACd;EAEA,IAAI,aAAU;AACZ,WAAO,CAAA;EACT;EAEA,IAAI,aAAU;AACZ,WAAO;EACT;EAEA,IAAI,aAAU;AACZ,UAAM,QAAgB,CAAA;AACtB,eAAW,CAAC,MAAM,KAAK,KAAK,KAAK,aAAa;AAC5C,YAAM,KAAK,EAAE,MAAM,MAAK,CAAU;IACpC;AACA,WAAO;EACT;EAEA,aAAa,OAAqB;AAChC,SAAK,cAAc,IAAI,cAAc,IAAI;AACzC,WAAO,KAAK;EACd;EAEA,aAAa,MAAY;AACvB,WAAO,KAAK,YAAY,IAAI,IAAI,KAAK;EACvC;EAEA,aAAa,MAAc,OAAa;AACtC,SAAK,YAAY,IAAI,MAAM,KAAK;EAClC;EAEA,gBAAgB,MAAY;AAC1B,SAAK,YAAY,OAAO,IAAI;EAC9B;EAEA,aAAa,MAAY;AACvB,WAAO,KAAK,YAAY,IAAI,IAAI;EAClC;EAEA,cAAc,WAAiB;AAC7B,WAAO;EACT;EAEA,iBAAiB,WAAiB;AAChC,WAAO,CAAA;EACT;EAEA,UAAU,QAAyB;EAEnC;EAEA,YAAY,MAAU;AACpB,WAAO;EACT;;AAIK,IAAM,kBAAkB,WAAW,eACvC;AAKG,SAAU,WAAW,MAAY;AACrC,SAAO,KACJ,WAAW,KAAK,OAAO,EACvB,WAAW,KAAK,MAAM,EACtB,WAAW,KAAK,MAAM,EACtB,WAAW,KAAK,QAAQ,EACxB,WAAW,KAAK,OAAO,EACvB,WAAW,KAAK,OAAO;AAC5B;AAKM,SAAU,aAAa,MAAY;AACvC,SAAO,KACJ,WAAW,SAAS,GAAG,EACvB,WAAW,SAAS,GAAG,EACvB,WAAW,UAAU,GAAG,EACxB,WAAW,QAAQ,GAAG,EACtB,WAAW,QAAQ,GAAG,EACtB,WAAW,SAAS,GAAG;AAC5B;AAMM,SAAU,eAAe,KAAa,YAAkB;AAC5D,SAAO,kBAAkB,UAAU;EAAQ,GAAG;;AAChD;AAKO,IAAM,kBAA0C;EACrD,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;;;;AC1JD,IAAO,aAAP,cAA0B,gBAAe;;;;AClBzC,IAAO,kBAAP,MAAO,yBAAwB,gBAAe;EAC1C,OAAO,WAAoC;EAC3C,OAAO,sBAA4C;EACnD,kBAA0C;;;;;;;;;;;EAYlD,OAAO,YAAY,UAA0B;AAC3C,qBAAgB,WAAW;AAC3B,qBAAgB,sBAAsB,SAAS,OAAO,SAAS,KAAI,IAAK;EAC1E;;EAGA,OAAO,wBAAqB;AAC1B,WAAO,iBAAgB;EACzB;;;;EAKQ,aAAa,cAAW;AAC9B,UAAM,WAAW,iBAAgB;AACjC,QAAI,CAAC,UAAU;AACb,YAAM,IAAI,MACR,wGAAwG;IAE5G;AAEA,QAAI,iBAAgB,qBAAqB;AACvC,YAAM,iBAAgB;IACxB;AAEA,WAAO;EACT;EAEA,MAAM,oBAAiB;AACrB,SAAK,kBAAkB,IAAI,gBAAe;AAC1C,UAAM,KAAK,YAAW;EACxB;EAEA,uBAAoB;AAClB,SAAK,iBAAiB,MAAK;AAC3B,SAAK,kBAAkB;EACzB;EAEQ,MAAM,cAAW;AACvB,UAAM,MAAM,KAAK,aAAa,KAAK;AACnC,UAAM,gBAAgB,KAAK,aAAa,KAAI;AAE5C,QAAI,KAAK;AACP,YAAM,KAAK,YAAY,GAAG;IAC5B,WAAW,eAAe;AACxB,YAAM,KAAK,cAAc,aAAa;IACxC,OAAO;AACL,WAAK,YAAY;IACnB;EACF;EAEQ,MAAM,YAAY,KAAW;AACnC,UAAM,SAAS,KAAK,iBAAiB;AAErC,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,KAAK,SAAS,EAAE,OAAM,IAAK,CAAA,CAAE;AAE1D,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,mBAAmB,GAAG,KAAK,SAAS,MAAM,EAAE;MAC9D;AAEA,YAAM,WAAW,MAAM,SAAS,KAAI;AACpC,YAAM,KAAK,cAAc,QAAQ;IACnC,SAAS,OAAO;AACd,UAAI,iBAAiB,SAAS,MAAM,SAAS,cAAc;AACzD;MACF;AACA,WAAK,UAAU,KAAK;IACtB;EACF;EAEQ,MAAM,cAAc,UAAgB;AAC1C,QAAI;AACF,YAAM,WAAW,MAAM,iBAAgB,YAAW;AAClD,WAAK,YAAY,SAAS,OAAO,QAAQ;IAC3C,SAAS,OAAO;AACd,WAAK,UAAU,KAAK;IACtB;EACF;EAEQ,UAAU,OAAc;AAC9B,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,SAAK,YAAY,wBAAwB,WAAW,OAAO,CAAC;EAC9D;;;;ACzFF,SAAS,gBAAmD,KAAM;AAChE,QAAM,SAAkC,CAAA;AACxC,MAAI,WAAW;AACf,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,GAAG,GAAG;AACxC,QAAI,MAAM,QAAW;AAAE,aAAO,CAAC,IAAI;AAAG,iBAAW;IAAM;EACzD;AAEA,SAAO,WAAW,SAAgB;AACpC;AAOM,IAAO,mBAAP,MAAO,0BAAyC,gBAAe;;EAE3D,OAAO,YAAY,oBAAI,IAAG;;EAG1B,OAAO,cAAc,oBAAI,IAAG;;EAG5B,OAAO,cAAc,oBAAI,IAAG;;EAG5B,OAAO;;EAGf,OAAO,mBAAmB,UAAqC;AAC7D,sBAAiB,gBAAgB;EACnC;EAEQ;EACA;EACA,SAAyB;EACzB,OAAqB;EACrB;EACA,QAAwB;EACxB,eAAe;EACf,WAA8C;EAC9C,kBAA0C;EAC1C,uBAAoD;;EAG5D,cAA4C;EAE5C,YAAY,WAAsC,OAAmB;AACnE,UAAK;AACL,SAAK,YAAY;AACjB,SAAK,iBAAiB;AAGtB,QAAI,CAAC,KAAK,YAAY;AACpB,WAAK,aAAa,EAAE,MAAM,OAAM,CAAE;IACpC;EACF;;;;;;;EAQA,OAAO,SACL,WACA,OAAmB;AAEnB,UAAM,UAAU,UAAU,UAAU,IAAI;AAExC,QAAI,CAAC,WAAW,kBAAkB,eAAe,IAAI,OAAO,GAAG;AAC7D;IACF;AAEA,UAAM,cAAc,UAAU;AAE9B,UAAM,eAAe,cAAc,kBAAwB;MACzD,cAAA;AACE,cAAM,IAAI,YAAW,GAAI,KAAK;MAChC;;AAGF,mBAAe,OAAO,SAAS,YAAY;EAC7C;;;;;EAMA,OAAO,cACL,aACA,MACA,OAAmB;AAEnB,UAAM,UAAU,UAAU,IAAI;AAE9B,QAAI,CAAC,WAAW,kBAAkB,eAAe,IAAI,OAAO,GAAG;AAC7D;IACF;AAEA,UAAM,eAAe,cAAc,kBAAwB;MACzD,cAAA;AACE,cAAM,IAAI,YAAW,GAAI,KAAK;MAChC;;AAGF,mBAAe,OAAO,SAAS,YAAY;EAC7C;;;;;;;EAQA,OAAO,aACL,MACA,OACA,QAA8B;AAE9B,UAAM,UAAU,UAAU,IAAI;AAC9B,QAAI,CAAC,WAAW,kBAAkB,eAAe,IAAI,OAAO;AAAG;AAE/D,sBAAiB,YAAY,IAAI,SAAS,MAAM;AAIhD,UAAM,cAAc;MAClB;MACA,SAAS,MAAM,QAAQ,QAAQ,IAAI;MACnC,YAAY,MAAM;MAClB,gBAAgB,MAAM;MACtB,aAAa,MAAM;MACnB,qBAAqB,MAAM;;AAG7B,UAAM,eAAe,cAAc,kBAAkC;MACnE,cAAA;AACE,cAAM,aAAa,KAAK;MAC1B;;AAGF,mBAAe,OAAO,SAAS,YAAY;EAC7C;;;;;EAMA,IAAI,QAAK;AACP,QAAI,KAAK,UAAU,SAAS;AAC1B,aAAO,QAAQ,QAAO;IACxB;AACA,SAAK,aAAa,QAAQ,cAAa;AACvC,WAAO,KAAK,SAAS;EACvB;EAEA,MAAM,oBAAiB;AAErB,UAAM,UAAU,KAAK,QAAQ,YAAW;AACxC,UAAM,aAAa,kBAAiB,YAAY,IAAI,OAAO;AAC3D,QAAI,YAAY;AACd,UAAI;AACF,YAAI,gBAAgB,kBAAiB,YAAY,IAAI,OAAO;AAC5D,YAAI,CAAC,eAAe;AAClB,0BAAgB,WAAU;AAC1B,4BAAiB,YAAY,IAAI,SAAS,aAAa;QACzD;AACA,cAAM,MAAM,MAAM;AAClB,mBAAW,OAAO,OAAO,OAAO,GAAG,GAAG;AACpC,cAAI,OAAO,OAAO,QAAQ,YAAY,aAAa,KAAK;AACtD,kBAAM,cAAc,IAAI;AACxB,iBAAK,YAAY,IAAI,YAAW;AAChC;UACF;AACA,cAAI,OAAO,QAAQ,cAAe,IAA8C,WAAW,SAAS;AAClG,iBAAK,YAAY,IAAK,IAA2C;AACjE;UACF;QACF;MACF,QAAQ;AAGN,YAAI,KAAK,aAAa,QAAQ,GAAG;AAC/B,eAAK,gBAAgB,QAAQ;AAC7B,eAAK,YAAW;AAChB;QACF;MACF;IACF;AAEA,SAAK,UAAU,UAAU;AACzB,SAAK,MAAM,oBAAoB;AAC/B,SAAK,kBAAkB,IAAI,gBAAe;AAC1C,UAAM,SAAS,KAAK,gBAAgB;AAGpC,UAAM,SAAkC,CAAA;AACxC,eAAW,QAAQ,KAAK,YAAY;AAClC,UAAI,KAAK,SAAS,YAAY,KAAK,SAAS;AAAW;AACvD,YAAM,MAAM,KAAK,KAAK,QAAQ,aAAa,CAAC,GAAG,MAAM,EAAE,YAAW,CAAE;AACpE,UAAI;AACF,eAAO,GAAG,IAAI,KAAK,MAAM,KAAK,KAAK;MACrC,QAAQ;AACN,eAAO,GAAG,IAAI,KAAK;MACrB;IACF;AACA,SAAK,SAAS;AAGd,QAAI,KAAK,UAAU,kBAAkB,KAAK,WAAW,MAAM;AACzD,YAAM,QAAQ,KAAK,UAAU,eAAe,KAAK,MAAM;AACvD,UAAI,OAAO;AACT,aAAK,SAAS,KAAK;AACnB;MACF;IACF;AAGA,UAAM,QAAQ,MAAM,KAAK,UAAS;AAClC,QAAI,OAAO;AAAS;AAEpB,UAAM,aAAa,WAAW,WAAW,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,IAAI,mBAAmB;AAC7F,UAAM,gBAAgB,gBAAgB,KAAK;AAC3C,UAAM,OAAyB;MAC7B,KAAK;MACL,UAAU,WAAW;MACrB,cAAc,WAAW;MACzB,QAAQ,KAAK,UAAU,CAAA;MACvB,GAAI,gBAAgB,EAAE,OAAO,cAAa,IAAK,CAAA;;AAEjD,SAAK,UAAU,kBAAiB,gBAAgB,kBAAiB,cAAc,IAAI,IAAI;AAGvF,QAAI,KAAK,aAAa,QAAQ,GAAG;AAC/B,WAAK,gBAAgB,QAAQ;AAG7B,YAAM,YAAY,KAAK,aAAa,KAAI;AACxC,UAAI,WAAW;AACb,YAAI;AACF,eAAK,OAAO,KAAK,MAAM,SAAS;QAClC,QAAQ;QAER;MACF;AAEA,WAAK,cAAc;AAEnB,WAAK,QAAQ;AAGb,UAAI,KAAK,UAAU,SAAS;AAC1B,cAAM,OAAO,EAAE,MAAM,KAAK,MAAM,QAAQ,KAAK,QAAS,SAAS,KAAK,QAAO;AAC3E,uBAAe,MAAK;AAClB,eAAK,UAAU,QAAS,IAAI;QAC9B,CAAC;MACH;AAEA,WAAK,YAAW;AAChB;IACF;AAGA,QAAI,KAAK,aAAa,SAAS,GAAG;AAChC,WAAK,uBAAuB,IAAI,qBAAqB,CAAC,CAAC,KAAK,MAAK;AAC/D,YAAI,MAAM,gBAAgB;AACxB,eAAK,sBAAsB,WAAU;AACrC,eAAK,uBAAuB;AAC5B,eAAK,SAAQ;QACf;MACF,CAAC;AACD,WAAK,qBAAqB,QAAQ,IAAI;AACtC;IACF;AAEA,UAAM,KAAK,SAAQ;EACrB;EAEA,uBAAoB;AAClB,SAAK,UAAU,UAAS;AACxB,SAAK,UAAU,UAAU;AACzB,SAAK,sBAAsB,WAAU;AACrC,SAAK,uBAAuB;AAC5B,SAAK,iBAAiB,MAAK;AAC3B,SAAK,kBAAkB;AACvB,SAAK,QAAQ;AACb,SAAK,OAAO;AACZ,SAAK,UAAU;AACf,SAAK,cAAc;AACnB,SAAK,eAAe;AACpB,SAAK,YAAW;AAChB,SAAK,WAAW;EAClB;;;;EAKA,MAAM,SAAM;AACV,QAAI,KAAK,WAAW;AAAM;AAG1B,SAAK,iBAAiB,MAAK;AAC3B,SAAK,kBAAkB,IAAI,gBAAe;AAE1C,UAAM,KAAK,SAAQ;EACrB;;;;;EAMQ,OAAO,SAAS,MAAY;AAClC,UAAM,SAAS,kBAAiB,UAAU,IAAI,IAAI;AAClD,QAAI;AAAQ,aAAO;AAEnB,UAAM,MAAM,KAAK,WAAW,SAAS,KAAK,KAAK,WAAW,UAAU,IAChE,OACC,KAAK,WAAW,GAAG,IAAI,OAAO,MAAM;AAEzC,UAAM,UAAU,MAAM,GAAG,EAAE,KACzB,CAAC,QAAQ,IAAI,KAAK,IAAI,KAAI,IAAK,QAC/B,MAAM,MAAS;AAGjB,sBAAiB,UAAU,IAAI,MAAM,OAAO;AAC5C,WAAO;EACT;;;;;EAMQ,MAAM,YAAS;AACrB,UAAM,YAAY,KAAK,kBAAkB,KAAK,UAAU;AACxD,QAAI,CAAC;AAAW,aAAO,CAAA;AAEvB,UAAM,CAAC,MAAM,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI;MACxC,UAAU,OAAO,kBAAiB,SAAS,UAAU,IAAI,IAAI;MAC7D,UAAU,KAAK,kBAAiB,SAAS,UAAU,EAAE,IAAI;MACzD,UAAU,MAAM,kBAAiB,SAAS,UAAU,GAAG,IAAI;KAC5D;AAED,WAAO,gBAAgB,EAAE,MAAM,IAAI,IAAG,CAAE,KAAK,CAAA;EAC/C;EAEQ,MAAM,WAAQ;AACpB,QAAI,KAAK,WAAW;AAAM;AAE1B,UAAM,SAAS,KAAK,iBAAiB;AAErC,SAAK,QAAQ;AACb,SAAK,OAAM;AAEX,QAAI;AACF,YAAM,UAAU,KAAK,UAAU,QAAQ;QACrC,QAAQ,KAAK;QACb,GAAI,SAAS,EAAE,OAAM,IAAK,CAAA;QAC1B,SAAS,KAAK;OACf;AACD,WAAK,cAAc;AACnB,WAAK,OAAO,MAAM;AAGlB,UAAI,QAAQ;AAAS;AAErB,WAAK,QAAQ;IACf,SAAS,GAAG;AACV,UAAI,aAAa,gBAAgB,EAAE,SAAS;AAAc;AAC1D,UAAI,QAAQ;AAAS;AAErB,WAAK,SAAS,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AACxD;IACF;AAEA,SAAK,OAAM;AACX,SAAK,YAAW;EAClB;EAEQ,SAAS,SAAe;AAC9B,SAAK,QAAQ;AACb,SAAK,eAAe;AACpB,SAAK,OAAM;AACX,SAAK,YAAW;EAClB;EAEQ,cAAW;AACjB,SAAK,UAAU,QAAO;AACtB,SAAK,WAAW;EAClB;EAEQ,SAAM;AACZ,QAAI,KAAK,WAAW,MAAM;AACxB,WAAK,WAAY,cAAc,EAAE;AACjC;IACF;AAEA,QAAI,KAAK,UAAU,SAAS;AAC1B,WAAK,WAAY,cAAc,KAAK,UAAU,YAAY;QACxD,OAAO,IAAI,MAAM,KAAK,YAAY;QAClC,QAAQ,KAAK;OACd,CAAC;AACF;IACF;AAEA,SAAK,WAAY,cAAc,KAAK,UAAU,WAAW;MACvD,MAAM,KAAK,UAAU,UAAU,KAAK,OAAO;MAC3C,QAAQ,KAAK;MACb,SAAS,KAAK;KACf,CAAC;AAGF,QAAI,KAAK,UAAU,WAAW,KAAK,UAAU,SAAS;AACpD,YAAM,OAAO,EAAE,MAAM,KAAK,MAAM,QAAQ,KAAK,QAAS,SAAS,KAAK,QAAO;AAC3E,qBAAe,MAAK;AAClB,aAAK,UAAU,QAAS,IAAI;MAC9B,CAAC;IACH;EACF;;;;ACzaI,IAAO,iBAAP,MAAqB;EACjB,UAAU,oBAAI,IAAG;;EAGzB,IAAI,QAAuB;AACzB,SAAK,QAAQ,IAAI,OAAO,MAAM,MAAM;EACtC;;EAGA,IAAI,MAAY;AACd,WAAO,KAAK,QAAQ,IAAI,IAAI;EAC9B;;EAGA,CAAC,OAAO,QAAQ,IAAC;AACf,WAAO,KAAK,QAAQ,OAAM;EAC5B;;EAGA,aAAU;AACR,UAAM,UAAiC,CAAA;AACvC,UAAM,gBAAwD,CAAA;AAE9D,eAAW,CAAC,MAAM,MAAM,KAAK,KAAK,SAAS;AACzC,YAAM,QAA6B;QACjC;QACA,YAAY;QACZ,SAAS,UAAU,IAAI;QACvB,GAAI,OAAO,QAAQ,EAAE,OAAO,OAAO,MAAK,IAAK,CAAA;;AAE/C,cAAQ,KAAK,KAAK;AAClB,oBAAc,IAAI,IAAI,MAAM,QAAQ,QAAQ,EAAE,SAAS,OAAO,YAAW,CAAE;IAC7E;AAEA,WAAO,EAAE,SAAS,cAAa;EACjC;;;;;;;;;;;;AChBK,IAAM,oBAA8B,EAAE,MAAM,SAAS,IAAI,OAAO,KAAK,OAAM;AAElF,IAAM,oBAAoB;AAGpB,SAAU,mBAAmB,KAAW;AAC5C,MAAI,kBAAkB,KAAK,IAAI,KAAI,CAAE,GAAG;AACtC,UAAM,IAAI,MAAM,gCAAgC,GAAG,EAAE;EACvD;AACF;AAGO,IAAM,qBAAkC;EAC7C,SAAS;EACT,MAAM;EACN,YAAY;;AAId,SAAS,cAAc,UAAuB;AAC5C,QAAM,OAAO,SAAS;AACtB,SAAO;IACL,SAAS,SAAS;IAClB,MAAM,KAAK,WAAW,aAAa;IACnC,YAAY,KAAK,YAAY,KAAK,OAAO,MAAM,KAAK,OAAO,MAAM,KAAK,OAAO,QAAQ,KAAK,OAAO,MAAM;IACvG,GAAI,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAK,IAAK,CAAA;;AAE7C;AAmBM,IAAO,YAAP,MAAgB;EACH;;EAER;EACD,YAAsC,oBAAI,IAAG;EAC7C,cAAoC,oBAAI,IAAG;EAC3C,kBAAuC,oBAAI,IAAG;EAC9C;EACR,eAAoC;EAC5B;EAER,YAAY,UAAyB,UAA4B,CAAA,GAAE;AACjE,SAAK,WAAW;AAChB,SAAK,WAAW,QAAQ,eACrB,CAAC,SAAS,MAAM,MAAM,EAAE,SAAS,EAAE,QAAQ,aAAY,EAAE,CAAE,EAAE,KAAK,CAAC,MAAM,EAAE,KAAI,CAAE;AACpF,SAAK,kBAAkB,QAAQ;AAC/B,SAAK,gBAAgB,QAAQ,iBAAiB,CAAA;EAChD;;;;EAKA,YAAS;AACP,WAAO,KAAK,cAAc,UAAU,CAAA;EACtC;;;;EAKA,iBAAiB,UAA6B;AAC5C,SAAK,UAAU,IAAI,QAAQ;AAC3B,WAAO,MAAM,KAAK,UAAU,OAAO,QAAQ;EAC7C;;;;EAKA,KAAK,OAAkB;AACrB,eAAW,YAAY,KAAK,WAAW;AACrC,UAAI;AACF,iBAAS,KAAK;MAChB,SAAS,GAAG;AACV,gBAAQ,MAAM,kCAAkC,CAAC;MACnD;IACF;EACF;;;;;EAMA,MAAM,KAAQ;AACZ,UAAM,WAAW,IAAI;AAErB,UAAM,WAAW,KAAK,SAAS,MAAM,QAAQ;AAC7C,QAAI,UAAU;AACZ,aAAO;QACL,OAAO,cAAc,QAAQ;QAC7B,QAAQ,SAAS;;IAErB;AAEA,QAAI,aAAa,OAAO,aAAa,IAAI;AACvC,aAAO;QACL,OAAO;QACP,QAAQ,CAAA;;IAEZ;AAEA,WAAO;EACT;;EAGA,cAAc,QAAc;AAC1B,UAAM,OAAO,KAAK,SAAS,UAAU,IAAI,MAAM,EAAE;AACjD,QAAI,CAAC;AAAM,aAAO;AAClB,WAAO;MACL,SAAS,IAAI,MAAM;MACnB,MAAM;MACN,YAAY,KAAK,OAAO,MAAM,KAAK,OAAO,MAAM,KAAK,OAAO,QAAQ,KAAK,OAAO,MAAM;MACtF,GAAI,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAK,IAAK,CAAA;;EAE7C;;EAGA,kBAAe;AACb,UAAM,aAAa,KAAK,SAAS,kBAAkB,GAAG;AACtD,QAAI,CAAC;AAAY,aAAO;AACxB,WAAO,EAAE,SAAS,KAAK,MAAM,SAAS,WAAU;EAClD;;;;;;EAOA,kBAAkB,UAAgB;AAChC,UAAM,aAAa,KAAK,SAAS,kBAAkB,QAAQ;AAC3D,QAAI,CAAC;AAAY,aAAO;AACxB,WAAO,EAAE,SAAS,UAAU,WAAU;EACxC;;;;;EAMA,UAAU,SAAe;AACvB,UAAM,OAAO,KAAK,SAAS,UAAU,OAAO;AAC5C,QAAI,CAAC;AAAM,aAAO;AAClB,WAAO;MACL;MACA,MAAM,KAAK,WAAW,aAAa;MACnC,YAAY,KAAK,YAAY,KAAK,OAAO,MAAM,KAAK,OAAO,MAAM,KAAK,OAAO,QAAQ,KAAK,OAAO,MAAM;MACvG,GAAI,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAK,IAAK,CAAA;;EAE7C;;;;;;;;EASA,oBAAoB,SAAe;AACjC,QAAI,YAAY,KAAK;AACnB,aAAO,CAAC,GAAG;IACb;AAEA,UAAM,WAAW,QAAQ,MAAM,GAAG,EAAE,OAAO,OAAO;AAElD,UAAM,YAAsB,CAAC,GAAG;AAChC,QAAI,UAAU;AACd,eAAW,WAAW,UAAU;AAC9B,iBAAW,MAAM;AACjB,gBAAU,KAAK,OAAO;IACxB;AAEA,WAAO;EACT;;;;EAKA,aAAa,KAAW;AACtB,QAAI,IAAI,SAAS,KAAK,IAAI,SAAS,GAAG,GAAG;AACvC,aAAO,IAAI,MAAM,GAAG,EAAE;IACxB;AACA,WAAO;EACT;;;;EAKA,eAAe,MAAY;AACzB,WAAO,KAAK,WAAW,GAAG,IAAI,OAAO,MAAM;EAC7C;;;;;EAMA,MAAM,WAAc,YAAkB;AACpC,QAAI,KAAK,YAAY,IAAI,UAAU,GAAG;AACpC,aAAO,KAAK,YAAY,IAAI,UAAU;IACxC;AAEA,QAAI;AACJ,UAAM,SAAS,KAAK,cAAc,UAAU;AAC5C,QAAI,QAAQ;AACV,eAAS,MAAM,OAAM;IACvB,OAAO;AACL,YAAM,eAAe,KAAK,eAAe,UAAU;AACnD,eAAS,MAAM,OAAM,iCAAC,YAAY;IACpC;AAEA,SAAK,YAAY,IAAI,YAAY,MAAM;AACvC,WAAO;EACT;;;;EAKA,MAAM,gBACJ,aAAyD;AAEzD,UAAM,OAAO,OAAO,SAA6C;AAC/D,YAAM,UAAU,KAAK,eAAe,IAAI;AACxC,YAAM,SAAS,KAAK,gBAAgB,IAAI,OAAO;AAC/C,UAAI,WAAW;AAAW,eAAO;AAEjC,UAAI;AACF,cAAM,UAAU,MAAM,KAAK,SAAS,OAAO;AAC3C,aAAK,gBAAgB,IAAI,SAAS,OAAO;AACzC,eAAO;MACT,SAAS,GAAG;AACV,gBAAQ,KACN,0CAA0C,IAAI,KAC9C,aAAa,QAAQ,EAAE,UAAU,CAAC;AAEpC,eAAO;MACT;IACF;AAEA,UAAM,CAAC,MAAM,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI;MACxC,YAAY,OAAO,KAAK,YAAY,IAAI,IAAI;MAC5C,YAAY,KAAK,KAAK,YAAY,EAAE,IAAI;MACxC,YAAY,MAAM,KAAK,YAAY,GAAG,IAAI;KAC3C;AAED,UAAM,SAAuD,CAAA;AAC7D,QAAI,QAAQ;AAAM,aAAO,OAAO;AAChC,QAAI,MAAM;AAAM,aAAO,KAAK;AAC5B,QAAI,OAAO;AAAM,aAAO,MAAM;AAC9B,WAAO;EACT;;;;;EAMA,YAAY,SAAuB,KAAQ;AACzC,WAAO;MACL;MACA,QAAQ,QAAQ;;EAEpB;;;;;EAMA,eAAe,YAAkB;AAC/B,UAAM,SAAS,KAAK,YAAY,IAAI,UAAU;AAC9C,QAAI,CAAC,UAAU,OAAO,WAAW;AAAU,aAAO;AAClD,UAAM,QAAS,OAAmC;AAClD,QAAI,CAAC,SAAS,OAAO,UAAU;AAAU,aAAO;AAChD,WAAO;EACT;;;;;;;EAQA,MAAM,sBACJ,WACA,OACA,QACA,QAAgB;AAEhB,UAAM,KAAK,MAAM;AACjB,UAAM,aAAa,IAAI,MAAM,IAAI;AAGjC,UAAM,UAAU,aAAa,KAAK,eAAe,UAAU,IAAI;AAE/D,QAAI;AACJ,QAAI;AACJ,QAAI;AAEJ,QAAI,SAAS;AACX,aAAO,QAAQ;AACf,WAAK,QAAQ;AACb,YAAM,QAAQ;IAChB,OAAO;AACL,YAAM,YAAY,CAAC,aACjB,KAAK,SAAS,KAAK,eAAe,QAAQ,CAAC;AAC7C,OAAC,MAAM,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAI;QAClC,IAAI,OAAO,UAAU,GAAG,IAAI,IAAI;QAChC,IAAI,KAAK,UAAU,GAAG,EAAE,IAAI;QAC5B,IAAI,MAAM,UAAU,GAAG,GAAG,IAAI;OAC/B;IACH;AAEA,UAAM,QAAsB,CAAA;AAC5B,QAAI,QAAQ;AAAM,YAAM,OAAO;AAC/B,QAAI,MAAM;AAAM,YAAM,KAAK;AAC3B,QAAI,OAAO;AAAM,YAAM,MAAM;AAE7B,UAAM,OAAyB;MAC7B,GAAG;MACH,UAAU,UAAU,IAAI;MACxB,cAAc,UAAU,IAAI;MAC5B;MACA,GAAI,SAAS,EAAE,OAAM,IAAK,CAAA;MAC1B,GAAI,UAAU,OAAO,EAAE,OAAM,IAAK,CAAA;;AAEpC,WAAO,KAAK,kBAAkB,KAAK,gBAAgB,IAAI,IAAI;EAC7D;;;;AC7UF,SAAS,aAAU;AACjB,SAAO,EAAE,QAAQ,oBAAI,IAAG,EAAE;AAC5B;AAGA,SAAS,WAAW,SAAe;AACjC,MAAI;AACF,WAAO,mBAAmB,OAAO;EACnC,QAAQ;AACN,WAAO;EACT;AACF;AAMA,SAAS,cAAc,UAAgB;AACrC,SAAO,SAAS,UAAU,CAAC,EAAE,MAAM,GAAG;AACxC;AAOA,SAAS,YAAY,QAAmB,SAAe;AACrD,QAAM,OAAO,WAAU;AAGvB,MAAI,OAAO,SAAS,OAAO,UAAU;AACnC,SAAK,QAAQ;AACb,SAAK,UAAU;EACjB;AAGA,MAAI,OAAO,eAAe;AACxB,SAAK,gBAAgB,OAAO;EAC9B;AAGA,MAAI,OAAO,UAAU;AACnB,eAAW,CAAC,SAAS,KAAK,KAAK,OAAO,QAAQ,OAAO,QAAQ,GAAG;AAC9D,YAAM,eAAe,YAAY,MAAM,IAAI,OAAO,KAAK,GAAG,OAAO,IAAI,OAAO;AAC5E,WAAK,OAAO,IAAI,SAAS,YAAY,OAAO,YAAY,CAAC;IAC3D;EACF;AAGA,MAAI,OAAO,SAAS;AAClB,UAAM,EAAE,OAAO,MAAK,IAAK,OAAO;AAChC,UAAM,eAAe,YAAY,MAAM,KAAK,KAAK,KAAK,GAAG,OAAO,KAAK,KAAK;AAC1E,SAAK,UAAU,EAAE,OAAO,MAAM,YAAY,OAAO,YAAY,EAAC;EAChE;AAGA,MAAI,OAAO,UAAU;AACnB,UAAM,EAAE,OAAO,MAAK,IAAK,OAAO;AAChC,UAAM,eAAe,YAAY,MAAM,KAAK,KAAK,MAAM,GAAG,OAAO,KAAK,KAAK;AAC3E,SAAK,WAAW,EAAE,OAAO,MAAM,YAAY,OAAO,YAAY,EAAC;EACjE;AAEA,SAAO;AACT;AAQM,IAAO,YAAP,MAAgB;EACH;EAEjB,YAAY,MAAe;AACzB,SAAK,OAAO,YAAY,MAAM,GAAG;EACnC;EAEA,MAAM,UAAgB;AAEpB,QAAI,SAAS,SAAS,KAAK,SAAS,SAAS,GAAG,GAAG;AACjD,iBAAW,SAAS,MAAM,GAAG,EAAE;IACjC;AAEA,QAAI,CAAC,SAAS,WAAW,GAAG,GAAG;AAC7B,iBAAW,MAAM;IACnB;AAEA,QAAI,aAAa,KAAK;AACpB,UAAI,KAAK,KAAK,OAAO;AACnB,eAAO,EAAE,MAAM,KAAK,KAAK,OAAO,SAAS,KAAK,QAAQ,CAAA,EAAE;MAC1D;AACA,aAAO;IACT;AAEA,UAAM,WAAW,cAAc,QAAQ;AACvC,WAAO,KAAK,KAAK,KAAK,MAAM,UAAU,GAAG,CAAA,CAAE;EAC7C;EAEA,kBAAkB,UAAgB;AAChC,QAAI,SAAS,SAAS,KAAK,SAAS,SAAS,GAAG,GAAG;AACjD,iBAAW,SAAS,MAAM,GAAG,EAAE;IACjC;AACA,QAAI,CAAC,SAAS,WAAW,GAAG,GAAG;AAC7B,iBAAW,MAAM;IACnB;AAEA,QAAI,aAAa;AAAK,aAAO,KAAK,KAAK;AAEvC,UAAM,WAAW,cAAc,QAAQ;AACvC,WAAO,KAAK,gBAAgB,KAAK,MAAM,UAAU,GAAG,KAAK,KAAK,aAAa;EAC7E;EAEA,UAAU,SAAe;AACvB,QAAI,YAAY,KAAK;AACnB,aAAO,KAAK,KAAK;IACnB;AAEA,UAAM,WAAW,cAAc,OAAO;AACtC,QAAI,OAAO,KAAK;AAEhB,eAAW,WAAW,UAAU;AAC9B,UAAI;AAEJ,UAAI,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG,GAAG;AACpD,gBAAQ,KAAK,UAAU;MACzB,WAAW,QAAQ,WAAW,GAAG,GAAG;AAClC,gBAAQ,KAAK,SAAS;MACxB,OAAO;AACL,gBAAQ,KAAK,OAAO,IAAI,OAAO;MACjC;AAEA,UAAI,CAAC;AAAO,eAAO;AACnB,aAAO;IACT;AAEA,WAAO,KAAK;EACd;;EAIQ,KACN,MACA,UACA,OACA,QAA8B;AAE9B,QAAI,UAAU,SAAS,QAAQ;AAC7B,UAAI,KAAK,OAAO;AACd,eAAO,EAAE,MAAM,KAAK,OAAO,SAAS,KAAK,SAAU,QAAQ,EAAE,GAAG,OAAM,EAAE;MAC1E;AACA,UAAI,KAAK,UAAU,KAAK,OAAO;AAC7B,eAAO;UACL,MAAM,KAAK,SAAS,KAAK;UACzB,SAAS,KAAK,SAAS,KAAK;UAC5B,QAAQ,EAAE,GAAG,QAAQ,CAAC,KAAK,SAAS,KAAK,GAAG,GAAE;;MAElD;AACA,aAAO;IACT;AAEA,UAAM,UAAU,SAAS,KAAK;AAG9B,UAAM,cAAc,KAAK,OAAO,IAAI,OAAO;AAC3C,QAAI,aAAa;AACf,YAAM,SAAS,KAAK,KAAK,aAAa,UAAU,QAAQ,GAAG,MAAM;AACjE,UAAI;AAAQ,eAAO;IACrB;AAGA,QAAI,KAAK,SAAS;AAChB,YAAM,EAAE,OAAO,MAAM,YAAW,IAAK,KAAK;AAC1C,aAAO,KAAK,IAAI,WAAW,OAAO;AAClC,YAAM,SAAS,KAAK,KAAK,aAAa,UAAU,QAAQ,GAAG,MAAM;AACjE,UAAI;AAAQ,eAAO;AACnB,aAAO,OAAO,KAAK;IACrB;AAGA,QAAI,KAAK,UAAU,KAAK,OAAO;AAC7B,YAAM,EAAE,OAAO,MAAM,aAAY,IAAK,KAAK;AAC3C,UAAI,OAAO,WAAW,SAAS,KAAK,CAAC;AACrC,eAAS,IAAI,QAAQ,GAAG,IAAI,SAAS,QAAQ,KAAK;AAChD,gBAAQ,MAAM,WAAW,SAAS,CAAC,CAAC;MACtC;AACA,aAAO;QACL,MAAM,aAAa;QACnB,SAAS,aAAa;QACtB,QAAQ,EAAE,GAAG,QAAQ,CAAC,KAAK,GAAG,KAAI;;IAEtC;AAEA,WAAO;EACT;;;;;;EAOQ,gBACN,MACA,UACA,OACA,SAA2B;AAE3B,QAAI,UAAU,SAAS,QAAQ;AAC7B,aAAO,KAAK,iBAAiB;IAC/B;AAEA,UAAM,UAAU,SAAS,KAAK;AAE9B,UAAM,cAAc,KAAK,OAAO,IAAI,OAAO;AAC3C,QAAI,aAAa;AACf,aAAO,KAAK,gBAAgB,aAAa,UAAU,QAAQ,GAAG,YAAY,iBAAiB,OAAO;IACpG;AAEA,QAAI,KAAK,SAAS;AAChB,aAAO,KAAK,gBAAgB,KAAK,QAAQ,MAAM,UAAU,QAAQ,GAAG,KAAK,QAAQ,KAAK,iBAAiB,OAAO;IAChH;AAEA,QAAI,KAAK,UAAU;AACjB,aAAO,KAAK,SAAS,KAAK,iBAAiB;IAC7C;AAEA,WAAO;EACT;;;;ACzPF,IAAM,OAAO,MAAK;AAAE;AAGb,IAAM,SAAiB,EAAE,OAAO,MAAM,MAAM,KAAI;AAGjD,SAAU,UAAU,MAAY;AACpC,SAAO,QAAQ,KAAK,MAAM,KAAK,IAAI;AACnC,SAAO,OAAO,KAAK,KAAK,KAAK,IAAI;AACnC;;;ACVO,IAAM,mBAAmB;AAgBhC,eAAsB,mBACpB,SACA,OACA,SACA,SACA,QAAQ,GAAC;AAET,MAAI,SAAS,kBAAkB;AAC7B,WAAO,KACL,uCAAuC,gBAAgB,uDACD;AAExD,WAAO;EACT;AAEA,QAAM,UAAU,MAAM,OAAO;AAC7B,MAAI,QAAQ,WAAW;AAAG,WAAO;AAEjC,QAAM,eAAe,oBAAI,IAAG;AAC5B,QAAM,QAAQ,IACZ,QAAQ,IAAI,OAAO,WAAU;AAC3B,QAAI,WAAW,MAAM,QAAQ,MAAM;AAGnC,eAAW,MAAM,mBAAmB,UAAU,OAAO,SAAS,SAAS,QAAQ,CAAC;AAEhF,iBAAa,IAAI,QAAQ,QAAQ;EACnC,CAAC,CAAC;AAGJ,SAAO,QAAQ,SAAS,YAAY;AACtC;AAgBM,SAAU,kBACd,MACA,UACA,WACA,WAIA,iBAAiC;AAEjC,QAAM,aACJ;AAGF,QAAM,WAAW,oBAAI,IAAG;AAGxB,QAAM,iBAAiB,IAAI,OAAO,MAAM,QAAQ,aAAa;AAG7D,QAAM,QAAQ,CAAC,YAAmB;AAChC,UAAM,UAAU,QAAQ,SAAS,UAAU,EAAE,QAAO;AACpD,WAAO,QAAQ,OAAO,CAAC,UAAS;AAC9B,YAAM,cAAc,MAAM,OAAQ,SAAS;AAC3C,aAAO,CAAC,eAAe,KAAK,WAAW;IACzC,CAAC;EACH;AAGA,QAAM,UAAU,OAAO,UAA2C;AAChE,UAAM,aAAa,MAAM,OAAQ;AACjC,UAAM,cAAc,MAAM,OAAQ,OAAO,KAAI,KAAM;AACnD,UAAM,SAAS,SAAS,IAAI,UAAU;AAEtC,QAAI,CAAC;AAAQ,aAAO,MAAM,CAAC;AAE3B,UAAM,SAAS,mBAAmB,WAAW;AAE7C,QAAI;AACF,UAAI;AACJ,UAAI,WAAW;AACb,gBAAQ,MAAM,UAAU,YAAY,OAAO,KAAK;MAClD;AAEA,YAAM,cAAgC;QACpC,GAAG;QACH,UAAU,UAAU,IAAI;QACxB,cAAc,UAAU,IAAI;QAC5B,GAAI,QAAQ,EAAE,MAAK,IAAK,CAAA;;AAE1B,YAAM,UAA4B,kBAAkB,gBAAgB,WAAW,IAAI;AAEnF,YAAM,OAAO,MAAM,OAAO,QAAQ,EAAE,QAAQ,QAAO,CAAE;AACrD,YAAM,WAAW,OAAO,WAAW,EAAE,MAAM,QAAQ,QAAO,CAAE;AAG5D,eAAS,IAAI,OAAO;QAClB,SAAS,UAAU,UAAU;QAC7B,OAAO,cAAc,IAAI,WAAW,KAAK;QACzC,SAAS,OAAO,gBAAgB,WAAW,KAAK,UAAU,IAAI,CAAC,IAAI;OACpE;AAED,aAAO;IACT,SAAS,GAAG;AACV,aAAO,MACL,sBAAsB,UAAU,mBAChC,aAAa,QAAQ,IAAI,MAAS;AAEpC,aAAO,MAAM,CAAC;IAChB;EACF;AAGA,QAAM,UAAU,CAAC,SAAiB,iBAA8C;AAC9E,QAAI,SAAS;AACb,UAAM,UAAU,CAAC,GAAG,aAAa,QAAO,CAAE,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,QAAS,EAAE,CAAC,EAAE,KAAM;AACpF,eAAW,CAAC,OAAO,SAAS,KAAK,SAAS;AACxC,YAAM,QAAQ,MAAM;AACpB,YAAM,MAAM,QAAQ,MAAM,CAAC,EAAE;AAC7B,YAAM,OAAO,SAAS,IAAI,KAAK;AAC/B,YAAM,eAAe,MAAM,UAAU,KAAK,UAAU;AACpD,YAAM,cAAc,OAChB,IAAI,KAAK,OAAO,GAAG,KAAK,KAAK,IAAI,QAAQ,oCAAoC,SAAS,cAAc,YAAY,KAAK,KAAK,OAAO,MACjI;AACJ,eAAS,OAAO,MAAM,GAAG,KAAK,IAAI,cAAc,OAAO,MAAM,GAAG;IAClE;AACA,WAAO;EACT;AAEA,SAAO,mBAAmB,MAAM,OAAO,SAAS,OAAO;AACzD;AAGM,SAAU,mBAAmB,aAAmB;AACpD,QAAM,SAAkC,CAAA;AACxC,MAAI,CAAC;AAAa,WAAO;AAEzB,QAAM,cACJ;AACF,aAAW,SAAS,YAAY,SAAS,WAAW,GAAG;AACrD,UAAM,EAAE,MAAM,UAAU,IAAI,IAAI,GAAE,IAAK,MAAM;AAC7C,QAAI,aAAa,YAAY,aAAa;AAAW;AACrD,UAAM,MAAM,SAAS,QAAQ,aAAa,CAAC,GAAG,MAAM,EAAE,YAAW,CAAE;AACnE,UAAM,WAAW,MAAM,MAAM;AAC7B,QAAI,aAAa,QAAW;AAC1B,aAAO,GAAG,IAAI;AACd;IACF;AACA,UAAM,MAAM,SAAS,WAAW,SAAS,GAAG,EAAE,WAAW,SAAS,GAAG,EAAE,WACrE,UACA,GAAG;AAEL,QAAI;AACF,aAAO,GAAG,IAAI,KAAK,MAAM,GAAG;IAC9B,QAAQ;AACN,aAAO,GAAG,IAAI;IAChB;EACF;AAEA,SAAO;AACT;AAGA,SAAS,WAAW,OAAa;AAC/B,SAAO,MAAM,WAAW,KAAK,OAAO,EAAE,WAAW,KAAK,OAAO;AAC/D;;;ACrHM,IAAgB,YAAhB,MAAyB;;EAuB7B;;EAGS;;;;;;;;;;;;;;EAeA;;;;;;;EAmCT,WAAW,MAAwB;AACjC,QAAI,KAAK,SAAS,MAAM;AACtB,aAAO,wBAAwB,KAAK,IAAI;IAC1C;AAGA,UAAM,WAAW,KAAK,eAAe;MACnC,MAAM,KAAK;MACX,QAAQ,KAAK;MACb,SAAS,KAAK;KACf;AACD,WAAO,wBAAwB,KAAK,IAAI,mBAAmB,WAAW,QAAQ,CAAC;EACjF;;;;EAmCA,YAAY,MAAyC;AACnD,UAAM,MAAM,KAAK,iBAAiB,QAAQ,KAAK,MAAM,UAAU,OAAO,KAAK,KAAK;AAChF,WAAO,wBAAwB,KAAK,IAAI,YAAY,WAAW,GAAG,CAAC;EACrE;;;;EAKA,oBAAoB,OAAc;AAChC,UAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACjE,WAAO,kBAAkB,KAAK,IAAI,QAAQ,GAAG;EAC/C;;;;AC5MI,IAAO,gBAAP,cAII,UAAmC;EACzB,OAAe;;EAGxB;;;;;;;;;;;;EAaA,QACP,OAAuB;AAEvB,WAAO,QAAQ,QAAQ,IAAI;EAC7B;;;;;;;;;;;;;;;;EAiBS,WACP,MAAwB;AAExB,UAAM,QAAQ,KAAK,QAAQ;AAC3B,UAAM,QAAQ,OAAO,MAAM,UAAU,MAAM,GAAG;IAAe;AAE7D,QAAI,OAAO,MAAM;AACf,UAAI,OAAO,QAAQ,MAAM;AACzB,UAAI,MAAM,MAAM,KAAK,SAAS,yBAAyB,GAAG;AACxD,eAAO,KAAK,QACV,2BACA,cAAc,WAAW,MAAM,EAAE,CAAC,cAAc;MAEpD;AACA,aAAO;IACT;AAEA,QAAI,OAAO,IAAI;AAOb,YAAM,UAAU,MAAM,GAAG,SAAS,gBAAgB;AAClD,YAAM,OAAO,KAAK,QAAQ,UAAU,UAAU,KAAK;AACnD,aAAO,GAAG,KAAK,cAAc,WAAW,MAAM,EAAE,CAAC,eAAe,IAAI;IACtE;AAEA,WAAO,KAAK,QAAQ,SAAS,KAAK;EACpC;;;;;;;;;;;;;;;EAgBS,eACP,MAAwB;AAExB,UAAM,QAAQ,KAAK,QAAQ;AAE3B,QAAI,OAAO,IAAI;AACb,aAAO,MAAM;IACf;AAEA,WAAO,KAAK,QAAQ,SAAS,KAAK;EACpC;;;;;;;;;;;;EAaA,SACE,OAAyB;AAEzB,WAAO;EACT;;AAIF,IAAA,yBAAe,IAAI,cAAa;;;AClG1B,IAAgB,cAAhB,MAAgB,aAAW;EACrB;EACA;EACA;EAGV,YAAY,UAAyB,UAA8B,CAAA,GAAE;AACnE,SAAK,OAAO,IAAI,UAAU,UAAU,OAAO;AAC3C,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,cAAc,QAAQ,eAAe,CAAA;EAC5C;;;;EAKA,MAAM,OACJ,KACA,QAAoB;AAEpB,UAAM,UAAU,KAAK,KAAK,MAAM,GAAG;AAEnC,QAAI,CAAC,SAAS;AACZ,YAAM,aAAa,KAAK,KAAK,cAAc,GAAG;AAC9C,UAAI,YAAY;AACd,YAAI;AACF,gBAAM,KAAgB,EAAE,KAAK,QAAQ,CAAA,EAAE;AACvC,gBAAM,SAAS,MAAM,KAAK,mBAAmB,IAAI,YAAY,QAAW,MAAM;AAC9E,iBAAO,EAAE,SAAS,KAAK,WAAW,OAAO,OAAO,GAAG,QAAQ,KAAK,GAAI,OAAO,SAAS,OAAO,EAAE,OAAO,OAAO,MAAK,IAAK,CAAA,EAAG;QAC1H,SAAS,GAAG;AACV,iBAAO,MACL,IAAI,KAAK,KAAK,0CAA0C,IAAI,QAAQ,IACpE,aAAa,QAAQ,IAAI,MAAS;QAEtC;MACF;AACA,aAAO,EAAE,SAAS,KAAK,iBAAiB,KAAK,GAAG,GAAG,QAAQ,IAAG;IAChE;AAGA,QAAI,QAAQ,MAAM,SAAS,YAAY;AACrC,YAAM,SAAS,MAAM,KAAK,KAAK,WAC7B,QAAQ,MAAM,UAAU;AAE1B,YAAM,iBAAiB,OAAO;AAC9B,yBAAmB,eAAe,EAAE;AACpC,aAAO;QACL,SAAS,KAAK,eAAe,eAAe,EAAE;QAC9C,QAAQ,eAAe,UAAU;QACjC,UAAU,eAAe;;IAE7B;AAEA,UAAM,YAAY,KAAK,KAAK,YAAY,SAAS,GAAG;AAEpD,QAAI;AACF,YAAM,EAAE,SAAS,MAAK,IAAK,MAAM,KAAK,WAAW,WAAW,SAAS,MAAM;AAC3E,aAAO,EAAE,SAAS,QAAQ,KAAK,GAAI,SAAS,OAAO,EAAE,MAAK,IAAK,CAAA,EAAG;IACpE,SAAS,OAAO;AACd,UAAI,iBAAiB,UAAU;AAC7B,cAAM,aAAa,KAAK,KAAK,cAAc,MAAM,MAAM;AACvD,YAAI,YAAY;AACd,cAAI;AACF,kBAAM,KAAgB,EAAE,KAAK,QAAQ,CAAA,EAAE;AACvC,kBAAM,SAAS,MAAM,KAAK,mBAAmB,IAAI,YAAY,QAAW,MAAM;AAC9E,mBAAO;cACL,SAAS,KAAK,WAAW,OAAO,OAAO;cACvC,QAAQ,MAAM;cACd,GAAI,OAAO,SAAS,OAAO,EAAE,OAAO,OAAO,MAAK,IAAK,CAAA;;UAEzD,SAAS,GAAG;AACV,mBAAO,MACL,IAAI,KAAK,KAAK,sBAAsB,MAAM,MAAM,oBAAoB,IAAI,QAAQ,IAChF,aAAa,QAAQ,IAAI,MAAS;UAEtC;QACF;AACA,eAAO,EAAE,SAAS,KAAK,iBAAiB,MAAM,QAAQ,GAAG,GAAG,QAAQ,MAAM,OAAM;MAClF;AACA,aAAO,MACL,IAAI,KAAK,KAAK,qBAAqB,IAAI,QAAQ,KAC/C,iBAAiB,QAAQ,QAAQ,MAAS;AAG5C,YAAM,WAAW,KAAK,KAAK,kBAAkB,IAAI,QAAQ;AACzD,UAAI,UAAU;AACZ,cAAM,SAAS,MAAM,KAAK,qBAAqB,SAAS,YAAY,KAAK,UAAU;AACnF,YAAI;AAAQ,iBAAO;MACrB;AAEA,YAAM,eAAe,KAAK,KAAK,gBAAe;AAC9C,UAAI,cAAc;AAChB,cAAM,SAAS,MAAM,KAAK,qBAAqB,aAAa,YAAY,KAAK,SAAS;AACtF,YAAI;AAAQ,iBAAO;MACrB;AAEA,aAAO,EAAE,SAAS,KAAK,gBAAgB,OAAO,GAAG,GAAG,QAAQ,IAAG;IACjE;EACF;;;;EAKU,MAAM,WACd,WACA,SACA,QAAoB;AAEpB,UAAM,YAAY,KAAK,KAAK,oBAAoB,QAAQ,MAAM,OAAO;AAGrE,UAAM,WAAsD,CAAA;AAC5D,aAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,YAAM,eAAe,UAAU,CAAC;AAChC,UAAI,QAAQ,KAAK,KAAK,UAAU,YAAY;AAE5C,UAAI,CAAC,SAAS,iBAAiB,KAAK;AAClC,gBAAQ;MACV;AAEA,UAAI,CAAC;AAAO;AACZ,UAAI,UAAU,QAAQ,SAAS,iBAAiB,QAAQ,MAAM;AAAS;AAEvE,eAAS,KAAK,EAAE,OAAO,QAAQ,MAAM,UAAU,SAAS,EAAC,CAAE;IAC7D;AAGA,UAAM,UAAU,MAAM,QAAQ,IAC5B,SAAS,IAAI,CAAC,EAAE,OAAO,OAAM,MAC3B,KAAK,mBAAmB,WAAW,OAAO,QAAQ,MAAM,CAAC,CAC1D;AAIH,QAAI,SAAS;AACb,QAAI;AACJ,QAAI,sBAAsB;AAE1B,aAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,YAAM,EAAE,SAAS,MAAK,IAAK,QAAQ,CAAC;AAEpC,UAAI,OAAO;AACT,oBAAY;MACd;AAEA,UAAI,WAAW,IAAI;AACjB,iBAAS;MACX,OAAO;AACL,cAAM,WAAW,KAAK,WAAW,QAAQ,SAAS,mBAAmB;AACrE,YAAI,aAAa,QAAQ;AACvB,iBAAO,KACL,IAAI,KAAK,KAAK,YAAY,mBAAmB,2CACvB,UAAU,CAAC,CAAC,2EACyB;QAE/D;AACA,iBAAS;MACX;AAEA,4BAAsB,SAAS,CAAC,EAAE,MAAM;IAC1C;AAEA,aAAS,KAAK,WAAW,MAAM;AAE/B,WAAO,EAAE,SAAS,QAAQ,GAAI,aAAa,OAAO,EAAE,OAAO,UAAS,IAAK,CAAA,EAAG;EAC9E;;EAUU,MAAM,iBACd,WACA,OACA,QACA,QAAoB;AAEpB,UAAM,QAAQ,MAAM,SAAS,CAAA;AAE7B,UAAM,WAAW,MAAM,MAAM,MAAM;AACnC,UAAM,YAA2B,YAC5B,MAAM,KAAK,KAAK,WAAuC,QAAQ,GAAG,UACnE;AAEJ,UAAM,UAAU,MAAM,KAAK,KAAK,sBAAsB,WAAW,OAAO,QAAQ,MAAM;AACtF,UAAM,OAAO,MAAM,UAAU,QAAQ,EAAE,QAAQ,UAAU,QAAQ,GAAI,SAAS,EAAE,OAAM,IAAK,CAAA,GAAK,QAAO,CAAE;AACzG,UAAM,UAAU,KAAK,cAAc,WAAW,EAAE,MAAM,QAAQ,UAAU,QAAQ,QAAO,CAAE;AACzF,UAAM,QAAQ,UAAU,SAAS,EAAE,MAAM,QAAQ,UAAU,QAAQ,QAAO,CAAE;AAE5E,WAAO,EAAE,SAAS,GAAI,SAAS,OAAO,EAAE,MAAK,IAAK,CAAA,EAAG;EACvD;;EASU,gBACR,WACA,MACA,SAAyB;AAEzB,WAAO,KAAK,cAAc,WAAW,EAAE,MAAM,QAAQ,CAAA,GAAI,QAAO,CAAE;EACpE;EAEQ,OAAgB,YAAY,IAAI,IAAI,cAAc;;EAGlD,MAAM,qBACZ,YACA,KACA,MAA4B;AAE5B,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,KAAK,WAAuC,UAAU;AAChF,YAAM,YAAY,OAAO;AACzB,YAAM,SAA2B;QAC/B,KAAK,aAAY;QACjB,QAAQ,CAAA;QACR,UAAU;QACV,cAAc,IAAI,gBAAe;;AAEnC,YAAM,OAAO,MAAM,UAAU,QAAQ,EAAE,QAAQ,CAAA,GAAI,SAAS,OAAM,CAAE;AACpE,YAAM,UAAU,KAAK,gBAAgB,WAAW,MAAM,MAAM;AAC5D,aAAO,EAAE,SAAS,QAAQ,IAAG;IAC/B,SAAS,GAAG;AACV,aAAO,MACL,IAAI,KAAK,KAAK,WAAW,IAAI,eAAe,IAAI,QAAQ,IACxD,aAAa,QAAQ,IAAI,MAAS;AAEpC,aAAO;IACT;EACF;;;;ACtPI,IAAO,gBAAP,cAA6B,YAAW;EAChB,QAAQ;EAC5B;EACA,gBAAsC;EAE9C,YAAY,UAAyB,UAAgC,CAAA,GAAE;AACrE,UAAM,UAAU,OAAO;AACvB,SAAK,mBAAmB,QAAQ,oBAAoB;AAEpD,QAAI,KAAK,kBAAkB,MAAM;AAC/B,WAAK,gBAAgB,KAAK,iBAAiB,KAAI;IACjD;EACF;EAEmB,WAAW,QAAgB,OAAe,eAAqB;AAChF,UAAM,UAAU,cAAc,QAAQ,uBAAuB,MAAM;AACnE,WAAO,OAAO,QACZ,IAAI,OAAO,mCAAmC,OAAO,uBAAuB,GAC5E,KAAK;EAET;EAEmB,WAAW,QAAc;AAC1C,WAAO,OAAO,QAAQ,sCAAsC,EAAE;EAChE;;;;EAKmB,MAAM,mBACvB,WACA,OACA,QACA,QAAoB;AAEpB,QAAI,MAAM,eAAe,mBAAmB,YAAY;AACtD,aAAO,EAAE,SAAS,yBAAyB,MAAM,OAAO,mBAAkB;IAC5E;AAEA,UAAM,EAAE,SAAS,YAAY,MAAK,IAAK,MAAM,KAAK,iBAAiB,WAAW,OAAO,QAAQ,MAAM;AACnG,QAAI,UAAU;AAGd,cAAU,MAAM,KAAK,eAAe,OAAO;AAI3C,cAAU,KAAK,eAAe,SAAS,MAAM,OAAO;AAGpD,QAAI,KAAK,SAAS;AAChB,gBAAU,MAAM,kBACd,SACA,KAAK,SACL,WACA,CAAC,MAAM,aAAY;AACjB,cAAM,QAAQ,KAAK,YAAY,IAAI,KAAK;AACxC,eAAO,QAAQ,KAAK,KAAK,gBAAgB,KAAK,IAAI,QAAQ,QAAQ,CAAA,CAAE;MACtE,GACA,KAAK,KAAK,eAAe;IAE7B;AAEA,WAAO,EAAE,SAAS,GAAI,SAAS,OAAO,EAAE,MAAK,IAAK,CAAA,EAAG;EACvD;EAEmB,cACjB,WACA,MAAiC;AAEjC,WAAO,UAAU,WAAW,IAAI;EAClC;EAEmB,eAAe,IAAU;AAC1C,WAAO,6CAA6C,WAAW,EAAE,CAAC;EACpE;EAEmB,iBAAiB,QAAgB,KAAQ;AAC1D,WAAO;YACC,gBAAgB,MAAM,KAAK,OAAO;iBAC7B,WAAW,IAAI,QAAQ,CAAC;;EAEvC;EAEmB,gBAAgB,OAAgB,KAAQ;AACzD,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;;iBAEM,WAAW,IAAI,QAAQ,CAAC;WAC9B,WAAW,OAAO,CAAC;;EAE5B;;EAGQ,eAAe,SAAiB,cAAoB;AAC1D,WAAO,QAAQ,QACb,2DACA,yBAAyB,YAAY,oBAAoB;EAE7D;;;;;EAMQ,MAAM,eAAe,SAAe;AAC1C,QAAI,CAAC,KAAK;AAAkB,aAAO;AACnC,QAAI,CAAC,QAAQ,SAAS,aAAa;AAAG,aAAO;AAE7C,QAAI,KAAK,eAAe;AACtB,YAAM,KAAK;IACb;AAEA,UAAM,WAAW,KAAK;AAGtB,UAAM,UAAU;AAEhB,WAAO,QAAQ,QAAQ,SAAS,CAAC,QAAQ,YAAmB;AAC1D,YAAM,WAAW,aAAa,OAAO;AACrC,YAAM,WAAW,SAAS,OAAO,QAAQ;AACzC,aAAO;IACT,CAAC;EACH;;;;ACpIF,IAAM,iBAAiB;AAQjB,SAAU,kBAAkB,UAAgB;AAChD,QAAM,SAA8B,CAAA;AAEpC,aAAW,SAAS,SAAS,SAAS,cAAc,GAAG;AACrD,UAAM,YAAY,MAAM,CAAC;AACzB,UAAM,EAAE,MAAM,YAAY,QAAQ,UAAS,IAAK,MAAM;AACtD,UAAM,aAAa,UAAU,KAAI;AACjC,UAAM,aAAa,MAAM;AAEzB,UAAM,QAA2B;MAC/B;MACA;MACA,QAAQ;MACR;MACA,UAAU,aAAa,UAAU;;AAInC,QAAI,YAAY;AACd,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,UAAU;AACpC,YAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC3E,gBAAM,SAAS;QACjB,OAAO;AACL,gBAAM,aAAa;QACrB;MACF,SAAS,GAAG;AACV,cAAM,aAAa,iBAAiB,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;MAChF;IACF,OAAO;AAEL,YAAM,SAAS,CAAA;IACjB;AAEA,WAAO,KAAK,KAAK;EACnB;AAEA,SAAO;AACT;AASM,SAAU,oBACd,UACA,cAA4C;AAI5C,QAAM,eAAe,CAAC,GAAG,aAAa,QAAO,CAAE,EAAE,KAC/C,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,aAAa,EAAE,UAAU;AAG3C,MAAI,SAAS;AACb,aAAW,CAAC,OAAO,WAAW,KAAK,cAAc;AAC/C,aAAS,OAAO,MAAM,GAAG,MAAM,UAAU,IAAI,cAAc,OAAO,MAAM,MAAM,QAAQ;EACxF;AAEA,SAAO;AACT;;;ACvEA,IAAM,kBAAkB;AAExB,SAAS,gBAAgB,SAAe;AACtC,SAAO;cAAkC,OAAO;;AAClD;AAQM,IAAO,cAAP,cAA2B,YAAW;EACd,QAAQ;EAEpC,YAAY,UAAyB,UAA8B,CAAA,GAAE;AACnE,UAAM,UAAU,OAAO;EACzB;EAEmB,WAAW,QAAgB,OAAe,eAAqB;AAChF,WAAO,OAAO,QAAQ,gBAAgB,aAAa,GAAG,KAAK;EAC7D;EAEmB,WAAW,QAAc;AAC1C,WAAO,OACJ,QAAQ,wCAAwC,EAAE,EAClD,KAAI;EACT;;;;EAKmB,MAAM,mBACvB,WACA,OACA,QACA,QAAoB;AAEpB,QAAI,MAAM,eAAe,mBAAmB,YAAY;AACtD,aAAO,EAAE,SAAS,gBAAgB,MAAM,OAAO,EAAC;IAClD;AAEA,UAAM,EAAE,SAAS,YAAY,MAAK,IAAK,MAAM,KAAK,iBAAiB,WAAW,OAAO,QAAQ,MAAM;AACnG,QAAI,UAAU;AAId,cAAU,QAAQ,WAAW,iBAAiB,gBAAgB,MAAM,OAAO,CAAC;AAG5E,QAAI,KAAK,SAAS;AAChB,gBAAU,MAAM,KAAK,eAAe,SAAS,SAAS;IACxD;AAEA,WAAO,EAAE,SAAS,GAAI,SAAS,OAAO,EAAE,MAAK,IAAK,CAAA,EAAG;EACvD;EAEmB,cACjB,WACA,MAAiC;AAEjC,WAAO,UAAU,eAAe,IAAI;EACtC;EAEmB,eAAe,IAAU;AAC1C,WAAO,gBAAgB,EAAE;EAC3B;EAEmB,iBAAiB,QAAgB,KAAQ;AAC1D,WAAO,KAAK,gBAAgB,MAAM,KAAK,OAAO;;UAAe,IAAI,QAAQ;EAC3E;EAEmB,gBAAgB,QAAiB,KAAQ;AAC1D,WAAO;;UAAsC,IAAI,QAAQ;EAC3D;;;;;EAMQ,eACN,SACA,WAAoB;AAEpB,WAAO,mBACL,SACA,mBACA,OAAO,UAAS;AACd,UAAI,MAAM,cAAc,CAAC,MAAM,QAAQ;AACrC,eAAO,kBAAkB,MAAM,UAAU,QAAQ,MAAM,UAAU;MACnE;AAEA,YAAM,SAAS,KAAK,QAAS,IAAI,MAAM,UAAU;AACjD,UAAI,CAAC,QAAQ;AACX,eAAO,iCAAiC,MAAM,UAAU;MAC1D;AAEA,UAAI;AACF,YAAI;AACJ,cAAM,YAAY,KAAK,YAAY,MAAM,UAAU,KAAK,OAAO;AAC/D,YAAI,WAAW;AACb,kBAAQ,MAAM,KAAK,KAAK,gBAAgB,SAAS;QACnD;AAEA,cAAM,cAAgC;UACpC,GAAG;UACH,UAAU,UAAU,IAAI;UACxB,cAAc,UAAU,IAAI;UAC5B,GAAI,QAAQ,EAAE,MAAK,IAAK,CAAA;;AAE1B,cAAM,UAA4B,KAAK,KAAK,kBACxC,KAAK,KAAK,gBAAgB,WAAW,IACrC;AACJ,cAAM,OAAO,MAAM,OAAO,QAAQ,EAAE,QAAQ,MAAM,QAAQ,QAAO,CAAE;AACnE,eAAO,OAAO,eAAe,EAAE,MAAM,QAAQ,MAAM,QAAQ,QAAO,CAAE;MACtE,SAAS,GAAG;AACV,eAAO,OAAO,oBAAoB,CAAC;MACrC;IACF,GACA,mBAAmB;EAEvB;;;;AClII,SAAU,eAAe,UAAkB,MAAc,cAAsB;AACnF,QAAM,SAAS,OAAO;AAEtB,QAAM,OAAO,aAAa,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,GAAG,EAAE,KAAK,GAAG;AAC/D,QAAM,WAAW,IAAI,OAAO,eAAe,IAAI,KAAK,GAAG;AACvD,QAAM,QAAQ,IAAI,OAAO,8BAA8B,IAAI,KAAK,GAAG;AAEnE,QAAM,QAAQ,SAAS,MAAM,IAAI;AACjC,MAAI,cAAc;AAElB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,QAAI,MAAM,CAAC,EAAE,WAAW,KAAK,GAAG;AAC9B,oBAAc,CAAC;AACf;IACF;AACA,QAAI;AAAa;AAEjB,UAAM,CAAC,IAAI,MAAM,CAAC,EAAE,WAAW,UAAU,KAAK,MAAM,EAAE;AACtD,UAAM,CAAC,IAAI,MAAM,CAAC,EAAE,WAAW,OAAO,KAAK,MAAM,EAAE;EACrD;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;;;ACdM,SAAU,kBAAkB,MAAiB,MAAc,QAAe;AAC9E,MAAI,SAAS,SAAS;AACpB,QAAI;AAAQ,aAAO;AAEnB,SAAK,aAAa,EAAE,OAAO,QAAQ,OAAO,CAAA,EAAE;AAC5C,WAAO,KAAK,SAAS;EACvB;AAEA,MAAI,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,GAAG,GAAG;AAC9C,UAAM,QAAQ,KAAK,MAAM,GAAG,EAAE;AAC9B,SAAK,YAAY,EAAE,OAAO,OAAO,CAAA,EAAE;AACnC,WAAO,KAAK,QAAQ;EACtB;AAGA,OAAK,aAAa,CAAA;AAClB,OAAK,SAAS,IAAI,MAAM,CAAA;AACxB,SAAO,KAAK,SAAS,IAAI;AAC3B;;;ACFO,IAAM,qBAAqB;AAC3B,IAAM,sBAAsB;AAC5B,IAAM,uBAAuB;AAC7B,IAAM,uBAAuB;AAC7B,IAAM,wBAAwB;AAC9B,IAAM,yBAAyB;AAoBhC,IAAgB,UAAhB,MAAuB;EACN;EAArB,YAAqB,SAAwB,CAAA,GAAE;AAA1B,SAAA,SAAA;AACnB,SAAK,SAAS;EAChB;;EAmBA,QAAQ,UAA0B,SAAwB;AACxD,UAAM,OAAO,OAAO,aAAa,WAC7B,WACA,IAAI,IAAI,oBAAoB,UAAU,SAAS,MAAM,SAAS,SAAQ,CAAE,EAAE;AAC9E,UAAM,SAAS,KAAK,OAAO,UAAU,EAAE,QAAQ,OAAO,GAAG,QAAO,CAAE;AAClE,UAAM,YAAY,KAAK,OAAO,aAAa;AAC3C,QAAI,KAAK,WAAW,YAAY,GAAG,GAAG;AACpC,aAAO,OAAO,KAAK,OAAO,QAAO;AAC/B,cAAM,KAAK,uBAAuB,MAAM,SAAS;AACjD,eAAO;MACT,CAAC;IACH;AACA,WAAO;EACT;;;;;;EAOQ,MAAM,uBACZ,UACA,WAAiB;AAEjB,UAAM,eAAe,SAAS,MAAM,UAAU,SAAS,CAAC;AACxD,UAAM,QAAQ,aAAa,MAAM,GAAG;AACpC,UAAM,WAAW,MAAM,MAAM,SAAS,CAAC;AACvC,UAAM,cAAc,MAAM,MAAM,GAAG,EAAE;AAErC,UAAM,QAAQ,SAAS,MAAM,qDAAqD;AAClF,QAAI,CAAC;AAAO;AAEZ,UAAM,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI;AAG5B,UAAM,WAAW,MAAM,KAAK,OAAO,oBAAoB;AACvD,UAAM,OAAkB,SAAS,WAAW,MACxC,CAAA,IACA,MAAM,SAAS,KAAI;AAGvB,QAAI,OAAO;AACX,eAAW,OAAO,aAAa;AAC7B,UAAI,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,GAAG;AAC5C,cAAM,QAAQ,IAAI,MAAM,GAAG,EAAE;AAC7B,aAAK,YAAY,EAAE,OAAO,OAAO,CAAA,EAAE;AACnC,eAAO,KAAK,QAAQ;MACtB,OAAO;AACL,aAAK,aAAa,CAAA;AAClB,aAAK,SAAS,GAAG,MAAM,CAAA;AACvB,eAAO,KAAK,SAAS,GAAG;MAC1B;IACF;AAGA,QAAI,SAAS,SAAS;AACpB,WAAK,gBAAgB;IACvB,OAAO;AACL,YAAM,SAAS,kBAAkB,MAAM,MAAM,YAAY,WAAW,CAAC;AACrE,UAAI,SAAS,YAAY;AACvB,eAAO,WAAW;MACpB,OAAO;AACL,eAAO,UAAU,CAAA;AACjB,eAAO,MAAM,GAAuB,IAAI;MAC1C;IACF;AAGA,SAAK,sBAAsB;AAC3B,UAAM,KAAK,OAAO,sBAAsB;MACtC,QAAQ;MACR,MAAM,KAAK,UAAU,IAAI;KAC1B;EACH;;;;;EAMA,WAAW,OAAa;AACtB,UAAM,IAAI,MAAM,kCAAkC,KAAK,YAAY,IAAI,EAAE;EAC3E;;;;;EAMA,UAAU,SAAe;AACvB,UAAM,IAAI,MAAM,iCAAiC,KAAK,YAAY,IAAI,EAAE;EAC1E;;EAIQ,sBAAuC;EACvC,uBAAwC;EACxC,wBAAyC;;EAGjD,sBAAmB;AACjB,SAAK,sBAAsB;AAC3B,SAAK,uBAAuB;AAC5B,SAAK,wBAAwB;EAC/B;;;;;EAMA,MAAM,wBAAqB;AACzB,QAAI,KAAK;AAAqB,aAAO,KAAK,oBAAoB,MAAK;AAEnE,UAAM,YAAY,KAAK,OAAO,aAAa;AAG3C,UAAM,cAAc,MAAM,KAAK,MAAM,YAAY,GAAG;AACpD,QAAI,YAAY,WAAW,KAAK;AAC9B,aAAO,IAAI,SAAS,aAAa,EAAE,QAAQ,IAAG,CAAE;IAClD;AAEA,UAAM,OAAO,MAAM,KAAK,WAAW,SAAS;AAE5C,SAAK,sBAAsB,SAAS,KAAK,IAAI;AAC7C,WAAO,KAAK,oBAAoB,MAAK;EACvC;;;;;EAMA,MAAM,yBAAsB;AAC1B,QAAI,KAAK;AAAsB,aAAO,KAAK,qBAAqB,MAAK;AAErE,UAAM,aAAa,KAAK,OAAO,cAAc;AAE7C,UAAM,cAAc,MAAM,KAAK,MAAM,aAAa,GAAG;AACrD,QAAI,YAAY,WAAW,KAAK;AAC9B,aAAO,IAAI,SAAS,aAAa,EAAE,QAAQ,IAAG,CAAE;IAClD;AAEA,UAAM,UAAU,MAAM,KAAK,YAAY,YAAY,WAAW,QAAQ,OAAO,EAAE,CAAC;AAChF,SAAK,uBAAuB,SAAS,KAAK,OAAO;AACjD,WAAO,KAAK,qBAAqB,MAAK;EACxC;;;;;EAMA,MAAM,0BAAuB;AAC3B,QAAI,KAAK;AAAuB,aAAO,KAAK,sBAAsB,MAAK;AAEvE,UAAM,cAAc,KAAK,OAAO,eAAe;AAE/C,UAAM,cAAc,MAAM,KAAK,MAAM,cAAc,GAAG;AACtD,QAAI,YAAY,WAAW,KAAK;AAC9B,aAAO,IAAI,SAAS,aAAa,EAAE,QAAQ,IAAG,CAAE;IAClD;AAEA,UAAM,UAAU,MAAM,KAAK,aAAa,aAAa,YAAY,QAAQ,OAAO,EAAE,CAAC;AACnF,SAAK,wBAAwB,SAAS,KAAK,OAAO;AAClD,WAAO,KAAK,sBAAsB,MAAK;EACzC;;EAIU,OAAO,cAAc,KAAW;AACxC,UAAM,cAAc,IAAI,SAAS,GAAG,IAAI,MAAM,MAAM;AACpD,UAAM,WAAW,MAAM,KAAK,MAAM,WAAW;AAC7C,UAAM,UAAoB,MAAM,SAAS,KAAI;AAE7C,eAAW,SAAS,SAAS;AAC3B,YAAM,OAAO,GAAG,WAAW,GAAG,KAAK;AACnC,UAAI,MAAM,SAAS,GAAG,GAAG;AACvB,eAAO,KAAK,cAAc,IAAI;MAChC,OAAO;AACL,cAAM;MACR;IACF;EACF;;;;;EAMU,MAAM,WAAW,WAAiB;AAC1C,UAAM,OAAkB,CAAA;AAExB,UAAM,WAAqB,CAAA;AAC3B,qBAAiB,QAAQ,KAAK,cAAc,SAAS,GAAG;AACtD,eAAS,KAAK,IAAI;IACpB;AAEA,eAAW,YAAY,UAAU;AAC/B,YAAM,eAAe,SAAS,QAAQ,GAAG,SAAS,KAAK,EAAE;AACzD,YAAM,QAAQ,aAAa,MAAM,GAAG;AACpC,YAAM,WAAW,MAAM,MAAM,SAAS,CAAC;AACvC,YAAM,cAAc,MAAM,MAAM,GAAG,EAAE;AAGrC,YAAM,QAAQ,SAAS,MAAM,qDAAqD;AAClF,UAAI,CAAC;AAAO;AAEZ,YAAM,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI;AAG5B,UAAI,OAAO;AACX,iBAAW,OAAO,aAAa;AAC7B,YAAI,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,GAAG;AAC5C,gBAAM,QAAQ,IAAI,MAAM,GAAG,EAAE;AAC7B,eAAK,YAAY,EAAE,OAAO,OAAO,CAAA,EAAE;AACnC,iBAAO,KAAK,QAAQ;QACtB,OAAO;AACL,eAAK,aAAa,CAAA;AAClB,eAAK,SAAS,GAAG,MAAM,CAAA;AACvB,iBAAO,KAAK,SAAS,GAAG;QAC1B;MACF;AAGA,UAAI,SAAS,SAAS;AAIpB,aAAK,gBAAgB;AACrB;MACF;AAGA,YAAM,SAAS,kBAAkB,MAAM,MAAM,YAAY,WAAW,CAAC;AAErE,UAAI,SAAS,YAAY;AACvB,eAAO,WAAW;MACpB,OAAO;AAEL,eAAO,UAAU,CAAA;AACjB,eAAO,MAAM,GAAuB,IAAI;MAC1C;IACF;AAEA,WAAO;EACT;EAEU,MAAM,YACd,YACA,YAAmB;AAEnB,UAAM,uBAAuB,CAAC,QAAQ,MAAM,KAAK;AACjD,UAAM,UAAiC,CAAA;AAEvC,UAAM,cAAc,WAAW,SAAS,GAAG,IAAI,aAAa,aAAa;AACzE,UAAM,WAAW,MAAM,KAAK,MAAM,WAAW;AAC7C,UAAM,UAAoB,MAAM,SAAS,KAAI;AAE7C,eAAW,QAAQ,SAAS;AAC1B,UAAI,CAAC,KAAK,SAAS,GAAG;AAAG;AAEzB,YAAM,OAAO,KAAK,MAAM,GAAG,EAAE;AAG7B,UAAI,aAAa,GAAG,IAAI;AACxB,UAAI,aAAa,GAAG,WAAW,GAAG,IAAI,IAAI,UAAU;AACpD,WAAK,MAAM,KAAK,MAAM,UAAU,GAAG,WAAW,KAAK;AACjD,qBAAa,GAAG,IAAI;AACpB,qBAAa,GAAG,WAAW,GAAG,IAAI,IAAI,UAAU;AAChD,aAAK,MAAM,KAAK,MAAM,UAAU,GAAG,WAAW;AAAK;MACrD;AAEA,YAAM,SAAS,aAAa,GAAG,UAAU,MAAM;AAC/C,YAAM,QAA6B;QACjC;QACA,YAAY,GAAG,MAAM,GAAG,IAAI,IAAI,UAAU;QAC1C,SAAS,UAAU,IAAI;;AAGzB,YAAM,QAAsD,CAAA;AAC5D,UAAI,WAAW;AACf,iBAAW,OAAO,sBAAsB;AACtC,cAAM,gBAAgB,GAAG,IAAI,WAAW,GAAG;AAC3C,cAAM,gBAAgB,GAAG,WAAW,GAAG,IAAI,IAAI,aAAa;AAC5D,aAAK,MAAM,KAAK,MAAM,aAAa,GAAG,WAAW,KAAK;AACpD,gBAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,IAAI,aAAa;AAC9C,qBAAW;QACb;MACF;AAEA,UAAI;AAAU,cAAM,QAAQ;AAC5B,cAAQ,KAAK,KAAK;IACpB;AAEA,YAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AACnD,WAAO;EACT;EAEU,MAAM,aACd,aACA,YAAmB;AAEnB,UAAM,UAAkC,CAAA;AAExC,UAAM,cAAc,YAAY,SAAS,GAAG,IAAI,cAAc,cAAc;AAC5E,UAAM,WAAW,MAAM,KAAK,MAAM,WAAW;AAC7C,UAAM,UAAoB,MAAM,SAAS,KAAI;AAE7C,eAAW,QAAQ,SAAS;AAC1B,UAAI,CAAC,KAAK,SAAS,GAAG;AAAG;AAEzB,YAAM,OAAO,KAAK,MAAM,GAAG,EAAE;AAG7B,UAAI,CAAC,KAAK,SAAS,GAAG,GAAG;AACvB,gBAAQ,KAAK,+BAA+B,IAAI,mEAAmE;AACnH;MACF;AAGA,UAAI,aAAa,GAAG,IAAI;AACxB,UAAI,aAAa,GAAG,WAAW,GAAG,IAAI,IAAI,UAAU;AACpD,WAAK,MAAM,KAAK,MAAM,UAAU,GAAG,WAAW,KAAK;AACjD,qBAAa,GAAG,IAAI;AACpB,qBAAa,GAAG,WAAW,GAAG,IAAI,IAAI,UAAU;AAChD,aAAK,MAAM,KAAK,MAAM,UAAU,GAAG,WAAW;AAAK;MACrD;AAEA,YAAM,SAAS,aAAa,GAAG,UAAU,MAAM;AAC/C,cAAQ,KAAK;QACX;QACA,YAAY,GAAG,MAAM,GAAG,IAAI,IAAI,UAAU;QAC1C,SAAS;OACV;IACH;AAEA,YAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AACnD,WAAO;EACT;;;;ACpWF,SAAS,oBACP,MACA,SAAgB;AAEhB,QAAM,QAAQ,oBAAI,IAAG;AAErB,WAAS,KAAK,MAAe;AAC3B,UAAM,aAAa,KAAK,OAAO,MAAM,KAAK,OAAO;AACjD,QAAI;AAAY,YAAM,IAAI,UAAU;AACpC,QAAI,KAAK;AAAU,YAAM,IAAI,KAAK,QAAQ;AAC1C,QAAI,KAAK;AAAe,YAAM,IAAI,KAAK,aAAa;AAEpD,QAAI,KAAK,UAAU;AACjB,iBAAW,SAAS,OAAO,OAAO,KAAK,QAAQ;AAAG,aAAK,KAAK;IAC9D;AACA,QAAI,KAAK;AAAS,WAAK,KAAK,QAAQ,KAAK;AACzC,QAAI,KAAK;AAAU,WAAK,KAAK,SAAS,KAAK;EAC7C;AAEA,OAAK,IAAI;AAET,QAAM,UAAkD,CAAA;AACxD,aAAW,QAAQ,OAAO;AACxB,YAAQ,IAAI,IAAI,MAAM,QAAQ,WAAW,IAAI;EAC/C;AACA,SAAO;AACT;AAKA,SAAS,oBACP,KAA4B;AAE5B,aAAW,SAAS,OAAO,OAAO,GAAG,GAAG;AACtC,QAAI,CAAC;AAAO;AACZ,QAAI,OAAO,UAAU,YAAY,aAAa,OAAO;AACnD,aAAO;IACT;AACA,QAAI,OAAO,UAAU,cAAc,MAAM,WAAW,SAAS;AAC3D,aAAO,IAAK,MAAmC;IACjD;EACF;AACA,SAAO;AACT;AAGA,eAAe,cACb,SACA,SACA,QAAuB;AAKvB,QAAM,WAAW,IAAI,eAAc;AACnC,QAAM,cAA4E,CAAA;AAElF,aAAW,SAAS,SAAS;AAC3B,QAAI;AACF,YAAM,cAAc,MAAM,WAAW,WAAW,GAAG,IAC/C,MAAM,aACN,IAAI,MAAM,UAAU;AAExB,YAAM,MAAM,MAAM,QAAQ,WAAW,WAAW;AAChD,YAAM,WAAW,oBAAoB,GAAG;AACxC,UAAI,CAAC;AAAU;AACf,eAAS,IAAI,QAAQ;AAGrB,YAAM,UAAU,IAAI;AACpB,UAAI,WAAW,OAAO,YAAY,UAAU;AAC1C,oBAAY,MAAM,IAAI,IAAI;MAC5B,WAAW,MAAM,OAAO;AACtB,oBAAY,MAAM,IAAI,IAAI,MAAM;MAClC;IACF,SAAS,GAAG;AACV,cAAQ,MAAM,mCAAmC,MAAM,UAAU,KAAK,CAAC;AACvE,UAAI,MAAM;AAAO,oBAAY,MAAM,IAAI,IAAI,MAAM;IACnD;EACF;AAEA,MAAI,QAAQ;AACV,eAAW,UAAU,QAAQ;AAC3B,eAAS,IAAI,MAAM;IACrB;EACF;AAEA,SAAO,EAAE,UAAU,YAAW;AAChC;AAKA,SAAS,eAAe,OAAe,UAAgB;AACrD,QAAM,UAAU,WAAW;gBAAmB,WAAW,QAAQ,CAAC,QAAQ;AAC1E,SAAO;;QAED,OAAO;;;WAGJ,WAAW,KAAK,CAAC;;;;;;;AAO5B;AAGA,SAAS,iBACP,MACA,SACA,OACA,UAAiB;AAEjB,QAAM,cAAc;AACpB,MAAI,CAAC,YAAY,KAAK,IAAI;AAAG,WAAO;AAEpC,QAAM,UAAU,WAAW,oBAAoB,QAAQ,MAAM;AAC7D,SAAO,KAAK,QAAQ,aAAa,eAAe,OAAO,IAAI,OAAO,gBAAgB;AAElF,MAAI,OAAO;AACT,WAAO,KAAK,QAAQ,yBAAyB,UAAU,WAAW,KAAK,CAAC,UAAU;EACpF;AAEA,SAAO;AACT;AAGA,eAAe,aACb,SACA,OACA,UAAgB;AAEhB,QAAM,WAAW,MAAM,QAAQ,MAAM,aAAa;AAClD,MAAI,SAAS,WAAW;AAAK,WAAO,MAAM,SAAS,KAAI;AACvD,SAAO,eAAe,OAAO,QAAQ;AACvC;AAWA,eAAsB,oBACpB,QACA,SAAgB;AAEhB,QAAM,EACJ,MAAM,OAAM,IACV;AAEJ,QAAM,EAAE,MAAM,UAAU,IAAI,QAAQ,KAAK,QAAO,IAAK,OAAO,YAAY;AAIxE,MAAI;AAEJ,MAAI,OAAO,WAAW;AACpB,gBAAY,OAAO;EACrB,OAAO;AACL,UAAM,mBAAmB,MAAM,QAAQ,MAAM,oBAAoB;AACjE,QAAI,iBAAiB,WAAW,KAAK;AACnC,YAAM,IAAI,MACR,aAAa,oBAAoB,uFACiC;IAEtE;AACA,gBAAY,MAAM,iBAAiB,KAAI;EACzC;AAEA,QAAM,gBAAgB,OAAO,iBAAiB,oBAAoB,WAAW,OAAO;AACpF,QAAM,WAAW,IAAI,UAAU,SAAS;AAIxC,MAAI,UAAsC,OAAO;AACjD,MAAI,cAA4E,CAAA;AAChF,MAAI,0BAAiD,CAAA;AAErD,QAAM,kBAAkB,MAAM,QAAQ,MAAM,qBAAqB;AACjE,MAAI,gBAAgB,WAAW,KAAK;AAClC,8BAA0B,MAAM,gBAAgB,KAAI;AACpD,QAAI,OAAO,SAAS;AAElB,gBAAU,OAAO;AACjB,iBAAW,SAAS,yBAAyB;AAC3C,YAAI,MAAM;AAAO,sBAAY,MAAM,IAAI,IAAI,MAAM;MACnD;IACF,OAAO;AACL,YAAM,WAAW,MAAM,cAAc,yBAAyB,OAAO;AACrE,gBAAU,SAAS;AACnB,oBAAc,SAAS;IACzB;EACF;AAIA,MAAI,2BAAmD,CAAA;AACvD,QAAM,mBAAmB,MAAM,QAAQ,MAAM,sBAAsB;AACnE,MAAI,iBAAiB,WAAW,KAAK;AACnC,+BAA2B,MAAM,iBAAiB,KAAI;EACxD;AAIA,MAAI,gBAAsC;AAC1C,MAAI,cAAkC;AAEtC,WAAS,kBAAe;AACtB,QAAI,QAAQ,QAAQ;AAClB,sBAAgB;AAChB,oBAAc;AACd;IACF;AAEA,oBAAgB,IAAI,cAAc,UAAU;MAC1C,YAAY,CAAC,SAAS,QAAQ,MAAM,MAAM,EAAE,IAAI,OAAM,CAAE;MACxD;MACA,GAAI,OAAO,mBAAmB,EAAE,kBAAkB,OAAO,iBAAgB,IAAK,CAAA;MAC9E,GAAI,OAAO,gBAAgB,EAAE,eAAe,OAAO,cAAa,IAAK,CAAA;MACrE,GAAI,UAAU,EAAE,QAAO,IAAK,CAAA;MAC5B;KACD;AAED,kBAAc,IAAI,YAAY,UAAU;MACtC,YAAY,CAAC,SAAS,QAAQ,MAAM,MAAM,EAAE,IAAI,OAAM,CAAE;MACxD;MACA,GAAI,OAAO,gBAAgB,EAAE,eAAe,OAAO,cAAa,IAAK,CAAA;MACrE,GAAI,UAAU,EAAE,QAAO,IAAK,CAAA;MAC5B;KACD;EACH;AAEA,kBAAe;AAIf,QAAM,QAAQ,OAAO,SAAS;AAC9B,QAAM,YAAa,QAAQ,UAAU,QAAQ,SAAU,UAAU;AACjE,MAAI,QAAQ,MAAM,aAAa,SAAS,OAAO,SAAS;AAGxD,OAAK,MAAM,QAAQ,MAAM,WAAW,GAAG,WAAW,KAAK;AACrD,YAAQ,MAAM,QAAQ,WAAW,qDAAqD;EACxF;AAIA,iBAAe,cAAc,KAAY;AACvC,UAAM,MAAM,IAAI,IAAI,IAAI,GAAG;AAC3B,UAAM,WAAW,IAAI;AAErB,UAAM,WAAW,SAAS;AAC1B,UAAM,aAAa,WAAW;AAC9B,UAAM,YAAY,UAAU;AAG5B,QACE,gBACC,SAAS,WAAW,QAAQ,KAAK,aAAa,SAC/C;AAEA,YAAM,YAAY,aAAa,SAAS,MAAM,SAAS,MAAM,OAAO,MAAM;AAC1E,UAAI,UAAU,SAAS,KAAK,UAAU,SAAS,GAAG,GAAG;AACnD,cAAM,YAAY,SAAS,UAAU,MAAM,GAAG,EAAE,KAAK,IAAI,UAAU;AACnE,eAAO,SAAS,SAAS,IAAI,IAAI,WAAW,IAAI,MAAM,GAAG,GAAG;MAC9D;AACA,UAAI;AACF,cAAM,WAAW,IAAI,IAAI,YAAY,IAAI,QAAQ,IAAI,MAAM;AAC3D,cAAM,EAAE,SAAS,QAAQ,SAAQ,IAAK,MAAM,YAAY,OAAO,UAAU,IAAI,MAAM;AACnF,YAAI,UAAU;AACZ,gBAAM,SAAS,SAAS,WAAW,GAAG,IAAI,SAAS,WAAW;AAC9D,iBAAO,SAAS,SAAS,IAAI,IAAI,QAAQ,IAAI,MAAM,GAAG,MAAM;QAC9D;AACA,eAAO,IAAI,SAAS,eAAe,SAAS,QAAQ,CAAC,QAAQ,QAAQ,CAAC,GAAG;UACvE;UACA,SAAS,EAAE,gBAAgB,mDAAkD;SAC9E;MACH,SAAS,GAAG;AACV,gBAAQ,MAAM,6BAA6B,QAAQ,KAAK,CAAC;AACzD,eAAO,IAAI,SAAS,yBAAyB,EAAE,QAAQ,IAAG,CAAE;MAC9D;IACF;AAGA,QACE,kBACC,SAAS,WAAW,UAAU,KAAK,aAAa,WACjD;AAEA,YAAM,YAAY,aAAa,WAAW,MAAM,SAAS,MAAM,SAAS,MAAM;AAC9E,UAAI,UAAU,SAAS,KAAK,UAAU,SAAS,GAAG,GAAG;AACnD,cAAM,YAAY,WAAW,UAAU,MAAM,GAAG,EAAE,KAAK,IAAI,UAAU;AACrE,eAAO,SAAS,SAAS,IAAI,IAAI,WAAW,IAAI,MAAM,GAAG,GAAG;MAC9D;AACA,UAAI;AACF,cAAM,WAAW,IAAI,IAAI,YAAY,IAAI,QAAQ,IAAI,MAAM;AAC3D,cAAM,SAAS,MAAM,cAAc,OAAO,UAAU,IAAI,MAAM;AAC9D,YAAI,OAAO,UAAU;AACnB,gBAAM,SAAS,OAAO,SAAS,WAAW,GAAG,IAAI,WAAW,OAAO,WAAW,OAAO;AACrF,iBAAO,SAAS,SAAS,IAAI,IAAI,QAAQ,IAAI,MAAM,GAAG,OAAO,MAAM;QACrE;AACA,cAAM,WAAW,OAAO,SAAS;AACjC,cAAM,OAAO,iBAAiB,OAAO,OAAO,SAAS,UAAU,QAAQ;AACvE,eAAO,IAAI,SAAS,MAAM;UACxB,QAAQ,OAAO;UACf,SAAS,EAAE,gBAAgB,2BAA0B;SACtD;MACH,SAAS,GAAG;AACV,gBAAQ,MAAM,6BAA6B,QAAQ,KAAK,CAAC;AACzD,eAAO,IAAI,SAAS,yBAAyB,EAAE,QAAQ,IAAG,CAAE;MAC9D;IACF;AAGA,QAAI,SAAS,WAAW,SAAS,KAAK,aAAa,SAAS;AAC1D,aAAO,IAAI,SAAS,OAAO;QACzB,QAAQ;QACR,SAAS,EAAE,gBAAgB,2BAA0B;OACtD;IACH;AAGA,QACE,SAAS,WAAW,UAAU,KAAK,aAAa,YAChD,SAAS,WAAW,QAAQ,KAAK,aAAa,QAC9C;AACA,aAAO,IAAI,SAAS,OAAO;QACzB,QAAQ;QACR,SAAS,EAAE,gBAAgB,2BAA0B;OACtD;IACH;AAGA,UAAM,cAAc,SAAS,MAAM,GAAG,EAAE,IAAG,KAAM;AACjD,QAAI,YAAY,SAAS,GAAG,GAAG;AAC7B,YAAM,eAAe,MAAM,QAAQ,OAAO,QAAQ;AAClD,UAAI,aAAa,WAAW;AAAK,eAAO;AACxC,aAAO;IACT;AAGA,UAAM,OAAQ,QAAQ,UAAU,QAAQ,SAAU,UAAU;AAC5D,UAAM,OAAO,aAAa,MAAM,KAAK,SAAS,MAAM,CAAC,EAAE,QAAQ,OAAO,EAAE;AACxE,WAAO,SAAS,SAAS,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,MAAM,GAAG,GAAG;EACtE;AAIA,SAAO;IACL;IACA,IAAI,aAAU;AACZ,aAAO;IACT;IACA,IAAI,WAAQ;AACV,aAAO;IACT;IACA,IAAI,YAAS;AACX,aAAO;IACT;IACA,IAAI,gBAAa;AACf,aAAO;IACT;IACA,IAAI,iBAAc;AAChB,aAAO;IACT;IACA,IAAI,QAAK;AACP,aAAO;IACT;;AAEJ;;;;;;;;;;;AC9ZM,IAAO,eAAP,cAA4B,QAAO;EACtB;;;;EAKjB,YAAY,QAAgB,SAAwB,CAAA,GAAE;AACpD,UAAM,MAAM;AACZ,SAAK,SAAS,OAAO,SAAS,GAAG,IAAI,OAAO,MAAM,GAAG,EAAE,IAAI;EAC7D;EAEA,OACE,UACA,MAAqB;AAErB,UAAM,MAAM,KAAK,MAAM,QAAQ;AAC/B,WAAO,MAAM,KAAK,IAAI;EACxB;EAUA,MACE,UACA,SAA0C;AAE1C,QAAI,SAAS,OAAO,QAAQ;AAC1B,aAAO,MAAM,KAAK,MAAM,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,KAAI,CAAE;IACzD;AACA,WAAO,KAAK,OAAO,UAAU,OAAO;EACtC;EAES,MAAM,WAAW,MAAY;AACpC,UAAM,MAAM,GAAG,KAAK,MAAM,GAAG,IAAI;AACjC,UAAM,WAAW,MAAM,MAAM,GAAG;AAChC,UAAM,KAAK,MAAM,SAAS,KAAI;AAC9B,UAAM,OAAO,IAAI,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,yBAAwB,CAAE;AAC9D,WAAO,OAAMA,kCAAC,IAAI,gBAAgB,IAAI,CAAC;EACzC;EAEQ,MAAM,UAAwB;AACpC,QAAI,OAAO,aAAa;AAAU,aAAO,GAAG,KAAK,MAAM,GAAG,QAAQ;AAClE,QAAI,oBAAoB;AAAK,aAAO,GAAG,KAAK,MAAM,GAAG,SAAS,QAAQ,GAAG,SAAS,MAAM;AACxF,WAAO,GAAG,KAAK,MAAM,GAAG,IAAI,IAAI,SAAS,GAAG,EAAE,QAAQ;EACxD;;;;ACtCI,IAAO,aAAP,MAAiB;EACJ;EACA;EACT,OAAuB;EACvB,kBAA0C;EAElD,YAAY,QAAuB,SAA2B;AAC5D,UAAM,KAAK,SAAS,YAAY;AAChC,SAAK,SAAS;AACd,SAAK,UAAU,GAAG;EACpB;EAEA,MAAM,WAAW,eAAe,eAAa;AAC3C,SAAK,OAAO,SAAS,cAAc,YAAY;AAE/C,QAAI,CAAC,KAAK,MAAM;AACd,cAAQ,MAAM,gCAAgC,YAAY;AAC1D;IACF;AAEA,QAAI,EAAE,gBAAgB,aAAa;AACjC,cAAQ,KAAK,2CAA2C;AACxD;IACF;AAEA,SAAK,kBAAkB,IAAI,gBAAe;AAC1C,UAAM,EAAE,OAAM,IAAK,KAAK;AAExB,eAAW,iBAAiB,YAAY,CAAC,UAAS;AAChD,UAAI,CAAC,MAAM;AAAc;AACzB,UAAI,MAAM;AAAY;AACtB,UAAI,MAAM,oBAAoB;AAAM;AAEpC,YAAM,MAAM,IAAI,IAAI,MAAM,YAAY,GAAG;AACzC,UAAI,CAAC,KAAK,UAAU,IAAI,QAAQ;AAAG;AAEnC,YAAM,UAAU;QACd,QAAQ;QACR,SAAS,YAAW;AAClB,gBAAM,KAAK,iBAAiB,KAAK,MAAM,MAAM;AAC7C,gBAAM,OAAM;QACd;OACD;IACH,GAAG,EAAE,OAAM,CAAE;AAGb,UAAM,WAAW,KAAK,KAAK,aAAa,gBAAgB;AACxD,QAAI,aAAa,SAAS,aAAa,YAAY,SAAS,aAAa,WAAW,MAAM;AACxF,WAAK,KAAK,gBAAgB,gBAAgB;AAC1C;IACF;AAGA,UAAM,KAAK,iBAAiB,IAAI,IAAI,SAAS,IAAI,GAAG,KAAK,gBAAgB,MAAM;EACjF;EAEA,UAAO;AACL,SAAK,iBAAiB,MAAK;AAC3B,SAAK,kBAAkB;AACvB,SAAK,OAAO;EACd;EAEA,MAAM,SAAS,KAAa,UAA2B,CAAA,GAAE;AACvD,QAAI;AACF,YAAM,EAAE,SAAQ,IAAK,WAAW,SAAS,KAAK;QAC5C,OAAO,QAAQ;QACf,SAAS,QAAQ,UAAU,YAAY;OACxC;AACD,YAAM;IACR,SAAS,GAAG;AACV,UAAI,aAAa,gBAAgB,EAAE,SAAS;AAAc;AAC1D,YAAM;IACR;EACF;EAEQ,UAAU,UAAgB;AAChC,WAAO,aAAa,KAAK,WAAW,SAAS,WAAW,KAAK,UAAU,GAAG;EAC5E;EAEQ,aAAa,UAAgB;AACnC,QAAI,aAAa,KAAK;AAAS,aAAO;AACtC,QAAI,SAAS,WAAW,KAAK,UAAU,GAAG;AAAG,aAAO,SAAS,MAAM,KAAK,QAAQ,MAAM;AACtF,WAAO;EACT;EAEQ,MAAM,iBAAiB,KAAU,QAAmB;AAC1D,QAAI,CAAC,KAAK,QAAQ,CAAC,KAAK,OAAO;AAAY;AAE3C,UAAM,YAAY,KAAK,aAAa,IAAI,QAAQ;AAChD,UAAM,WAAW,IAAI,IAAI,YAAY,IAAI,QAAQ,IAAI,MAAM;AAE3D,QAAI;AACF,YAAM,EAAE,SAAS,OAAO,SAAQ,IAAK,MAAM,KAAK,OAAO,WAAW,OAAO,UAAU,MAAM;AAEzF,UAAI,OAAO;AAAS;AAEpB,UAAI,UAAU;AACZ,2BAAmB,QAAQ;AAC3B,cAAM,SAAS,SAAS,WAAW,GAAG,IAAI,KAAK,UAAU,WAAW;AACpE,mBAAW,SAAS,QAAQ,EAAE,SAAS,UAAS,CAAE;AAClD;MACF;AAEA,UAAI,SAAS,qBAAqB;AAChC,cAAM,aAAa,SAAS,oBAAoB,MAAK;AACnD,eAAK,KAAM,cAAc,OAAO;QAClC,CAAC;AACD,eAAO,iBAAiB,SAAS,MAAM,WAAW,eAAc,GAAI,EAAE,MAAM,KAAI,CAAE;AAClF,cAAM,WAAW;MACnB,OAAO;AACL,aAAK,KAAK,cAAc,OAAO;MACjC;AAEA,UAAI;AAAO,iBAAS,QAAQ;IAC9B,SAAS,OAAO;AACd,UAAI,OAAO;AAAS;AACpB,cAAQ,MAAM,kCAAkC,KAAK;AACrD,UAAI,KAAK,MAAM;AACb,cAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,aAAK,KAAK,cAAc,oBAAoB,WAAW,OAAO,CAAC,MAAM;MACvE;IACF;EACF;;AAQF,eAAsB,iBACpB,QACA,SAA2B;AAE3B,QAAM,IAAI;AACV,MAAI,EAAE,eAAe;AACnB,YAAQ,KAAK,mCAAmC;AAChD,WAAO,EAAE;EACX;AACA,QAAM,MAAM,IAAI,WAAW,QAAQ,OAAO;AAC1C,QAAM,IAAI,WAAU;AACpB,IAAE,gBAAgB;AAClB,SAAO;AACT;AAoBA,eAAsB,eAAe,SAAqB;AACxD,QAAM,SAAS,SAAS,UAAU,SAAS;AAC3C,QAAM,UAAU,IAAI,aAAa,MAAM;AAGvC,QAAM,iBAAiB,MAAM,QAAQ,OAAO,oBAAoB;AAChE,MAAI,CAAC,eAAe,IAAI;AACtB,UAAM,IAAI,MAAM,6BAA6B,oBAAoB,KAAK,eAAe,MAAM,EAAE;EAC/F;AACA,QAAM,YAAuB,MAAM,eAAe,KAAI;AAGtD,QAAM,kBAAkB,MAAM,QAAQ,OAAO,qBAAqB;AAClE,QAAM,gBAAuC,gBAAgB,KACzD,MAAM,gBAAgB,KAAI,IAC1B,CAAA;AAGJ,QAAM,mBAAmB,MAAM,QAAQ,OAAO,sBAAsB;AACpE,QAAM,iBAAyC,iBAAiB,KAC5D,MAAM,iBAAiB,KAAI,IAC3B,CAAA;AAGJ,QAAM,gBAAgB,iBAAiB,WAAW,eAAe,gBAAgB,OAAO;AAGxF,QAAM,UAAU,IAAI,eAAc;AAClC,aAAW,SAAS,eAAe;AACjC,qBAAiB,aAAa,MAAM,MAAM,MAAM,OAAO,cAAc,MAAM,UAAU,CAAC;EACxF;AAGA,aAAW,SAAS,gBAAgB;AAClC,UAAM,SAAS,cAAc,MAAM,UAAU;AAC7C,QAAI,QAAQ;AACV,aAAM,EAAG,KAAK,CAAC,QAAO;AACpB,cAAM,MAAO,IAAgC;AAC7C,YAAI,OAAO,QAAQ,cAAc,CAAC,eAAe,IAAI,MAAM,OAAO,GAAG;AACnE,yBAAe,OAAO,MAAM,SAAS,GAA+B;QACtE;MACF,CAAC,EAAE,MAAM,CAAC,MAAK;AACb,gBAAQ,MAAM,oCAAoC,MAAM,OAAO,KAAK,CAAC;MACvE,CAAC;IACH;EACF;AAGA,QAAM,aAAa,gBAAgB,sBAAqB;AACxD,QAAM,SAAS,MAAM,oBAAoB;IACvC;IACA;IACA;IACA,GAAI,aAAa,EAAE,kBAAkB,WAAU,IAAK,CAAA;KACnD,OAAO;AAEV,SAAO,iBAAiB,QAAQ,OAAO;AACzC;AAMA,SAAS,iBACP,MACA,eACA,gBACA,SAAqB;AAErB,QAAM,QAAQ,oBAAI,IAAG;AAErB,WAAS,KAAK,MAAe;AAC3B,UAAM,aAAa,KAAK,OAAO,MAAM,KAAK,OAAO;AACjD,QAAI;AAAY,YAAM,IAAI,UAAU;AACpC,QAAI,KAAK;AAAU,YAAM,IAAI,KAAK,QAAQ;AAC1C,QAAI,KAAK;AAAe,YAAM,IAAI,KAAK,aAAa;AACpD,QAAI,KAAK,UAAU;AACjB,iBAAW,SAAS,OAAO,OAAO,KAAK,QAAQ;AAAG,aAAK,KAAK;IAC9D;AACA,QAAI,KAAK;AAAS,WAAK,KAAK,QAAQ,KAAK;AACzC,QAAI,KAAK;AAAU,WAAK,KAAK,SAAS,KAAK;EAC7C;AAEA,OAAK,IAAI;AACT,aAAW,SAAS;AAAe,UAAM,IAAI,MAAM,UAAU;AAC7D,aAAW,SAAS;AAAgB,UAAM,IAAI,MAAM,UAAU;AAE9D,QAAM,UAAkD,CAAA;AACxD,aAAW,QAAQ,OAAO;AACxB,UAAM,WAAW,KAAK,WAAW,GAAG,IAAI,OAAO,MAAM;AACrD,YAAQ,IAAI,IAAI,MAAM,QAAQ,WAAW,QAAQ;EACnD;AACA,SAAO;AACT;;;AC7QM,IAAgB,kBAAhB,cAII,UAAmC;;;;;;;;;;;;;;;;EAgBlC,WACP,MAAwB;AAExB,UAAM,QAAQ,KAAK,QAAQ;AAE3B,UAAM,QAAQ,OAAO,MAAM,UAAU,eAAe,MAAM,KAAK,KAAK,IAAI,CAAC;IAAe;AAExF,QAAI,OAAO,MAAM;AACf,aAAO,QAAQ,MAAM;IACvB;AAEA,QAAI,OAAO,IAAI;AACb,aAAO,GAAG,KAAK,cAAc,WAAW,MAAM,EAAE,CAAC;IACnD;AAEA,QAAI,OAAO;AACT,aAAO,QAAQ,MAAM,WAAW,IAAI;IACtC;AAEA,WAAO,MAAM,WAAW,IAAI;EAC9B;;;;;;;;;;;;;;;EAgBS,eACP,MAAwB;AAExB,UAAM,QAAQ,KAAK,QAAQ;AAE3B,QAAI,OAAO,IAAI;AACb,aAAO,MAAM;IACf;AAEA,WAAO;EACT;;;;AC3EK,IAAM;;EAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACQ5C,IAAM,2BAA2B;AAOjC,SAAS,eAAe,IAAiB,QAAkB;AACzD,KAAG,aAAa,mBAAmB,EAAE;AAErC,MAAI,OAAO;AACX,QAAM,SAAS,MAAK;AAClB,QAAI;AAAM;AACV,WAAO;AACP,WAAM;EACR;AAEA,KAAG,iBAAiB,iBAAiB,QAAQ,EAAE,MAAM,KAAI,CAAE;AAC3D,aAAW,QAAQ,wBAAwB;AAC7C;AAEM,SAAU,uBAAoB;AAClC,MAAI,gBAAgB;AAGpB,MAAI,SAAmC;AAOvC,MAAI,eAA8C;AAClD,MAAI;AAGJ,MAAI,iBAAwC;AAG5C,MAAI,YAAmC;AACvC,MAAI,wBAAiD;AACrD,QAAM,iBAAiB,OAAO,QAAQ,eACpC,IAAI,SAAS,eAAe,KAAK;AAEnC,WAAS,YAAS;AAChB,QAAI;AAAe;AACnB,oBAAgB;AAChB,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,cAAc;AACpB,aAAS,KAAK,YAAY,KAAK;EACjC;AAEA,WAAS,eAAY;AACnB,QAAI;AAAQ,aAAO;AACnB,cAAS;AACT,aAAS,SAAS,cAAc,QAAQ;AACxC,WAAO,aAAa,sBAAsB,EAAE;AAC5C,aAAS,KAAK,YAAY,MAAM;AAEhC,WAAO,iBAAiB,SAAS,CAAC,MAAK;AACrC,UAAI,EAAE,WAAW,QAAQ;AACvB,mBAAW,MAAS;MACtB;IACF,CAAC;AAED,WAAO;EACT;AAEA,WAAS,uBAAoB;AAC3B,QAAI;AAAgB,aAAO;AAC3B,cAAS;AACT,qBAAiB,SAAS,cAAc,KAAK;AAC7C,mBAAe,aAAa,gCAAgC,EAAE;AAC9D,aAAS,KAAK,YAAY,cAAc;AACxC,WAAO;EACT;AAEA,WAAS,gBAAa;AACpB,QAAI;AAAW,aAAO;AACtB,cAAS;AACT,gBAAY,SAAS,cAAc,KAAK;AACxC,cAAU,aAAa,wBAAwB,EAAE;AACjD,cAAU,aAAa,WAAW,EAAE;AACpC,aAAS,KAAK,YAAY,SAAS;AACnC,WAAO;EACT;AAIA,WAAS,MAAqB,SAAwB;AACpD,UAAM,IAAI,aAAY;AAGtB,MAAE,gBAAgB,iBAAiB;AAGnC,yBAAoB;AAGpB,QAAI,EAAE,MAAM;AACV,QAAE,MAAK;AACP,UAAI,cAAc;AAChB,qBAAa,MAAS;AACtB,uBAAe;MACjB;AACA,UAAI,cAAc;AAChB,qBAAY;AACZ,uBAAe;MACjB;IACF;AAEA,MAAE,YAAY;AACd,YAAQ,OAAO,CAAC;AAChB,mBAAe,QAAQ;AAEvB,UAAM,EAAE,SAAS,QAAO,IAAK,QAAQ,cAAa;AAClD,mBAAe;AAEf,MAAE,UAAS;AAEX,WAAO;EACT;AAEA,WAAS,WAAc,OAAS;AAC9B,QAAI,CAAC,UAAU,CAAC,OAAO;AAAM;AAE7B,UAAM,UAAU;AAChB,UAAM,UAAU;AAChB,UAAM,YAAY;AAClB,mBAAe;AACf,mBAAe;AAEf,mBAAe,WAAW,MAAK;AAC7B,UAAI,aAAa,UAAU,MAAM;AAC/B,kBAAU,MAAK;AACf,YAAI;AAAS,kBAAQ,KAAK;AAC1B,YAAI;AAAS,kBAAO;MACtB;IACF,CAAC;EACH;AAKA,WAAS,gBAAgB,WAAyB;AAChD,eAAW,SAAS,CAAC,GAAG,UAAU,QAAQ,GAAG;AAC3C,YAAM,KAAK;AACX,UAAI,GAAG,aAAa,iBAAiB,GAAG;AACtC,WAAG,OAAM;MACX;IACF;EACF;AAEA,WAAS,MAAM,SAAqB;AAClC,UAAM,YAAY,qBAAoB;AAGtC,oBAAgB,SAAS;AAEzB,UAAM,KAAK,SAAS,cAAc,KAAK;AACvC,OAAG,aAAa,sBAAsB,EAAE;AAExC,UAAM,UAAU,QAAQ,WAAW;AACnC,QAAI,YAAY,GAAG;AACjB,SAAG,aAAa,qBAAqB,EAAE;IACzC,OAAO;AACL,SAAG,MAAM,YAAY,4BAA4B,GAAG,OAAO,IAAI;IACjE;AAEA,YAAQ,OAAO,EAAE;AACjB,cAAU,YAAY,EAAE;AAExB,QAAI,YAAY;AAChB,UAAM,UAAU,MAAK;AACnB,UAAI;AAAW;AACf,kBAAY;AACZ,SAAG,aAAa,mBAAmB,EAAE;IACvC;AAEA,WAAO,EAAE,QAAO;EAClB;AAIA,WAAS,QAAQ,SAAuB;AACtC,UAAM,KAAK,cAAa;AAGxB,iCAA4B;AAC5B,QAAI;AACF,SAAG,YAAW;IAChB,QAAQ;IAER;AACA,OAAG,gBAAgB,iBAAiB;AAEpC,OAAG,YAAY;AACf,YAAQ,OAAO,EAAE;AAGjB,QAAI,gBAAgB;AAClB,YAAM,aAAa;AACnB,cAAQ,OAAO,MAAM,YAAY,eAAe,UAAU;AAC1D,SAAG,MAAM,YAAY,mBAAmB,UAAU;AAClD,SAAG,MAAM,eAAe,KAAK;AAC7B,SAAG,MAAM,eAAe,MAAM;IAChC,OAAO;AACL,YAAM,OAAO,QAAQ,OAAO,sBAAqB;AACjD,SAAG,MAAM,MAAM,GAAG,KAAK,SAAS,WAAW,OAAO;AAClD,SAAG,MAAM,OAAO,GAAG,KAAK,OAAO,WAAW,OAAO;AACjD,SAAG,MAAM,WAAW;IACtB;AAEA,OAAG,YAAW;AAGd,0BAAsB,QAAQ,MAAM;EACtC;AAEA,WAAS,sBAAsB,QAAmB;AAChD,iCAA4B;AAE5B,UAAM,SAAS,OAAO;AACtB,QAAI,CAAC,QAAQ;AACX,mBAAY;AACZ;IACF;AAEA,4BAAwB,IAAI,iBAAiB,MAAK;AAChD,UAAI,CAAC,SAAS,SAAS,MAAM,GAAG;AAC9B,qBAAY;MACd;IACF,CAAC;AAED,0BAAsB,QAAQ,QAAQ,EAAE,WAAW,KAAI,CAAE;EAC3D;AAGA,WAAS,uBAAoB;AAC3B,iCAA4B;AAC5B,QAAI,CAAC;AAAW;AAChB,QAAI;AACF,gBAAU,YAAW;IACvB,QAAQ;IAER;AACA,cAAU,gBAAgB,iBAAiB;EAC7C;AAEA,WAAS,+BAA4B;AACnC,QAAI,uBAAuB;AACzB,4BAAsB,WAAU;AAChC,8BAAwB;IAC1B;EACF;AAEA,WAAS,eAAY;AACnB,iCAA4B;AAE5B,QAAI,CAAC;AAAW;AAGhB,QAAI;AACJ,QAAI;AACF,eAAS,UAAU,QAAQ,eAAe;IAC5C,QAAQ;AAEN,eAAS,UAAU,aAAa,SAAS,KAAK,UAAU,MAAM,YAAY;IAC5E;AAEA,QAAI,CAAC;AAAQ;AAEb,mBAAe,WAAW,MAAK;AAC7B,UAAI;AACF,kBAAW,YAAW;MACxB,QAAQ;MAER;IACF,CAAC;EACH;AAIA,WAAS,aAAU;AAEjB,QAAI,UAAU,OAAO,MAAM;AACzB,YAAM,UAAU;AAChB,YAAM,UAAU;AAChB,qBAAe;AACf,qBAAe;AAEf,aAAO,gBAAgB,iBAAiB;AACxC,aAAO,MAAK;AAEZ,UAAI;AAAS,gBAAQ,MAAS;AAC9B,UAAI;AAAS,gBAAO;IACtB;AAGA,yBAAoB;AAGpB,QAAI,gBAAgB;AAClB,iBAAW,SAAS,eAAe,UAAU;AAC1C,cAAsB,aAAa,mBAAmB,EAAE;MAC3D;IACF;AAGA,QAAI;AACF,iBAAW,MAAM,SAAS,iBAAiB,eAAe,GAAG;AAC1D,WAAmB,YAAW;MACjC;IACF,QAAQ;IAER;AAGA,eAAW,MAAM,SAAS,iBAAoC,cAAc,GAAG;AAC7E,UAAI,OAAO;AAAQ,WAAG,MAAK;IAC7B;EACF;AAEA,SAAO;IACL;IACA;IACA;IACA;IACA;IACA;;AAEJ;;;ACvUM,IAAO,kBAAP,cAA+B,gBAA+C;EAChE,OAAO;EAEhB,QACP,MAAuD;AAEvD,WAAO,QAAQ,QAAQ,EAAE,OAAO,KAAK,OAAO,MAAK,CAAE;EACrD;EAES,WACP,MAA6D;AAE7D,UAAM,QAAQ,KAAK,MAAM,SAAS,KAAK,OAAO;AAC9C,QAAI,SAAS,OAAO,aAAa,aAAa;AAC5C,eAAS,QAAQ;IACnB;AACA,WAAO;EACT;EAES,eACP,OAA8D;AAE9D,WAAO;EACT;EAES,eAAe,QAAuB;AAC7C,QAAI,CAAC,OAAO,SAAS,OAAO,OAAO,UAAU,UAAU;AACrD,aAAO;IACT;AACA,WAAO;EACT;;;;AC9BF,IAAM,yBAAyB;AAC/B,IAAM,uBAAuB;AAgBvB,IAAO,mBAAP,cAAgC,gBAAiD;EACnE,OAAO;EAEhB,QACP,MAAmF;AAEnF,UAAM,WAAW,KAAK,QAAQ,YAAY;AAC1C,UAAM,QAAQ,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO;AAEhD,UAAM,WAAgC;MACpC,EAAE,OAAO,QAAQ,MAAM,IAAG;;AAG5B,QAAI,cAAc;AAClB,eAAW,QAAQ,OAAO;AACxB,qBAAe,MAAM;AACrB,eAAS,KAAK;QACZ,OAAO,KAAK,OAAO,CAAC,EAAE,YAAW,IAAK,KAAK,MAAM,CAAC,EAAE,QAAQ,MAAM,GAAG;QACrE,MAAM;OACP;IACH;AAEA,WAAO,QAAQ,QAAQ,EAAE,SAAQ,CAAE;EACrC;EAES,WACP,MAA0F;AAE1F,QAAI,CAAC,KAAK,QAAQ,KAAK,KAAK,SAAS,WAAW;AAAG,aAAO;AAE1D,UAAM,MAAM,KAAK,OAAO,aAAa;AACrC,UAAM,WAAW,KAAK,KAAK;AAE3B,UAAM,QAAQ,SAAS,IAAI,CAAC,KAAK,MAAK;AACpC,YAAM,UAAU,WAAW,IAAI,KAAK;AACpC,UAAI,MAAM,SAAS,SAAS,GAAG;AAC7B,eAAO,6BAA6B,OAAO;MAC7C;AACA,aAAO,YAAY,WAAW,IAAI,IAAI,CAAC,KAAK,OAAO;IACrD,CAAC;AAED,WAAO,gCAAgC,MAAM,KAAK,WAAW,GAAG,CAAC,CAAC;EACpE;EAES,eACP,MAA0F;AAE1F,QAAI,CAAC,KAAK,QAAQ,KAAK,KAAK,SAAS,WAAW;AAAG,aAAO;AAE1D,UAAM,MAAM,KAAK,OAAO,aAAa;AACrC,WAAO,KAAK,KAAK,SACd,IAAI,CAAC,KAAK,GAAG,QACZ,MAAM,IAAI,SAAS,IAAI,KAAK,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,GAAG,EAE1E,KAAK,GAAG;EACb;;;;ACrCF,IAAI,WAAW,gBAAgB;AAC7B,MAAI,CAAC,eAAe,IAAI,aAAa;AAAG,mBAAe,OAAO,eAAe,UAAU;AACvF,MAAI,CAAC,eAAe,IAAI,WAAW;AAAG,mBAAe,OAAO,aAAa,eAAe;AAC1F;",
6
6
  "names": ["__rewriteRelativeImportExtension"]
7
7
  }