veryfront 0.1.992 → 0.1.994

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 (40) hide show
  1. package/esm/deno.js +3 -3
  2. package/esm/src/build/production-build/templates.d.ts.map +1 -1
  3. package/esm/src/build/production-build/templates.js +1 -1
  4. package/esm/src/html/html-injection.d.ts +7 -0
  5. package/esm/src/html/html-injection.d.ts.map +1 -1
  6. package/esm/src/html/html-injection.js +7 -1
  7. package/esm/src/html/hydration-script-builder/templates/renderer.d.ts.map +1 -1
  8. package/esm/src/html/hydration-script-builder/templates/renderer.js +6 -2
  9. package/esm/src/html/hydration-script-builder/templates/router.d.ts.map +1 -1
  10. package/esm/src/html/hydration-script-builder/templates/router.js +49 -8
  11. package/esm/src/react/runtime/core.d.ts +57 -5
  12. package/esm/src/react/runtime/core.d.ts.map +1 -1
  13. package/esm/src/react/runtime/core.js +168 -6
  14. package/esm/src/rendering/layouts/layout-applicator.d.ts.map +1 -1
  15. package/esm/src/rendering/layouts/layout-applicator.js +2 -5
  16. package/esm/src/rendering/orchestrator/html.d.ts.map +1 -1
  17. package/esm/src/rendering/orchestrator/html.js +1 -0
  18. package/esm/src/rendering/page-rendering.d.ts.map +1 -1
  19. package/esm/src/rendering/page-rendering.js +2 -5
  20. package/esm/src/rendering/rsc/client-boot.ts +5 -1
  21. package/esm/src/rendering/rsc/client-module-strategy.d.ts +14 -0
  22. package/esm/src/rendering/rsc/client-module-strategy.d.ts.map +1 -1
  23. package/esm/src/rendering/rsc/client-module-strategy.js +11 -0
  24. package/esm/src/rendering/rsc/hydrate-client.ts +9 -2
  25. package/esm/src/rendering/script-page-handling.d.ts.map +1 -1
  26. package/esm/src/rendering/script-page-handling.js +2 -5
  27. package/esm/src/routing/api/context-builder.d.ts +4 -0
  28. package/esm/src/routing/api/context-builder.d.ts.map +1 -1
  29. package/esm/src/routing/api/context-builder.js +6 -5
  30. package/esm/src/routing/flatten-route-params.d.ts +11 -0
  31. package/esm/src/routing/flatten-route-params.d.ts.map +1 -0
  32. package/esm/src/routing/flatten-route-params.js +20 -0
  33. package/esm/src/routing/index.d.ts +1 -0
  34. package/esm/src/routing/index.d.ts.map +1 -1
  35. package/esm/src/routing/index.js +1 -0
  36. package/esm/src/server/services/rsc/endpoints/rsc-bundles.generated.d.ts.map +1 -1
  37. package/esm/src/server/services/rsc/endpoints/rsc-bundles.generated.js +1 -1
  38. package/esm/src/utils/version-constant.d.ts +1 -1
  39. package/esm/src/utils/version-constant.js +1 -1
  40. package/package.json +1 -1
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.992",
3
+ "version": "0.1.994",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "minimumDependencyAge": {
@@ -393,12 +393,12 @@ export default {
393
393
  "build:npm": "deno run -A scripts/build/generate-integrations-module.ts && deno task generate && deno run -A scripts/build/build-npm-dnt.ts",
394
394
  "release": "deno run -A scripts/release.ts",
395
395
  "test": "deno task generate && VF_DISABLE_LRU_INTERVAL=1 SSR_TRANSFORM_PER_PROJECT_LIMIT=0 REVALIDATION_PER_PROJECT_LIMIT=0 NODE_ENV=production LOG_FORMAT=text deno test --preload=src/schemas/_test-setup.ts --no-check --parallel --allow-all '--ignore=tests/e2e,tests/integration/compiled-binary-e2e.test.ts' --unstable-worker-options --unstable-net",
396
- "test:unit": "deno task generate && VF_DISABLE_LRU_INTERVAL=1 SSR_TRANSFORM_PER_PROJECT_LIMIT=0 REVALIDATION_PER_PROJECT_LIMIT=0 NODE_ENV=production LOG_FORMAT=text deno test --preload=src/schemas/_test-setup.ts --no-check --parallel --allow-all --v8-flags=--max-old-space-size=8192 '--ignore=tests,src/workflow/__tests__' --unstable-worker-options --unstable-net $(find src cli -name '*.test.ts' ! -name '*.integration.test.ts')",
396
+ "test:unit": "deno task generate && VF_DISABLE_LRU_INTERVAL=1 SSR_TRANSFORM_PER_PROJECT_LIMIT=0 REVALIDATION_PER_PROJECT_LIMIT=0 NODE_ENV=production LOG_FORMAT=text deno test --preload=src/schemas/_test-setup.ts --no-check --parallel --allow-all --v8-flags=--max-old-space-size=8192 '--ignore=tests,src/workflow/__tests__' --unstable-worker-options --unstable-net $(find src cli -name '*.test.ts*' ! -name '*.integration.test.ts*')",
397
397
  "test:integration": "deno task generate && VF_DISABLE_LRU_INTERVAL=1 SSR_TRANSFORM_PER_PROJECT_LIMIT=0 REVALIDATION_PER_PROJECT_LIMIT=0 NODE_ENV=production LOG_FORMAT=text deno test --preload=src/schemas/_test-setup.ts --no-check --parallel --allow-all '--ignore=tests/e2e,tests/integration/compiled-binary-e2e.test.ts' tests --unstable-worker-options --unstable-net",
398
398
  "test:integration:cli": "VF_DISABLE_LRU_INTERVAL=1 SSR_TRANSFORM_PER_PROJECT_LIMIT=0 REVALIDATION_PER_PROJECT_LIMIT=0 NODE_ENV=production LOG_FORMAT=text deno test --no-check --parallel --allow-all --unstable-worker-options --unstable-net $(find cli -name '*.integration.test.ts')",
399
399
  "test:record": "VCR=record deno test --no-check --allow-all $(find cli -name '*.integration.test.ts' -path '*/commands/*')",
400
400
  "test:coverage": "rm -rf coverage && deno task generate && VF_DISABLE_LRU_INTERVAL=1 SSR_TRANSFORM_PER_PROJECT_LIMIT=0 REVALIDATION_PER_PROJECT_LIMIT=0 NODE_ENV=production LOG_FORMAT=text deno test --preload=src/schemas/_test-setup.ts --no-check --parallel --fail-fast --allow-all --v8-flags=--max-old-space-size=8192 --coverage=coverage '--ignore=tests/integration/compiled-binary-e2e.test.ts' --unstable-worker-options --unstable-net || exit 1",
401
- "test:coverage:unit": "rm -rf coverage && deno task generate && VF_DISABLE_LRU_INTERVAL=1 SSR_TRANSFORM_PER_PROJECT_LIMIT=0 REVALIDATION_PER_PROJECT_LIMIT=0 NODE_ENV=production LOG_FORMAT=text deno test --preload=src/schemas/_test-setup.ts --no-check --parallel --fail-fast --allow-all --v8-flags=--max-old-space-size=8192 --coverage=coverage '--ignore=tests,src/workflow/__tests__' --unstable-worker-options --unstable-net $(find src cli -name '*.test.ts' ! -name '*.integration.test.ts') || exit 1",
401
+ "test:coverage:unit": "rm -rf coverage && deno task generate && VF_DISABLE_LRU_INTERVAL=1 SSR_TRANSFORM_PER_PROJECT_LIMIT=0 REVALIDATION_PER_PROJECT_LIMIT=0 NODE_ENV=production LOG_FORMAT=text deno test --preload=src/schemas/_test-setup.ts --no-check --parallel --fail-fast --allow-all --v8-flags=--max-old-space-size=8192 --coverage=coverage '--ignore=tests,src/workflow/__tests__' --unstable-worker-options --unstable-net $(find src cli -name '*.test.ts*' ! -name '*.integration.test.ts*') || exit 1",
402
402
  "test:coverage:integration": "rm -rf coverage && deno task generate && VF_DISABLE_LRU_INTERVAL=1 SSR_TRANSFORM_PER_PROJECT_LIMIT=0 REVALIDATION_PER_PROJECT_LIMIT=0 NODE_ENV=production LOG_FORMAT=text deno test --preload=src/schemas/_test-setup.ts --no-check --parallel --fail-fast --allow-all --v8-flags=--max-old-space-size=8192 --coverage=coverage '--ignore=tests/e2e,tests/integration/compiled-binary-e2e.test.ts' tests --unstable-worker-options --unstable-net || exit 1",
403
403
  "coverage:report": "deno coverage coverage --include=src/ --exclude=tests '--exclude=src/**/*_test.ts' '--exclude=src/**/*_test.tsx' '--exclude=src/**/*.test.ts' '--exclude=src/**/*.test.tsx' --lcov > coverage/lcov.info && deno run --allow-read scripts/lint/check-coverage.ts 80",
404
404
  "coverage:gate": "deno coverage coverage --include=src/ --exclude=tests '--exclude=src/**/*_test.ts' '--exclude=src/**/*_test.tsx' '--exclude=src/**/*.test.ts' '--exclude=src/**/*.test.tsx' --lcov > coverage/lcov.info && deno run --allow-read scripts/lint/check-coverage.ts 68",
@@ -1 +1 @@
1
- {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../../../src/src/build/production-build/templates.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,eAAO,MAAM,aAAa,8KACmJ,CAAC;AAE9K,eAAO,MAAM,oBAAoB,EAAE,MAAM,GAAG,SACky2B,CAAC;AAE/02B,eAAO,MAAM,sBAAsB,EAAE,MAAM,GAAG,SAC630B,CAAC"}
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../../../src/src/build/production-build/templates.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,eAAO,MAAM,aAAa,8KACmJ,CAAC;AAE9K,eAAO,MAAM,oBAAoB,EAAE,MAAM,GAAG,SAC8z8B,CAAC;AAE328B,eAAO,MAAM,sBAAsB,EAAE,MAAM,GAAG,SAC630B,CAAC"}
@@ -7,5 +7,5 @@
7
7
  * @module
8
8
  */
9
9
  export const CLIENT_STYLES = ".error-container {\n max-width: 600px;\n margin: 2rem auto;\n padding: 2rem;\n background: #fee;\n border: 1px solid #fcc;\n border-radius: 8px;\n color: #c00;\n}";
10
- export const CLIENT_ROUTER_BUNDLE = 'var __defProp = Object.defineProperty;\nvar __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;\nvar __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);\n\n// src/rendering/client/browser-stubs/logger.ts\nfunction noop() {\n}\nvar logger = {\n debug: noop,\n info: console.log.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n component: () => logger\n};\nvar rendererLogger = logger;\nvar PREFETCH_MAX_SIZE_BYTES = 200 * 1024;\n\n// src/rendering/client/router.ts\nimport ReactDOM from "react-dom/client";\n\n// src/routing/client/dom-utils.ts\nvar logger2 = rendererLogger.component("veryfront");\nfunction isInternalLink(target) {\n const href = target.getAttribute("href");\n if (!href) return false;\n if (href.startsWith("http") || href.startsWith("mailto:") || href.startsWith("#")) return false;\n const linkTarget = target.getAttribute("target");\n if (linkTarget === "_blank" || target.hasAttribute("download")) return false;\n return true;\n}\nfunction findAnchorElement(element) {\n let current = element;\n while (current && current.tagName !== "A") {\n current = current.parentElement;\n }\n return current instanceof HTMLAnchorElement ? current : null;\n}\nfunction updateMetaTags(frontmatter) {\n if (frontmatter.description) {\n updateMetaTag(\'meta[name="description"]\', "name", "description", frontmatter.description);\n }\n if (frontmatter.ogTitle) {\n updateMetaTag(\'meta[property="og:title"]\', "property", "og:title", frontmatter.ogTitle);\n }\n}\nfunction updateMetaTag(selector, attributeName, attributeValue, content) {\n let metaTag = document.querySelector(selector);\n if (!metaTag) {\n metaTag = document.createElement("meta");\n metaTag.setAttribute(attributeName, attributeValue);\n document.head.appendChild(metaTag);\n }\n metaTag.setAttribute("content", content);\n}\nfunction executeScripts(container) {\n for (const oldScript of container.querySelectorAll("script")) {\n const newScript = document.createElement("script");\n for (const { name, value } of oldScript.attributes) {\n newScript.setAttribute(name, value);\n }\n newScript.textContent = oldScript.textContent;\n oldScript.parentNode?.replaceChild(newScript, oldScript);\n }\n}\nfunction applyHeadDirectives(container) {\n const nodes = container.querySelectorAll(\'[data-veryfront-head="1"], vf-head\');\n if (!nodes.length) return;\n cleanManagedHeadTags();\n for (const wrapper of nodes) {\n const contentSource = typeof HTMLTemplateElement !== "undefined" && wrapper instanceof HTMLTemplateElement ? wrapper.content : wrapper;\n processHeadWrapper(contentSource);\n wrapper.parentElement?.removeChild(wrapper);\n }\n}\nfunction cleanManagedHeadTags() {\n for (const element of document.head.querySelectorAll(\'[data-veryfront-managed="1"]\')) {\n element.parentElement?.removeChild(element);\n }\n}\nfunction processHeadWrapper(wrapper) {\n for (const node of wrapper.childNodes) {\n if (!(node instanceof Element)) continue;\n const tagName = node.tagName.toLowerCase();\n if (tagName === "title") {\n document.title = node.textContent || document.title;\n continue;\n }\n const clone = document.createElement(tagName);\n for (const { name, value } of node.attributes) {\n clone.setAttribute(name, value);\n }\n if (node.textContent && !clone.hasAttribute("src")) {\n clone.textContent = node.textContent;\n }\n clone.setAttribute("data-veryfront-managed", "1");\n document.head.appendChild(clone);\n }\n}\nfunction manageFocus(container) {\n try {\n const focusElement = container.querySelector("[data-router-focus]") || container.querySelector("main") || container.querySelector("h1");\n focusElement?.focus?.({ preventScroll: true });\n } catch (error) {\n logger2.warn("focus management failed", error);\n }\n}\nfunction extractPageDataFromScript() {\n const pageDataScript = document.querySelector("script[data-veryfront-page]");\n if (!pageDataScript) return null;\n try {\n const content = pageDataScript.textContent;\n if (!content) {\n logger2.warn("Page data script has no content");\n return {};\n }\n return JSON.parse(content);\n } catch (error) {\n logger2.error("Failed to parse page data:", error);\n return null;\n }\n}\nfunction parsePageDataFromHTML(html) {\n const doc = new DOMParser().parseFromString(html, "text/html");\n const root = doc.getElementById("root");\n if (!root) logger2.warn("[Veryfront] No root element found in HTML");\n const content = root?.innerHTML ?? "";\n const pageDataScript = doc.querySelector("script[data-veryfront-page]");\n let pageData = {};\n if (pageDataScript) {\n try {\n const scriptContent = pageDataScript.textContent;\n if (!scriptContent) {\n logger2.warn("Page data script in HTML has no content");\n } else {\n pageData = JSON.parse(scriptContent);\n }\n } catch (error) {\n logger2.error("Failed to parse page data from HTML:", error);\n }\n }\n return { content, pageData };\n}\n\n// src/rendering/client/browser-stubs/config.ts\nvar DEFAULT_PREFETCH_DELAY_MS = 100;\nvar PAGE_TRANSITION_DELAY_MS = 150;\n\n// src/routing/client/navigation-handlers.ts\nvar logger3 = rendererLogger.component("veryfront");\nvar MAX_SCROLL_POSITIONS = 100;\nvar NavigationHandlers = class {\n constructor(prefetchDelay = DEFAULT_PREFETCH_DELAY_MS, prefetchOptions = {}) {\n __publicField(this, "prefetchQueue", /* @__PURE__ */ new Set());\n __publicField(this, "pendingTimeouts", /* @__PURE__ */ new Map());\n __publicField(this, "scrollPositions", /* @__PURE__ */ new Map());\n __publicField(this, "isPopStateNav", false);\n __publicField(this, "prefetchDelay");\n __publicField(this, "prefetchOptions");\n this.prefetchDelay = prefetchDelay;\n this.prefetchOptions = prefetchOptions;\n }\n createClickHandler(callbacks) {\n return (event) => {\n if (!(event.target instanceof HTMLElement)) return;\n const anchor = findAnchorElement(event.target);\n if (!anchor || !isInternalLink(anchor)) return;\n const href = anchor.getAttribute("href");\n if (!href) return;\n event.preventDefault();\n callbacks.onNavigate(href);\n };\n }\n createPopStateHandler(callbacks) {\n return (_event) => {\n this.isPopStateNav = true;\n callbacks.onNavigate(globalThis.location.pathname);\n };\n }\n createMouseOverHandler(callbacks) {\n return (event) => {\n if (!(event.target instanceof HTMLElement)) return;\n if (event.target.tagName !== "A") return;\n const href = event.target.getAttribute("href");\n if (!href || href.startsWith("http") || href.startsWith("#")) return;\n if (!this.shouldPrefetchOnHover(event.target)) return;\n if (this.prefetchQueue.has(href)) return;\n this.prefetchQueue.add(href);\n const timeoutId = setTimeout(() => {\n callbacks.onPrefetch(href);\n this.prefetchQueue.delete(href);\n this.pendingTimeouts.delete(href);\n }, this.prefetchDelay);\n this.pendingTimeouts.set(href, timeoutId);\n };\n }\n shouldPrefetchOnHover(target) {\n const prefetchAttribute = target.getAttribute("data-prefetch");\n if (prefetchAttribute === "false") return false;\n if (prefetchAttribute === "true") return true;\n return Boolean(this.prefetchOptions.hover);\n }\n saveScrollPosition(path) {\n try {\n if (this.scrollPositions.size >= MAX_SCROLL_POSITIONS) {\n const oldest = this.scrollPositions.keys().next().value;\n if (oldest) this.scrollPositions.delete(oldest);\n }\n const scrollY = globalThis.scrollY;\n if (typeof scrollY !== "number") {\n logger3.debug("No valid scrollY value available");\n this.scrollPositions.set(path, 0);\n return;\n }\n this.scrollPositions.set(path, scrollY);\n } catch (error) {\n logger3.warn("failed to record scroll position", error);\n }\n }\n getScrollPosition(path) {\n const position = this.scrollPositions.get(path);\n if (position === void 0) {\n logger3.debug(`No scroll position stored for ${path}`);\n return 0;\n }\n return position;\n }\n isPopState() {\n return this.isPopStateNav;\n }\n clearPopStateFlag() {\n this.isPopStateNav = false;\n }\n clear() {\n for (const timeoutId of this.pendingTimeouts.values()) clearTimeout(timeoutId);\n this.pendingTimeouts.clear();\n this.prefetchQueue.clear();\n this.scrollPositions.clear();\n this.isPopStateNav = false;\n }\n};\n\n// src/rendering/client/browser-stubs/error-registry.ts\nfunction createBrowserError(name, fallbackMessage) {\n return {\n create(options = {}) {\n const error = new Error(options.detail ?? fallbackMessage);\n error.name = name;\n Object.assign(error, {\n status: options.status,\n context: options.context\n });\n return error;\n }\n };\n}\nvar NETWORK_ERROR = createBrowserError("NetworkError", "Network request failed");\nvar SECURITY_VIOLATION = createBrowserError("SecurityViolation", "Security violation");\n\n// src/routing/client/page-loader.ts\nvar logger4 = rendererLogger.component("veryfront");\nvar MAX_CACHE_SIZE = 50;\nvar PageLoader = class {\n constructor() {\n __publicField(this, "cache", /* @__PURE__ */ new Map());\n __publicField(this, "spaCache", /* @__PURE__ */ new Map());\n __publicField(this, "pendingRequests", /* @__PURE__ */ new Map());\n __publicField(this, "pendingSpaRequests", /* @__PURE__ */ new Map());\n }\n evictIfFull(map) {\n if (map.size < MAX_CACHE_SIZE) return;\n const oldest = map.keys().next().value;\n if (oldest) map.delete(oldest);\n }\n getCached(path) {\n return this.cache.get(path);\n }\n isCached(path) {\n return this.cache.has(path);\n }\n setCache(path, data) {\n this.evictIfFull(this.cache);\n this.cache.set(path, data);\n }\n clearCache() {\n this.cache.clear();\n this.spaCache.clear();\n this.pendingRequests.clear();\n this.pendingSpaRequests.clear();\n }\n getSpaCached(path) {\n return this.spaCache.get(path);\n }\n isSpaDataCached(path) {\n return this.spaCache.has(path);\n }\n setSpaCache(path, data) {\n this.evictIfFull(this.spaCache);\n this.spaCache.set(path, data);\n }\n async fetchPageData(path) {\n return await this.tryFetchJSON(path) ?? this.fetchAndParseHTML(path);\n }\n async tryFetchJSON(path) {\n try {\n const response = await fetch(`/_veryfront/data${path}.json`, {\n headers: { "X-Veryfront-Navigation": "client" }\n });\n if (!response.ok) return null;\n return await response.json();\n } catch (error) {\n logger4.debug(`JSON fetch failed for ${path}, falling back to HTML:`, error);\n return null;\n }\n }\n async fetchAndParseHTML(path) {\n const response = await fetch(path, {\n headers: { "X-Veryfront-Navigation": "client" }\n });\n if (!response.ok) {\n throw NETWORK_ERROR.create({\n detail: `Failed to fetch ${path}`,\n status: response.status,\n context: { path }\n });\n }\n const html = await response.text();\n const { content, pageData } = parsePageDataFromHTML(html);\n return { html: content, ...pageData };\n }\n loadPage(path) {\n const cachedData = this.getCached(path);\n if (cachedData) {\n logger4.debug(`Loading ${path} from cache`);\n return Promise.resolve(cachedData);\n }\n const pending = this.pendingRequests.get(path);\n if (pending) {\n logger4.debug(`Reusing pending request for ${path}`);\n return pending;\n }\n logger4.debug(`Creating pending request for ${path}`);\n return this.createPendingRequest(path, this.pendingRequests, async () => {\n const data = await this.fetchPageData(path);\n this.setCache(path, data);\n return data;\n });\n }\n async prefetch(path) {\n if (this.isCached(path)) return;\n logger4.debug(`Prefetching ${path}`);\n try {\n await this.loadPage(path);\n } catch (error) {\n logger4.warn(\n `[Veryfront] Failed to prefetch ${path}`,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n async fetchSpaPageData(path) {\n const normalizedPath = path === "/" ? "" : path.replace(/^\\//, "");\n const endpoint = `/_veryfront/page-data/${normalizedPath}.json`;\n logger4.debug(`Fetching SPA page data from ${endpoint}`);\n const response = await fetch(endpoint, {\n headers: { "X-Veryfront-Navigation": "spa" }\n });\n if (!response.ok) {\n throw NETWORK_ERROR.create({\n detail: `Failed to fetch SPA page data for ${path}`,\n status: response.status,\n context: { path }\n });\n }\n return response.json();\n }\n loadSpaPageData(path) {\n const cachedData = this.getSpaCached(path);\n if (cachedData) {\n logger4.debug(`Loading SPA data for ${path} from cache`);\n return Promise.resolve(cachedData);\n }\n const pending = this.pendingSpaRequests.get(path);\n if (pending) {\n logger4.debug(`Reusing pending SPA request for ${path}`);\n return pending;\n }\n logger4.debug(`Creating pending SPA request for ${path}`);\n return this.createPendingRequest(path, this.pendingSpaRequests, async () => {\n const data = await this.fetchSpaPageData(path);\n this.setSpaCache(path, data);\n return data;\n });\n }\n async prefetchSpaPageData(path) {\n if (this.isSpaDataCached(path)) return;\n logger4.debug(`Prefetching SPA page data for ${path}`);\n try {\n await this.loadSpaPageData(path);\n } catch (error) {\n logger4.warn(\n `[Veryfront] Failed to prefetch SPA data for ${path}`,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n createPendingRequest(path, pendingMap, fetcher) {\n const request = (async () => {\n try {\n return await fetcher();\n } finally {\n pendingMap.delete(path);\n }\n })();\n pendingMap.set(path, request);\n return request;\n }\n};\n\n// src/security/client/html-sanitizer.ts\nvar SUSPICIOUS_PATTERN_SPECS = [\n { source: String.raw`<script[^>]*>[\\s\\S]*?<\\/script>`, flags: "gi", name: "inline script" },\n { source: String.raw`javascript:`, flags: "gi", name: "javascript: URL" },\n { source: String.raw`\\bon\\w+\\s*=`, flags: "gi", name: "event handler attribute" },\n { source: String.raw`data:\\s*text\\/html`, flags: "gi", name: "data: HTML URL" }\n];\nfunction createSuspiciousPatterns() {\n return SUSPICIOUS_PATTERN_SPECS.map(({ source, flags, name }) => ({\n pattern: new RegExp(source, flags),\n name\n }));\n}\nfunction isDevMode() {\n const g = globalThis;\n return g.__VERYFRONT_DEV__ === true || g.Deno?.env?.get?.("VERYFRONT_ENV") === "development";\n}\nfunction validateTrustedHtml(html, options = {}) {\n const { allowInlineScripts = false, strict = false, warn = true } = options;\n for (const { pattern, name } of createSuspiciousPatterns()) {\n if (allowInlineScripts && name === "inline script") continue;\n pattern.lastIndex = 0;\n if (!pattern.test(html)) continue;\n if (warn) console.warn(`[Security] Suspicious ${name} detected in server HTML`);\n if (strict || !isDevMode()) {\n throw SECURITY_VIOLATION.create({ detail: `Potentially unsafe HTML: ${name} detected` });\n }\n }\n return html;\n}\n\n// src/routing/client/page-transition.ts\nvar logger5 = rendererLogger.component("veryfront");\nvar PageTransition = class {\n constructor(setupViewportPrefetch) {\n __publicField(this, "setupViewportPrefetch", setupViewportPrefetch);\n __publicField(this, "pendingTransitionTimeout");\n }\n destroy() {\n if (this.pendingTransitionTimeout === void 0) return;\n clearTimeout(this.pendingTransitionTimeout);\n this.pendingTransitionTimeout = void 0;\n }\n updatePage(data, isPopState, scrollY) {\n const title = data.frontmatter?.title;\n if (title) document.title = title;\n updateMetaTags(data.frontmatter ?? {});\n const rootElement = document.getElementById("root");\n if (!rootElement || !data.html) return;\n this.performTransition(rootElement, data, isPopState, scrollY);\n }\n performTransition(rootElement, data, isPopState, scrollY) {\n if (this.pendingTransitionTimeout !== void 0) {\n clearTimeout(this.pendingTransitionTimeout);\n this.pendingTransitionTimeout = void 0;\n }\n rootElement.style.opacity = "0";\n this.pendingTransitionTimeout = setTimeout(() => {\n this.pendingTransitionTimeout = void 0;\n rootElement.innerHTML = validateTrustedHtml(String(data.html), { allowInlineScripts: true });\n rootElement.style.opacity = "1";\n executeScripts(rootElement);\n applyHeadDirectives(rootElement);\n this.setupViewportPrefetch(rootElement);\n manageFocus(rootElement);\n this.handleScroll(isPopState, scrollY);\n }, PAGE_TRANSITION_DELAY_MS);\n }\n handleScroll(isPopState, scrollY) {\n try {\n globalThis.scrollTo(0, isPopState ? scrollY : 0);\n } catch (error) {\n logger5.warn("scroll handling failed", error);\n }\n }\n showError(error) {\n const rootElement = document.getElementById("root");\n if (!rootElement) return;\n const errorDiv = document.createElement("div");\n errorDiv.className = "veryfront-error-page";\n const heading = document.createElement("h1");\n heading.textContent = "Oops! Something went wrong";\n const message = document.createElement("p");\n message.textContent = error.message;\n const button = document.createElement("button");\n button.type = "button";\n button.textContent = "Reload Page";\n button.onclick = () => globalThis.location.reload();\n errorDiv.append(heading, message, button);\n rootElement.innerHTML = "";\n rootElement.appendChild(errorDiv);\n }\n setLoadingState(loading) {\n const indicator = document.getElementById("veryfront-loading");\n if (indicator) indicator.style.display = loading ? "block" : "none";\n document.body.classList.toggle("veryfront-loading", loading);\n }\n};\n\n// src/routing/client/viewport-prefetch.ts\nvar logger6 = rendererLogger.component("veryfront");\nvar ViewportPrefetch = class {\n constructor(prefetchCallback, prefetchOptions = {}) {\n __publicField(this, "observer", null);\n __publicField(this, "prefetchCallback");\n __publicField(this, "prefetchOptions");\n this.prefetchCallback = prefetchCallback;\n this.prefetchOptions = prefetchOptions;\n }\n setup(root) {\n try {\n if (!("IntersectionObserver" in globalThis)) return;\n this.observer?.disconnect();\n this.createObserver();\n this.observeLinks(root);\n } catch (error) {\n logger6.debug("setupViewportPrefetch failed", error);\n }\n }\n createObserver() {\n this.observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (!entry.isIntersecting) continue;\n if (!(entry.target instanceof HTMLAnchorElement)) continue;\n const href = entry.target.getAttribute("href");\n if (href) this.prefetchCallback(href);\n this.observer?.unobserve(entry.target);\n }\n },\n { rootMargin: "200px" }\n );\n }\n observeLinks(root) {\n const anchors = root.querySelectorAll(\'a[href]:not([target="_blank"])\');\n const isViewportEnabled = Boolean(this.prefetchOptions.viewport);\n for (const anchor of anchors) {\n if (!this.shouldObserveAnchor(anchor, isViewportEnabled)) continue;\n this.observer?.observe(anchor);\n }\n }\n shouldObserveAnchor(anchor, isViewportEnabled) {\n const href = anchor.getAttribute("href");\n if (!href) return false;\n if (href.startsWith("http") || href.startsWith("#")) return false;\n if (anchor.getAttribute("download")) return false;\n const prefetchAttribute = anchor.getAttribute("data-prefetch");\n if (prefetchAttribute === "false") return false;\n return prefetchAttribute === "viewport" || isViewportEnabled;\n }\n disconnect() {\n if (!this.observer) return;\n try {\n this.observer.disconnect();\n } catch (error) {\n logger6.warn("prefetchObserver.disconnect failed", error);\n } finally {\n this.observer = null;\n }\n }\n};\n\n// src/rendering/client/router.ts\nvar logger7 = rendererLogger.component("veryfront");\nvar VeryfrontRouter = class {\n constructor(options = {}) {\n __publicField(this, "baseUrl");\n __publicField(this, "currentPath");\n __publicField(this, "root", null);\n __publicField(this, "options");\n __publicField(this, "spaMode");\n __publicField(this, "spaNavigationHandler", null);\n __publicField(this, "pageLoader");\n __publicField(this, "navigationHandlers");\n __publicField(this, "pageTransition");\n __publicField(this, "viewportPrefetch");\n __publicField(this, "handleClick");\n __publicField(this, "handlePopState");\n __publicField(this, "handleMouseOver");\n const globalOptions = this.loadGlobalOptions();\n this.options = { ...globalOptions, ...options };\n this.baseUrl = this.options.baseUrl || globalThis.location.origin;\n this.currentPath = globalThis.location.pathname;\n this.spaMode = this.options.spaMode ?? globalThis.__VERYFRONT_SPA_MODE__ ?? false;\n this.pageLoader = new PageLoader();\n this.navigationHandlers = new NavigationHandlers(\n this.options.prefetchDelay,\n this.options.prefetch\n );\n this.pageTransition = new PageTransition((root) => this.viewportPrefetch.setup(root));\n this.viewportPrefetch = new ViewportPrefetch(\n (path) => this.prefetch(path),\n this.options.prefetch\n );\n this.handleClick = this.navigationHandlers.createClickHandler({\n onNavigate: (url) => this.navigate(url),\n onPrefetch: (url) => this.prefetch(url)\n });\n this.handlePopState = this.navigationHandlers.createPopStateHandler({\n onNavigate: (url) => this.navigate(url, false),\n onPrefetch: (url) => this.prefetch(url)\n });\n this.handleMouseOver = this.navigationHandlers.createMouseOverHandler({\n onNavigate: (url) => this.navigate(url),\n onPrefetch: (url) => this.prefetch(url)\n });\n }\n registerNavigationHandler(handler) {\n logger7.debug("Registering SPA navigation handler");\n this.spaNavigationHandler = handler;\n this.spaMode = true;\n }\n loadGlobalOptions() {\n try {\n const options = globalThis.__VERYFRONT_ROUTER_OPTS__;\n if (!options) {\n logger7.debug("No global options configured");\n return {};\n }\n return options;\n } catch (error) {\n logger7.error("Failed to read global options:", error);\n return {};\n }\n }\n init() {\n logger7.debug("Initializing client-side router");\n const rootElement = document.getElementById("root");\n if (!rootElement) {\n logger7.error("Root element not found");\n return;\n }\n const ReactDOMToUse = globalThis.ReactDOM ?? ReactDOM;\n this.root = ReactDOMToUse.createRoot(rootElement);\n document.addEventListener("click", this.handleClick);\n globalThis.addEventListener("popstate", this.handlePopState);\n document.addEventListener("mouseover", this.handleMouseOver);\n this.viewportPrefetch.setup(document);\n this.cacheCurrentPage();\n }\n cacheCurrentPage() {\n const pageData = extractPageDataFromScript();\n if (pageData) this.pageLoader.setCache(this.currentPath, pageData);\n }\n async navigate(url, pushState = true) {\n logger7.debug(`Navigating to ${url} (SPA mode: ${this.spaMode})`);\n this.navigationHandlers.saveScrollPosition(this.currentPath);\n this.options.onStart?.(url);\n if (pushState) globalThis.history.pushState({}, "", url);\n if (this.spaMode && this.spaNavigationHandler) {\n await this.loadSpaPage(url);\n } else {\n await this.loadPage(url);\n }\n this.options.onNavigate?.(url);\n }\n async loadSpaPage(path) {\n logger7.debug(`Loading SPA page: ${path}`);\n try {\n const spaData = await this.pageLoader.loadSpaPageData(path);\n await this.spaNavigationHandler?.(spaData);\n this.currentPath = path;\n this.handleScrollAfterNavigation();\n this.options.onComplete?.(path);\n } catch (error) {\n const normalizedError = error instanceof Error ? error : new Error(String(error));\n logger7.error(`Failed to load SPA page ${path}`, normalizedError);\n this.options.onError?.(normalizedError);\n this.pageTransition.showError(normalizedError);\n }\n }\n handleScrollAfterNavigation() {\n const isPopState = this.navigationHandlers.isPopState();\n const scrollY = this.navigationHandlers.getScrollPosition(this.currentPath);\n try {\n globalThis.scrollTo(0, isPopState ? scrollY : 0);\n } catch (error) {\n logger7.warn("scroll handling failed", error);\n }\n this.navigationHandlers.clearPopStateFlag();\n }\n async loadPage(path, updateUI = true) {\n if (this.pageLoader.isCached(path)) {\n logger7.debug(`Loading ${path} from cache`);\n const data = this.pageLoader.getCached(path);\n if (data) {\n if (updateUI) this.updatePage(data);\n return;\n }\n logger7.warn(`Cache entry for ${path} was unexpectedly null, fetching fresh data`);\n }\n this.pageTransition.setLoadingState(true);\n try {\n const data = await this.pageLoader.loadPage(path);\n if (updateUI) this.updatePage(data);\n this.currentPath = path;\n this.options.onComplete?.(path);\n } catch (error) {\n const normalizedError = error instanceof Error ? error : new Error(String(error));\n logger7.error(`Failed to load ${path}`, normalizedError);\n this.options.onError?.(normalizedError);\n this.pageTransition.showError(normalizedError);\n } finally {\n this.pageTransition.setLoadingState(false);\n }\n }\n async prefetch(path) {\n if (this.spaMode) {\n await this.pageLoader.prefetchSpaPageData(path);\n return;\n }\n await this.pageLoader.prefetch(path);\n }\n updatePage(data) {\n if (!this.root) return;\n const isPopState = this.navigationHandlers.isPopState();\n const scrollY = this.navigationHandlers.getScrollPosition(this.currentPath);\n this.pageTransition.updatePage(data, isPopState, scrollY);\n this.navigationHandlers.clearPopStateFlag();\n }\n destroy() {\n document.removeEventListener("click", this.handleClick);\n globalThis.removeEventListener("popstate", this.handlePopState);\n document.removeEventListener("mouseover", this.handleMouseOver);\n this.viewportPrefetch.disconnect();\n this.pageLoader.clearCache();\n this.navigationHandlers.clear();\n this.pageTransition.destroy();\n }\n};\nfunction boot(options = {}) {\n if (typeof window === "undefined" || !globalThis.document) return null;\n const globalWithRouter = globalThis;\n if (globalWithRouter.veryFrontRouter) return globalWithRouter.veryFrontRouter;\n const { slug: _slug, ...routerOptions } = options;\n const router = new VeryfrontRouter(routerOptions);\n if (document.readyState === "loading") {\n document.addEventListener("DOMContentLoaded", () => router.init(), { once: true });\n } else {\n router.init();\n }\n globalWithRouter.veryFrontRouter = router;\n return router;\n}\nif (typeof window !== "undefined" && globalThis.document) {\n boot();\n}\nexport {\n VeryfrontRouter,\n boot\n};\n';
10
+ export const CLIENT_ROUTER_BUNDLE = 'var __defProp = Object.defineProperty;\nvar __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;\nvar __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);\n\n// src/rendering/client/browser-stubs/logger.ts\nfunction noop() {\n}\nvar logger = {\n debug: noop,\n info: console.log.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n component: () => logger\n};\nvar rendererLogger = logger;\nvar PREFETCH_MAX_SIZE_BYTES = 200 * 1024;\n\n// src/rendering/client/navigation-store.ts\nvar STORE_KEY = /* @__PURE__ */ Symbol.for("veryfront.navigation.store.v1");\nfunction getNavigationStore() {\n const holder = globalThis;\n const existing = holder[STORE_KEY];\n if (existing) return existing;\n const listeners = /* @__PURE__ */ new Set();\n let navigator = null;\n const store = {\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n getHref() {\n const loc = globalThis.location;\n return loc ? `${loc.pathname}${loc.search}${loc.hash}` : "/";\n },\n notify() {\n for (const listener of [...listeners]) {\n try {\n listener();\n } catch {\n }\n }\n },\n navigate(href, options) {\n if (navigator) return navigator(href, options);\n globalThis.location?.assign(href);\n return Promise.resolve();\n },\n setNavigator(next) {\n navigator = next;\n }\n };\n holder[STORE_KEY] = store;\n return store;\n}\n\n// src/rendering/client/router.ts\nimport ReactDOM from "react-dom/client";\n\n// src/routing/client/dom-utils.ts\nvar logger2 = rendererLogger.component("veryfront");\nfunction isInternalLink(target) {\n const href = target.getAttribute("href");\n if (!href) return false;\n if (href.startsWith("http") || href.startsWith("mailto:") || href.startsWith("#")) return false;\n const linkTarget = target.getAttribute("target");\n if (linkTarget === "_blank" || target.hasAttribute("download")) return false;\n return true;\n}\nfunction findAnchorElement(element) {\n let current = element;\n while (current && current.tagName !== "A") {\n current = current.parentElement;\n }\n return current instanceof HTMLAnchorElement ? current : null;\n}\nfunction updateMetaTags(frontmatter) {\n if (frontmatter.description) {\n updateMetaTag(\'meta[name="description"]\', "name", "description", frontmatter.description);\n }\n if (frontmatter.ogTitle) {\n updateMetaTag(\'meta[property="og:title"]\', "property", "og:title", frontmatter.ogTitle);\n }\n}\nfunction updateMetaTag(selector, attributeName, attributeValue, content) {\n let metaTag = document.querySelector(selector);\n if (!metaTag) {\n metaTag = document.createElement("meta");\n metaTag.setAttribute(attributeName, attributeValue);\n document.head.appendChild(metaTag);\n }\n metaTag.setAttribute("content", content);\n}\nfunction executeScripts(container) {\n for (const oldScript of container.querySelectorAll("script")) {\n const newScript = document.createElement("script");\n for (const { name, value } of oldScript.attributes) {\n newScript.setAttribute(name, value);\n }\n newScript.textContent = oldScript.textContent;\n oldScript.parentNode?.replaceChild(newScript, oldScript);\n }\n}\nfunction applyHeadDirectives(container) {\n const nodes = container.querySelectorAll(\'[data-veryfront-head="1"], vf-head\');\n if (!nodes.length) return;\n cleanManagedHeadTags();\n for (const wrapper of nodes) {\n const contentSource = typeof HTMLTemplateElement !== "undefined" && wrapper instanceof HTMLTemplateElement ? wrapper.content : wrapper;\n processHeadWrapper(contentSource);\n wrapper.parentElement?.removeChild(wrapper);\n }\n}\nfunction cleanManagedHeadTags() {\n for (const element of document.head.querySelectorAll(\'[data-veryfront-managed="1"]\')) {\n element.parentElement?.removeChild(element);\n }\n}\nfunction processHeadWrapper(wrapper) {\n for (const node of wrapper.childNodes) {\n if (!(node instanceof Element)) continue;\n const tagName = node.tagName.toLowerCase();\n if (tagName === "title") {\n document.title = node.textContent || document.title;\n continue;\n }\n const clone = document.createElement(tagName);\n for (const { name, value } of node.attributes) {\n clone.setAttribute(name, value);\n }\n if (node.textContent && !clone.hasAttribute("src")) {\n clone.textContent = node.textContent;\n }\n clone.setAttribute("data-veryfront-managed", "1");\n document.head.appendChild(clone);\n }\n}\nfunction manageFocus(container) {\n try {\n const focusElement = container.querySelector("[data-router-focus]") || container.querySelector("main") || container.querySelector("h1");\n focusElement?.focus?.({ preventScroll: true });\n } catch (error) {\n logger2.warn("focus management failed", error);\n }\n}\nfunction extractPageDataFromScript() {\n const pageDataScript = document.querySelector("script[data-veryfront-page]");\n if (!pageDataScript) return null;\n try {\n const content = pageDataScript.textContent;\n if (!content) {\n logger2.warn("Page data script has no content");\n return {};\n }\n return JSON.parse(content);\n } catch (error) {\n logger2.error("Failed to parse page data:", error);\n return null;\n }\n}\nfunction parsePageDataFromHTML(html) {\n const doc = new DOMParser().parseFromString(html, "text/html");\n const root = doc.getElementById("root");\n if (!root) logger2.warn("[Veryfront] No root element found in HTML");\n const content = root?.innerHTML ?? "";\n const pageDataScript = doc.querySelector("script[data-veryfront-page]");\n let pageData = {};\n if (pageDataScript) {\n try {\n const scriptContent = pageDataScript.textContent;\n if (!scriptContent) {\n logger2.warn("Page data script in HTML has no content");\n } else {\n pageData = JSON.parse(scriptContent);\n }\n } catch (error) {\n logger2.error("Failed to parse page data from HTML:", error);\n }\n }\n return { content, pageData };\n}\n\n// src/rendering/client/browser-stubs/config.ts\nvar DEFAULT_PREFETCH_DELAY_MS = 100;\nvar PAGE_TRANSITION_DELAY_MS = 150;\n\n// src/routing/client/navigation-handlers.ts\nvar logger3 = rendererLogger.component("veryfront");\nvar MAX_SCROLL_POSITIONS = 100;\nvar NavigationHandlers = class {\n constructor(prefetchDelay = DEFAULT_PREFETCH_DELAY_MS, prefetchOptions = {}) {\n __publicField(this, "prefetchQueue", /* @__PURE__ */ new Set());\n __publicField(this, "pendingTimeouts", /* @__PURE__ */ new Map());\n __publicField(this, "scrollPositions", /* @__PURE__ */ new Map());\n __publicField(this, "isPopStateNav", false);\n __publicField(this, "prefetchDelay");\n __publicField(this, "prefetchOptions");\n this.prefetchDelay = prefetchDelay;\n this.prefetchOptions = prefetchOptions;\n }\n createClickHandler(callbacks) {\n return (event) => {\n if (!(event.target instanceof HTMLElement)) return;\n const anchor = findAnchorElement(event.target);\n if (!anchor || !isInternalLink(anchor)) return;\n const href = anchor.getAttribute("href");\n if (!href) return;\n event.preventDefault();\n callbacks.onNavigate(href);\n };\n }\n createPopStateHandler(callbacks) {\n return (_event) => {\n this.isPopStateNav = true;\n callbacks.onNavigate(globalThis.location.pathname);\n };\n }\n createMouseOverHandler(callbacks) {\n return (event) => {\n if (!(event.target instanceof HTMLElement)) return;\n if (event.target.tagName !== "A") return;\n const href = event.target.getAttribute("href");\n if (!href || href.startsWith("http") || href.startsWith("#")) return;\n if (!this.shouldPrefetchOnHover(event.target)) return;\n if (this.prefetchQueue.has(href)) return;\n this.prefetchQueue.add(href);\n const timeoutId = setTimeout(() => {\n callbacks.onPrefetch(href);\n this.prefetchQueue.delete(href);\n this.pendingTimeouts.delete(href);\n }, this.prefetchDelay);\n this.pendingTimeouts.set(href, timeoutId);\n };\n }\n shouldPrefetchOnHover(target) {\n const prefetchAttribute = target.getAttribute("data-prefetch");\n if (prefetchAttribute === "false") return false;\n if (prefetchAttribute === "true") return true;\n return Boolean(this.prefetchOptions.hover);\n }\n saveScrollPosition(path) {\n try {\n if (this.scrollPositions.size >= MAX_SCROLL_POSITIONS) {\n const oldest = this.scrollPositions.keys().next().value;\n if (oldest) this.scrollPositions.delete(oldest);\n }\n const scrollY = globalThis.scrollY;\n if (typeof scrollY !== "number") {\n logger3.debug("No valid scrollY value available");\n this.scrollPositions.set(path, 0);\n return;\n }\n this.scrollPositions.set(path, scrollY);\n } catch (error) {\n logger3.warn("failed to record scroll position", error);\n }\n }\n getScrollPosition(path) {\n const position = this.scrollPositions.get(path);\n if (position === void 0) {\n logger3.debug(`No scroll position stored for ${path}`);\n return 0;\n }\n return position;\n }\n isPopState() {\n return this.isPopStateNav;\n }\n clearPopStateFlag() {\n this.isPopStateNav = false;\n }\n clear() {\n for (const timeoutId of this.pendingTimeouts.values()) clearTimeout(timeoutId);\n this.pendingTimeouts.clear();\n this.prefetchQueue.clear();\n this.scrollPositions.clear();\n this.isPopStateNav = false;\n }\n};\n\n// src/rendering/client/browser-stubs/error-registry.ts\nfunction createBrowserError(name, fallbackMessage) {\n return {\n create(options = {}) {\n const error = new Error(options.detail ?? fallbackMessage);\n error.name = name;\n Object.assign(error, {\n status: options.status,\n context: options.context\n });\n return error;\n }\n };\n}\nvar NETWORK_ERROR = createBrowserError("NetworkError", "Network request failed");\nvar SECURITY_VIOLATION = createBrowserError("SecurityViolation", "Security violation");\n\n// src/routing/client/page-loader.ts\nvar logger4 = rendererLogger.component("veryfront");\nvar MAX_CACHE_SIZE = 50;\nvar PageLoader = class {\n constructor() {\n __publicField(this, "cache", /* @__PURE__ */ new Map());\n __publicField(this, "spaCache", /* @__PURE__ */ new Map());\n __publicField(this, "pendingRequests", /* @__PURE__ */ new Map());\n __publicField(this, "pendingSpaRequests", /* @__PURE__ */ new Map());\n }\n evictIfFull(map) {\n if (map.size < MAX_CACHE_SIZE) return;\n const oldest = map.keys().next().value;\n if (oldest) map.delete(oldest);\n }\n getCached(path) {\n return this.cache.get(path);\n }\n isCached(path) {\n return this.cache.has(path);\n }\n setCache(path, data) {\n this.evictIfFull(this.cache);\n this.cache.set(path, data);\n }\n clearCache() {\n this.cache.clear();\n this.spaCache.clear();\n this.pendingRequests.clear();\n this.pendingSpaRequests.clear();\n }\n getSpaCached(path) {\n return this.spaCache.get(path);\n }\n isSpaDataCached(path) {\n return this.spaCache.has(path);\n }\n setSpaCache(path, data) {\n this.evictIfFull(this.spaCache);\n this.spaCache.set(path, data);\n }\n async fetchPageData(path) {\n return await this.tryFetchJSON(path) ?? this.fetchAndParseHTML(path);\n }\n async tryFetchJSON(path) {\n try {\n const response = await fetch(`/_veryfront/data${path}.json`, {\n headers: { "X-Veryfront-Navigation": "client" }\n });\n if (!response.ok) return null;\n return await response.json();\n } catch (error) {\n logger4.debug(`JSON fetch failed for ${path}, falling back to HTML:`, error);\n return null;\n }\n }\n async fetchAndParseHTML(path) {\n const response = await fetch(path, {\n headers: { "X-Veryfront-Navigation": "client" }\n });\n if (!response.ok) {\n throw NETWORK_ERROR.create({\n detail: `Failed to fetch ${path}`,\n status: response.status,\n context: { path }\n });\n }\n const html = await response.text();\n const { content, pageData } = parsePageDataFromHTML(html);\n return { html: content, ...pageData };\n }\n loadPage(path) {\n const cachedData = this.getCached(path);\n if (cachedData) {\n logger4.debug(`Loading ${path} from cache`);\n return Promise.resolve(cachedData);\n }\n const pending = this.pendingRequests.get(path);\n if (pending) {\n logger4.debug(`Reusing pending request for ${path}`);\n return pending;\n }\n logger4.debug(`Creating pending request for ${path}`);\n return this.createPendingRequest(path, this.pendingRequests, async () => {\n const data = await this.fetchPageData(path);\n this.setCache(path, data);\n return data;\n });\n }\n async prefetch(path) {\n if (this.isCached(path)) return;\n logger4.debug(`Prefetching ${path}`);\n try {\n await this.loadPage(path);\n } catch (error) {\n logger4.warn(\n `[Veryfront] Failed to prefetch ${path}`,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n async fetchSpaPageData(path) {\n const normalizedPath = path === "/" ? "" : path.replace(/^\\//, "");\n const endpoint = `/_veryfront/page-data/${normalizedPath}.json`;\n logger4.debug(`Fetching SPA page data from ${endpoint}`);\n const response = await fetch(endpoint, {\n headers: { "X-Veryfront-Navigation": "spa" }\n });\n if (!response.ok) {\n throw NETWORK_ERROR.create({\n detail: `Failed to fetch SPA page data for ${path}`,\n status: response.status,\n context: { path }\n });\n }\n return response.json();\n }\n loadSpaPageData(path) {\n const cachedData = this.getSpaCached(path);\n if (cachedData) {\n logger4.debug(`Loading SPA data for ${path} from cache`);\n return Promise.resolve(cachedData);\n }\n const pending = this.pendingSpaRequests.get(path);\n if (pending) {\n logger4.debug(`Reusing pending SPA request for ${path}`);\n return pending;\n }\n logger4.debug(`Creating pending SPA request for ${path}`);\n return this.createPendingRequest(path, this.pendingSpaRequests, async () => {\n const data = await this.fetchSpaPageData(path);\n this.setSpaCache(path, data);\n return data;\n });\n }\n async prefetchSpaPageData(path) {\n if (this.isSpaDataCached(path)) return;\n logger4.debug(`Prefetching SPA page data for ${path}`);\n try {\n await this.loadSpaPageData(path);\n } catch (error) {\n logger4.warn(\n `[Veryfront] Failed to prefetch SPA data for ${path}`,\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n createPendingRequest(path, pendingMap, fetcher) {\n const request = (async () => {\n try {\n return await fetcher();\n } finally {\n pendingMap.delete(path);\n }\n })();\n pendingMap.set(path, request);\n return request;\n }\n};\n\n// src/security/client/html-sanitizer.ts\nvar SUSPICIOUS_PATTERN_SPECS = [\n { source: String.raw`<script[^>]*>[\\s\\S]*?<\\/script>`, flags: "gi", name: "inline script" },\n { source: String.raw`javascript:`, flags: "gi", name: "javascript: URL" },\n { source: String.raw`\\bon\\w+\\s*=`, flags: "gi", name: "event handler attribute" },\n { source: String.raw`data:\\s*text\\/html`, flags: "gi", name: "data: HTML URL" }\n];\nfunction createSuspiciousPatterns() {\n return SUSPICIOUS_PATTERN_SPECS.map(({ source, flags, name }) => ({\n pattern: new RegExp(source, flags),\n name\n }));\n}\nfunction isDevMode() {\n const g = globalThis;\n return g.__VERYFRONT_DEV__ === true || g.Deno?.env?.get?.("VERYFRONT_ENV") === "development";\n}\nfunction validateTrustedHtml(html, options = {}) {\n const { allowInlineScripts = false, strict = false, warn = true } = options;\n for (const { pattern, name } of createSuspiciousPatterns()) {\n if (allowInlineScripts && name === "inline script") continue;\n pattern.lastIndex = 0;\n if (!pattern.test(html)) continue;\n if (warn) console.warn(`[Security] Suspicious ${name} detected in server HTML`);\n if (strict || !isDevMode()) {\n throw SECURITY_VIOLATION.create({ detail: `Potentially unsafe HTML: ${name} detected` });\n }\n }\n return html;\n}\n\n// src/routing/client/page-transition.ts\nvar logger5 = rendererLogger.component("veryfront");\nvar PageTransition = class {\n constructor(setupViewportPrefetch) {\n __publicField(this, "setupViewportPrefetch", setupViewportPrefetch);\n __publicField(this, "pendingTransitionTimeout");\n }\n destroy() {\n if (this.pendingTransitionTimeout === void 0) return;\n clearTimeout(this.pendingTransitionTimeout);\n this.pendingTransitionTimeout = void 0;\n }\n updatePage(data, isPopState, scrollY) {\n const title = data.frontmatter?.title;\n if (title) document.title = title;\n updateMetaTags(data.frontmatter ?? {});\n const rootElement = document.getElementById("root");\n if (!rootElement || !data.html) return;\n this.performTransition(rootElement, data, isPopState, scrollY);\n }\n performTransition(rootElement, data, isPopState, scrollY) {\n if (this.pendingTransitionTimeout !== void 0) {\n clearTimeout(this.pendingTransitionTimeout);\n this.pendingTransitionTimeout = void 0;\n }\n rootElement.style.opacity = "0";\n this.pendingTransitionTimeout = setTimeout(() => {\n this.pendingTransitionTimeout = void 0;\n rootElement.innerHTML = validateTrustedHtml(String(data.html), { allowInlineScripts: true });\n rootElement.style.opacity = "1";\n executeScripts(rootElement);\n applyHeadDirectives(rootElement);\n this.setupViewportPrefetch(rootElement);\n manageFocus(rootElement);\n this.handleScroll(isPopState, scrollY);\n }, PAGE_TRANSITION_DELAY_MS);\n }\n handleScroll(isPopState, scrollY) {\n try {\n globalThis.scrollTo(0, isPopState ? scrollY : 0);\n } catch (error) {\n logger5.warn("scroll handling failed", error);\n }\n }\n showError(error) {\n const rootElement = document.getElementById("root");\n if (!rootElement) return;\n const errorDiv = document.createElement("div");\n errorDiv.className = "veryfront-error-page";\n const heading = document.createElement("h1");\n heading.textContent = "Oops! Something went wrong";\n const message = document.createElement("p");\n message.textContent = error.message;\n const button = document.createElement("button");\n button.type = "button";\n button.textContent = "Reload Page";\n button.onclick = () => globalThis.location.reload();\n errorDiv.append(heading, message, button);\n rootElement.innerHTML = "";\n rootElement.appendChild(errorDiv);\n }\n setLoadingState(loading) {\n const indicator = document.getElementById("veryfront-loading");\n if (indicator) indicator.style.display = loading ? "block" : "none";\n document.body.classList.toggle("veryfront-loading", loading);\n }\n};\n\n// src/routing/client/viewport-prefetch.ts\nvar logger6 = rendererLogger.component("veryfront");\nvar ViewportPrefetch = class {\n constructor(prefetchCallback, prefetchOptions = {}) {\n __publicField(this, "observer", null);\n __publicField(this, "prefetchCallback");\n __publicField(this, "prefetchOptions");\n this.prefetchCallback = prefetchCallback;\n this.prefetchOptions = prefetchOptions;\n }\n setup(root) {\n try {\n if (!("IntersectionObserver" in globalThis)) return;\n this.observer?.disconnect();\n this.createObserver();\n this.observeLinks(root);\n } catch (error) {\n logger6.debug("setupViewportPrefetch failed", error);\n }\n }\n createObserver() {\n this.observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (!entry.isIntersecting) continue;\n if (!(entry.target instanceof HTMLAnchorElement)) continue;\n const href = entry.target.getAttribute("href");\n if (href) this.prefetchCallback(href);\n this.observer?.unobserve(entry.target);\n }\n },\n { rootMargin: "200px" }\n );\n }\n observeLinks(root) {\n const anchors = root.querySelectorAll(\'a[href]:not([target="_blank"])\');\n const isViewportEnabled = Boolean(this.prefetchOptions.viewport);\n for (const anchor of anchors) {\n if (!this.shouldObserveAnchor(anchor, isViewportEnabled)) continue;\n this.observer?.observe(anchor);\n }\n }\n shouldObserveAnchor(anchor, isViewportEnabled) {\n const href = anchor.getAttribute("href");\n if (!href) return false;\n if (href.startsWith("http") || href.startsWith("#")) return false;\n if (anchor.getAttribute("download")) return false;\n const prefetchAttribute = anchor.getAttribute("data-prefetch");\n if (prefetchAttribute === "false") return false;\n return prefetchAttribute === "viewport" || isViewportEnabled;\n }\n disconnect() {\n if (!this.observer) return;\n try {\n this.observer.disconnect();\n } catch (error) {\n logger6.warn("prefetchObserver.disconnect failed", error);\n } finally {\n this.observer = null;\n }\n }\n};\n\n// src/rendering/client/router.ts\nvar logger7 = rendererLogger.component("veryfront");\nfunction toHistoryMode(options) {\n if (typeof options === "boolean") return options ? "push" : "none";\n return options?.history ?? "push";\n}\nvar VeryfrontRouter = class {\n constructor(options = {}) {\n __publicField(this, "baseUrl");\n __publicField(this, "currentPath");\n __publicField(this, "root", null);\n __publicField(this, "options");\n __publicField(this, "spaMode");\n __publicField(this, "spaNavigationHandler", null);\n __publicField(this, "pageLoader");\n __publicField(this, "navigationHandlers");\n __publicField(this, "pageTransition");\n __publicField(this, "viewportPrefetch");\n __publicField(this, "handleClick");\n __publicField(this, "handlePopState");\n __publicField(this, "handleMouseOver");\n const globalOptions = this.loadGlobalOptions();\n this.options = { ...globalOptions, ...options };\n this.baseUrl = this.options.baseUrl || globalThis.location.origin;\n this.currentPath = globalThis.location.pathname;\n this.spaMode = this.options.spaMode ?? globalThis.__VERYFRONT_SPA_MODE__ ?? false;\n this.pageLoader = new PageLoader();\n this.navigationHandlers = new NavigationHandlers(\n this.options.prefetchDelay,\n this.options.prefetch\n );\n this.pageTransition = new PageTransition((root) => this.viewportPrefetch.setup(root));\n this.viewportPrefetch = new ViewportPrefetch(\n (path) => this.prefetch(path),\n this.options.prefetch\n );\n this.handleClick = this.navigationHandlers.createClickHandler({\n onNavigate: (url) => this.navigate(url),\n onPrefetch: (url) => this.prefetch(url)\n });\n this.handlePopState = this.navigationHandlers.createPopStateHandler({\n // The browser already updated the URL for a popstate, so don\'t touch history.\n onNavigate: (url) => this.navigate(url, { history: "none" }),\n onPrefetch: (url) => this.prefetch(url)\n });\n this.handleMouseOver = this.navigationHandlers.createMouseOverHandler({\n onNavigate: (url) => this.navigate(url),\n onPrefetch: (url) => this.prefetch(url)\n });\n getNavigationStore().setNavigator((href, options2) => this.navigate(href, options2));\n }\n registerNavigationHandler(handler) {\n logger7.debug("Registering SPA navigation handler");\n this.spaNavigationHandler = handler;\n this.spaMode = true;\n }\n /**\n * Notify React (and any other) subscribers that a navigation completed —\n * after full page loads, soft same-route changes, and popstate. Delegates to\n * the shared navigation store, the single subscription surface both bundles\n * share.\n */\n notify() {\n getNavigationStore().notify();\n }\n pathnameOf(url) {\n try {\n return new URL(url, this.baseUrl).pathname;\n } catch {\n return url.split("?")[0]?.split("#")[0] || this.currentPath;\n }\n }\n loadGlobalOptions() {\n try {\n const options = globalThis.__VERYFRONT_ROUTER_OPTS__;\n if (!options) {\n logger7.debug("No global options configured");\n return {};\n }\n return options;\n } catch (error) {\n logger7.error("Failed to read global options:", error);\n return {};\n }\n }\n init() {\n logger7.debug("Initializing client-side router");\n const rootElement = document.getElementById("root");\n if (!rootElement) {\n logger7.error("Root element not found");\n return;\n }\n const ReactDOMToUse = globalThis.ReactDOM ?? ReactDOM;\n this.root = ReactDOMToUse.createRoot(rootElement);\n document.addEventListener("click", this.handleClick);\n globalThis.addEventListener("popstate", this.handlePopState);\n document.addEventListener("mouseover", this.handleMouseOver);\n this.viewportPrefetch.setup(document);\n this.cacheCurrentPage();\n }\n cacheCurrentPage() {\n const pageData = extractPageDataFromScript();\n if (pageData) this.pageLoader.setCache(this.currentPath, pageData);\n }\n /**\n * Navigate to a URL. `options` selects the history behaviour: `{ history:\n * "push" }` (default), `"replace"`, or `"none"` (the URL already reflects the\n * target, as after popstate). A boolean is accepted for backward\n * compatibility — `true` pushes, `false` maps to `"none"`.\n */\n async navigate(url, options) {\n logger7.debug(`Navigating to ${url} (SPA mode: ${this.spaMode})`);\n const history = toHistoryMode(options);\n const sameRoute = this.pathnameOf(url) === this.pathnameOf(this.currentPath);\n this.navigationHandlers.saveScrollPosition(this.currentPath);\n this.options.onStart?.(url);\n if (history === "replace") globalThis.history.replaceState({}, "", url);\n else if (history === "push") globalThis.history.pushState({}, "", url);\n if (sameRoute && !this.shouldRevalidate(url, sameRoute)) {\n this.currentPath = url;\n this.notify();\n this.options.onComplete?.(url);\n this.options.onNavigate?.(url);\n return;\n }\n if (this.spaMode && this.spaNavigationHandler) {\n await this.loadSpaPage(url);\n } else {\n await this.loadPage(url);\n }\n this.notify();\n this.options.onNavigate?.(url);\n }\n /**\n * Whether a navigation should refetch page data. A route change always does;\n * a same-route (query/hash-only) change consults `options.shouldRevalidate`,\n * defaulting to `true` so server data is never shown stale.\n */\n shouldRevalidate(nextUrl, sameRoute) {\n const policy = this.options.shouldRevalidate;\n if (!policy) return true;\n return policy({ currentHref: this.currentPath, nextHref: nextUrl, sameRoute });\n }\n async loadSpaPage(path) {\n logger7.debug(`Loading SPA page: ${path}`);\n try {\n const spaData = await this.pageLoader.loadSpaPageData(path);\n await this.spaNavigationHandler?.(spaData);\n this.currentPath = path;\n this.handleScrollAfterNavigation();\n this.options.onComplete?.(path);\n } catch (error) {\n const normalizedError = error instanceof Error ? error : new Error(String(error));\n logger7.error(`Failed to load SPA page ${path}`, normalizedError);\n this.options.onError?.(normalizedError);\n this.pageTransition.showError(normalizedError);\n }\n }\n handleScrollAfterNavigation() {\n const isPopState = this.navigationHandlers.isPopState();\n const scrollY = this.navigationHandlers.getScrollPosition(this.currentPath);\n try {\n globalThis.scrollTo(0, isPopState ? scrollY : 0);\n } catch (error) {\n logger7.warn("scroll handling failed", error);\n }\n this.navigationHandlers.clearPopStateFlag();\n }\n async loadPage(path, updateUI = true) {\n if (this.pageLoader.isCached(path)) {\n logger7.debug(`Loading ${path} from cache`);\n const data = this.pageLoader.getCached(path);\n if (data) {\n if (updateUI) this.updatePage(data);\n return;\n }\n logger7.warn(`Cache entry for ${path} was unexpectedly null, fetching fresh data`);\n }\n this.pageTransition.setLoadingState(true);\n try {\n const data = await this.pageLoader.loadPage(path);\n if (updateUI) this.updatePage(data);\n this.currentPath = path;\n this.options.onComplete?.(path);\n } catch (error) {\n const normalizedError = error instanceof Error ? error : new Error(String(error));\n logger7.error(`Failed to load ${path}`, normalizedError);\n this.options.onError?.(normalizedError);\n this.pageTransition.showError(normalizedError);\n } finally {\n this.pageTransition.setLoadingState(false);\n }\n }\n async prefetch(path) {\n if (this.spaMode) {\n await this.pageLoader.prefetchSpaPageData(path);\n return;\n }\n await this.pageLoader.prefetch(path);\n }\n updatePage(data) {\n if (!this.root) return;\n const isPopState = this.navigationHandlers.isPopState();\n const scrollY = this.navigationHandlers.getScrollPosition(this.currentPath);\n this.pageTransition.updatePage(data, isPopState, scrollY);\n this.navigationHandlers.clearPopStateFlag();\n }\n destroy() {\n document.removeEventListener("click", this.handleClick);\n globalThis.removeEventListener("popstate", this.handlePopState);\n document.removeEventListener("mouseover", this.handleMouseOver);\n this.viewportPrefetch.disconnect();\n this.pageLoader.clearCache();\n this.navigationHandlers.clear();\n this.pageTransition.destroy();\n }\n};\nfunction boot(options = {}) {\n if (typeof window === "undefined" || !globalThis.document) return null;\n const globalWithRouter = globalThis;\n if (globalWithRouter.veryFrontRouter) return globalWithRouter.veryFrontRouter;\n const { slug: _slug, ...routerOptions } = options;\n const router = new VeryfrontRouter(routerOptions);\n if (document.readyState === "loading") {\n document.addEventListener("DOMContentLoaded", () => router.init(), { once: true });\n } else {\n router.init();\n }\n globalWithRouter.veryFrontRouter = router;\n return router;\n}\nif (typeof window !== "undefined" && globalThis.document) {\n boot();\n}\nexport {\n VeryfrontRouter,\n boot\n};\n';
11
11
  export const CLIENT_PREFETCH_BUNDLE = 'var __defProp = Object.defineProperty;\nvar __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;\nvar __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);\n\n// src/rendering/client/browser-logger.ts\nvar ConditionalBrowserLogger = class {\n constructor(prefix, level) {\n __publicField(this, "prefix", prefix);\n __publicField(this, "level", level);\n }\n log(minLevel, fn, message, ...args) {\n if (this.level > minLevel) return;\n fn?.(message, ...args);\n }\n debug(message, ...args) {\n this.log(\n 0 /* DEBUG */,\n console.debug,\n `[${this.prefix}] DEBUG: ${message}`,\n ...args\n );\n }\n info(message, ...args) {\n this.log(1 /* INFO */, console.log, `[${this.prefix}] ${message}`, ...args);\n }\n warn(message, ...args) {\n this.log(\n 2 /* WARN */,\n console.warn,\n `[${this.prefix}] WARN: ${message}`,\n ...args\n );\n }\n error(message, ...args) {\n this.log(\n 3 /* ERROR */,\n console.error,\n `[${this.prefix}] ERROR: ${message}`,\n ...args\n );\n }\n};\nfunction getBrowserLogLevel() {\n if (typeof window === "undefined") return 2 /* WARN */;\n const g = globalThis;\n const isDevelopment = g.__VERYFRONT_DEV__ || g.__RSC_DEV__;\n if (!isDevelopment) return 2 /* WARN */;\n const isDebugEnabled2 = g.__VERYFRONT_DEBUG__ || g.__RSC_DEBUG__;\n return isDebugEnabled2 ? 0 /* DEBUG */ : 1 /* INFO */;\n}\nvar defaultLevel = getBrowserLogLevel();\nvar rscLogger = new ConditionalBrowserLogger("RSC", defaultLevel);\nvar prefetchLogger = new ConditionalBrowserLogger("PREFETCH", defaultLevel);\nvar hydrateLogger = new ConditionalBrowserLogger("HYDRATE", defaultLevel);\nvar browserLogger = new ConditionalBrowserLogger("VERYFRONT", defaultLevel);\n\n// src/rendering/client/prefetch/link-observer.ts\nfunction isAnchorElement(element) {\n return typeof HTMLAnchorElement !== "undefined" ? element instanceof HTMLAnchorElement : element.tagName === "A";\n}\nvar LinkObserver = class {\n constructor(options, prefetchedUrls) {\n __publicField(this, "options");\n __publicField(this, "intersectionObserver", null);\n __publicField(this, "mutationObserver", null);\n __publicField(this, "prefetchedUrls");\n __publicField(this, "pendingTimeouts", /* @__PURE__ */ new Map());\n __publicField(this, "elementTimeoutMap", /* @__PURE__ */ new WeakMap());\n __publicField(this, "timeoutCounter", 0);\n this.options = options;\n this.prefetchedUrls = prefetchedUrls;\n }\n init() {\n this.createIntersectionObserver();\n this.observeLinks();\n this.setupMutationObserver();\n }\n createIntersectionObserver() {\n this.intersectionObserver = new IntersectionObserver(\n (entries) => this.handleIntersection(entries),\n { rootMargin: this.options.rootMargin }\n );\n }\n handleIntersection(entries) {\n for (const entry of entries) {\n if (!entry.isIntersecting) continue;\n if (!isAnchorElement(entry.target)) continue;\n const link = entry.target;\n if (this.timeoutCounter > 1e6) this.timeoutCounter = 0;\n const timeoutKey = this.timeoutCounter++;\n const timeoutId = setTimeout(() => {\n this.pendingTimeouts.delete(timeoutKey);\n this.elementTimeoutMap.delete(link);\n this.options.onLinkVisible(link);\n }, this.options.delay);\n this.pendingTimeouts.set(timeoutKey, timeoutId);\n this.elementTimeoutMap.set(link, timeoutKey);\n }\n }\n observeLinks() {\n this.observeAnchors(document.querySelectorAll(\'a[href^="/"], a[href^="./"]\'));\n }\n setupMutationObserver() {\n this.mutationObserver = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n if (mutation.type !== "childList") continue;\n for (const node of mutation.addedNodes) {\n if (node.nodeType !== Node.ELEMENT_NODE) continue;\n this.observeElement(node);\n }\n for (const node of mutation.removedNodes) {\n if (node.nodeType !== Node.ELEMENT_NODE) continue;\n this.clearElementTimeouts(node);\n }\n }\n });\n this.mutationObserver.observe(document.body, { childList: true, subtree: true });\n }\n clearTimeoutForElement(element) {\n const timeoutKey = this.elementTimeoutMap.get(element);\n if (timeoutKey === void 0) return;\n const timeoutId = this.pendingTimeouts.get(timeoutKey);\n if (timeoutId !== void 0) {\n clearTimeout(timeoutId);\n this.pendingTimeouts.delete(timeoutKey);\n }\n this.elementTimeoutMap.delete(element);\n }\n clearElementTimeouts(element) {\n if (isAnchorElement(element)) this.clearTimeoutForElement(element);\n for (const link of element.querySelectorAll("a")) {\n this.clearTimeoutForElement(link);\n }\n }\n observeElement(element) {\n if (isAnchorElement(element) && this.isValidLink(element)) {\n this.intersectionObserver?.observe(element);\n }\n this.observeAnchors(element.querySelectorAll(\'a[href^="/"], a[href^="./"]\'));\n }\n observeAnchors(links) {\n for (const link of links) {\n if (!isAnchorElement(link)) continue;\n if (!this.isValidLink(link)) continue;\n this.intersectionObserver?.observe(link);\n }\n }\n isValidLink(link) {\n if (link.hostname !== globalThis.location.hostname) return false;\n if (link.hasAttribute("download")) return false;\n if (link.target === "_blank") return false;\n const url = link.href;\n if (this.prefetchedUrls.has(url)) return false;\n if (url === globalThis.location.href) return false;\n if (link.hash && link.pathname === globalThis.location.pathname) return false;\n if (link.dataset.noPrefetch) return false;\n return true;\n }\n destroy() {\n for (const timeoutId of this.pendingTimeouts.values()) {\n clearTimeout(timeoutId);\n }\n this.pendingTimeouts.clear();\n this.timeoutCounter = 0;\n this.intersectionObserver?.disconnect();\n this.intersectionObserver = null;\n this.mutationObserver?.disconnect();\n this.mutationObserver = null;\n }\n};\n\n// src/rendering/client/prefetch/network-utils.ts\nvar NetworkUtils = class {\n constructor(allowedNetworks = ["4g", "wifi", "ethernet"]) {\n __publicField(this, "networkInfo");\n __publicField(this, "allowedNetworks");\n this.allowedNetworks = allowedNetworks;\n this.networkInfo = this.getNetworkConnection();\n }\n getNavigatorWithConnection() {\n if (typeof globalThis.navigator === "undefined") return null;\n return globalThis.navigator;\n }\n getNetworkConnection() {\n const nav = this.getNavigatorWithConnection();\n return nav?.connection ?? nav?.mozConnection ?? nav?.webkitConnection ?? null;\n }\n shouldPrefetch() {\n if (this.networkInfo?.saveData) return false;\n const effectiveType = this.networkInfo?.effectiveType;\n if (effectiveType != null && !this.allowedNetworks.includes(effectiveType)) return false;\n return true;\n }\n onNetworkChange(callback) {\n this.networkInfo?.addEventListener?.("change", callback);\n }\n getNetworkInfo() {\n return this.networkInfo;\n }\n};\n\n// src/utils/constants/buffers.ts\nvar DEFAULT_MAX_BODY_SIZE_BYTES = 1024 * 1024;\nvar DEFAULT_MAX_FILE_SIZE_BYTES = 5 * 1024 * 1024;\nvar PREFETCH_QUEUE_MAX_SIZE_BYTES = DEFAULT_MAX_BODY_SIZE_BYTES;\nvar MAX_BUNDLE_CHUNK_SIZE_BYTES = 4096 * 1024;\n\n// src/utils/constants/cache.ts\nvar SECONDS_PER_MINUTE = 60;\nvar MINUTES_PER_HOUR = 60;\nvar HOURS_PER_DAY = 24;\nvar MS_PER_SECOND = 1e3;\nvar MS_PER_MINUTE = SECONDS_PER_MINUTE * MS_PER_SECOND;\nvar MS_PER_HOUR = MINUTES_PER_HOUR * MS_PER_MINUTE;\nvar ONE_DAY_MS = HOURS_PER_DAY * MS_PER_HOUR;\nfunction getEnvString(key) {\n const g = globalThis;\n try {\n return g.Deno?.env?.get?.(key) ?? g.process?.env?.[key];\n } catch (_) {\n return void 0;\n }\n}\nfunction getEnvNumber(key, fallback) {\n const value = getEnvString(key);\n if (value == null) return fallback;\n const parsed = Number.parseInt(value, 10);\n if (Number.isNaN(parsed)) return fallback;\n return parsed;\n}\nvar DEFAULT_LRU_MAX_ENTRIES = getEnvNumber("LRU_DEFAULT_MAX_ENTRIES", 100);\nvar COMPONENT_LOADER_MAX_ENTRIES = getEnvNumber("COMPONENT_LOADER_MAX_ENTRIES", 200);\nvar COMPONENT_LOADER_TTL_MS = 10 * MS_PER_MINUTE;\nvar MDX_RENDERER_MAX_ENTRIES = getEnvNumber("MDX_RENDERER_MAX_ENTRIES", 500);\nvar MDX_RENDERER_TTL_MS = 10 * MS_PER_MINUTE;\nvar RENDERER_CORE_MAX_ENTRIES = getEnvNumber("RENDERER_CORE_MAX_ENTRIES", 200);\nvar RENDERER_CORE_TTL_MS = 5 * MS_PER_MINUTE;\nvar TSX_LAYOUT_MAX_ENTRIES = getEnvNumber("TSX_LAYOUT_MAX_ENTRIES", 100);\nvar TSX_LAYOUT_TTL_MS = 10 * MS_PER_MINUTE;\nvar TSX_LAYOUT_PER_PROJECT_MAX_ENTRIES = getEnvNumber(\n "TSX_LAYOUT_PER_PROJECT_MAX_ENTRIES",\n Math.ceil(TSX_LAYOUT_MAX_ENTRIES / 10)\n);\nvar DATA_FETCHING_MAX_ENTRIES = getEnvNumber("DATA_FETCHING_MAX_ENTRIES", 500);\nvar DATA_FETCHING_TTL_MS = 10 * MS_PER_MINUTE;\nvar MDX_CACHE_TTL_DEVELOPMENT_MS = 5 * MS_PER_MINUTE;\nvar BUNDLE_CACHE_TTL_DEVELOPMENT_MS = 5 * MS_PER_MINUTE;\nvar BUNDLE_MANIFEST_PROD_TTL_MS = 7 * ONE_DAY_MS;\nvar SERVER_ACTION_DEFAULT_TTL_SEC = MINUTES_PER_HOUR * SECONDS_PER_MINUTE;\nvar DISTRIBUTED_SSR_MODULE_TTL_PRODUCTION_SEC = getEnvNumber(\n "DISTRIBUTED_SSR_MODULE_TTL_SEC",\n 6 * MINUTES_PER_HOUR * SECONDS_PER_MINUTE\n);\nvar DISTRIBUTED_SSR_MODULE_TTL_PREVIEW_SEC = getEnvNumber(\n "DISTRIBUTED_SSR_MODULE_TTL_PREVIEW_SEC",\n 10 * SECONDS_PER_MINUTE\n);\nvar DISTRIBUTED_TRANSFORM_TTL_PRODUCTION_SEC = getEnvNumber(\n "DISTRIBUTED_TRANSFORM_TTL_SEC",\n 6 * MINUTES_PER_HOUR * SECONDS_PER_MINUTE\n);\nvar DISTRIBUTED_TRANSFORM_TTL_PREVIEW_SEC = getEnvNumber(\n "DISTRIBUTED_TRANSFORM_TTL_PREVIEW_SEC",\n 10 * SECONDS_PER_MINUTE\n);\nvar DISTRIBUTED_FILE_TTL_PRODUCTION_SEC = getEnvNumber(\n "DISTRIBUTED_FILE_TTL_SEC",\n MINUTES_PER_HOUR * SECONDS_PER_MINUTE\n);\nvar DISTRIBUTED_FILE_TTL_PREVIEW_SEC = getEnvNumber(\n "DISTRIBUTED_FILE_TTL_PREVIEW_SEC",\n 5 * SECONDS_PER_MINUTE\n);\nvar DISTRIBUTED_CSS_TTL_PRODUCTION_SEC = getEnvNumber(\n "DISTRIBUTED_CSS_TTL_SEC",\n 6 * MINUTES_PER_HOUR * SECONDS_PER_MINUTE\n);\nvar DISTRIBUTED_CSS_TTL_PREVIEW_SEC = getEnvNumber(\n "DISTRIBUTED_CSS_TTL_PREVIEW_SEC",\n 10 * SECONDS_PER_MINUTE\n);\nvar LRU_DEFAULT_MAX_ENTRIES_V2 = getEnvNumber("LRU_MAX_ENTRIES", 2e3);\nvar LRU_DEFAULT_MAX_SIZE_BYTES = getEnvNumber("LRU_MAX_SIZE_MB", 200) * 1024 * 1024;\nvar MEMORY_CACHE_MAX_ENTRIES = getEnvNumber("MEMORY_CACHE_MAX_ENTRIES", 2e3);\nvar MEMORY_CACHE_MAX_SIZE_BYTES = getEnvNumber("MEMORY_CACHE_MAX_SIZE_MB", 50) * 1024 * 1024;\nvar FILE_CACHE_MAX_ENTRIES = getEnvNumber("FILE_CACHE_MAX_ENTRIES", 1e3);\nvar FILE_CACHE_MAX_SIZE_MB = getEnvNumber("FILE_CACHE_MAX_SIZE_MB", 100);\nvar MAX_CONCURRENT_REVALIDATIONS = getEnvNumber("MAX_CONCURRENT_REVALIDATIONS", 32);\nvar MAX_CONCURRENT_HTTP_FETCHES = getEnvNumber("MAX_CONCURRENT_HTTP_FETCHES", 50);\nvar REVALIDATION_TIMEOUT_MS = getEnvNumber("REVALIDATION_TIMEOUT_MS", 15e3);\nvar REVALIDATION_PER_PROJECT_LIMIT = getEnvNumber(\n "REVALIDATION_PER_PROJECT_LIMIT",\n Math.ceil(MAX_CONCURRENT_REVALIDATIONS / 3)\n);\nvar BUNDLE_MANIFEST_DISTRIBUTED_TTL_SEC = getEnvNumber(\n "BUNDLE_MANIFEST_DISTRIBUTED_TTL_SEC",\n HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE\n // 24 hours (86400)\n);\nvar BUNDLE_MANIFEST_LRU_MAX_ENTRIES = getEnvNumber(\n "BUNDLE_MANIFEST_LRU_MAX_ENTRIES",\n 5e3\n);\nvar HTTP_MODULE_CACHE_MAX_ENTRIES = getEnvNumber("HTTP_MODULE_CACHE_MAX_ENTRIES", 2e3);\nvar HTTP_MODULE_DISTRIBUTED_TTL_SEC = getEnvNumber(\n "HTTP_MODULE_DISTRIBUTED_TTL_SEC",\n HOURS_PER_DAY * MINUTES_PER_HOUR * SECONDS_PER_MINUTE\n // 24 hours (86400)\n);\nvar TRANSFORM_DISTRIBUTED_TTL_SEC = getEnvNumber(\n "TRANSFORM_DISTRIBUTED_TTL_SEC",\n 6 * MINUTES_PER_HOUR * SECONDS_PER_MINUTE\n // 6 hours (21600)\n);\nvar MODULE_CACHE_MAX_ENTRIES = getEnvNumber("MODULE_CACHE_MAX_ENTRIES", 1e4);\nvar MODULE_CACHE_TTL_MS = getEnvNumber(\n "MODULE_CACHE_TTL_MS",\n 5 * MS_PER_MINUTE\n // 5 minutes - short enough to pick up changes, long enough to cache\n);\nvar ESM_CACHE_MAX_ENTRIES = getEnvNumber("ESM_CACHE_MAX_ENTRIES", 5e3);\nvar ESM_CACHE_TTL_MS = getEnvNumber(\n "ESM_CACHE_TTL_MS",\n 10 * MS_PER_MINUTE\n // 10 minutes - external modules change less frequently\n);\n\n// src/utils/constants/http.ts\nvar KB_IN_BYTES = 1024;\nvar PREFETCH_MAX_SIZE_BYTES = 200 * KB_IN_BYTES;\n\n// src/utils/constants/hmr.ts\nvar HMR_MAX_MESSAGE_SIZE_BYTES = 1024 * KB_IN_BYTES;\n\n// src/utils/constants/network.ts\nvar BYTES_PER_KB = 1024;\nvar BYTES_PER_MB = BYTES_PER_KB * BYTES_PER_KB;\n\n// src/utils/constants/server.ts\nvar INTERNAL_PREFIX = "/_veryfront";\nvar INTERNAL_PATH_PREFIXES = {\n /** React Server Components endpoints */\n RSC: `${INTERNAL_PREFIX}/rsc/`,\n /** File system access endpoints (base64 encoded paths) */\n FS: `${INTERNAL_PREFIX}/fs/`,\n /** Virtual module system */\n MODULES: `${INTERNAL_PREFIX}/modules/`,\n /** Generated page modules */\n PAGES: `${INTERNAL_PREFIX}/pages/`,\n /** Data JSON endpoints */\n DATA: `${INTERNAL_PREFIX}/data/`,\n /** Library modules and large vendor surfaces */\n LIB: `${INTERNAL_PREFIX}/lib/`,\n /** Chunk assets */\n CHUNKS: `${INTERNAL_PREFIX}/chunks/`,\n /** Client component modules */\n CLIENT: `${INTERNAL_PREFIX}/client/`\n};\nvar INTERNAL_ENDPOINTS = {\n // Development endpoints\n HMR_RUNTIME: `${INTERNAL_PREFIX}/hmr-runtime.js`,\n HMR: `${INTERNAL_PREFIX}/hmr.js`,\n ERROR_OVERLAY: `${INTERNAL_PREFIX}/error-overlay.js`,\n // Legacy endpoint retained for backward compatibility (no active handler).\n DEV_LOADER: `${INTERNAL_PREFIX}/dev-loader.js`,\n CLIENT_LOG: `${INTERNAL_PREFIX}/log`,\n // Production endpoints\n CLIENT_JS: `${INTERNAL_PREFIX}/client.js`,\n ROUTER_JS: `${INTERNAL_PREFIX}/router.js`,\n PREFETCH_JS: `${INTERNAL_PREFIX}/prefetch.js`,\n MANIFEST_JSON: `${INTERNAL_PREFIX}/manifest.json`,\n APP_JS: `${INTERNAL_PREFIX}/app.js`,\n // RSC endpoints\n RSC_CLIENT: `${INTERNAL_PREFIX}/rsc/client.js`,\n RSC_MANIFEST: `${INTERNAL_PREFIX}/rsc/manifest`,\n RSC_STREAM: `${INTERNAL_PREFIX}/rsc/stream`,\n RSC_PAYLOAD: `${INTERNAL_PREFIX}/rsc/payload`,\n RSC_RENDER: `${INTERNAL_PREFIX}/rsc/render`,\n RSC_PAGE: `${INTERNAL_PREFIX}/rsc/page`,\n RSC_MODULE: `${INTERNAL_PREFIX}/rsc/module`,\n RSC_DOM: `${INTERNAL_PREFIX}/rsc/dom.js`,\n // Library module endpoints\n LIB_CHAT_REACT: `${INTERNAL_PREFIX}/lib/chat/react.js`,\n LIB_CHAT_COMPONENTS: `${INTERNAL_PREFIX}/lib/chat/components.js`,\n LIB_CHAT_PRIMITIVES: `${INTERNAL_PREFIX}/lib/chat/primitives.js`\n};\nvar PROJECT_DIRS = {\n /** Base veryfront internal directory */\n ROOT: ".veryfront",\n /** Cache directory for build artifacts, transforms, etc. */\n CACHE: ".veryfront/cache",\n /** KV store directory */\n KV: ".veryfront/kv",\n /** Log files directory */\n LOGS: ".veryfront/logs",\n /** Temporary files directory */\n TMP: ".veryfront/tmp"\n};\nvar DEFAULT_CACHE_DIR = PROJECT_DIRS.CACHE;\nvar DEV_SERVER_ENDPOINTS = {\n HMR_RUNTIME: INTERNAL_ENDPOINTS.HMR_RUNTIME,\n ERROR_OVERLAY: INTERNAL_ENDPOINTS.ERROR_OVERLAY\n};\n\n// src/rendering/client/prefetch/prefetch-queue.ts\nvar DEFAULT_OPTIONS = {\n maxConcurrent: 4,\n maxSize: PREFETCH_QUEUE_MAX_SIZE_BYTES,\n timeout: 5e3\n};\nfunction isAbortError(error) {\n if (typeof error !== "object" || error === null) return false;\n if (!("name" in error)) return false;\n return error.name === "AbortError";\n}\nvar PrefetchQueue = class {\n constructor(options = {}, prefetchedUrls) {\n __publicField(this, "options");\n __publicField(this, "controllers", /* @__PURE__ */ new Map());\n __publicField(this, "prefetchedUrls");\n __publicField(this, "concurrent", 0);\n __publicField(this, "stopped", false);\n __publicField(this, "onResourcesFetched");\n this.options = { ...DEFAULT_OPTIONS, ...options };\n this.prefetchedUrls = prefetchedUrls ?? /* @__PURE__ */ new Set();\n }\n setResourceCallback(callback) {\n this.onResourcesFetched = callback;\n }\n enqueue(url) {\n void this.prefetch(url);\n }\n has(url) {\n return this.prefetchedUrls.has(url) || this.controllers.has(url);\n }\n get size() {\n return this.controllers.size;\n }\n clear() {\n this.stopAll();\n this.prefetchedUrls.clear();\n }\n start() {\n this.stopped = false;\n }\n stop() {\n this.stopped = true;\n this.stopAll();\n }\n getQueueSize() {\n return this.controllers.size;\n }\n getConcurrentCount() {\n return this.concurrent;\n }\n async prefetchLink(link) {\n if (this.stopped) return;\n const url = link.href;\n if (!url || this.controllers.has(url) || this.prefetchedUrls.has(url)) return;\n if (this.concurrent >= this.options.maxConcurrent) {\n prefetchLogger.debug?.(`Prefetch queue full, skipping ${url}`);\n return;\n }\n let parsedUrl;\n try {\n parsedUrl = new URL(url);\n } catch (_) {\n prefetchLogger.debug?.(`Invalid prefetch URL ${url}`);\n return;\n }\n const controller = new AbortController();\n this.controllers.set(url, controller);\n this.concurrent += 1;\n const timeoutId = this.options.timeout > 0 ? setTimeout(() => controller.abort(), this.options.timeout) : void 0;\n try {\n const response = await fetch(parsedUrl.toString(), {\n method: "GET",\n signal: controller.signal,\n headers: { "X-Veryfront-Prefetch": "1" }\n });\n if (!response.ok) return;\n if (this.isResponseTooLarge(response)) {\n prefetchLogger.debug?.(`Prefetch too large, skipping ${url}`);\n return;\n }\n this.prefetchedUrls.add(url);\n if (!this.onResourcesFetched) return;\n try {\n await this.onResourcesFetched(response, url);\n } catch (callbackError) {\n prefetchLogger.error?.(`Prefetch callback failed for ${url}`, callbackError);\n }\n } catch (error) {\n if (!isAbortError(error)) {\n prefetchLogger.error?.(`Failed to prefetch ${url}`, error);\n }\n } finally {\n if (timeoutId !== void 0) clearTimeout(timeoutId);\n this.controllers.delete(url);\n this.concurrent = Math.max(0, this.concurrent - 1);\n }\n }\n async prefetch(url) {\n const link = typeof document !== "undefined" ? document.createElement("a") : { href: url };\n link.href = url;\n await this.prefetchLink(link);\n }\n stopAll() {\n for (const controller of this.controllers.values()) {\n controller.abort();\n }\n this.controllers.clear();\n this.concurrent = 0;\n }\n isResponseTooLarge(response) {\n const rawLength = response.headers.get("content-length");\n if (rawLength === null) return false;\n const size = Number.parseInt(rawLength, 10);\n if (!Number.isFinite(size)) return false;\n return size > this.options.maxSize;\n }\n};\nvar prefetchQueue = new PrefetchQueue();\n\n// src/rendering/client/prefetch/resource-hints.ts\nvar ResourceHintsManager = class {\n constructor() {\n __publicField(this, "appliedHints", /* @__PURE__ */ new Set());\n }\n applyResourceHints(hints) {\n for (const hint of hints) {\n const key = `${hint.type}:${hint.href}`;\n if (this.appliedHints.has(key)) continue;\n const existing = document.querySelector(\n `link[rel="${hint.type}"][href="${hint.href}"]`\n );\n if (existing) {\n this.appliedHints.add(key);\n continue;\n }\n this.createAndAppendHint(hint);\n this.appliedHints.add(key);\n prefetchLogger.debug(`Added resource hint: ${hint.type} ${hint.href}`);\n }\n }\n createAndAppendHint(hint) {\n if (!document.head) {\n prefetchLogger.warn("document.head is not available, skipping resource hint");\n return;\n }\n const link = document.createElement("link");\n link.rel = hint.type;\n link.href = hint.href;\n if (hint.as) link.setAttribute("as", hint.as);\n if (hint.crossOrigin) link.setAttribute("crossorigin", hint.crossOrigin);\n if (hint.media) link.setAttribute("media", hint.media);\n document.head.appendChild(link);\n }\n extractResourceHints(html, prefetchedUrls) {\n try {\n const doc = new DOMParser().parseFromString(html, "text/html");\n const hints = [];\n this.extractPreloadLinks(doc, prefetchedUrls, hints);\n this.extractScripts(doc, prefetchedUrls, hints);\n this.extractStylesheets(doc, prefetchedUrls, hints);\n return hints;\n } catch (error) {\n prefetchLogger.error("Failed to parse prefetched page", error);\n return [];\n }\n }\n isValidResourceHintType(rel) {\n switch (rel) {\n case "prefetch":\n case "preload":\n case "preconnect":\n case "dns-prefetch":\n return true;\n default:\n return false;\n }\n }\n extractPreloadLinks(doc, prefetchedUrls, hints) {\n const links = doc.querySelectorAll(\n \'link[rel="preload"], link[rel="prefetch"]\'\n );\n for (const link of links) {\n const href = link.href;\n if (!href) continue;\n if (prefetchedUrls.has(href)) continue;\n if (!this.isValidResourceHintType(link.rel)) continue;\n hints.push({\n type: link.rel,\n href,\n as: link.getAttribute("as") ?? void 0\n });\n }\n }\n extractScripts(doc, prefetchedUrls, hints) {\n for (const script of doc.querySelectorAll("script[src]")) {\n const src = script.src;\n if (!src || prefetchedUrls.has(src)) continue;\n hints.push({ type: "prefetch", href: src, as: "script" });\n }\n }\n extractStylesheets(doc, prefetchedUrls, hints) {\n for (const link of doc.querySelectorAll(\'link[rel="stylesheet"]\')) {\n const href = link.href;\n if (!href || prefetchedUrls.has(href)) continue;\n hints.push({ type: "prefetch", href, as: "style" });\n }\n }\n static generateResourceHints(_route, assets) {\n const hints = [\n \'<link rel="dns-prefetch" href="https://cdn.jsdelivr.net">\',\n \'<link rel="dns-prefetch" href="https://esm.sh">\',\n \'<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin>\'\n ];\n for (const asset of assets) {\n if (asset.endsWith(".js")) {\n hints.push(`<link rel="modulepreload" href="${asset}">`);\n continue;\n }\n if (asset.endsWith(".css")) {\n hints.push(`<link rel="preload" as="style" href="${asset}">`);\n continue;\n }\n if (/\\.(woff2?|ttf|otf)$/.test(asset)) {\n hints.push(`<link rel="preload" as="font" href="${asset}" crossorigin>`);\n }\n }\n return hints.join("\\n");\n }\n};\n\n// src/rendering/client/browser-stubs/logger.ts\nfunction noop() {\n}\nvar logger = {\n debug: noop,\n info: console.log.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n component: () => logger\n};\nvar PREFETCH_MAX_SIZE_BYTES2 = 200 * 1024;\nvar PREFETCH_DEFAULT_TIMEOUT_MS2 = 1e4;\nvar PREFETCH_DEFAULT_DELAY_MS2 = 200;\n\n// src/rendering/client/prefetch.ts\nvar PrefetchManager = class {\n constructor(options = {}) {\n __publicField(this, "options");\n __publicField(this, "prefetchedUrls", /* @__PURE__ */ new Set());\n __publicField(this, "networkUtils");\n __publicField(this, "linkObserver", null);\n __publicField(this, "resourceHintsManager");\n __publicField(this, "prefetchQueue");\n this.options = {\n rootMargin: options.rootMargin ?? "50px",\n delay: options.delay ?? PREFETCH_DEFAULT_DELAY_MS2,\n maxConcurrent: options.maxConcurrent ?? 2,\n allowedNetworks: options.allowedNetworks ?? ["4g", "wifi", "ethernet"],\n maxSize: options.maxSize ?? PREFETCH_MAX_SIZE_BYTES2,\n timeout: options.timeout ?? PREFETCH_DEFAULT_TIMEOUT_MS2\n };\n this.networkUtils = new NetworkUtils(this.options.allowedNetworks);\n this.resourceHintsManager = new ResourceHintsManager();\n this.prefetchQueue = new PrefetchQueue(\n {\n maxConcurrent: this.options.maxConcurrent,\n maxSize: this.options.maxSize,\n timeout: this.options.timeout\n },\n this.prefetchedUrls\n );\n this.prefetchQueue.setResourceCallback(\n (response, url) => this.prefetchPageResources(response, url)\n );\n }\n init() {\n prefetchLogger.info("Initializing prefetch manager");\n if (!this.networkUtils.shouldPrefetch()) {\n prefetchLogger.info("Prefetching disabled due to network conditions");\n return;\n }\n this.linkObserver = new LinkObserver(\n {\n rootMargin: this.options.rootMargin,\n delay: this.options.delay,\n onLinkVisible: (link) => this.prefetchQueue.prefetchLink(link)\n },\n this.prefetchedUrls\n );\n this.linkObserver.init();\n this.networkUtils.onNetworkChange(() => {\n if (!this.networkUtils.shouldPrefetch()) this.prefetchQueue.stopAll();\n });\n }\n async prefetchPageResources(response, _pageUrl) {\n const html = await response.text();\n const hints = this.resourceHintsManager.extractResourceHints(html, this.prefetchedUrls);\n this.resourceHintsManager.applyResourceHints(hints);\n }\n applyResourceHints(hints) {\n this.resourceHintsManager.applyResourceHints(hints);\n }\n async prefetch(url) {\n await this.prefetchQueue.prefetch(url);\n }\n static generateResourceHints(route, assets) {\n return ResourceHintsManager.generateResourceHints(route, assets);\n }\n destroy() {\n this.linkObserver?.destroy();\n this.prefetchQueue.stopAll();\n this.prefetchedUrls.clear();\n }\n};\nfunction initPrefetch(options) {\n const prefetchManager = new PrefetchManager(options);\n if (document.readyState === "loading") {\n document.addEventListener("DOMContentLoaded", () => prefetchManager.init(), { once: true });\n } else {\n prefetchManager.init();\n }\n globalThis.veryFrontPrefetch = prefetchManager;\n return prefetchManager;\n}\nfunction resolveAutoInitOptions() {\n const setting = globalThis.__VERYFRONT_PREFETCH__;\n if (!setting) return null;\n if (setting === true) return {};\n if (typeof setting === "object") return setting;\n return null;\n}\nfunction shouldAutoInitPrefetch(options) {\n if (!options) return false;\n if (typeof window === "undefined" || typeof document === "undefined") return false;\n const win = window;\n const doc = document;\n if (win.__veryfrontSSRStub || doc.__veryfrontSSRStub) return false;\n if (typeof IntersectionObserver === "undefined") return false;\n if (typeof MutationObserver === "undefined") return false;\n return true;\n}\nvar autoInitOptions = resolveAutoInitOptions();\nif (shouldAutoInitPrefetch(autoInitOptions)) initPrefetch(autoInitOptions);\nexport {\n PrefetchManager,\n initPrefetch\n};\n';
@@ -9,6 +9,13 @@ export interface InjectHTMLContentOptions {
9
9
  projectDir?: string;
10
10
  /** Whether the page has 'use client' directive */
11
11
  isClientPage?: boolean;
12
+ /**
13
+ * Route params from the initial match, seeded into the 'use client' hydration
14
+ * payload so full-HTML-document client pages hydrate with their params
15
+ * instead of an empty object (issue #2741). Catch-all arrays are preserved;
16
+ * the client runtime joins them (issue #2742).
17
+ */
18
+ params?: Record<string, string | string[]>;
12
19
  /** Whether page is embedded in Studio iframe */
13
20
  studioEmbed?: boolean;
14
21
  /** Project ID for Studio communication */
@@ -1 +1 @@
1
- {"version":3,"file":"html-injection.d.ts","sourceRoot":"","sources":["../../../src/src/html/html-injection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAkB/D,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gDAAgD;IAChD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,WAAW,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC;IACvC,+DAA+D;IAC/D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAgBD,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,wBAAwB,GAChC,MAAM,CAwGR"}
1
+ {"version":3,"file":"html-injection.d.ts","sourceRoot":"","sources":["../../../src/src/html/html-injection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAmB/D,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC3C,gDAAgD;IAChD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,WAAW,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC;IACvC,+DAA+D;IAC/D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAgBD,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,wBAAwB,GAChC,MAAM,CA6GR"}
@@ -2,6 +2,7 @@ import { resolveRelativePath } from "../modules/react-loader/path-resolver.js";
2
2
  import { determineClientModuleStrategy } from "../rendering/rsc/client-module-strategy.js";
3
3
  import { generateLinkTags, generateMetaTags, generateScriptTags, generateStyleTags, } from "./tag-generators.js";
4
4
  import { buildNonceAttribute } from "./html-escape.js";
5
+ import { jsonForInlineScript } from "../security/client/html-sanitizer.js";
5
6
  import { getDevScripts, getDevStyles, getPreviewStylesheetLink, getProdScripts, getStudioScripts, } from "./dev-scripts.js";
6
7
  function toProjectRelativePath(absolutePath, projectDir) {
7
8
  const normalizedPath = absolutePath.replace(/\\/g, "/");
@@ -49,10 +50,15 @@ export function injectHTMLContent(template, content, metadata, options) {
49
50
  const hasBodyClose = /<\/body>/i.test(html);
50
51
  // Inject hydration data for 'use client' pages (before scripts, so client.js can find it)
51
52
  if (options.pagePath && options.isClientPage && hasBodyClose) {
52
- const hydrationData = JSON.stringify({
53
+ // Serialize with jsonForInlineScript, not raw JSON.stringify: route params
54
+ // (and slug) are URL-derived and decoded, so a segment like `%3C/script%3E`
55
+ // would otherwise break out of the <script> tag (reflected XSS). This escapes
56
+ // `<`, `>`, `&`, and line separators, matching the main shell hydration path.
57
+ const hydrationData = jsonForInlineScript({
53
58
  pagePath: toProjectRelativePath(options.pagePath, options.projectDir),
54
59
  slug: options.slug,
55
60
  isClientPage: true,
61
+ params: options.params ?? {},
56
62
  clientModuleStrategy: determineClientModuleStrategy({
57
63
  isLocalProject: options.isLocalProject ?? options.mode === "development",
58
64
  environment: options.environment,
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../../../src/src/html/hydration-script-builder/templates/renderer.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,cAwN7B,CAAC"}
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../../../src/src/html/hydration-script-builder/templates/renderer.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,cA4N7B,CAAC"}
@@ -112,7 +112,11 @@ export const getRendererScript = () => `
112
112
  return;
113
113
  }
114
114
 
115
- const pageProps = { ...(data.props || {}), params: data.params || {} };
115
+ // Normalize catch-all params (arrays -> joined strings) so the hydrated
116
+ // props and page context match the server render. normalizeRouteParams
117
+ // is defined in router.ts, which loads first (issue #2742).
118
+ const normalizedParams = normalizeRouteParams(data.params);
119
+ const pageProps = { ...(data.props || {}), params: normalizedParams };
116
120
  let tree = React.createElement(PageComponent, pageProps);
117
121
 
118
122
  const layouts = data.layouts;
@@ -143,7 +147,7 @@ export const getRendererScript = () => `
143
147
  const pageContext = {
144
148
  slug: data.slug || '',
145
149
  path: data.pagePath || resolvedPathname,
146
- params: data.params || {},
150
+ params: normalizedParams,
147
151
  query: Object.fromEntries(new URLSearchParams(window.location.search)),
148
152
  frontmatter: data.frontmatter || {},
149
153
  headings,
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../../../src/src/html/hydration-script-builder/templates/router.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,cAklC3B,CAAC"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../../../src/src/html/hydration-script-builder/templates/router.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,cA2nC3B,CAAC"}
@@ -604,13 +604,18 @@ export const getRouterScript = () => `
604
604
  window.history.pushState({ pageData, scrollY: 0 }, '', href);
605
605
  }
606
606
 
607
- perfStart('nav:render:' + href);
608
- await renderPageFromData(pageData, targetPath);
609
- perfEnd('nav:render:' + href);
610
-
607
+ // Update the shared router snapshot BEFORE rendering. RouterProvider
608
+ // reads router.params during render, so mutating after renderPageFromData
609
+ // would leave the new page's first render with the previous route's
610
+ // params (issue #2741). pathname/query move up for the same reason.
611
611
  currentPath = targetPath;
612
612
  window.__veryfrontRouter.pathname = targetPath;
613
613
  window.__veryfrontRouter.query = Object.fromEntries(new URLSearchParams(window.location.search));
614
+ window.__veryfrontRouter.params = normalizeRouteParams(pageData.params);
615
+
616
+ perfStart('nav:render:' + href);
617
+ await renderPageFromData(pageData, targetPath);
618
+ perfEnd('nav:render:' + href);
614
619
 
615
620
  if (restoreScroll) {
616
621
  restoreScrollPosition(targetPath);
@@ -708,9 +713,15 @@ export const getRouterScript = () => `
708
713
  }
709
714
  }
710
715
 
716
+ // Normalize catch-all params (arrays -> joined strings) so page props and
717
+ // page context match the server render exactly. SSR emits joined strings
718
+ // via flattenRouteParams; without this the client would hand raw arrays to
719
+ // props and usePageContext() after navigation (issue #2742).
720
+ const normalizedParams = normalizeRouteParams(pageData.params);
721
+
711
722
  let tree = React.createElement(PageComponent, {
712
723
  ...pageData.props,
713
- params: pageData.params
724
+ params: normalizedParams
714
725
  });
715
726
 
716
727
  if (pageData.layouts?.length) {
@@ -733,7 +744,7 @@ export const getRouterScript = () => `
733
744
  const pageContext = {
734
745
  slug: pageData.slug || '',
735
746
  path: pageData.pagePath || targetPath,
736
- params: pageData.params || {},
747
+ params: normalizedParams,
737
748
  query: Object.fromEntries(new URLSearchParams(window.location.search)),
738
749
  frontmatter: pageData.frontmatter || {},
739
750
  headings: headingsArray,
@@ -951,6 +962,22 @@ export const getRouterScript = () => `
951
962
  }, IDLE_PREFETCH_DELAY_MS);
952
963
  }
953
964
 
965
+ // ============================================
966
+ // Route params normalization
967
+ // ============================================
968
+ // Catch-all segments arrive as arrays and are joined so no path info is
969
+ // lost, matching the server flattenRouteParams + RSC hydration normalizer.
970
+ function normalizeRouteParams(raw) {
971
+ const out = {};
972
+ if (!raw) return out;
973
+ for (const key in raw) {
974
+ const value = raw[key];
975
+ if (value === undefined) continue;
976
+ out[key] = Array.isArray(value) ? value.join('/') : value;
977
+ }
978
+ return out;
979
+ }
980
+
954
981
  // ============================================
955
982
  // Router object
956
983
  // ============================================
@@ -974,7 +1001,17 @@ export const getRouterScript = () => `
974
1001
  },
975
1002
  pathname: window.location.pathname,
976
1003
  query: Object.fromEntries(new URLSearchParams(window.location.search)),
977
- params: {},
1004
+ // Seed route params from the hydration data (issue #2741). Catch-all
1005
+ // segments arrive as arrays and are joined so no path info is lost.
1006
+ params: (function () {
1007
+ try {
1008
+ const el = document.getElementById('veryfront-hydration-data');
1009
+ const raw = (JSON.parse(el && el.textContent ? el.textContent : '{}') || {}).params || {};
1010
+ return normalizeRouteParams(raw);
1011
+ } catch (_) {
1012
+ return {};
1013
+ }
1014
+ })(),
978
1015
  isPreview: false,
979
1016
  isMounted: true,
980
1017
  navigate: (path) => navigateSPA(path, true),
@@ -999,10 +1036,14 @@ export const getRouterScript = () => `
999
1036
 
1000
1037
  showNavigationProgress();
1001
1038
  try {
1002
- await renderPageFromData(e.state.pageData, path);
1039
+ // Update the router snapshot before rendering so RouterProvider reads
1040
+ // this route's params, not the previous route's (issue #2741).
1003
1041
  currentPath = path;
1004
1042
  window.__veryfrontRouter.pathname = path;
1005
1043
  window.__veryfrontRouter.query = Object.fromEntries(new URLSearchParams(window.location.search));
1044
+ window.__veryfrontRouter.params = normalizeRouteParams(e.state.pageData.params);
1045
+
1046
+ await renderPageFromData(e.state.pageData, path);
1006
1047
 
1007
1048
  restoreScrollPosition(path);
1008
1049
  hideNavigationProgress();
@@ -33,7 +33,15 @@ export type LinkProps = React.AnchorHTMLAttributes<HTMLAnchorElement> & {
33
33
  export interface RouterProviderProps {
34
34
  /** React children rendered within the router context. */
35
35
  children: React.ReactNode;
36
- /** Router value to expose to descendants. */
36
+ /**
37
+ * The router snapshot. On the server it is exposed verbatim. On the client it
38
+ * seeds `params`/`domain`/`isPreview` and the initial `pathname`/`query` — the
39
+ * server-render snapshot the first client render must match — after which
40
+ * `pathname`/`query` track the live URL through the navigation store.
41
+ *
42
+ * This is the single source for everything the URL and route match know;
43
+ * callers hand over one `RouterValue` rather than loose href/param fields.
44
+ */
37
45
  router?: RouterValue;
38
46
  }
39
47
  /** Heading metadata extracted from MDX content. */
@@ -69,13 +77,57 @@ export interface PageContextProviderProps {
69
77
  /** Page context value to expose to descendants. */
70
78
  pageContext?: PageContextValue;
71
79
  }
72
- /** Provides the router context value used by `useRouter()`. */
73
- export declare function RouterProvider({ children, router, }: RouterProviderProps): React.ReactElement;
74
- /** Reads the current router context. */
80
+ /**
81
+ * Provides the router context. `pathname`/`query` track the live URL through the
82
+ * shared navigation store's `useSyncExternalStore` surface; `params`/`domain`
83
+ * are seeded from the `router` prop. One component serves both sides: React uses
84
+ * `getServerSnapshot` (the seed href) during SSR and the live store on the
85
+ * client, so there is no environment branch — the server render and the first
86
+ * client render match by construction.
87
+ *
88
+ * The store is a stable singleton that exists on first access, so there is no
89
+ * "is the router mounted yet?" race: the subscription is live from the first
90
+ * render, and the router's navigations notify through the same object. Page
91
+ * context (frontmatter/slug/headings) is a separate concern, provided by
92
+ * `PageContextProvider`, which derives its live location from this router.
93
+ */
94
+ export declare function RouterProvider({ router, children }: RouterProviderProps): React.ReactElement;
95
+ /** Options for {@link wrapForHydration}. */
96
+ export interface HydrationWrapOptions {
97
+ /** Route params from the initial match. */
98
+ params?: Record<string, string>;
99
+ /** Page frontmatter, exposed reactively through `usePageContext()`. */
100
+ frontmatter?: Record<string, unknown>;
101
+ }
102
+ /**
103
+ * Wraps a hydrated client component in `RouterProvider` (router state) nested
104
+ * with `PageContextProvider` (frontmatter), seeded from the live location plus
105
+ * the initial route match — mirroring how SSR wraps the tree.
106
+ *
107
+ * The RSC hydration path calls this through a runtime import of
108
+ * `veryfront/router`, so it runs under the app's React instance — the same one
109
+ * the hydrated component uses, and the same providers and `React` this module
110
+ * already reference. That is why the caller does not (and must not) pass a
111
+ * `React` across the module boundary: the wrapping happens here, inside the
112
+ * module that owns React.
113
+ */
114
+ export declare function wrapForHydration(child: React.ReactNode, options?: HydrationWrapOptions): React.ReactElement;
115
+ /**
116
+ * Reads the router context: `pathname`, `query`, `params`, and the navigation
117
+ * actions. Reactive across client-side navigation — this is the single hook for
118
+ * location and navigation state.
119
+ */
75
120
  export declare function useRouter(): RouterValue;
76
121
  /** Renders an anchor element annotated for Veryfront prefetch handling. */
77
122
  export declare function Link({ prefetch, children, ...rest }: LinkProps): React.ReactElement;
78
- /** Provides page context to route and MDX descendants. */
123
+ /**
124
+ * Provides page context to route and MDX descendants. Page-authored fields
125
+ * (`frontmatter`, `slug`, `headings`) come from the `pageContext` prop; the
126
+ * location fields (`path`, `query`, `params`) are derived from the router so
127
+ * they stay reactive and there is a single source of truth — `usePageContext()`
128
+ * exposes the same `query`/`pathname` as `useRouter()`. When rendered outside a
129
+ * `RouterProvider` (no live router) it falls back to the seed's own location.
130
+ */
79
131
  export declare function PageContextProvider({ children, pageContext, }: PageContextProviderProps): React.ReactElement;
80
132
  /** Reads the current page context. */
81
133
  export declare function usePageContext(): PageContextValue;
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../../src/src/react/runtime/core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../../../src/src/react/runtime/core.ts"],"names":[],"mappings":"AACA,OAAO,KAAoB,MAAM,yBAAyB,CAAC;AAE3D,kDAAkD;AAClD,MAAM,WAAW,WAAW;IAC1B,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,qDAAqD;IACrD,SAAS,EAAE,OAAO,CAAC;IACnB,4CAA4C;IAC5C,SAAS,EAAE,OAAO,CAAC;IACnB,iDAAiD;IACjD,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,6CAA6C;IAC7C,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,oDAAoD;IACpD,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,gCAAgC;IAChC,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED,kCAAkC;AAClC,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,GAAG;IACtE,wDAAwD;IACxD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,4CAA4C;AAC5C,MAAM,WAAW,mBAAmB;IAClC,yDAAyD;IACzD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,mDAAmD;AACnD,MAAM,WAAW,UAAU;IACzB,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wDAAwD;AACxD,MAAM,WAAW,gBAAgB;IAC/B,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,+BAA+B;IAC/B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,+CAA+C;IAC/C,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,mDAAmD;IACnD,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED,iDAAiD;AACjD,MAAM,WAAW,wBAAwB;IACvC,uDAAuD;IACvD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,mDAAmD;IACnD,WAAW,CAAC,EAAE,gBAAgB,CAAC;CAChC;AAqKD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,mBAAmB,GAAG,KAAK,CAAC,YAAY,CA0C5F;AAED,4CAA4C;AAC5C,MAAM,WAAW,oBAAoB;IACnC,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,uEAAuE;IACvE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,KAAK,CAAC,SAAS,EACtB,OAAO,GAAE,oBAAyB,GACjC,KAAK,CAAC,YAAY,CA6BpB;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,WAAW,CAEvC;AAED,2EAA2E;AAC3E,wBAAgB,IAAI,CAAC,EACnB,QAAe,EACf,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,SAAS,GAAG,KAAK,CAAC,YAAY,CAMhC;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,WAAW,GACZ,EAAE,wBAAwB,GAAG,KAAK,CAAC,YAAY,CAc/C;AAED,sCAAsC;AACtC,wBAAgB,cAAc,IAAI,gBAAgB,CAEjD;AAED,sEAAsE;AACtE,wBAAgB,IAAI,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,GAAG,KAAK,CAAC,YAAY,CAwIpF;AAED,OAAO,EAAE,cAAc,IAAI,MAAM,EAAE,CAAC"}