void-plugin-hono-jsx 0.1.0-alpha.2 → 0.1.0-alpha.4

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 (95) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/README.md +73 -20
  3. package/THIRD_PARTY_NOTICES.md +2 -2
  4. package/dist/browser/client.d.ts +2 -1
  5. package/dist/browser/client.d.ts.map +1 -1
  6. package/dist/browser/client.js +76 -22
  7. package/dist/browser/client.js.map +1 -1
  8. package/dist/browser/document-head.d.ts +1 -1
  9. package/dist/browser/document-head.d.ts.map +1 -1
  10. package/dist/browser/document-head.js +22 -1
  11. package/dist/browser/document-head.js.map +1 -1
  12. package/dist/browser/form-view.d.ts +10 -0
  13. package/dist/browser/form-view.d.ts.map +1 -0
  14. package/dist/browser/form-view.js +16 -0
  15. package/dist/browser/form-view.js.map +1 -0
  16. package/dist/browser/form.d.ts +28 -12
  17. package/dist/browser/form.d.ts.map +1 -1
  18. package/dist/browser/form.js +84 -23
  19. package/dist/browser/form.js.map +1 -1
  20. package/dist/browser/markdown.d.ts +15 -0
  21. package/dist/browser/markdown.d.ts.map +1 -0
  22. package/dist/browser/markdown.js +6 -0
  23. package/dist/browser/markdown.js.map +1 -0
  24. package/dist/browser/navigation.d.ts +13 -0
  25. package/dist/browser/navigation.d.ts.map +1 -0
  26. package/dist/browser/navigation.js +83 -0
  27. package/dist/browser/navigation.js.map +1 -0
  28. package/dist/browser/pages.d.ts +33 -3
  29. package/dist/browser/pages.d.ts.map +1 -1
  30. package/dist/browser/pages.js +76 -13
  31. package/dist/browser/pages.js.map +1 -1
  32. package/dist/plugins/compatibility.d.ts +12 -1
  33. package/dist/plugins/compatibility.d.ts.map +1 -1
  34. package/dist/plugins/compatibility.js +65 -22
  35. package/dist/plugins/compatibility.js.map +1 -1
  36. package/dist/plugins/hono-islands.d.ts +1 -1
  37. package/dist/plugins/hono-islands.d.ts.map +1 -1
  38. package/dist/plugins/hono-islands.js +156 -24
  39. package/dist/plugins/hono-islands.js.map +1 -1
  40. package/dist/plugins/hono-markdown.d.ts +4 -0
  41. package/dist/plugins/hono-markdown.d.ts.map +1 -0
  42. package/dist/plugins/hono-markdown.js +91 -0
  43. package/dist/plugins/hono-markdown.js.map +1 -0
  44. package/dist/plugins/hono-pages.d.ts +10 -2
  45. package/dist/plugins/hono-pages.d.ts.map +1 -1
  46. package/dist/plugins/hono-pages.js +55 -18
  47. package/dist/plugins/hono-pages.js.map +1 -1
  48. package/dist/plugins/markdown-api.d.ts +10 -0
  49. package/dist/plugins/markdown-api.d.ts.map +1 -0
  50. package/dist/plugins/markdown-api.js +13 -0
  51. package/dist/plugins/markdown-api.js.map +1 -0
  52. package/dist/plugins/markdown-compiler.d.ts +43 -0
  53. package/dist/plugins/markdown-compiler.d.ts.map +1 -0
  54. package/dist/plugins/markdown-compiler.js +91 -0
  55. package/dist/plugins/markdown-compiler.js.map +1 -0
  56. package/dist/plugins/resolve-component.d.ts +3 -0
  57. package/dist/plugins/resolve-component.d.ts.map +1 -0
  58. package/dist/plugins/resolve-component.js +15 -0
  59. package/dist/plugins/resolve-component.js.map +1 -0
  60. package/dist/plugins/runtime-paths.d.ts +1 -0
  61. package/dist/plugins/runtime-paths.d.ts.map +1 -1
  62. package/dist/plugins/runtime-paths.js +2 -0
  63. package/dist/plugins/runtime-paths.js.map +1 -1
  64. package/dist/server/form-view.d.ts +10 -0
  65. package/dist/server/form-view.d.ts.map +1 -0
  66. package/dist/server/form-view.js +16 -0
  67. package/dist/server/form-view.js.map +1 -0
  68. package/dist/server/form.d.ts +28 -12
  69. package/dist/server/form.d.ts.map +1 -1
  70. package/dist/server/form.js +84 -23
  71. package/dist/server/form.js.map +1 -1
  72. package/dist/server/markdown.d.ts +15 -0
  73. package/dist/server/markdown.d.ts.map +1 -0
  74. package/dist/server/markdown.js +6 -0
  75. package/dist/server/markdown.js.map +1 -0
  76. package/dist/server/pages.d.ts +33 -3
  77. package/dist/server/pages.d.ts.map +1 -1
  78. package/dist/server/pages.js +76 -13
  79. package/dist/server/pages.js.map +1 -1
  80. package/package.json +24 -6
  81. package/src/plugins/compatibility.ts +56 -19
  82. package/src/plugins/hono-islands.ts +121 -23
  83. package/src/plugins/hono-markdown.ts +78 -0
  84. package/src/plugins/hono-pages.ts +54 -17
  85. package/src/plugins/markdown-api.ts +17 -0
  86. package/src/plugins/markdown-compiler.ts +77 -0
  87. package/src/plugins/resolve-component.ts +12 -0
  88. package/src/plugins/runtime-paths.ts +2 -0
  89. package/src/runtime/client.tsx +66 -24
  90. package/src/runtime/document-head.ts +20 -1
  91. package/src/runtime/form-view.tsx +23 -0
  92. package/src/runtime/form.ts +82 -41
  93. package/src/runtime/markdown.ts +7 -0
  94. package/src/runtime/navigation.ts +72 -0
  95. package/src/runtime/pages.tsx +77 -15
@@ -1 +1 @@
1
- {"version":3,"file":"pages.js","sourceRoot":"","sources":["../../src/runtime/pages.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAY,MAAM,UAAU,CAAC;AAK/D,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,CAAoB,IAAI,CAAC,CAAC;AACpE,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAoB,IAAI,CAAC,CAAC;AAElE,SAAS,OAAO;IACd,MAAM,IAAI,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACrC,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IAC9E,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,SAAS,KAAK,OAAO,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;AACxD,MAAM,UAAU,SAAS,KAAK,OAAO,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;AACxD,MAAM,UAAU,SAAS,KAAK,OAAO,OAAO,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC;AAE9D,MAAM,UAAU,SAAS;IACvB,MAAM,MAAM,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IAChF,OAAO,MAAM,CAAC;AAChB,CAAC;AASD,MAAM,UAAU,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,UAAU,EAAa;IACvF,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,OAAO,eAAO,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,KAAiB,EAAE,EAAE;YACnE,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;YACjB,IAAI,KAAK,CAAC,gBAAgB,IAAI,cAAc,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM;gBAAE,OAAO;YAC/I,IAAI,UAAU,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,UAAU,CAAC,MAAM,KAAK,OAAO,CAAC,IAAI,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;gBAAE,OAAO;YAC3J,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAChD,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAAE,OAAO;YACjG,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,KAAK,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;gBAC3D,MAAM,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,6BAA6B,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;YAC1F,CAAC,CAAC,CAAC;QACL,CAAC,GAAI,CAAC;AACR,CAAC","sourcesContent":["import { createContext, useContext, type JSX } from 'hono/jsx';\nimport type { VoidRouter } from 'void/pages-client';\nimport type { PageObject } from 'void/pages-protocol';\nexport type { DeferredState as Deferred } from 'void';\n\nexport const RouterContext = createContext<VoidRouter | null>(null);\nexport const PageContext = createContext<PageObject | null>(null);\n\nfunction usePage() {\n const page = useContext(PageContext);\n if (!page) throw new Error('Hono Pages: page data requires a page provider.');\n return page;\n}\n\nexport function useShared() { return usePage().shared; }\nexport function useParams() { return usePage().params; }\nexport function useErrors() { return usePage().errors ?? {}; }\n\nexport function useRouter(): VoidRouter {\n const router = useContext(RouterContext);\n if (!router) throw new Error('Hono Pages: useRouter requires a page provider.');\n return router;\n}\n\ntype LinkProps = Omit<JSX.IntrinsicElements['a'], 'href' | 'onClick'> & {\n href: string;\n reloadDocument?: boolean;\n replace?: boolean;\n onClick?: (event: MouseEvent) => void;\n};\n\nexport function Link({ href, reloadDocument, replace, onClick, ...attributes }: LinkProps) {\n const router = useRouter();\n return <a {...attributes} href={href} onClick={(event: MouseEvent) => {\n onClick?.(event);\n if (event.defaultPrevented || reloadDocument || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;\n if (attributes.download !== undefined || (attributes.target && attributes.target !== '_self') || attributes.rel?.split(/\\s+/).includes('external')) return;\n const url = new URL(href, window.location.href);\n if (url.origin !== window.location.origin || !['http:', 'https:'].includes(url.protocol)) return;\n event.preventDefault();\n void router.visit(url, { replace }).catch((error: unknown) => {\n window.dispatchEvent(new CustomEvent('hono-pages:navigation-error', { detail: error }));\n });\n }} />;\n}\n"]}
1
+ {"version":3,"file":"pages.js","sourceRoot":"","sources":["../../src/runtime/pages.tsx"],"names":[],"mappings":"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","sourcesContent":["import { createContext, useContext, useEffect, useRef, type JSX } from 'hono/jsx';\nimport { createActionClient, mergeDataIntoHref, type NavigationState, type NavigationMethod, type VoidRouter } from 'void/pages-client';\nimport type { CacheForInput } from 'void/pages-prefetch';\nimport type { PageObject } from 'void/pages-protocol';\nexport type { DeferredState as Deferred } from 'void';\n\nconst actionClient = createActionClient();\nexport const action = actionClient.action;\nexport const setActionRouter = actionClient.setActionRouter;\n\nexport const RouterContext = createContext<VoidRouter | null>(null);\nexport const NavigationContext = createContext<NavigationState | null>(null);\nexport const PageContext = createContext<PageObject | null>(null);\n\nfunction usePage() {\n const page = useContext(PageContext);\n if (!page) throw new Error('Hono Pages: page data requires a page provider.');\n return page;\n}\n\nexport function useNavigation(): NavigationState {\n const navigation = useContext(NavigationContext);\n if (!navigation) throw new Error('Hono Pages: useNavigation requires a page provider.');\n return navigation;\n}\n\nexport function useShared() { return usePage().shared; }\nexport function useParams() { return usePage().params; }\nexport function useErrors() { return usePage().errors ?? {}; }\n\nexport function useRouter(): VoidRouter {\n const router = useContext(RouterContext);\n if (!router) throw new Error('Hono Pages: useRouter requires a page provider.');\n return router;\n}\n\nexport type PrefetchStrategy = 'hover' | 'click' | 'mount' | 'visible';\nexport type LinkProps = Omit<JSX.IntrinsicElements['a'], 'href' | 'onClick'> & {\n href: string;\n method?: NavigationMethod | Lowercase<NavigationMethod>;\n data?: Record<string, unknown>;\n preserveScroll?: boolean;\n preserveState?: boolean;\n reloadDocument?: boolean;\n replace?: boolean;\n viewTransition?: boolean;\n prefetch?: boolean | PrefetchStrategy | ReadonlyArray<PrefetchStrategy>;\n cacheFor?: CacheForInput;\n onNavigate?: (event: { preventDefault(): void }) => void;\n onClick?: (event: MouseEvent) => void;\n};\n\nexport function Link({ href, method = 'GET', data, preserveScroll, preserveState, reloadDocument, replace, viewTransition,\n prefetch = false, cacheFor, onNavigate, onClick, onMouseEnter, onMouseLeave, onFocus, onMouseDown, onTouchStart,\n ...attributes }: LinkProps) {\n const router = useRouter();\n const element = useRef<HTMLAnchorElement | HTMLButtonElement | null>(null);\n const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n const normalized = method.toUpperCase();\n const get = normalized === 'GET';\n if (!['GET', 'POST', 'PUT', 'PATCH', 'DELETE'].includes(normalized)) throw new Error('Hono Link: unsupported method.');\n if (!get && (prefetch !== false || reloadDocument)) throw new Error('Hono Link: prefetch and reloadDocument only support GET links.');\n const destination = get ? mergeDataIntoHref(href, data) : href;\n const strategies = reloadDocument || prefetch === false ? [] : prefetch === true ? ['hover'] : typeof prefetch === 'string' ? [prefetch] : prefetch;\n if (strategies.some((strategy) => !['hover', 'click', 'mount', 'visible'].includes(strategy))) throw new Error('Hono Link: unsupported prefetch strategy.');\n const clear = () => { clearTimeout(timer.current); timer.current = undefined; };\n const canHandle = () => {\n const url = new URL(destination, window.location.href);\n return !reloadDocument && attributes.download === undefined && (!attributes.target || attributes.target === '_self') &&\n !attributes.rel?.split(/\\s+/).includes('external') && url.origin === window.location.origin && ['http:', 'https:'].includes(url.protocol);\n };\n const report = (error: unknown) => window.dispatchEvent(new CustomEvent('hono-pages:navigation-error', { detail: error }));\n const fetchAhead = () => {\n if (canHandle()) void router.prefetch(destination, { cacheFor }).catch(report);\n };\n useEffect(() => {\n if (strategies.includes('mount')) fetchAhead();\n let observer: IntersectionObserver | undefined;\n if (strategies.includes('visible') && element.current) {\n observer = new IntersectionObserver((entries) => {\n if (entries.some((entry) => entry.isIntersecting)) { observer?.disconnect(); fetchAhead(); }\n });\n observer.observe(element.current);\n }\n return () => { clear(); observer?.disconnect(); };\n }, [destination, prefetch, cacheFor, reloadDocument, router]);\n const events = {\n onClick(event: MouseEvent) {\n onClick?.(event);\n if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || !canHandle()) return;\n let cancelled = false;\n onNavigate?.({ preventDefault() { cancelled = true; } });\n event.preventDefault();\n if (!cancelled) void router.visit(new URL(destination, window.location.href), { method: normalized, data: get ? undefined : data, preserveScroll, preserveState, replace, viewTransition }).catch(report);\n },\n onMouseEnter(event: MouseEvent) {\n onMouseEnter?.(event); clear();\n if (!event.defaultPrevented && strategies.includes('hover')) timer.current = setTimeout(fetchAhead, router._hoverDelay);\n },\n onMouseLeave(event: MouseEvent) { onMouseLeave?.(event); clear(); },\n onFocus(event: FocusEvent) { onFocus?.(event); if (!event.defaultPrevented && strategies.includes('hover')) fetchAhead(); },\n onMouseDown(event: MouseEvent) { onMouseDown?.(event); if (!event.defaultPrevented && strategies.includes('click')) fetchAhead(); },\n onTouchStart(event: TouchEvent) { onTouchStart?.(event); if (!event.defaultPrevented && strategies.includes('click')) fetchAhead(); },\n };\n if (get) return <a {...attributes} {...events} ref={element} href={destination} />;\n return <button {...attributes} {...events} ref={element} type=\"button\" />;\n}\n"]}
@@ -1,2 +1,13 @@
1
- export declare function assertSupportedFrameworks(): void;
1
+ export declare const supportedFrameworkRanges: {
2
+ void: string;
3
+ hono: string;
4
+ vite: string;
5
+ };
6
+ export declare const supportedViteRange: string;
7
+ export declare function supportsFramework(name: keyof typeof supportedFrameworkRanges, version: unknown): boolean;
8
+ export declare const supportsVite: (version: unknown) => boolean;
9
+ export declare function assertSupportedFrameworks({ root, viteVersion }: {
10
+ root: string;
11
+ viteVersion: unknown;
12
+ }): void;
2
13
  //# sourceMappingURL=compatibility.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compatibility.d.ts","sourceRoot":"","sources":["../../src/plugins/compatibility.ts"],"names":[],"mappings":"AAKA,wBAAgB,yBAAyB,SAqBxC"}
1
+ {"version":3,"file":"compatibility.d.ts","sourceRoot":"","sources":["../../src/plugins/compatibility.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,wBAAwB;IACnC,IAAI;IACJ,IAAI;IACJ,IAAI;CACL,CAAC;AACF,eAAO,MAAM,kBAAkB,QAAgC,CAAC;AAIhE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,OAAO,wBAAwB,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CASxG;AACD,eAAO,MAAM,YAAY,YAAa,OAAO,KAAG,OAA6C,CAAC;AAwB9F,wBAAgB,yBAAyB,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,QAetG"}
@@ -1,30 +1,73 @@
1
1
  import { createRequire } from 'node:module';
2
2
  import { existsSync, readFileSync } from 'node:fs';
3
3
  import { dirname, join } from 'node:path';
4
- const supported = { void: '0.26.1', hono: '4.13.13', vite: '8.3.3' };
5
- export function assertSupportedFrameworks() {
6
- const require = createRequire(import.meta.url);
7
- for (const [name, expected] of Object.entries(supported)) {
8
- let directory = dirname(require.resolve(name));
9
- let version;
10
- while (true) {
11
- const path = join(directory, 'package.json');
12
- if (existsSync(path)) {
13
- const metadata = JSON.parse(readFileSync(path, 'utf8'));
14
- if (typeof metadata === 'object' && metadata !== null && 'name' in metadata && metadata.name === name) {
15
- if (!('version' in metadata) || typeof metadata.version !== 'string')
16
- throw new Error(`Hono Pages: ${name} package version is missing.`);
17
- version = metadata.version;
18
- break;
19
- }
4
+ import { version as helperViteVersion } from 'vite';
5
+ export const supportedFrameworkRanges = {
6
+ void: '>=0.26.1 <0.28.0',
7
+ hono: '>=4.13.13 <5.0.0',
8
+ vite: '>=8.0.16 <9.0.0',
9
+ };
10
+ export const supportedViteRange = supportedFrameworkRanges.vite;
11
+ // Only stable releases are admitted. Void is pre-1.0, so its next minor
12
+ // requires explicit validation; Hono and Vite use their current major lines.
13
+ export function supportsFramework(name, version) {
14
+ if (typeof version !== 'string')
15
+ return false;
16
+ const match = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.exec(version);
17
+ if (!match)
18
+ return false;
19
+ const [major, minor, patch] = match.slice(1).map(Number);
20
+ if (![major, minor, patch].every(Number.isSafeInteger))
21
+ return false;
22
+ if (name === 'void')
23
+ return major === 0 && ((minor === 26 && patch >= 1) || minor === 27);
24
+ if (name === 'hono')
25
+ return major === 4 && (minor > 13 || (minor === 13 && patch >= 13));
26
+ return major === 8 && (minor > 0 || patch >= 16);
27
+ }
28
+ export const supportsVite = (version) => supportsFramework('vite', version);
29
+ function packageInfo(name, require) {
30
+ let directory = dirname(require.resolve(name));
31
+ while (true) {
32
+ const path = join(directory, 'package.json');
33
+ if (existsSync(path)) {
34
+ const metadata = JSON.parse(readFileSync(path, 'utf8'));
35
+ if (typeof metadata === 'object' && metadata !== null && 'name' in metadata && (metadata.name === name || (name === 'vite' && metadata.name === '@voidzero-dev/vite-plus-core'))) {
36
+ if (!('version' in metadata) || typeof metadata.version !== 'string')
37
+ throw new Error(`Hono Pages: ${name} package version is missing (${path}).`);
38
+ return { version: metadata.version, path };
20
39
  }
21
- const parent = dirname(directory);
22
- if (parent === directory)
23
- throw new Error(`Hono Pages: cannot locate ${name} package metadata.`);
24
- directory = parent;
25
40
  }
26
- if (version !== expected)
27
- throw new Error(`Hono Pages: ${name} ${version} is unverified; install ${name}@${expected}. The adapter requires void@0.26.1, hono@4.13.13 and vite@8.3.3.`);
41
+ const parent = dirname(directory);
42
+ if (parent === directory)
43
+ throw new Error(`Hono Pages: cannot locate ${name} package metadata from ${require.resolve(name)}.`);
44
+ directory = parent;
45
+ }
46
+ }
47
+ function describe(name, require) {
48
+ try {
49
+ const info = packageInfo(name, require);
50
+ return `${info.path} (metadata ${info.version})`;
51
+ }
52
+ catch {
53
+ return `not resolved from ${require.resolve.paths(name)?.join(', ') ?? 'this context'}`;
54
+ }
55
+ }
56
+ export function assertSupportedFrameworks({ root, viteVersion }) {
57
+ const adapter = createRequire(import.meta.url);
58
+ const project = createRequire(join(root, 'package.json'));
59
+ const diagnostic = () => `Running Vite from hook context: ${typeof viteVersion === 'string' ? viteVersion : 'unavailable'}. Adapter helper Vite: ${helperViteVersion}; package.json: ${describe('vite', adapter)}. Project Vite package.json: ${describe('vite', project)}. Package paths are diagnostics, not the running Vite identity.`;
60
+ if (!supportsVite(viteVersion)) {
61
+ throw new Error(`Hono Pages: running Vite ${typeof viteVersion === 'string' ? viteVersion : 'unavailable'} is unsupported; expected ${supportedViteRange}. ${diagnostic()} Update the CLI/launcher that executes Vite. For bundled launchers such as vp, installing project vite alone does not update the running Vite. For standard Vite, install vite@^8.3.4 and run vite directly.`);
62
+ }
63
+ if (!supportsVite(helperViteVersion)) {
64
+ throw new Error(`Hono Pages: adapter helper Vite ${helperViteVersion} is unsupported; expected ${supportedViteRange}. ${diagnostic()} Inspect the adapter's resolved peer copy; install vite@^8.3.4 and refresh the adapter's peer resolution/lockfile if a stale copy remains.`);
65
+ }
66
+ for (const name of ['void', 'hono']) {
67
+ const expected = supportedFrameworkRanges[name];
68
+ const info = packageInfo(name, adapter);
69
+ if (!supportsFramework(name, info.version))
70
+ throw new Error(`Hono Pages: ${name} ${info.version} is unsupported; install ${name}@"${expected}". Resolved package.json: ${info.path}. Project package.json: ${describe(name, project)}. ${diagnostic()}`);
28
71
  }
29
72
  }
30
73
  //# sourceMappingURL=compatibility.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"compatibility.js","sourceRoot":"","sources":["../../src/plugins/compatibility.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,SAAS,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AACrE,MAAM,UAAU,yBAAyB;IACvC,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACzD,IAAI,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/C,IAAI,OAA2B,CAAC;QAChC,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;YAC7C,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrB,MAAM,QAAQ,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;gBACjE,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,IAAI,MAAM,IAAI,QAAQ,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;oBACtG,IAAI,CAAC,CAAC,SAAS,IAAI,QAAQ,CAAC,IAAI,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ;wBAAE,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,8BAA8B,CAAC,CAAC;oBACzI,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;oBAC3B,MAAM;gBACR,CAAC;YACH,CAAC;YACD,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;YAClC,IAAI,MAAM,KAAK,SAAS;gBAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,oBAAoB,CAAC,CAAC;YACjG,SAAS,GAAG,MAAM,CAAC;QACrB,CAAC;QACD,IAAI,OAAO,KAAK,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,IAAI,OAAO,2BAA2B,IAAI,IAAI,QAAQ,kEAAkE,CAAC,CAAC;IACzL,CAAC;AACH,CAAC","sourcesContent":["import { createRequire } from 'node:module';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nconst supported = { void: '0.26.1', hono: '4.13.13', vite: '8.3.3' };\nexport function assertSupportedFrameworks() {\n const require = createRequire(import.meta.url);\n for (const [name, expected] of Object.entries(supported)) {\n let directory = dirname(require.resolve(name));\n let version: string | undefined;\n while (true) {\n const path = join(directory, 'package.json');\n if (existsSync(path)) {\n const metadata: unknown = JSON.parse(readFileSync(path, 'utf8'));\n if (typeof metadata === 'object' && metadata !== null && 'name' in metadata && metadata.name === name) {\n if (!('version' in metadata) || typeof metadata.version !== 'string') throw new Error(`Hono Pages: ${name} package version is missing.`);\n version = metadata.version;\n break;\n }\n }\n const parent = dirname(directory);\n if (parent === directory) throw new Error(`Hono Pages: cannot locate ${name} package metadata.`);\n directory = parent;\n }\n if (version !== expected) throw new Error(`Hono Pages: ${name} ${version} is unverified; install ${name}@${expected}. The adapter requires void@0.26.1, hono@4.13.13 and vite@8.3.3.`);\n }\n}\n"]}
1
+ {"version":3,"file":"compatibility.js","sourceRoot":"","sources":["../../src/plugins/compatibility.ts"],"names":[],"mappings":"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","sourcesContent":["import { createRequire } from 'node:module';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { version as helperViteVersion } from 'vite';\n\nexport const supportedFrameworkRanges = {\n void: '>=0.26.1 <0.28.0',\n hono: '>=4.13.13 <5.0.0',\n vite: '>=8.0.16 <9.0.0',\n};\nexport const supportedViteRange = supportedFrameworkRanges.vite;\n\n// Only stable releases are admitted. Void is pre-1.0, so its next minor\n// requires explicit validation; Hono and Vite use their current major lines.\nexport function supportsFramework(name: keyof typeof supportedFrameworkRanges, version: unknown): boolean {\n if (typeof version !== 'string') return false;\n const match = /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$/.exec(version);\n if (!match) return false;\n const [major, minor, patch] = match.slice(1).map(Number);\n if (![major, minor, patch].every(Number.isSafeInteger)) return false;\n if (name === 'void') return major === 0 && ((minor === 26 && patch >= 1) || minor === 27);\n if (name === 'hono') return major === 4 && (minor > 13 || (minor === 13 && patch >= 13));\n return major === 8 && (minor > 0 || patch >= 16);\n}\nexport const supportsVite = (version: unknown): boolean => supportsFramework('vite', version);\n\ntype PackageInfo = { version: string; path: string };\nfunction packageInfo(name: string, require: NodeRequire): PackageInfo {\n let directory = dirname(require.resolve(name));\n while (true) {\n const path = join(directory, 'package.json');\n if (existsSync(path)) {\n const metadata: unknown = JSON.parse(readFileSync(path, 'utf8'));\n if (typeof metadata === 'object' && metadata !== null && 'name' in metadata && (metadata.name === name || (name === 'vite' && metadata.name === '@voidzero-dev/vite-plus-core'))) {\n if (!('version' in metadata) || typeof metadata.version !== 'string') throw new Error(`Hono Pages: ${name} package version is missing (${path}).`);\n return { version: metadata.version, path };\n }\n }\n const parent = dirname(directory);\n if (parent === directory) throw new Error(`Hono Pages: cannot locate ${name} package metadata from ${require.resolve(name)}.`);\n directory = parent;\n }\n}\nfunction describe(name: string, require: NodeRequire): string {\n try { const info = packageInfo(name, require); return `${info.path} (metadata ${info.version})`; }\n catch { return `not resolved from ${require.resolve.paths(name)?.join(', ') ?? 'this context'}`; }\n}\n\nexport function assertSupportedFrameworks({ root, viteVersion }: { root: string; viteVersion: unknown }) {\n const adapter = createRequire(import.meta.url);\n const project = createRequire(join(root, 'package.json'));\n const diagnostic = () => `Running Vite from hook context: ${typeof viteVersion === 'string' ? viteVersion : 'unavailable'}. Adapter helper Vite: ${helperViteVersion}; package.json: ${describe('vite', adapter)}. Project Vite package.json: ${describe('vite', project)}. Package paths are diagnostics, not the running Vite identity.`;\n if (!supportsVite(viteVersion)) {\n throw new Error(`Hono Pages: running Vite ${typeof viteVersion === 'string' ? viteVersion : 'unavailable'} is unsupported; expected ${supportedViteRange}. ${diagnostic()} Update the CLI/launcher that executes Vite. For bundled launchers such as vp, installing project vite alone does not update the running Vite. For standard Vite, install vite@^8.3.4 and run vite directly.`);\n }\n if (!supportsVite(helperViteVersion)) {\n throw new Error(`Hono Pages: adapter helper Vite ${helperViteVersion} is unsupported; expected ${supportedViteRange}. ${diagnostic()} Inspect the adapter's resolved peer copy; install vite@^8.3.4 and refresh the adapter's peer resolution/lockfile if a stale copy remains.`);\n }\n for (const name of ['void', 'hono'] as const) {\n const expected = supportedFrameworkRanges[name];\n const info = packageInfo(name, adapter);\n if (!supportsFramework(name, info.version)) throw new Error(`Hono Pages: ${name} ${info.version} is unsupported; install ${name}@\"${expected}\". Resolved package.json: ${info.path}. Project package.json: ${describe(name, project)}. ${diagnostic()}`);\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
1
  import { type Plugin } from 'vite';
2
- /** Narrow adapter for Void's load-on-page-load island convention. */
2
+ /** Hono mounting through Void's shared island scheduler. */
3
3
  export declare function honoIslands(): Plugin;
4
4
  //# sourceMappingURL=hono-islands.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hono-islands.d.ts","sourceRoot":"","sources":["../../src/plugins/hono-islands.ts"],"names":[],"mappings":"AAEA,OAAO,EAA4B,KAAK,MAAM,EAAE,MAAM,MAAM,CAAC;AAI7D,qEAAqE;AACrE,wBAAgB,WAAW,IAAI,MAAM,CAiGpC"}
1
+ {"version":3,"file":"hono-islands.d.ts","sourceRoot":"","sources":["../../src/plugins/hono-islands.ts"],"names":[],"mappings":"AAEA,OAAO,EAA4B,KAAK,MAAM,EAAE,MAAM,MAAM,CAAC;AAQ7D,4DAA4D;AAC5D,wBAAgB,WAAW,IAAI,MAAM,CA+LpC"}
@@ -1,30 +1,49 @@
1
1
  import { readFileSync, realpathSync } from 'node:fs';
2
2
  import { join, relative } from 'node:path';
3
3
  import { normalizePath, parseSync } from 'vite';
4
- import { scanPages, resolvePagesDir } from 'void/pages';
5
- import { findIslandImports, editIslandSource, resolveSpecifier, computePagesNeedingClientJS, ISLANDS_RENDERER_ID, ISLANDS_CLIENT_ENTRY_ID } from 'void/pages-islands-plugin';
6
- /** Narrow adapter for Void's load-on-page-load island convention. */
4
+ import { scanPages, resolveEffectiveLayoutChain, resolvePagesDir } from 'void/pages';
5
+ import { findIslandImports, editIslandSource, computePagesNeedingClientJS, ISLANDS_RENDERER_ID, ISLANDS_CLIENT_ENTRY_ID } from 'void/pages-islands-plugin';
6
+ import { resolveComponent } from './resolve-component.js';
7
+ import { markdownApi, markdownDiagnostic } from './markdown-api.js';
8
+ /** Hono mounting through Void's shared island scheduler. */
7
9
  export function honoIslands() {
8
10
  const root = process.cwd();
9
11
  const pagesDir = resolvePagesDir(root);
10
12
  const islands = new Map();
11
13
  const pageFiles = new Set();
14
+ const graph = new Map();
15
+ const directlyInteractive = new Set();
16
+ const interactivePages = new Set();
17
+ const scriptOnlyPages = new Set();
12
18
  let scan;
19
+ let markdown;
13
20
  function islandImports(code, filename) {
14
21
  const found = findIslandImports(code, filename);
15
22
  const attributed = parseSync(filename, code).program.body.filter((node) => node.type === 'ImportDeclaration' && node.attributes?.some(({ key }) => ('name' in key && key.name === 'island') || ('value' in key && key.value === 'island')));
16
23
  if (attributed.length !== found.length)
17
- throw new Error(`Hono islands: use one default import with exactly one island: 'load' attribute in ${filename}.`);
24
+ throw new Error(`Hono islands: use one default import with exactly one island attribute using load, visible, idle or media:query in ${filename}.`);
18
25
  return found;
19
26
  }
20
27
  function imports(code, filename) {
21
28
  const found = islandImports(code, filename);
22
29
  for (const entry of found) {
23
- if (entry.hydrate !== 'load')
24
- throw new Error(`Hono islands: unsupported policy '${entry.hydrate}' in ${filename}; use island: 'load'.`);
30
+ if (!['load', 'visible', 'idle'].includes(entry.hydrate)) {
31
+ const query = entry.hydrate.startsWith('media:') ? entry.hydrate.slice(6).trim() : '';
32
+ let balance = 0;
33
+ for (const character of query) {
34
+ if (character === '(')
35
+ balance++;
36
+ if (character === ')')
37
+ balance--;
38
+ if (balance < 0)
39
+ break;
40
+ }
41
+ if (!query || balance !== 0 || /[{};]/.test(query))
42
+ throw new Error(`Hono islands: unsupported policy or invalid media query '${entry.hydrate}' in ${filename}.`);
43
+ }
25
44
  if (!entry.specifier.startsWith('.'))
26
45
  throw new Error(`Hono islands: use a relative TSX/JSX component import in ${filename}.`);
27
- const path = resolveSpecifier(entry.specifier, join(filename, '..'), ['.tsx', '.jsx']);
46
+ const path = resolveComponent(entry.specifier, join(filename, '..'), ['.tsx', '.jsx']);
28
47
  if (!path || !/\.[jt]sx$/.test(path))
29
48
  throw new Error(`Hono islands: cannot resolve TSX/JSX component ${entry.specifier} in ${filename}.`);
30
49
  const canonical = realpathSync(path);
@@ -35,21 +54,107 @@ export function honoIslands() {
35
54
  }
36
55
  async function rescan() {
37
56
  scan = await scanPages(root, { pagesDir });
57
+ // Never pass Markdown text to the JavaScript static-graph parser.
58
+ for (const file of [...scan.pages.map(page => page.componentPath), ...scan.layouts.map(layout => layout.filePath), ...scan.namedLayouts.map(layout => layout.filePath)]) {
59
+ if (/\.md$/.test(file) && !markdown)
60
+ throw new Error(`${markdownDiagnostic} ${file}`);
61
+ }
38
62
  islands.clear();
39
63
  pageFiles.clear();
64
+ graph.clear();
65
+ directlyInteractive.clear();
66
+ interactivePages.clear();
67
+ scriptOnlyPages.clear();
68
+ const visit = (filename) => {
69
+ const canonical = realpathSync(filename);
70
+ if (graph.has(canonical))
71
+ return;
72
+ const dependencies = new Set();
73
+ graph.set(canonical, dependencies);
74
+ pageFiles.add(canonical);
75
+ const code = canonical.endsWith('.md') && markdown ? markdown.getGraphSource(canonical) : readFileSync(canonical, 'utf8');
76
+ const found = imports(code, canonical);
77
+ if (found.length) {
78
+ if (!/\.[jt]sx$/.test(canonical) && !(canonical.endsWith('.md') && markdown))
79
+ throw new Error('Hono islands: attributed imports require a static TSX/JSX module.');
80
+ directlyInteractive.add(canonical);
81
+ }
82
+ for (const node of parseSync(canonical, code).program.body) {
83
+ const source = node.type === 'ImportDeclaration' ? node.source : node.type === 'ExportNamedDeclaration' || node.type === 'ExportAllDeclaration' ? node.source : undefined;
84
+ const typeOnly = node.type === 'ImportDeclaration' ? node.importKind === 'type' || (node.specifiers.length > 0 && node.specifiers.every((entry) => entry.type === 'ImportSpecifier' && entry.importKind === 'type')) : (node.type === 'ExportNamedDeclaration' || node.type === 'ExportAllDeclaration') && node.exportKind === 'type';
85
+ if (!source || typeOnly || !source.value.startsWith('.') || found.some((entry) => entry.specifier === source.value))
86
+ continue;
87
+ const target = resolveComponent(source.value, join(canonical, '..'), ['.tsx', '.jsx', '.ts', '.js']);
88
+ if (!target || !/\.[jt]sx?$/.test(target))
89
+ continue;
90
+ dependencies.add(realpathSync(target));
91
+ visit(target);
92
+ }
93
+ };
94
+ for (const entry of [...scan.pages.filter((page) => page.island).map((page) => page.componentPath), ...scan.layouts.filter((layout) => layout.island).map((layout) => layout.filePath), ...scan.namedLayouts.filter((layout) => layout.island).map((layout) => layout.filePath)])
95
+ visit(join(pagesDir, entry));
96
+ const validateInteractive = (filename, seen = new Set()) => {
97
+ const canonical = realpathSync(filename);
98
+ if (seen.has(canonical))
99
+ return;
100
+ seen.add(canonical);
101
+ const code = canonical.endsWith('.md') && markdown ? markdown.getGraphSource(canonical) : readFileSync(canonical, 'utf8');
102
+ if (islandImports(code, canonical).length)
103
+ throw new Error('Hono islands: attributed imports inside an interactive component are unsupported; use ordinary component imports there.');
104
+ for (const node of parseSync(canonical, code).program.body) {
105
+ const source = node.type === 'ImportDeclaration' ? node.source : node.type === 'ExportNamedDeclaration' || node.type === 'ExportAllDeclaration' ? node.source : undefined;
106
+ const typeOnly = node.type === 'ImportDeclaration' ? node.importKind === 'type' || (node.specifiers.length > 0 && node.specifiers.every((entry) => entry.type === 'ImportSpecifier' && entry.importKind === 'type')) : (node.type === 'ExportNamedDeclaration' || node.type === 'ExportAllDeclaration') && node.exportKind === 'type';
107
+ if (!source || typeOnly || !source.value.startsWith('.'))
108
+ continue;
109
+ const target = resolveComponent(source.value, join(canonical, '..'), ['.tsx', '.jsx', '.ts', '.js']);
110
+ if (target && /\.[jt]sx?$/.test(target))
111
+ validateInteractive(target, seen);
112
+ }
113
+ };
114
+ for (const target of islands.values())
115
+ validateInteractive(target);
116
+ for (const page of scan.pages.filter((page) => !page.island)) {
117
+ for (const file of [page.componentPath, ...resolveEffectiveLayoutChain(page, scan.layouts, scan.namedLayouts).map((layout) => layout.filePath)])
118
+ validateInteractive(join(pagesDir, file));
119
+ }
120
+ const needsJS = new Set(directlyInteractive);
121
+ let changed = true;
122
+ while (changed) {
123
+ changed = false;
124
+ for (const [file, dependencies] of graph)
125
+ if (!needsJS.has(file) && [...dependencies].some((target) => needsJS.has(target))) {
126
+ needsJS.add(file);
127
+ changed = true;
128
+ }
129
+ }
40
130
  for (const page of scan.pages.filter((page) => page.island)) {
41
- const filename = realpathSync(join(pagesDir, page.componentPath));
42
- pageFiles.add(filename);
43
- imports(readFileSync(filename, 'utf8'), filename);
131
+ const files = [page.componentPath, ...resolveEffectiveLayoutChain(page, scan.layouts, scan.namedLayouts).map((layout) => layout.filePath)];
132
+ const hasIslands = files.some(file => needsJS.has(realpathSync(join(pagesDir, file))));
133
+ const hasScript = markdown?.getClientScripts().has(page.componentId);
134
+ if (hasIslands || hasScript)
135
+ interactivePages.add(page.componentId);
136
+ if (hasScript && !hasIslands)
137
+ scriptOnlyPages.add(page.componentId);
44
138
  }
45
139
  }
46
140
  return {
47
141
  name: 'void-hono:islands',
48
142
  enforce: 'pre',
143
+ configResolved(config) { markdown = markdownApi(config.plugins); },
49
144
  buildStart: rescan,
50
- async hotUpdate({ file }) {
51
- if (normalizePath(file).startsWith(normalizePath(pagesDir) + '/'))
52
- await rescan();
145
+ async hotUpdate({ file, modules, timestamp }) {
146
+ const inPages = normalizePath(file).startsWith(normalizePath(pagesDir) + '/');
147
+ if (!inPages && ![...pageFiles, ...islands.values()].some((path) => normalizePath(path) === normalizePath(file)))
148
+ return;
149
+ await rescan();
150
+ const invalidated = new Set();
151
+ for (const id of [ISLANDS_RENDERER_ID, ISLANDS_CLIENT_ENTRY_ID, 'virtual:void-pages-renderer']) {
152
+ const module = this.environment.moduleGraph.getModuleById(`\0${id}`);
153
+ if (module)
154
+ this.environment.moduleGraph.invalidateModule(module, invalidated, timestamp, true);
155
+ }
156
+ if (!inPages && this.environment.config.consumer === 'client')
157
+ this.environment.hot.send({ type: 'full-reload' });
53
158
  },
54
159
  config() {
55
160
  return { build: { rollupOptions: { input: { 'islands-client': ISLANDS_CLIENT_ENTRY_ID } } } };
@@ -63,47 +168,74 @@ export function honoIslands() {
63
168
  if (!/\.[jt]sx$/.test(filename) || filename.includes('/node_modules/'))
64
169
  return;
65
170
  const canonical = realpathSync(filename);
66
- if ((pageFiles.has(canonical) || [...islands.values()].includes(canonical)) && parseSync(filename, code).program.body.some((node) => node.type === 'ImportDeclaration' && node.source.value === 'void-plugin-hono-jsx/form')) {
67
- throw new Error('Hono islands: form helpers are unsupported; use a full Pages component.');
171
+ if ((pageFiles.has(canonical) || [...islands.values()].includes(canonical)) && parseSync(filename, code).program.body.some((node) => node.type === 'ImportDeclaration' && node.importKind !== 'type' && ['void-plugin-hono-jsx/form', 'void-plugin-hono-jsx/pages'].includes(node.source.value) && node.specifiers.some((entry) => entry.type !== 'ImportSpecifier' ? node.source.value.endsWith('/form') : entry.importKind !== 'type' && ['useForm', 'action', 'setActionRouter'].includes('name' in entry.imported ? entry.imported.name : entry.imported.value)))) {
172
+ throw new Error('Hono islands: useForm/action require full Pages; use named useIslandForm/Form imports for islands.');
68
173
  }
69
174
  const found = islandImports(code, filename);
70
175
  if (!found.length)
71
176
  return;
72
- if (!pageFiles.has(realpathSync(filename)))
73
- throw new Error('Hono islands: attributed imports are supported only directly in .island.tsx/.island.jsx pages.');
177
+ if (!pageFiles.has(canonical))
178
+ throw new Error('Hono islands: attributed imports require a static island page, layout or component graph; use ordinary imports inside interactive components.');
74
179
  imports(code, filename);
180
+ // Void requests static modules in the client environment to collect CSS.
181
+ // Actual interactive entry graphs were validated above; strip attributes
182
+ // for that traversal rather than generating server-only marker wrappers.
183
+ if (this.environment?.config.consumer === 'client')
184
+ return editIslandSource(code, found.map((entry) => ({ start: entry.start, end: entry.end, text: `import ${entry.importName} from ${entry.specifierRaw};` })));
75
185
  return editIslandSource(code, found.map((entry) => {
76
- const path = resolveSpecifier(entry.specifier, join(filename, '..'), ['.tsx', '.jsx']);
186
+ const path = resolveComponent(entry.specifier, join(filename, '..'), ['.tsx', '.jsx']);
77
187
  if (!path)
78
188
  throw new Error(`Hono islands: missing component ${entry.specifier}.`);
79
189
  const islandId = normalizePath(relative(root, realpathSync(path)));
80
190
  const component = `__honoIslandComponent${entry.start}`;
81
191
  return { start: entry.start, end: entry.end, text: `import ${component} from ${entry.specifierRaw};
82
- const ${entry.importName} = (props) => __honoIslandJsx('div', { 'data-island': ${JSON.stringify(islandId)}, 'data-hydrate': 'load', 'data-props': JSON.stringify(props), children: __honoIslandJsx(${component}, props) });` };
192
+ const ${entry.importName} = (props) => __honoIslandJsx('div', { 'data-island': ${JSON.stringify(islandId)}, 'data-hydrate': ${JSON.stringify(entry.hydrate)}, 'data-props': JSON.stringify(props), children: __honoIslandJsx(${component}, props) });` };
83
193
  }), { prepend: "import { jsx as __honoIslandJsx } from 'hono/jsx/jsx-runtime';\n" });
84
194
  },
85
195
  load(id) {
86
196
  if (id === `\0${ISLANDS_RENDERER_ID}`) {
87
197
  if (!scan)
88
198
  throw new Error('Hono islands: page discovery has not completed.');
89
- const interactive = [...computePagesNeedingClientJS(scan, pagesDir, null)];
199
+ const interactive = [...new Set([...computePagesNeedingClientJS(scan, pagesDir, null), ...interactivePages])];
90
200
  return `import { renderPage } from 'virtual:void-pages-renderer';
91
201
  const interactive = new Set(${JSON.stringify(interactive)});
202
+ const scriptOnly = new Set(${JSON.stringify([...scriptOnlyPages])});
203
+ const markdownScripts = new Set(${JSON.stringify([...(markdown?.getClientScripts().keys() ?? [])])});
92
204
  export function renderIslandPage(page, assets) {
93
205
  if (page.deferred?.length || page.deferredKeys) throw new Error('Hono islands: deferred props are unsupported.');
94
- return renderPage(page, interactive.has(page.component) ? assets : { ...assets, preloads: '', body: '' });
206
+ if (!markdownScripts.has(page.component)) assets = { ...assets,
207
+ body: assets.body.replace(/<script\\b[^>]*src=["'][^"']*(?:void-hono-markdown-client|markdown-client-)[^"']*["'][^>]*>\\s*<\\/script>/g, ''),
208
+ preloads: assets.preloads.replace(/<link\\b[^>]*href=["'][^"']*markdown-client-[^"']*["'][^>]*>/g, ''),
209
+ };
210
+ if (!interactive.has(page.component)) return renderPage(page, { ...assets, preloads: '', body: '' });
211
+ if (scriptOnly.has(page.component)) {
212
+ // Keep the Markdown entry; its dynamic import loads only this page's code.
213
+ // Framework preloads and the island scheduler have no work on this chain.
214
+ const body = assets.body.replace(/<script\\b[^>]*src=["'][^"']*(?:void-islands-client|islands-client-)[^"']*["'][^>]*>\\s*<\\/script>/g, '');
215
+ return renderPage(page, { ...assets, preloads: '', body });
216
+ }
217
+ return renderPage(page, assets);
95
218
  }`;
96
219
  }
97
220
  if (id === `\0${ISLANDS_CLIENT_ENTRY_ID}`) {
98
- if (!islands.size)
221
+ if (!islands.size || !interactivePages.size)
99
222
  return 'export {};';
100
223
  const loaders = [...islands].map(([name, path]) => `${JSON.stringify(name)}: () => import(${JSON.stringify(path)})`).join(',\n');
101
- return `import { initIslands } from 'void/pages-client';
224
+ return `${markdown ? "import { MarkdownContext } from 'void-plugin-hono-jsx/markdown';" : ''}
225
+ import { initIslands } from 'void/pages-client';
102
226
  import { jsx } from 'hono/jsx/dom/jsx-runtime';
103
227
  import { render } from 'hono/jsx/dom';
228
+ for (const element of document.querySelectorAll('[data-hydrate^="media:"]')) {
229
+ const query = element.getAttribute('data-hydrate').slice(6).trim();
230
+ if (matchMedia(query).media === 'not all' && query !== 'not all') throw new Error('Hono islands: invalid or unsupported media query ' + query);
231
+ }
104
232
  initIslands({ ${loaders} }, (element, module, props) => {
105
233
  if (typeof module.default !== 'function') throw new Error('Hono islands: a component must export a default function.');
106
- render(jsx(module.default, props), element);
234
+ let content = jsx(module.default, props);
235
+ ${markdown ? `const metadata = JSON.parse(document.getElementById('app')?.getAttribute('data-hono-markdown') || '{}');
236
+ const page = JSON.parse(document.getElementById('__VOID_PAGE_DATA__')?.textContent || '{}');
237
+ content = jsx(MarkdownContext.Provider, { value: { frontmatter: metadata.frontmatter ?? {}, headings: metadata.headings ?? [], props: page.props ?? {} }, children: content });` : ''}
238
+ render(content, element);
107
239
  element.setAttribute('data-hono-island', 'mounted');
108
240
  });`;
109
241
  }
@@ -1 +1 @@
1
- {"version":3,"file":"hono-islands.js","sourceRoot":"","sources":["../../src/plugins/hono-islands.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync, realpathSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport { normalizePath, parseSync, type Plugin } from 'vite';\nimport { scanPages, resolvePagesDir, type PageScanResult } from 'void/pages';\nimport { findIslandImports, editIslandSource, resolveSpecifier, computePagesNeedingClientJS, ISLANDS_RENDERER_ID, ISLANDS_CLIENT_ENTRY_ID } from 'void/pages-islands-plugin';\n\n/** Narrow adapter for Void's load-on-page-load island convention. */\nexport function honoIslands(): Plugin {\n const root = process.cwd();\n const pagesDir = resolvePagesDir(root);\n const islands = new Map<string, string>();\n const pageFiles = new Set<string>();\n let scan: PageScanResult | undefined;\n\n function islandImports(code: string, filename: string) {\n const found = findIslandImports(code, filename);\n const attributed = parseSync(filename, code).program.body.filter((node) => node.type === 'ImportDeclaration' && node.attributes?.some(({ key }) => ('name' in key && key.name === 'island') || ('value' in key && key.value === 'island')));\n if (attributed.length !== found.length) throw new Error(`Hono islands: use one default import with exactly one island: 'load' attribute in ${filename}.`);\n return found;\n }\n\n function imports(code: string, filename: string) {\n const found = islandImports(code, filename);\n for (const entry of found) {\n if (entry.hydrate !== 'load') throw new Error(`Hono islands: unsupported policy '${entry.hydrate}' in ${filename}; use island: 'load'.`);\n if (!entry.specifier.startsWith('.')) throw new Error(`Hono islands: use a relative TSX/JSX component import in ${filename}.`);\n const path = resolveSpecifier(entry.specifier, join(filename, '..'), ['.tsx', '.jsx']);\n if (!path || !/\\.[jt]sx$/.test(path)) throw new Error(`Hono islands: cannot resolve TSX/JSX component ${entry.specifier} in ${filename}.`);\n const canonical = realpathSync(path);\n const id = normalizePath(relative(root, canonical));\n islands.set(id, canonical);\n }\n return found;\n }\n\n async function rescan() {\n scan = await scanPages(root, { pagesDir });\n islands.clear();\n pageFiles.clear();\n for (const page of scan.pages.filter((page) => page.island)) {\n const filename = realpathSync(join(pagesDir, page.componentPath));\n pageFiles.add(filename);\n imports(readFileSync(filename, 'utf8'), filename);\n }\n }\n\n return {\n name: 'void-hono:islands',\n enforce: 'pre',\n buildStart: rescan,\n async hotUpdate({ file }) {\n if (normalizePath(file).startsWith(normalizePath(pagesDir) + '/')) await rescan();\n },\n config() {\n return { build: { rollupOptions: { input: { 'islands-client': ISLANDS_CLIENT_ENTRY_ID } } } };\n },\n resolveId(id) {\n if (id === ISLANDS_RENDERER_ID || id === ISLANDS_CLIENT_ENTRY_ID) return `\\0${id}`;\n },\n transform(code, id) {\n const filename = id.split('?')[0];\n if (!/\\.[jt]sx$/.test(filename) || filename.includes('/node_modules/')) return;\n const canonical = realpathSync(filename);\n if ((pageFiles.has(canonical) || [...islands.values()].includes(canonical)) && parseSync(filename, code).program.body.some((node) => node.type === 'ImportDeclaration' && node.source.value === 'void-plugin-hono-jsx/form')) {\n throw new Error('Hono islands: form helpers are unsupported; use a full Pages component.');\n }\n const found = islandImports(code, filename);\n if (!found.length) return;\n if (!pageFiles.has(realpathSync(filename))) throw new Error('Hono islands: attributed imports are supported only directly in .island.tsx/.island.jsx pages.');\n imports(code, filename);\n return editIslandSource(code, found.map((entry) => {\n const path = resolveSpecifier(entry.specifier, join(filename, '..'), ['.tsx', '.jsx']);\n if (!path) throw new Error(`Hono islands: missing component ${entry.specifier}.`);\n const islandId = normalizePath(relative(root, realpathSync(path)));\n const component = `__honoIslandComponent${entry.start}`;\n return { start: entry.start, end: entry.end, text: `import ${component} from ${entry.specifierRaw};\nconst ${entry.importName} = (props) => __honoIslandJsx('div', { 'data-island': ${JSON.stringify(islandId)}, 'data-hydrate': 'load', 'data-props': JSON.stringify(props), children: __honoIslandJsx(${component}, props) });` };\n }), { prepend: \"import { jsx as __honoIslandJsx } from 'hono/jsx/jsx-runtime';\\n\" });\n },\n load(id) {\n if (id === `\\0${ISLANDS_RENDERER_ID}`) {\n if (!scan) throw new Error('Hono islands: page discovery has not completed.');\n const interactive = [...computePagesNeedingClientJS(scan, pagesDir, null)];\n return `import { renderPage } from 'virtual:void-pages-renderer';\nconst interactive = new Set(${JSON.stringify(interactive)});\nexport function renderIslandPage(page, assets) {\n if (page.deferred?.length || page.deferredKeys) throw new Error('Hono islands: deferred props are unsupported.');\n return renderPage(page, interactive.has(page.component) ? assets : { ...assets, preloads: '', body: '' });\n}`;\n }\n if (id === `\\0${ISLANDS_CLIENT_ENTRY_ID}`) {\n if (!islands.size) return 'export {};';\n const loaders = [...islands].map(([name, path]) => `${JSON.stringify(name)}: () => import(${JSON.stringify(path)})`).join(',\\n');\n return `import { initIslands } from 'void/pages-client';\nimport { jsx } from 'hono/jsx/dom/jsx-runtime';\nimport { render } from 'hono/jsx/dom';\ninitIslands({ ${loaders} }, (element, module, props) => {\n if (typeof module.default !== 'function') throw new Error('Hono islands: a component must export a default function.');\n render(jsx(module.default, props), element);\n element.setAttribute('data-hono-island', 'mounted');\n});`;\n }\n },\n };\n}\n"]}
1
+ {"version":3,"file":"hono-islands.js","sourceRoot":"","sources":["../../src/plugins/hono-islands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,SAAS,EAAe,MAAM,MAAM,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,2BAA2B,EAAE,eAAe,EAAuB,MAAM,YAAY,CAAC;AAC1G,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAE3J,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAwB,MAAM,mBAAmB,CAAC;AAE1F,4DAA4D;AAC5D,MAAM,UAAU,WAAW;IACzB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC3B,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC1C,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC7C,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9C,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAU,CAAC;IAC3C,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;IAC1C,IAAI,IAAgC,CAAC;IACrC,IAAI,QAAqC,CAAC;IAE1C,SAAS,aAAa,CAAC,IAAY,EAAE,QAAgB;QACnD,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAChD,MAAM,UAAU,GAAG,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,mBAAmB,IAAI,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,CAAC,OAAO,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC5O,IAAI,UAAU,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,sHAAsH,QAAQ,GAAG,CAAC,CAAC;QAC3L,OAAO,KAAK,CAAC;IACf,CAAC;IAED,SAAS,OAAO,CAAC,IAAY,EAAE,QAAgB;QAC7C,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC5C,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;YAC1B,IAAI,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;gBACzD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtF,IAAI,OAAO,GAAG,CAAC,CAAC;gBAChB,KAAK,MAAM,SAAS,IAAI,KAAK,EAAE,CAAC;oBAAC,IAAI,SAAS,KAAK,GAAG;wBAAE,OAAO,EAAE,CAAC;oBAAC,IAAI,SAAS,KAAK,GAAG;wBAAE,OAAO,EAAE,CAAC;oBAAC,IAAI,OAAO,GAAG,CAAC;wBAAE,MAAM;gBAAC,CAAC;gBAC9H,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;oBAAE,MAAM,IAAI,KAAK,CAAC,4DAA4D,KAAK,CAAC,OAAO,QAAQ,QAAQ,GAAG,CAAC,CAAC;YACpK,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,4DAA4D,QAAQ,GAAG,CAAC,CAAC;YAC/H,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;YACvF,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,kDAAkD,KAAK,CAAC,SAAS,OAAO,QAAQ,GAAG,CAAC,CAAC;YAC3I,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;YACrC,MAAM,EAAE,GAAG,aAAa,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;YACpD,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,UAAU,MAAM;QACnB,IAAI,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3C,kEAAkE;QAClE,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;YACxK,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ;gBAAE,MAAM,IAAI,KAAK,CAAC,GAAG,kBAAkB,IAAI,IAAI,EAAE,CAAC,CAAC;QACxF,CAAC;QACD,OAAO,CAAC,KAAK,EAAE,CAAC;QAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC;QAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;QAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QAClI,MAAM,KAAK,GAAG,CAAC,QAAgB,EAAE,EAAE;YACjC,MAAM,SAAS,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;YACzC,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;gBAAE,OAAO;YACjC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;YAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;YAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACrG,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAC1H,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACvC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBACjB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC;oBAAE,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;gBACnK,mBAAmB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACrC,CAAC;YACD,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gBAC3D,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,KAAK,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,wBAAwB,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAsB,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC1K,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,KAAK,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,KAAK,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,iBAAiB,IAAI,KAAK,CAAC,UAAU,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,wBAAwB,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAsB,CAAC,IAAI,IAAI,CAAC,UAAU,KAAK,MAAM,CAAC;gBACtU,IAAI,CAAC,MAAM,IAAI,QAAQ,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,KAAK,MAAM,CAAC,KAAK,CAAC;oBAAE,SAAS;gBAC9H,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;gBACrG,IAAI,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC;oBAAE,SAAS;gBACpD,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;gBAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACxD,CAAC;QAEH,CAAC,CAAC;QACF,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;QAC/S,MAAM,mBAAmB,GAAG,CAAC,QAAgB,EAAE,IAAI,GAAG,IAAI,GAAG,EAAU,EAAE,EAAE;YACzE,MAAM,SAAS,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;YACzC,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;gBAAE,OAAO;YAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACrD,MAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAC1H,IAAI,aAAa,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,yHAAyH,CAAC,CAAC;YACtL,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gBAC3D,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,KAAK,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,wBAAwB,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAsB,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC1K,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,KAAK,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,KAAK,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,iBAAiB,IAAI,KAAK,CAAC,UAAU,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,wBAAwB,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAsB,CAAC,IAAI,IAAI,CAAC,UAAU,KAAK,MAAM,CAAC;gBACtU,IAAI,CAAC,MAAM,IAAI,QAAQ,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;oBAAE,SAAS;gBACnE,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;gBACrG,IAAI,MAAM,IAAI,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC;oBAAE,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC7E,CAAC;QACH,CAAC,CAAC;QACF,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,MAAM,EAAE;YAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACnE,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7D,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,2BAA2B,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAAE,mBAAmB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;QAC7L,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,mBAAmB,CAAC,CAAC;QAC7C,IAAI,OAAO,GAAG,IAAI,CAAC;QACnB,OAAO,OAAO,EAAE,CAAC;YACf,OAAO,GAAG,KAAK,CAAC;YAChB,KAAK,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,KAAK;gBAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;oBAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;oBAAC,OAAO,GAAG,IAAI,CAAC;gBAAC,CAAC;QACrK,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5D,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,2BAA2B,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;YAC3I,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACvF,MAAM,SAAS,GAAG,QAAQ,EAAE,gBAAgB,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACrE,IAAI,UAAU,IAAI,SAAS;gBAAE,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACpE,IAAI,SAAS,IAAI,CAAC,UAAU;gBAAE,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAED,OAAO;QACL,IAAI,EAAE,mBAAmB;QACzB,OAAO,EAAE,KAAK;QACd,cAAc,CAAC,MAAM,IAAI,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAClE,UAAU,EAAE,MAAM;QAClB,KAAK,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE;YAC1C,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC;YAC9E,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,SAAS,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,aAAa,CAAC,IAAI,CAAC,CAAC;gBAAE,OAAO;YACzH,MAAM,MAAM,EAAE,CAAC;YACf,MAAM,WAAW,GAAG,IAAI,GAAG,EAA4B,CAAC;YACxD,KAAK,MAAM,EAAE,IAAI,CAAC,mBAAmB,EAAE,uBAAuB,EAAE,6BAA6B,CAAC,EAAE,CAAC;gBAC/F,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACrE,IAAI,MAAM;oBAAE,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;YAClG,CAAC;YACD,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,KAAK,QAAQ;gBAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;QACpH,CAAC;QACD,MAAM;YACJ,OAAO,EAAE,KAAK,EAAE,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,EAAE,EAAE,EAAE,CAAC;QAChG,CAAC;QACD,SAAS,CAAC,EAAE;YACV,IAAI,EAAE,KAAK,mBAAmB,IAAI,EAAE,KAAK,uBAAuB;gBAAE,OAAO,KAAK,EAAE,EAAE,CAAC;QACrF,CAAC;QACD,SAAS,CAAC,IAAI,EAAE,EAAE;YAChB,MAAM,QAAQ,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAClC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC;gBAAE,OAAO;YAC/E,MAAM,SAAS,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;YACzC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,IAAI,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,mBAAmB,IAAI,IAAI,CAAC,UAAU,KAAK,MAAM,IAAI,CAAC,2BAA2B,EAAE,4BAA4B,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,KAAK,MAAM,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC,QAAQ,CAAC,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtiB,MAAM,IAAI,KAAK,CAAC,oGAAoG,CAAC,CAAC;YACxH,CAAC;YACD,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YAC5C,IAAI,CAAC,KAAK,CAAC,MAAM;gBAAE,OAAO;YAC1B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,+IAA+I,CAAC,CAAC;YAChM,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACxB,yEAAyE;YACzE,yEAAyE;YACzE,yEAAyE;YACzE,IAAI,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,KAAK,QAAQ;gBAAE,OAAO,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,UAAU,KAAK,CAAC,UAAU,SAAS,KAAK,CAAC,YAAY,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;YAClN,OAAO,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;gBAChD,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;gBACvF,IAAI,CAAC,IAAI;oBAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;gBAClF,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBACnE,MAAM,SAAS,GAAG,wBAAwB,KAAK,CAAC,KAAK,EAAE,CAAC;gBACxD,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,UAAU,SAAS,SAAS,KAAK,CAAC,YAAY;QACjG,KAAK,CAAC,UAAU,yDAAyD,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,qBAAqB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,oEAAoE,SAAS,cAAc,EAAE,CAAC;YACnP,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,kEAAkE,EAAE,CAAC,CAAC;QACvF,CAAC;QACD,IAAI,CAAC,EAAE;YACL,IAAI,EAAE,KAAK,KAAK,mBAAmB,EAAE,EAAE,CAAC;gBACtC,IAAI,CAAC,IAAI;oBAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;gBAC9E,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,2BAA2B,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;gBAC9G,OAAO;8BACe,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;6BAC5B,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC;kCAC/B,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,gBAAgB,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;EAehG,CAAC;YACG,CAAC;YACD,IAAI,EAAE,KAAK,KAAK,uBAAuB,EAAE,EAAE,CAAC;gBAC1C,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI;oBAAE,OAAO,YAAY,CAAC;gBACjE,MAAM,OAAO,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACjI,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,kEAAkE,CAAC,CAAC,CAAC,EAAE;;;;;;;;gBAQpF,OAAO;;;IAGnB,QAAQ,CAAC,CAAC,CAAC;;kLAEmK,CAAC,CAAC,CAAC,EAAE;;;IAGnL,CAAC;YACC,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { readFileSync, realpathSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport { normalizePath, parseSync, type Plugin } from 'vite';\nimport { scanPages, resolveEffectiveLayoutChain, resolvePagesDir, type PageScanResult } from 'void/pages';\nimport { findIslandImports, editIslandSource, computePagesNeedingClientJS, ISLANDS_RENDERER_ID, ISLANDS_CLIENT_ENTRY_ID } from 'void/pages-islands-plugin';\n\nimport { resolveComponent } from './resolve-component.ts';\n\nimport { markdownApi, markdownDiagnostic, type HonoMarkdownApi } from './markdown-api.ts';\n\n/** Hono mounting through Void's shared island scheduler. */\nexport function honoIslands(): Plugin {\n const root = process.cwd();\n const pagesDir = resolvePagesDir(root);\n const islands = new Map<string, string>();\n const pageFiles = new Set<string>();\n const graph = new Map<string, Set<string>>();\n const directlyInteractive = new Set<string>();\n const interactivePages = new Set<string>();\n const scriptOnlyPages = new Set<string>();\n let scan: PageScanResult | undefined;\n let markdown: HonoMarkdownApi | undefined;\n\n function islandImports(code: string, filename: string) {\n const found = findIslandImports(code, filename);\n const attributed = parseSync(filename, code).program.body.filter((node) => node.type === 'ImportDeclaration' && node.attributes?.some(({ key }) => ('name' in key && key.name === 'island') || ('value' in key && key.value === 'island')));\n if (attributed.length !== found.length) throw new Error(`Hono islands: use one default import with exactly one island attribute using load, visible, idle or media:query in ${filename}.`);\n return found;\n }\n\n function imports(code: string, filename: string) {\n const found = islandImports(code, filename);\n for (const entry of found) {\n if (!['load', 'visible', 'idle'].includes(entry.hydrate)) {\n const query = entry.hydrate.startsWith('media:') ? entry.hydrate.slice(6).trim() : '';\n let balance = 0;\n for (const character of query) { if (character === '(') balance++; if (character === ')') balance--; if (balance < 0) break; }\n if (!query || balance !== 0 || /[{};]/.test(query)) throw new Error(`Hono islands: unsupported policy or invalid media query '${entry.hydrate}' in ${filename}.`);\n }\n if (!entry.specifier.startsWith('.')) throw new Error(`Hono islands: use a relative TSX/JSX component import in ${filename}.`);\n const path = resolveComponent(entry.specifier, join(filename, '..'), ['.tsx', '.jsx']);\n if (!path || !/\\.[jt]sx$/.test(path)) throw new Error(`Hono islands: cannot resolve TSX/JSX component ${entry.specifier} in ${filename}.`);\n const canonical = realpathSync(path);\n const id = normalizePath(relative(root, canonical));\n islands.set(id, canonical);\n }\n return found;\n }\n\n async function rescan() {\n scan = await scanPages(root, { pagesDir });\n // Never pass Markdown text to the JavaScript static-graph parser.\n for (const file of [...scan.pages.map(page => page.componentPath), ...scan.layouts.map(layout => layout.filePath), ...scan.namedLayouts.map(layout => layout.filePath)]) {\n if (/\\.md$/.test(file) && !markdown) throw new Error(`${markdownDiagnostic} ${file}`);\n }\n islands.clear(); pageFiles.clear(); graph.clear(); directlyInteractive.clear(); interactivePages.clear(); scriptOnlyPages.clear();\n const visit = (filename: string) => {\n const canonical = realpathSync(filename);\n if (graph.has(canonical)) return;\n const dependencies = new Set<string>(); graph.set(canonical, dependencies); pageFiles.add(canonical);\n const code = canonical.endsWith('.md') && markdown ? markdown.getGraphSource(canonical) : readFileSync(canonical, 'utf8');\n const found = imports(code, canonical);\n if (found.length) {\n if (!/\\.[jt]sx$/.test(canonical) && !(canonical.endsWith('.md') && markdown)) throw new Error('Hono islands: attributed imports require a static TSX/JSX module.');\n directlyInteractive.add(canonical);\n }\n for (const node of parseSync(canonical, code).program.body) {\n const source = node.type === 'ImportDeclaration' ? node.source : node.type === 'ExportNamedDeclaration' || node.type === 'ExportAllDeclaration' ? node.source : undefined;\n const typeOnly = node.type === 'ImportDeclaration' ? node.importKind === 'type' || (node.specifiers.length > 0 && node.specifiers.every((entry) => entry.type === 'ImportSpecifier' && entry.importKind === 'type')) : (node.type === 'ExportNamedDeclaration' || node.type === 'ExportAllDeclaration') && node.exportKind === 'type';\n if (!source || typeOnly || !source.value.startsWith('.') || found.some((entry) => entry.specifier === source.value)) continue;\n const target = resolveComponent(source.value, join(canonical, '..'), ['.tsx', '.jsx', '.ts', '.js']);\n if (!target || !/\\.[jt]sx?$/.test(target)) continue;\n dependencies.add(realpathSync(target)); visit(target);\n }\n\n };\n for (const entry of [...scan.pages.filter((page) => page.island).map((page) => page.componentPath), ...scan.layouts.filter((layout) => layout.island).map((layout) => layout.filePath), ...scan.namedLayouts.filter((layout) => layout.island).map((layout) => layout.filePath)]) visit(join(pagesDir, entry));\n const validateInteractive = (filename: string, seen = new Set<string>()) => {\n const canonical = realpathSync(filename);\n if (seen.has(canonical)) return; seen.add(canonical);\n const code = canonical.endsWith('.md') && markdown ? markdown.getGraphSource(canonical) : readFileSync(canonical, 'utf8');\n if (islandImports(code, canonical).length) throw new Error('Hono islands: attributed imports inside an interactive component are unsupported; use ordinary component imports there.');\n for (const node of parseSync(canonical, code).program.body) {\n const source = node.type === 'ImportDeclaration' ? node.source : node.type === 'ExportNamedDeclaration' || node.type === 'ExportAllDeclaration' ? node.source : undefined;\n const typeOnly = node.type === 'ImportDeclaration' ? node.importKind === 'type' || (node.specifiers.length > 0 && node.specifiers.every((entry) => entry.type === 'ImportSpecifier' && entry.importKind === 'type')) : (node.type === 'ExportNamedDeclaration' || node.type === 'ExportAllDeclaration') && node.exportKind === 'type';\n if (!source || typeOnly || !source.value.startsWith('.')) continue;\n const target = resolveComponent(source.value, join(canonical, '..'), ['.tsx', '.jsx', '.ts', '.js']);\n if (target && /\\.[jt]sx?$/.test(target)) validateInteractive(target, seen);\n }\n };\n for (const target of islands.values()) validateInteractive(target);\n for (const page of scan.pages.filter((page) => !page.island)) {\n for (const file of [page.componentPath, ...resolveEffectiveLayoutChain(page, scan.layouts, scan.namedLayouts).map((layout) => layout.filePath)]) validateInteractive(join(pagesDir, file));\n }\n const needsJS = new Set(directlyInteractive);\n let changed = true;\n while (changed) {\n changed = false;\n for (const [file, dependencies] of graph) if (!needsJS.has(file) && [...dependencies].some((target) => needsJS.has(target))) { needsJS.add(file); changed = true; }\n }\n for (const page of scan.pages.filter((page) => page.island)) {\n const files = [page.componentPath, ...resolveEffectiveLayoutChain(page, scan.layouts, scan.namedLayouts).map((layout) => layout.filePath)];\n const hasIslands = files.some(file => needsJS.has(realpathSync(join(pagesDir, file))));\n const hasScript = markdown?.getClientScripts().has(page.componentId);\n if (hasIslands || hasScript) interactivePages.add(page.componentId);\n if (hasScript && !hasIslands) scriptOnlyPages.add(page.componentId);\n }\n }\n\n return {\n name: 'void-hono:islands',\n enforce: 'pre',\n configResolved(config) { markdown = markdownApi(config.plugins); },\n buildStart: rescan,\n async hotUpdate({ file, modules, timestamp }) {\n const inPages = normalizePath(file).startsWith(normalizePath(pagesDir) + '/');\n if (!inPages && ![...pageFiles, ...islands.values()].some((path) => normalizePath(path) === normalizePath(file))) return;\n await rescan();\n const invalidated = new Set<(typeof modules)[number]>();\n for (const id of [ISLANDS_RENDERER_ID, ISLANDS_CLIENT_ENTRY_ID, 'virtual:void-pages-renderer']) {\n const module = this.environment.moduleGraph.getModuleById(`\\0${id}`);\n if (module) this.environment.moduleGraph.invalidateModule(module, invalidated, timestamp, true);\n }\n if (!inPages && this.environment.config.consumer === 'client') this.environment.hot.send({ type: 'full-reload' });\n },\n config() {\n return { build: { rollupOptions: { input: { 'islands-client': ISLANDS_CLIENT_ENTRY_ID } } } };\n },\n resolveId(id) {\n if (id === ISLANDS_RENDERER_ID || id === ISLANDS_CLIENT_ENTRY_ID) return `\\0${id}`;\n },\n transform(code, id) {\n const filename = id.split('?')[0];\n if (!/\\.[jt]sx$/.test(filename) || filename.includes('/node_modules/')) return;\n const canonical = realpathSync(filename);\n if ((pageFiles.has(canonical) || [...islands.values()].includes(canonical)) && parseSync(filename, code).program.body.some((node) => node.type === 'ImportDeclaration' && node.importKind !== 'type' && ['void-plugin-hono-jsx/form', 'void-plugin-hono-jsx/pages'].includes(node.source.value) && node.specifiers.some((entry) => entry.type !== 'ImportSpecifier' ? node.source.value.endsWith('/form') : entry.importKind !== 'type' && ['useForm', 'action', 'setActionRouter'].includes('name' in entry.imported ? entry.imported.name : entry.imported.value)))) {\n throw new Error('Hono islands: useForm/action require full Pages; use named useIslandForm/Form imports for islands.');\n }\n const found = islandImports(code, filename);\n if (!found.length) return;\n if (!pageFiles.has(canonical)) throw new Error('Hono islands: attributed imports require a static island page, layout or component graph; use ordinary imports inside interactive components.');\n imports(code, filename);\n // Void requests static modules in the client environment to collect CSS.\n // Actual interactive entry graphs were validated above; strip attributes\n // for that traversal rather than generating server-only marker wrappers.\n if (this.environment?.config.consumer === 'client') return editIslandSource(code, found.map((entry) => ({ start: entry.start, end: entry.end, text: `import ${entry.importName} from ${entry.specifierRaw};` })));\n return editIslandSource(code, found.map((entry) => {\n const path = resolveComponent(entry.specifier, join(filename, '..'), ['.tsx', '.jsx']);\n if (!path) throw new Error(`Hono islands: missing component ${entry.specifier}.`);\n const islandId = normalizePath(relative(root, realpathSync(path)));\n const component = `__honoIslandComponent${entry.start}`;\n return { start: entry.start, end: entry.end, text: `import ${component} from ${entry.specifierRaw};\nconst ${entry.importName} = (props) => __honoIslandJsx('div', { 'data-island': ${JSON.stringify(islandId)}, 'data-hydrate': ${JSON.stringify(entry.hydrate)}, 'data-props': JSON.stringify(props), children: __honoIslandJsx(${component}, props) });` };\n }), { prepend: \"import { jsx as __honoIslandJsx } from 'hono/jsx/jsx-runtime';\\n\" });\n },\n load(id) {\n if (id === `\\0${ISLANDS_RENDERER_ID}`) {\n if (!scan) throw new Error('Hono islands: page discovery has not completed.');\n const interactive = [...new Set([...computePagesNeedingClientJS(scan, pagesDir, null), ...interactivePages])];\n return `import { renderPage } from 'virtual:void-pages-renderer';\nconst interactive = new Set(${JSON.stringify(interactive)});\nconst scriptOnly = new Set(${JSON.stringify([...scriptOnlyPages])});\nconst markdownScripts = new Set(${JSON.stringify([...(markdown?.getClientScripts().keys() ?? [])])});\nexport function renderIslandPage(page, assets) {\n if (page.deferred?.length || page.deferredKeys) throw new Error('Hono islands: deferred props are unsupported.');\n if (!markdownScripts.has(page.component)) assets = { ...assets,\n body: assets.body.replace(/<script\\\\b[^>]*src=[\"'][^\"']*(?:void-hono-markdown-client|markdown-client-)[^\"']*[\"'][^>]*>\\\\s*<\\\\/script>/g, ''),\n preloads: assets.preloads.replace(/<link\\\\b[^>]*href=[\"'][^\"']*markdown-client-[^\"']*[\"'][^>]*>/g, ''),\n };\n if (!interactive.has(page.component)) return renderPage(page, { ...assets, preloads: '', body: '' });\n if (scriptOnly.has(page.component)) {\n // Keep the Markdown entry; its dynamic import loads only this page's code.\n // Framework preloads and the island scheduler have no work on this chain.\n const body = assets.body.replace(/<script\\\\b[^>]*src=[\"'][^\"']*(?:void-islands-client|islands-client-)[^\"']*[\"'][^>]*>\\\\s*<\\\\/script>/g, '');\n return renderPage(page, { ...assets, preloads: '', body });\n }\n return renderPage(page, assets);\n}`;\n }\n if (id === `\\0${ISLANDS_CLIENT_ENTRY_ID}`) {\n if (!islands.size || !interactivePages.size) return 'export {};';\n const loaders = [...islands].map(([name, path]) => `${JSON.stringify(name)}: () => import(${JSON.stringify(path)})`).join(',\\n');\n return `${markdown ? \"import { MarkdownContext } from 'void-plugin-hono-jsx/markdown';\" : ''}\nimport { initIslands } from 'void/pages-client';\nimport { jsx } from 'hono/jsx/dom/jsx-runtime';\nimport { render } from 'hono/jsx/dom';\nfor (const element of document.querySelectorAll('[data-hydrate^=\"media:\"]')) {\n const query = element.getAttribute('data-hydrate').slice(6).trim();\n if (matchMedia(query).media === 'not all' && query !== 'not all') throw new Error('Hono islands: invalid or unsupported media query ' + query);\n}\ninitIslands({ ${loaders} }, (element, module, props) => {\n if (typeof module.default !== 'function') throw new Error('Hono islands: a component must export a default function.');\n let content = jsx(module.default, props);\n ${markdown ? `const metadata = JSON.parse(document.getElementById('app')?.getAttribute('data-hono-markdown') || '{}');\n const page = JSON.parse(document.getElementById('__VOID_PAGE_DATA__')?.textContent || '{}');\n content = jsx(MarkdownContext.Provider, { value: { frontmatter: metadata.frontmatter ?? {}, headings: metadata.headings ?? [], props: page.props ?? {} }, children: content });` : ''}\n render(content, element);\n element.setAttribute('data-hono-island', 'mounted');\n});`;\n }\n },\n };\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import { type Plugin } from 'vite';
2
+ /** Optional authored Markdown compiler; independent of @void/md private files. */
3
+ export declare function voidHonoMarkdown(): Plugin;
4
+ //# sourceMappingURL=hono-markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hono-markdown.d.ts","sourceRoot":"","sources":["../../src/plugins/hono-markdown.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,MAAM,EAAE,MAAM,MAAM,CAAC;AAUlD,kFAAkF;AAClF,wBAAgB,gBAAgB,IAAI,MAAM,CAgEzC"}