@jasonshimmy/vite-plugin-cer-app 0.23.2 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (392) hide show
  1. package/dist/cli/checks/lighthouse.d.ts +26 -0
  2. package/dist/cli/checks/lighthouse.d.ts.map +1 -0
  3. package/dist/cli/checks/lighthouse.js +121 -0
  4. package/dist/cli/checks/lighthouse.js.map +1 -0
  5. package/dist/cli/checks/links.d.ts +12 -0
  6. package/dist/cli/checks/links.d.ts.map +1 -0
  7. package/dist/cli/checks/links.js +89 -0
  8. package/dist/cli/checks/links.js.map +1 -0
  9. package/dist/cli/checks/performance.d.ts +17 -0
  10. package/dist/cli/checks/performance.d.ts.map +1 -0
  11. package/dist/cli/checks/performance.js +61 -0
  12. package/dist/cli/checks/performance.js.map +1 -0
  13. package/dist/cli/commands/check.d.ts +3 -0
  14. package/dist/cli/commands/check.d.ts.map +1 -0
  15. package/dist/cli/commands/check.js +85 -0
  16. package/dist/cli/commands/check.js.map +1 -0
  17. package/dist/cli/create/index.d.ts +11 -1
  18. package/dist/cli/create/index.d.ts.map +1 -1
  19. package/dist/cli/create/index.js +135 -65
  20. package/dist/cli/create/index.js.map +1 -1
  21. package/dist/cli/create/templates/spa/package.json.tpl +5 -3
  22. package/dist/cli/create/templates/ssg/cer.config.ts.tpl +2 -0
  23. package/dist/cli/create/templates/ssg/package.json.tpl +5 -3
  24. package/dist/cli/create/templates/ssr/package.json.tpl +5 -3
  25. package/dist/cli/index.js +2 -0
  26. package/dist/cli/index.js.map +1 -1
  27. package/dist/index.d.ts +3 -1
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/plugin/build-ssg.d.ts +22 -6
  30. package/dist/plugin/build-ssg.d.ts.map +1 -1
  31. package/dist/plugin/build-ssg.js +227 -17
  32. package/dist/plugin/build-ssg.js.map +1 -1
  33. package/dist/plugin/content/parser.d.ts.map +1 -1
  34. package/dist/plugin/content/parser.js +54 -10
  35. package/dist/plugin/content/parser.js.map +1 -1
  36. package/dist/plugin/dev-server.d.ts +4 -1
  37. package/dist/plugin/dev-server.d.ts.map +1 -1
  38. package/dist/plugin/dev-server.js.map +1 -1
  39. package/dist/plugin/dts-generator.d.ts.map +1 -1
  40. package/dist/plugin/dts-generator.js +50 -8
  41. package/dist/plugin/dts-generator.js.map +1 -1
  42. package/dist/plugin/generated-dir.d.ts +2 -0
  43. package/dist/plugin/generated-dir.d.ts.map +1 -1
  44. package/dist/plugin/generated-dir.js +17 -6
  45. package/dist/plugin/generated-dir.js.map +1 -1
  46. package/dist/plugin/html-post-process.d.ts +6 -0
  47. package/dist/plugin/html-post-process.d.ts.map +1 -1
  48. package/dist/plugin/html-post-process.js +24 -0
  49. package/dist/plugin/html-post-process.js.map +1 -1
  50. package/dist/plugin/index.d.ts.map +1 -1
  51. package/dist/plugin/index.js +60 -13
  52. package/dist/plugin/index.js.map +1 -1
  53. package/dist/plugin/transforms/auto-import.d.ts.map +1 -1
  54. package/dist/plugin/transforms/auto-import.js +7 -0
  55. package/dist/plugin/transforms/auto-import.js.map +1 -1
  56. package/dist/plugin/transforms/prune-runtime-css.d.ts +8 -0
  57. package/dist/plugin/transforms/prune-runtime-css.d.ts.map +1 -0
  58. package/dist/plugin/transforms/prune-runtime-css.js +40 -0
  59. package/dist/plugin/transforms/prune-runtime-css.js.map +1 -0
  60. package/dist/runtime/app-template.d.ts +1 -1
  61. package/dist/runtime/app-template.d.ts.map +1 -1
  62. package/dist/runtime/app-template.js +206 -36
  63. package/dist/runtime/app-template.js.map +1 -1
  64. package/dist/runtime/composables/index.d.ts +4 -0
  65. package/dist/runtime/composables/index.d.ts.map +1 -1
  66. package/dist/runtime/composables/index.js +2 -0
  67. package/dist/runtime/composables/index.js.map +1 -1
  68. package/dist/runtime/composables/use-active-headings.d.ts +24 -0
  69. package/dist/runtime/composables/use-active-headings.d.ts.map +1 -0
  70. package/dist/runtime/composables/use-active-headings.js +112 -0
  71. package/dist/runtime/composables/use-active-headings.js.map +1 -0
  72. package/dist/runtime/composables/use-content-page.d.ts +45 -0
  73. package/dist/runtime/composables/use-content-page.d.ts.map +1 -0
  74. package/dist/runtime/composables/use-content-page.js +179 -0
  75. package/dist/runtime/composables/use-content-page.js.map +1 -0
  76. package/dist/runtime/composables/use-content-search.d.ts.map +1 -1
  77. package/dist/runtime/composables/use-content-search.js +1 -5
  78. package/dist/runtime/composables/use-content-search.js.map +1 -1
  79. package/dist/runtime/composables/use-fetch.d.ts +2 -1
  80. package/dist/runtime/composables/use-fetch.d.ts.map +1 -1
  81. package/dist/runtime/composables/use-fetch.js +112 -43
  82. package/dist/runtime/composables/use-fetch.js.map +1 -1
  83. package/dist/runtime/composables/use-route.d.ts.map +1 -1
  84. package/dist/runtime/composables/use-route.js +39 -11
  85. package/dist/runtime/composables/use-route.js.map +1 -1
  86. package/dist/runtime/content/client.js +2 -2
  87. package/dist/runtime/content/client.js.map +1 -1
  88. package/dist/runtime/entry-server-template.d.ts +16 -1
  89. package/dist/runtime/entry-server-template.d.ts.map +1 -1
  90. package/dist/runtime/entry-server-template.js +120 -13
  91. package/dist/runtime/entry-server-template.js.map +1 -1
  92. package/dist/types/config.d.ts +45 -4
  93. package/dist/types/config.d.ts.map +1 -1
  94. package/dist/types/config.js.map +1 -1
  95. package/dist/types/middleware.d.ts +2 -2
  96. package/dist/types/middleware.d.ts.map +1 -1
  97. package/package.json +22 -19
  98. package/.github/copilot-instructions.md +0 -169
  99. package/.github/workflows/publish.yml +0 -257
  100. package/.nvmrc +0 -1
  101. package/CHANGELOG.md +0 -236
  102. package/CLAUDE.md +0 -113
  103. package/commits.txt +0 -1
  104. package/cypress.config.ts +0 -16
  105. package/docs/authentication.md +0 -285
  106. package/docs/cli.md +0 -324
  107. package/docs/components.md +0 -237
  108. package/docs/composables.md +0 -907
  109. package/docs/configuration.md +0 -696
  110. package/docs/content.md +0 -570
  111. package/docs/data-loading.md +0 -336
  112. package/docs/getting-started.md +0 -237
  113. package/docs/head-management.md +0 -212
  114. package/docs/i18n.md +0 -159
  115. package/docs/layouts.md +0 -224
  116. package/docs/middleware.md +0 -234
  117. package/docs/plugins.md +0 -170
  118. package/docs/rendering-modes.md +0 -377
  119. package/docs/routing.md +0 -485
  120. package/docs/server-api.md +0 -253
  121. package/docs/testing.md +0 -455
  122. package/docs/use-fetch.md +0 -183
  123. package/e2e/cypress/e2e/api.cy.ts +0 -123
  124. package/e2e/cypress/e2e/async-component.cy.ts +0 -27
  125. package/e2e/cypress/e2e/component-splitting.cy.ts +0 -50
  126. package/e2e/cypress/e2e/content.cy.ts +0 -425
  127. package/e2e/cypress/e2e/cookie.cy.ts +0 -85
  128. package/e2e/cypress/e2e/data.cy.ts +0 -158
  129. package/e2e/cypress/e2e/error-boundary.cy.ts +0 -88
  130. package/e2e/cypress/e2e/fouc.cy.ts +0 -254
  131. package/e2e/cypress/e2e/group-meta.cy.ts +0 -36
  132. package/e2e/cypress/e2e/head.cy.ts +0 -89
  133. package/e2e/cypress/e2e/i18n.cy.ts +0 -79
  134. package/e2e/cypress/e2e/interactive.cy.ts +0 -137
  135. package/e2e/cypress/e2e/isr-nested-runtime.cy.ts +0 -102
  136. package/e2e/cypress/e2e/jit-css-custom-colors.cy.ts +0 -43
  137. package/e2e/cypress/e2e/middleware-chain.cy.ts +0 -89
  138. package/e2e/cypress/e2e/middleware-status.cy.ts +0 -30
  139. package/e2e/cypress/e2e/middleware.cy.ts +0 -45
  140. package/e2e/cypress/e2e/navigate.cy.ts +0 -39
  141. package/e2e/cypress/e2e/observability.cy.ts +0 -77
  142. package/e2e/cypress/e2e/per-route-error.cy.ts +0 -42
  143. package/e2e/cypress/e2e/per-route-render.cy.ts +0 -70
  144. package/e2e/cypress/e2e/preview-hardening.cy.ts +0 -88
  145. package/e2e/cypress/e2e/routes.cy.ts +0 -128
  146. package/e2e/cypress/e2e/seo-meta.cy.ts +0 -108
  147. package/e2e/cypress/e2e/server-middleware.cy.ts +0 -46
  148. package/e2e/cypress/e2e/session-rotation.cy.ts +0 -25
  149. package/e2e/cypress/e2e/session.cy.ts +0 -73
  150. package/e2e/cypress/e2e/ssr-render-error.cy.ts +0 -68
  151. package/e2e/cypress/e2e/synthetic-404.cy.ts +0 -45
  152. package/e2e/cypress/e2e/use-page-data.cy.ts +0 -122
  153. package/e2e/cypress/e2e/use-state.cy.ts +0 -138
  154. package/e2e/cypress/support/commands.ts +0 -120
  155. package/e2e/cypress/support/e2e.ts +0 -10
  156. package/e2e/cypress/tsconfig.json +0 -14
  157. package/e2e/kitchen-sink/app/components/ks-badge.ts +0 -8
  158. package/e2e/kitchen-sink/app/composables/useKsCounter.ts +0 -9
  159. package/e2e/kitchen-sink/app/error.ts +0 -18
  160. package/e2e/kitchen-sink/app/layouts/admin.ts +0 -13
  161. package/e2e/kitchen-sink/app/layouts/default.ts +0 -25
  162. package/e2e/kitchen-sink/app/layouts/group.ts +0 -9
  163. package/e2e/kitchen-sink/app/layouts/minimal.ts +0 -7
  164. package/e2e/kitchen-sink/app/loading.ts +0 -9
  165. package/e2e/kitchen-sink/app/middleware/auth.ts +0 -9
  166. package/e2e/kitchen-sink/app/middleware/custom-log.ts +0 -4
  167. package/e2e/kitchen-sink/app/middleware/group-auth.ts +0 -7
  168. package/e2e/kitchen-sink/app/middleware/logger.ts +0 -14
  169. package/e2e/kitchen-sink/app/pages/(auth)/login.ts +0 -13
  170. package/e2e/kitchen-sink/app/pages/(auth)/protected.ts +0 -16
  171. package/e2e/kitchen-sink/app/pages/404.ts +0 -9
  172. package/e2e/kitchen-sink/app/pages/about.ts +0 -17
  173. package/e2e/kitchen-sink/app/pages/admin/_layout.ts +0 -1
  174. package/e2e/kitchen-sink/app/pages/admin/dashboard.ts +0 -11
  175. package/e2e/kitchen-sink/app/pages/async-component-error-test.ts +0 -18
  176. package/e2e/kitchen-sink/app/pages/async-component-test.ts +0 -18
  177. package/e2e/kitchen-sink/app/pages/blog/[slug].ts +0 -59
  178. package/e2e/kitchen-sink/app/pages/blog/index.ts +0 -51
  179. package/e2e/kitchen-sink/app/pages/content-blog.ts +0 -37
  180. package/e2e/kitchen-sink/app/pages/content-doc.ts +0 -42
  181. package/e2e/kitchen-sink/app/pages/content-fallback.ts +0 -36
  182. package/e2e/kitchen-sink/app/pages/content-guides.ts +0 -35
  183. package/e2e/kitchen-sink/app/pages/content-index.ts +0 -39
  184. package/e2e/kitchen-sink/app/pages/content-search.ts +0 -36
  185. package/e2e/kitchen-sink/app/pages/cookie-test.ts +0 -22
  186. package/e2e/kitchen-sink/app/pages/counter.ts +0 -17
  187. package/e2e/kitchen-sink/app/pages/group-auth-blocked.ts +0 -9
  188. package/e2e/kitchen-sink/app/pages/group-meta-test/_layout.ts +0 -6
  189. package/e2e/kitchen-sink/app/pages/group-meta-test/custom-mw.ts +0 -14
  190. package/e2e/kitchen-sink/app/pages/group-meta-test/page.ts +0 -9
  191. package/e2e/kitchen-sink/app/pages/group-meta-test/protected.ts +0 -8
  192. package/e2e/kitchen-sink/app/pages/head.ts +0 -20
  193. package/e2e/kitchen-sink/app/pages/i18n-test.ts +0 -14
  194. package/e2e/kitchen-sink/app/pages/index.ts +0 -27
  195. package/e2e/kitchen-sink/app/pages/isr-test.ts +0 -17
  196. package/e2e/kitchen-sink/app/pages/items/[id].ts +0 -20
  197. package/e2e/kitchen-sink/app/pages/jit-css-custom-colors-test.ts +0 -14
  198. package/e2e/kitchen-sink/app/pages/loader-error-test.ts +0 -13
  199. package/e2e/kitchen-sink/app/pages/loader-props-test.ts +0 -19
  200. package/e2e/kitchen-sink/app/pages/loader-response-error-test.ts +0 -13
  201. package/e2e/kitchen-sink/app/pages/middleware-chain-test.ts +0 -12
  202. package/e2e/kitchen-sink/app/pages/middleware-status-test.ts +0 -9
  203. package/e2e/kitchen-sink/app/pages/navigate-test.ts +0 -16
  204. package/e2e/kitchen-sink/app/pages/observability-test.ts +0 -25
  205. package/e2e/kitchen-sink/app/pages/per-route-error-test.error.ts +0 -13
  206. package/e2e/kitchen-sink/app/pages/per-route-error-test.ts +0 -15
  207. package/e2e/kitchen-sink/app/pages/plugin-dsd-test.ts +0 -10
  208. package/e2e/kitchen-sink/app/pages/render-error-test.ts +0 -12
  209. package/e2e/kitchen-sink/app/pages/render-server-test.ts +0 -12
  210. package/e2e/kitchen-sink/app/pages/render-spa-test.ts +0 -12
  211. package/e2e/kitchen-sink/app/pages/route-info.ts +0 -14
  212. package/e2e/kitchen-sink/app/pages/seo-test.ts +0 -23
  213. package/e2e/kitchen-sink/app/pages/session-rotation-test.ts +0 -25
  214. package/e2e/kitchen-sink/app/pages/use-state-test.ts +0 -37
  215. package/e2e/kitchen-sink/app/plugins/01.setup.ts +0 -7
  216. package/e2e/kitchen-sink/app/plugins/02.ks-plugin-components.ts +0 -27
  217. package/e2e/kitchen-sink/cer-auto-imports.d.ts +0 -51
  218. package/e2e/kitchen-sink/cer-env.d.ts +0 -35
  219. package/e2e/kitchen-sink/cer-tsconfig.json +0 -30
  220. package/e2e/kitchen-sink/cer.config.ts +0 -43
  221. package/e2e/kitchen-sink/content/01.guides/01.index.md +0 -8
  222. package/e2e/kitchen-sink/content/01.guides/02.intro.md +0 -8
  223. package/e2e/kitchen-sink/content/01.guides/10.advanced.md +0 -8
  224. package/e2e/kitchen-sink/content/blog/2026-04-01-hello.md +0 -26
  225. package/e2e/kitchen-sink/content/blog/2026-04-02-draft.md +0 -10
  226. package/e2e/kitchen-sink/content/blog/index.md +0 -8
  227. package/e2e/kitchen-sink/content/blog/no-frontmatter.md +0 -7
  228. package/e2e/kitchen-sink/content/docs/getting-started.md +0 -48
  229. package/e2e/kitchen-sink/content/index.md +0 -16
  230. package/e2e/kitchen-sink/server/api/echo.ts +0 -12
  231. package/e2e/kitchen-sink/server/api/health.ts +0 -3
  232. package/e2e/kitchen-sink/server/api/posts/[slug].ts +0 -11
  233. package/e2e/kitchen-sink/server/api/posts/index.ts +0 -5
  234. package/e2e/kitchen-sink/server/api/session.ts +0 -23
  235. package/e2e/kitchen-sink/server/data/posts.ts +0 -21
  236. package/e2e/kitchen-sink/server/middleware/01-headers.ts +0 -6
  237. package/e2e/kitchen-sink/server/middleware/02-status-test.ts +0 -10
  238. package/e2e/kitchen-sink/tsconfig.json +0 -3
  239. package/e2e/scripts/clean.mjs +0 -14
  240. package/eslint.config.ts +0 -22
  241. package/src/__tests__/cli/adapters/cloudflare-worker.integration.test.ts +0 -132
  242. package/src/__tests__/cli/adapters/cloudflare.test.ts +0 -332
  243. package/src/__tests__/cli/adapters/netlify-bridge.integration.test.ts +0 -139
  244. package/src/__tests__/cli/adapters/netlify.test.ts +0 -286
  245. package/src/__tests__/cli/adapters/vercel-launcher.integration.test.ts +0 -129
  246. package/src/__tests__/cli/adapters/vercel.test.ts +0 -263
  247. package/src/__tests__/cli/preview-hardening.test.ts +0 -265
  248. package/src/__tests__/cli/preview-isr.test.ts +0 -320
  249. package/src/__tests__/index.test.ts +0 -21
  250. package/src/__tests__/plugin/app-template.test.ts +0 -166
  251. package/src/__tests__/plugin/build-ssg-render.test.ts +0 -155
  252. package/src/__tests__/plugin/build-ssg.test.ts +0 -598
  253. package/src/__tests__/plugin/build-ssr.test.ts +0 -192
  254. package/src/__tests__/plugin/cer-app-plugin.test.ts +0 -552
  255. package/src/__tests__/plugin/content/emitter.test.ts +0 -117
  256. package/src/__tests__/plugin/content/loader.test.ts +0 -154
  257. package/src/__tests__/plugin/content/parser.test.ts +0 -381
  258. package/src/__tests__/plugin/content/path-utils.test.ts +0 -69
  259. package/src/__tests__/plugin/content/search.test.ts +0 -119
  260. package/src/__tests__/plugin/dev-server.test.ts +0 -813
  261. package/src/__tests__/plugin/dts-generator.test.ts +0 -394
  262. package/src/__tests__/plugin/entry-server-template.test.ts +0 -385
  263. package/src/__tests__/plugin/generated-dir.test.ts +0 -144
  264. package/src/__tests__/plugin/html-post-process.test.ts +0 -146
  265. package/src/__tests__/plugin/path-utils.test.ts +0 -411
  266. package/src/__tests__/plugin/resolve-config.test.ts +0 -233
  267. package/src/__tests__/plugin/scanner.test.ts +0 -186
  268. package/src/__tests__/plugin/transforms/auto-import.test.ts +0 -510
  269. package/src/__tests__/plugin/transforms/head-inject.test.ts +0 -178
  270. package/src/__tests__/plugin/virtual/composables.test.ts +0 -57
  271. package/src/__tests__/plugin/virtual/content-components.test.ts +0 -66
  272. package/src/__tests__/plugin/virtual/error.test.ts +0 -71
  273. package/src/__tests__/plugin/virtual/layouts.test.ts +0 -70
  274. package/src/__tests__/plugin/virtual/loading.test.ts +0 -72
  275. package/src/__tests__/plugin/virtual/middleware.test.ts +0 -83
  276. package/src/__tests__/plugin/virtual/plugins.test.ts +0 -129
  277. package/src/__tests__/plugin/virtual/routes.test.ts +0 -884
  278. package/src/__tests__/plugin/virtual/server-api.test.ts +0 -164
  279. package/src/__tests__/plugin/virtual/server-middleware.test.ts +0 -102
  280. package/src/__tests__/runtime/app-template.test.ts +0 -208
  281. package/src/__tests__/runtime/define-middleware.test.ts +0 -64
  282. package/src/__tests__/runtime/define-server-middleware.test.ts +0 -54
  283. package/src/__tests__/runtime/entry-client-template.test.ts +0 -61
  284. package/src/__tests__/runtime/isr-handler.test.ts +0 -338
  285. package/src/__tests__/runtime/oauth/handler.test.ts +0 -358
  286. package/src/__tests__/runtime/oauth/providers.test.ts +0 -47
  287. package/src/__tests__/runtime/oauth-index.test.ts +0 -43
  288. package/src/__tests__/runtime/use-auth.test.ts +0 -169
  289. package/src/__tests__/runtime/use-content-search-composable.test.ts +0 -405
  290. package/src/__tests__/runtime/use-content-search.test.ts +0 -163
  291. package/src/__tests__/runtime/use-content.test.ts +0 -226
  292. package/src/__tests__/runtime/use-cookie.test.ts +0 -277
  293. package/src/__tests__/runtime/use-fetch-component.test.ts +0 -214
  294. package/src/__tests__/runtime/use-fetch.test.ts +0 -377
  295. package/src/__tests__/runtime/use-head.test.ts +0 -311
  296. package/src/__tests__/runtime/use-inject-client.test.ts +0 -67
  297. package/src/__tests__/runtime/use-inject.test.ts +0 -66
  298. package/src/__tests__/runtime/use-locale.test.ts +0 -152
  299. package/src/__tests__/runtime/use-navigate.test.ts +0 -121
  300. package/src/__tests__/runtime/use-page-data.test.ts +0 -298
  301. package/src/__tests__/runtime/use-route.test.ts +0 -156
  302. package/src/__tests__/runtime/use-runtime-config.test.ts +0 -182
  303. package/src/__tests__/runtime/use-seo-meta.test.ts +0 -109
  304. package/src/__tests__/runtime/use-session.test.ts +0 -320
  305. package/src/__tests__/runtime/use-state.test.ts +0 -340
  306. package/src/__tests__/types/config.test.ts +0 -18
  307. package/src/cli/adapters/cloudflare.ts +0 -335
  308. package/src/cli/adapters/netlify.ts +0 -326
  309. package/src/cli/adapters/vercel.ts +0 -311
  310. package/src/cli/commands/adapt.ts +0 -84
  311. package/src/cli/commands/build.ts +0 -165
  312. package/src/cli/commands/dev.ts +0 -125
  313. package/src/cli/commands/generate.ts +0 -91
  314. package/src/cli/commands/preview-isr.ts +0 -172
  315. package/src/cli/commands/preview.ts +0 -523
  316. package/src/cli/create/index.ts +0 -275
  317. package/src/cli/create/templates/shared/.gitignore.tpl +0 -25
  318. package/src/cli/create/templates/shared/app/layouts/default.ts.tpl +0 -15
  319. package/src/cli/create/templates/shared/app/pages/index.ts.tpl +0 -8
  320. package/src/cli/create/templates/shared/index.html.tpl +0 -12
  321. package/src/cli/create/templates/shared/tsconfig.json.tpl +0 -6
  322. package/src/cli/create/templates/spa/cer.config.ts.tpl +0 -6
  323. package/src/cli/create/templates/spa/package.json.tpl +0 -18
  324. package/src/cli/create/templates/ssg/cer.config.ts.tpl +0 -10
  325. package/src/cli/create/templates/ssg/package.json.tpl +0 -19
  326. package/src/cli/create/templates/ssr/cer.config.ts.tpl +0 -6
  327. package/src/cli/create/templates/ssr/package.json.tpl +0 -18
  328. package/src/cli/index.ts +0 -22
  329. package/src/index.ts +0 -20
  330. package/src/plugin/build-ssg.ts +0 -403
  331. package/src/plugin/build-ssr.ts +0 -134
  332. package/src/plugin/content/emitter.ts +0 -50
  333. package/src/plugin/content/index.ts +0 -233
  334. package/src/plugin/content/parser.ts +0 -259
  335. package/src/plugin/content/path-utils.ts +0 -55
  336. package/src/plugin/content/scanner.ts +0 -26
  337. package/src/plugin/content/search.ts +0 -28
  338. package/src/plugin/dev-server.ts +0 -379
  339. package/src/plugin/dts-generator.ts +0 -273
  340. package/src/plugin/generated-dir.ts +0 -121
  341. package/src/plugin/html-post-process.ts +0 -96
  342. package/src/plugin/index.ts +0 -584
  343. package/src/plugin/path-utils.ts +0 -186
  344. package/src/plugin/scanner.ts +0 -65
  345. package/src/plugin/transforms/auto-import.ts +0 -206
  346. package/src/plugin/transforms/head-inject.ts +0 -161
  347. package/src/plugin/virtual/composables.ts +0 -28
  348. package/src/plugin/virtual/content-components.ts +0 -83
  349. package/src/plugin/virtual/error.ts +0 -34
  350. package/src/plugin/virtual/layouts.ts +0 -41
  351. package/src/plugin/virtual/loading.ts +0 -32
  352. package/src/plugin/virtual/middleware.ts +0 -45
  353. package/src/plugin/virtual/plugins.ts +0 -46
  354. package/src/plugin/virtual/routes.ts +0 -514
  355. package/src/plugin/virtual/server-api.ts +0 -85
  356. package/src/plugin/virtual/server-middleware.ts +0 -44
  357. package/src/runtime/app-template.ts +0 -377
  358. package/src/runtime/composables/define-middleware.ts +0 -17
  359. package/src/runtime/composables/define-server-middleware.ts +0 -18
  360. package/src/runtime/composables/index.ts +0 -27
  361. package/src/runtime/composables/use-auth.ts +0 -125
  362. package/src/runtime/composables/use-content-search.ts +0 -205
  363. package/src/runtime/composables/use-content.ts +0 -146
  364. package/src/runtime/composables/use-cookie.ts +0 -135
  365. package/src/runtime/composables/use-fetch.ts +0 -438
  366. package/src/runtime/composables/use-head.ts +0 -234
  367. package/src/runtime/composables/use-inject.ts +0 -49
  368. package/src/runtime/composables/use-locale.ts +0 -109
  369. package/src/runtime/composables/use-navigate.ts +0 -58
  370. package/src/runtime/composables/use-page-data.ts +0 -93
  371. package/src/runtime/composables/use-route.ts +0 -71
  372. package/src/runtime/composables/use-runtime-config.ts +0 -123
  373. package/src/runtime/composables/use-seo-meta.ts +0 -80
  374. package/src/runtime/composables/use-session.ts +0 -186
  375. package/src/runtime/composables/use-state.ts +0 -92
  376. package/src/runtime/content/client.ts +0 -168
  377. package/src/runtime/entry-client-template.ts +0 -39
  378. package/src/runtime/entry-server-template.ts +0 -493
  379. package/src/runtime/isr-handler.ts +0 -184
  380. package/src/runtime/oauth/handler.ts +0 -407
  381. package/src/runtime/oauth/index.ts +0 -49
  382. package/src/runtime/oauth/providers.ts +0 -38
  383. package/src/types/api.ts +0 -40
  384. package/src/types/config.ts +0 -379
  385. package/src/types/content.ts +0 -66
  386. package/src/types/index.ts +0 -7
  387. package/src/types/middleware.ts +0 -63
  388. package/src/types/page.ts +0 -117
  389. package/src/types/plugin.ts +0 -34
  390. package/tsconfig.build.json +0 -10
  391. package/tsconfig.json +0 -19
  392. package/vitest.config.ts +0 -33
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Removes the opt-in extended palette from the runtime's global variables
3
+ * stylesheet when an app uses the default core palette. Utility declarations
4
+ * retain their own color fallbacks, so this avoids shipping hundreds of unused
5
+ * custom-property declarations without changing rendered colors.
6
+ */
7
+ export declare function pruneRuntimeExtendedColorVariables(code: string, id: string, extendedColors: boolean | string[]): string;
8
+ //# sourceMappingURL=prune-runtime-css.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prune-runtime-css.d.ts","sourceRoot":"","sources":["../../../src/plugin/transforms/prune-runtime-css.ts"],"names":[],"mappings":"AA6BA;;;;;GAKG;AACH,wBAAgB,kCAAkC,CAChD,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,cAAc,EAAE,OAAO,GAAG,MAAM,EAAE,GACjC,MAAM,CAcR"}
@@ -0,0 +1,40 @@
1
+ const EXTENDED_COLOR_FAMILIES = [
2
+ 'slate',
3
+ 'gray',
4
+ 'zinc',
5
+ 'stone',
6
+ 'red',
7
+ 'orange',
8
+ 'amber',
9
+ 'yellow',
10
+ 'lime',
11
+ 'green',
12
+ 'emerald',
13
+ 'teal',
14
+ 'cyan',
15
+ 'sky',
16
+ 'blue',
17
+ 'indigo',
18
+ 'violet',
19
+ 'purple',
20
+ 'fuchsia',
21
+ 'pink',
22
+ 'rose',
23
+ ];
24
+ const EXTENDED_COLOR_DECLARATION = new RegExp(String.raw `[\t ]*--cer-color-(${EXTENDED_COLOR_FAMILIES.join('|')})-[\w-]+\s*:[^;{}]*(?:;|(?=\s*}))[\t ]*`, 'g');
25
+ /**
26
+ * Removes the opt-in extended palette from the runtime's global variables
27
+ * stylesheet when an app uses the default core palette. Utility declarations
28
+ * retain their own color fallbacks, so this avoids shipping hundreds of unused
29
+ * custom-property declarations without changing rendered colors.
30
+ */
31
+ export function pruneRuntimeExtendedColorVariables(code, id, extendedColors) {
32
+ if (extendedColors === true ||
33
+ !id.includes('@jasonshimmy/custom-elements-runtime') ||
34
+ !/\/(?:style|variables)\.css(?:\?|$)/.test(id)) {
35
+ return code;
36
+ }
37
+ const enabled = new Set(Array.isArray(extendedColors) ? extendedColors : []);
38
+ return code.replace(EXTENDED_COLOR_DECLARATION, (declaration, family) => enabled.has(family) ? declaration : '');
39
+ }
40
+ //# sourceMappingURL=prune-runtime-css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prune-runtime-css.js","sourceRoot":"","sources":["../../../src/plugin/transforms/prune-runtime-css.ts"],"names":[],"mappings":"AAAA,MAAM,uBAAuB,GAAG;IAC9B,OAAO;IACP,MAAM;IACN,MAAM;IACN,OAAO;IACP,KAAK;IACL,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,MAAM;IACN,OAAO;IACP,SAAS;IACT,MAAM;IACN,MAAM;IACN,KAAK;IACL,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,MAAM;IACN,MAAM;CACE,CAAA;AAEV,MAAM,0BAA0B,GAAG,IAAI,MAAM,CAC3C,MAAM,CAAC,GAAG,CAAA,sBAAsB,uBAAuB,CAAC,IAAI,CAAC,GAAG,CAAC,yCAAyC,EAC1G,GAAG,CACJ,CAAA;AAED;;;;;GAKG;AACH,MAAM,UAAU,kCAAkC,CAChD,IAAY,EACZ,EAAU,EACV,cAAkC;IAElC,IACE,cAAc,KAAK,IAAI;QACvB,CAAC,EAAE,CAAC,QAAQ,CAAC,sCAAsC,CAAC;QACpD,CAAC,oCAAoC,CAAC,IAAI,CAAC,EAAE,CAAC,EAC9C,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IAC5E,OAAO,IAAI,CAAC,OAAO,CACjB,0BAA0B,EAC1B,CAAC,WAAW,EAAE,MAAc,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CACxE,CAAA;AACH,CAAC"}
@@ -5,5 +5,5 @@
5
5
  * automatically receive the latest bootstrap code on plugin update.
6
6
  * This file is gitignored and should never be edited directly.
7
7
  */
8
- export declare function generateAppEntryTemplate(): string;
8
+ export declare function generateAppEntryTemplate(globalImports?: readonly string[]): string;
9
9
  //# sourceMappingURL=app-template.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"app-template.d.ts","sourceRoot":"","sources":["../../src/runtime/app-template.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAiXjD"}
1
+ {"version":3,"file":"app-template.d.ts","sourceRoot":"","sources":["../../src/runtime/app-template.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,aAAa,GAAE,SAAS,MAAM,EAAO,GAAG,MAAM,CA2hBtF"}
@@ -5,12 +5,15 @@
5
5
  * automatically receive the latest bootstrap code on plugin update.
6
6
  * This file is gitignored and should never be edited directly.
7
7
  */
8
- export function generateAppEntryTemplate() {
8
+ export function generateAppEntryTemplate(globalImports = []) {
9
+ const integrationImports = [...new Set(globalImports)]
10
+ .map((specifier) => `import '${specifier.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`)
11
+ .join('\n');
9
12
  return `// AUTO-GENERATED by @jasonshimmy/vite-plugin-cer-app — do not edit.
10
13
  // Regenerated automatically on every dev server start and build.
11
14
 
12
15
  import '@jasonshimmy/custom-elements-runtime/css'
13
- import 'virtual:cer-jit-css'
16
+ ${integrationImports}${integrationImports ? '\n' : ''}import 'virtual:cer-jit-css'
14
17
  // virtual:cer-jit-init must run before virtual:cer-layouts and virtual:cer-plugins
15
18
  // so JIT CSS is enabled before those modules upgrade custom elements via
16
19
  // customElements.define(). Static imports execute depth-first in module order,
@@ -22,7 +25,7 @@ import layouts from 'virtual:cer-layouts'
22
25
  import plugins from 'virtual:cer-plugins'
23
26
  import { hasLoading, loadingTag } from 'virtual:cer-loading'
24
27
  import { hasError, errorTag } from 'virtual:cer-error'
25
- import { runtimeConfig } from 'virtual:cer-app-config'
28
+ import { runtimeConfig, appConfig } from 'virtual:cer-app-config'
26
29
  import {
27
30
  component,
28
31
  ref,
@@ -53,7 +56,7 @@ registerBuiltinComponents()
53
56
  setDevMode(_cerRuntimeDev)
54
57
  initRuntimeConfig(runtimeConfig)
55
58
 
56
- const router = initRouter({ routes })
59
+ const router = initRouter({ ...appConfig.router, routes })
57
60
 
58
61
  // Expose the router globally so useRoute() and navigateTo() can access it
59
62
  // from any composable without circular imports.
@@ -66,10 +69,17 @@ const router = initRouter({ routes })
66
69
  // the page element directly with the correct attributes (enabling useProps()).
67
70
  let _currentPageTag = null
68
71
  let _currentPageAttrs = {}
72
+ // Changes only when a page load successfully publishes. Keying the rendered
73
+ // page with this value prevents dynamic/catch-all routes that share one custom
74
+ // element tag from retaining loader-backed state from the previous URL.
75
+ let _currentPageKey = null
69
76
  // The pathname this tag was loaded for — used to detect router-internal
70
77
  // redirects (e.g. middleware returning '/login') so cer-layout-view falls
71
78
  // back to <router-view> when the current route differs from what was pre-loaded.
72
79
  let _currentPagePath = null
80
+ // Route chunks and loaders may resolve out of order during rapid navigation or
81
+ // initial hydration. Only the newest request is allowed to publish page state.
82
+ let _pageLoadVersion = 0
73
83
 
74
84
  function _toLoaderAttrs(data) {
75
85
  if (data === undefined || data === null || typeof data !== 'object') return {}
@@ -81,6 +91,7 @@ function _toLoaderAttrs(data) {
81
91
  // Pre-loads the page module for \`path\`, calls its loader if present, and
82
92
  // stores the results so cer-layout-view can pass them as element attributes.
83
93
  async function _loadPageForPath(path, options = {}) {
94
+ const loadVersion = ++_pageLoadVersion
84
95
  try {
85
96
  const url = new URL(path, 'http://x')
86
97
  const query = Object.fromEntries(url.searchParams)
@@ -88,26 +99,29 @@ async function _loadPageForPath(path, options = {}) {
88
99
  const matched = router.matchRoute(url.pathname)
89
100
  const route = matched?.route
90
101
  if (!route?.load) {
102
+ if (loadVersion !== _pageLoadVersion) return
91
103
  _currentPageTag = null
92
104
  _currentPageAttrs = {}
105
+ _currentPageKey = null
93
106
  _currentPagePath = url.pathname
94
107
  return
95
108
  }
96
109
  const mod = await route.load()
97
- _currentPageTag = mod.default ?? null
98
- _currentPagePath = url.pathname
110
+ if (loadVersion !== _pageLoadVersion) return
99
111
  const params = matched.params ?? {}
100
112
  let loaderAttrs = { ...params }
101
113
  let loaderData = initialData
114
+ let hasFreshLoaderData = false
102
115
  if (typeof mod.loader === 'function' && runLoader) {
103
116
  try {
104
117
  const data = await mod.loader({ params, query })
118
+ if (loadVersion !== _pageLoadVersion) return
105
119
  if (data !== undefined && data !== null) {
106
120
  loaderData = data
107
- // Make loader data available via usePageData() for this navigation.
108
- ;(globalThis).__CER_DATA__ = data
121
+ hasFreshLoaderData = true
109
122
  }
110
123
  } catch (err) {
124
+ if (loadVersion !== _pageLoadVersion) return
111
125
  // Loader errors are surfaced through currentError so the error boundary
112
126
  // (app/error.ts) can display a meaningful message — consistent with how
113
127
  // the server-side handler behaves when a loader throws.
@@ -118,11 +132,21 @@ async function _loadPageForPath(path, options = {}) {
118
132
  // loader payload in globalThis.__CER_DATA__ / window.__CER_DATA__. Reuse it
119
133
  // instead of re-running the loader on the client, then derive primitive attrs
120
134
  // from that payload so useProps() stays consistent with usePageData().
135
+ if (loadVersion !== _pageLoadVersion) return
121
136
  loaderAttrs = { ...loaderAttrs, ..._toLoaderAttrs(loaderData) }
137
+ if (hasFreshLoaderData) {
138
+ // Publish loader data only after confirming this is still the newest route.
139
+ ;(globalThis).__CER_DATA__ = loaderData
140
+ }
141
+ _currentPageTag = mod.default ?? null
142
+ _currentPagePath = url.pathname
122
143
  _currentPageAttrs = loaderAttrs
144
+ _currentPageKey = loadVersion
123
145
  } catch {
146
+ if (loadVersion !== _pageLoadVersion) return
124
147
  _currentPageTag = null
125
148
  _currentPageAttrs = {}
149
+ _currentPageKey = null
126
150
  _currentPagePath = null
127
151
  }
128
152
  }
@@ -140,9 +164,15 @@ const resetError = () => {
140
164
 
141
165
  const _push = router.push.bind(router)
142
166
  const _replace = router.replace.bind(router)
167
+ // Captures navigation intent synchronously, before route imports resolve or the
168
+ // History API changes the visible URL. Hydration uses this to avoid restoring a
169
+ // stale entry page over an already-requested navigation.
170
+ let _navigationIntent = 0
143
171
 
144
172
  router.push = async (path) => {
173
+ const navigationIntent = ++_navigationIntent
145
174
  isNavigating.value = true
175
+ _activateClientRouteRendering()
146
176
  currentError.value = null
147
177
  try {
148
178
  // Clear stale loader data from the previous route before loading the new one.
@@ -150,29 +180,92 @@ router.push = async (path) => {
150
180
  // correctly returns null instead of leaking the previous page's data.
151
181
  delete (globalThis).__CER_DATA__
152
182
  await _loadPageForPath(path)
183
+ if (navigationIntent !== _navigationIntent) return
153
184
  await _push(path)
154
185
  } catch (err) {
155
186
  currentError.value = err instanceof Error ? err.message : String(err)
156
187
  } finally {
157
- isNavigating.value = false
188
+ if (navigationIntent === _navigationIntent) isNavigating.value = false
158
189
  }
159
190
  }
160
191
 
161
192
  router.replace = async (path) => {
193
+ const navigationIntent = ++_navigationIntent
162
194
  isNavigating.value = true
195
+ _activateClientRouteRendering()
163
196
  currentError.value = null
164
197
  try {
165
198
  // Clear stale loader data from the previous route before loading the new one.
166
199
  delete (globalThis).__CER_DATA__
167
200
  await _loadPageForPath(path)
201
+ if (navigationIntent !== _navigationIntent) return
168
202
  await _replace(path)
169
203
  } catch (err) {
170
204
  currentError.value = err instanceof Error ? err.message : String(err)
171
205
  } finally {
172
- isNavigating.value = false
206
+ if (navigationIntent === _navigationIntent) isNavigating.value = false
173
207
  }
174
208
  }
175
209
 
210
+ // Make ordinary internal links participate in client-side routing even when
211
+ // their owning custom element has not hydrated yet. The listener runs in the
212
+ // bubble phase so an upgraded component gets first refusal: handlers such as
213
+ // breadcrumbs can call preventDefault() and perform their own navigation.
214
+ // composedPath() is required because document-level delegation cannot otherwise
215
+ // discover an anchor rendered inside a shadow root.
216
+ document.addEventListener('click', (event) => {
217
+ if (
218
+ event.defaultPrevented ||
219
+ event.button !== 0 ||
220
+ event.metaKey ||
221
+ event.ctrlKey ||
222
+ event.shiftKey ||
223
+ event.altKey
224
+ ) return
225
+
226
+ const anchor = event.composedPath().find(
227
+ (target) => target instanceof HTMLAnchorElement,
228
+ )
229
+ if (!anchor || anchor.hasAttribute('download')) return
230
+ if (anchor.getAttribute('aria-disabled') === 'true') return
231
+
232
+ const target = anchor.getAttribute('target')
233
+ if (target && target.toLowerCase() !== '_self') return
234
+
235
+ const href = anchor.getAttribute('href')
236
+ if (!href) return
237
+
238
+ let url
239
+ try {
240
+ url = new URL(href, window.location.href)
241
+ } catch {
242
+ return
243
+ }
244
+
245
+ if (
246
+ (url.protocol !== 'http:' && url.protocol !== 'https:') ||
247
+ url.origin !== window.location.origin
248
+ ) return
249
+
250
+ const navigationPath = url.pathname + url.search + url.hash
251
+
252
+ // Same-page anchors do not need a loader or page-tree replacement. Use the
253
+ // underlying runtime router so its configured offset, retries, cancellation,
254
+ // and history state remain consistent with cross-route fragment navigation.
255
+ if (
256
+ url.pathname === window.location.pathname &&
257
+ url.search === window.location.search &&
258
+ url.hash
259
+ ) {
260
+ event.preventDefault()
261
+ void _push(url.pathname + url.search + url.hash)
262
+ return
263
+ }
264
+
265
+ event.preventDefault()
266
+ void router.push(navigationPath)
267
+ })
268
+
176
269
  // ─── Plugins ─────────────────────────────────────────────────────────────────
177
270
 
178
271
  // Collect plugin-provided values so cer-layout-view can forward them into
@@ -187,14 +280,30 @@ const _pluginProvides = new Map()
187
280
 
188
281
  // ─── <cer-layout-view> ───────────────────────────────────────────────────────
189
282
 
190
- // True until the initial page module has loaded and _replace has been called.
191
- // While true, cer-layout-view renders a <slot> so the SSR/SSG pre-rendered
192
- // light-DOM content stays visible and no FOUC occurs during the hydration gap.
283
+ // True while the upgraded SSR/SSG light DOM is the live application. The slot
284
+ // stays active after initial route setup so the framework does not construct a
285
+ // second, duplicate component tree. The first real navigation switches to the
286
+ // client-rendered route tree and releases the server DOM.
193
287
  // Declared here (before component()) because customElements.define() upgrades
194
288
  // existing DOM elements synchronously, so the render function reads this ref
195
289
  // on the very first call — before _doHydrate has a chance to run.
196
290
  const _cerHydrating = ref(true)
197
291
 
292
+ function _activateClientRouteRendering() {
293
+ if (!_cerHydrating.value) return
294
+ _cerHydrating.value = false
295
+
296
+ // The initial SSR tree lives in cer-layout-view's light DOM. Once its slot is
297
+ // no longer used, disconnect it so hidden components, listeners, and reactive
298
+ // state do not remain retained for the lifetime of the application. Queue the
299
+ // cleanup after the reactive render requested above so navigation never
300
+ // exposes a momentarily empty view.
301
+ const host = document.querySelector('cer-layout-view')
302
+ if (host?.childNodes.length) {
303
+ queueMicrotask(() => host.replaceChildren())
304
+ }
305
+ }
306
+
198
307
  component('cer-layout-view', () => {
199
308
  // Forward plugin-provided values into the component context so inject() in
200
309
  // any descendant component can resolve them by walking up the DOM tree.
@@ -210,13 +319,9 @@ component('cer-layout-view', () => {
210
319
  // store.subscribe() synchronously pushes the current route once on
211
320
  // subscription. That initial callback is not a real navigation and must not
212
321
  // tear down the SSR slot before _doHydrate has pre-loaded the page.
213
- // Subsequent callbacks may be real navigations, but initRouter() also fires
214
- // a queueMicrotask(() => navigate(...)) to run guards on the entry URL.
215
- // That startup microtask resolves during the await route.load() gap —
216
- // before _currentPageTag is set — so we must not drop the slot until the
217
- // page module has actually been loaded (_currentPageTag !== null).
218
- // The explicit _cerHydrating.value = false in _doHydrate() fires after
219
- // _loadPageForPath completes and is the authoritative hydration trigger.
322
+ // Later state pushes update the stored route, but the SSR slot is released
323
+ // only by the wrapped push/replace methods on a real client navigation.
324
+ // initRouter's startup guard replay therefore cannot duplicate the tree.
220
325
  unsub = router.subscribe((s) => {
221
326
  const _isInitialSubscribePush = !_sawInitialRouteState
222
327
  _sawInitialRouteState = true
@@ -224,7 +329,6 @@ component('cer-layout-view', () => {
224
329
  current.value = s
225
330
  return
226
331
  }
227
- if (_cerHydrating.value && _currentPageTag !== null) _cerHydrating.value = false
228
332
  current.value = s
229
333
  })
230
334
  })
@@ -264,7 +368,7 @@ component('cer-layout-view', () => {
264
368
  // is rendered without stale pre-loaded state.
265
369
  const _useDirectRender = _currentPageTag && _currentPagePath === current.value.path
266
370
  const pageVnode = _useDirectRender
267
- ? { tag: _currentPageTag, props: { attrs: _currentPageAttrs }, children: [] }
371
+ ? { tag: _currentPageTag, key: _currentPageKey, props: { attrs: _currentPageAttrs }, children: [] }
268
372
  : { tag: 'router-view', props: {}, children: [] }
269
373
 
270
374
  // Support nested layout chains: meta.layoutChain = ['default', 'admin']
@@ -307,36 +411,102 @@ for (const plugin of plugins) {
307
411
  if (typeof window !== 'undefined') {
308
412
  const _initMatch = router.matchRoute(window.location.pathname)
309
413
  const _hydrateStrategy = _initMatch?.route?.meta?.hydrate ?? 'load'
414
+ const _entryHost = document.querySelector('cer-layout-view')
415
+ const _entryHasServerTree = Boolean(_entryHost && Array.from(_entryHost.childNodes).some(
416
+ (node) => node.nodeType === 1 || Boolean(node.textContent?.trim()),
417
+ ))
418
+ const _entryServerTreePath = _entryHost?.getAttribute('data-cer-route')
419
+ const _entryServerTreeMatches = !_entryServerTreePath ||
420
+ decodeURIComponent(_entryServerTreePath) === window.location.pathname
421
+ const _canKeepStaticEntry = _entryHasServerTree && _entryServerTreeMatches
422
+
423
+ if (_hydrateStrategy === 'none' && _canKeepStaticEntry) {
424
+ // Matching static HTML only — leave the page output and loader data
425
+ // untouched. Load its module after the first paint so explicitly
426
+ // interactive descendants (breadcrumbs, TOCs, menus, etc.) can upgrade
427
+ // without putting the static page chunk on the critical rendering path.
428
+ const _loadStaticRouteModule = () => {
429
+ const _load = _initMatch?.route?.load
430
+ if (typeof _load === 'function') {
431
+ void _load().catch((error) => {
432
+ console.error('[cer-app] Failed to activate static route islands:', error)
433
+ })
434
+ }
435
+ }
436
+ if (typeof requestAnimationFrame === 'function') {
437
+ requestAnimationFrame(() => setTimeout(_loadStaticRouteModule, 0))
438
+ } else {
439
+ setTimeout(_loadStaticRouteModule, 0)
440
+ }
310
441
 
311
- if (_hydrateStrategy === 'none') {
312
- // Static HTML only — leave SSR output untouched, clean up data immediately.
313
- delete (globalThis).__CER_DATA__
442
+ // The server marks the page host with data-cer-hydrate="none", so upgrading
443
+ // its custom element cannot trigger a second render. Keep __CER_DATA__
444
+ // available for nested static components as they upgrade; the first
445
+ // real client navigation clears it before rendering the destination route.
446
+ // A static host may serve another entry's HTML as its history fallback;
447
+ // that mismatched tree must go through normal client route activation.
314
448
  } else {
315
449
  const _doHydrate = async () => {
450
+ const _hydrationIntent = _navigationIntent
316
451
  const _initPath = window.location.pathname + window.location.search + window.location.hash
452
+ const _hasInitialServerTree = _entryHasServerTree
453
+ const _serverTreePath = _entryServerTreePath
454
+ const _serverTreeMatchesEntry = !_serverTreePath ||
455
+ decodeURIComponent(_serverTreePath) === new URL(_initPath, window.location.origin).pathname
317
456
  const _hasInitialLoaderData = Object.prototype.hasOwnProperty.call(globalThis, '__CER_DATA__')
318
457
  // Pre-load the page module and run the loader so cer-layout-view renders
319
458
  // the page tag directly with loader attrs (enables useProps() on hydration).
320
- await _loadPageForPath(
321
- _initPath,
322
- _hasInitialLoaderData
323
- ? { runLoader: false, initialData: (globalThis).__CER_DATA__ }
324
- : undefined,
325
- )
459
+ if (_hydrationIntent === 0) {
460
+ await _loadPageForPath(
461
+ _initPath,
462
+ _hasInitialLoaderData && _serverTreeMatchesEntry
463
+ ? { runLoader: false, initialData: (globalThis).__CER_DATA__ }
464
+ : undefined,
465
+ )
466
+ }
326
467
  // Only activate the initial route if the URL hasn't changed while we were
327
468
  // loading the module asynchronously (e.g. a test or plugin navigated away
328
469
  // before _doHydrate finished). Calling _replace with a stale path would
329
470
  // override any navigation that happened during the async gap.
330
471
  const _currentPath = window.location.pathname + window.location.search + window.location.hash
331
- // Drop the hydration slot cover unconditionally: the page module is loaded
332
- // and cer-layout-view must switch from the <slot> to live rendering whether
333
- // or not a redirect changed the path during loading.
334
- _cerHydrating.value = false
335
- if (_currentPath === _initPath) {
472
+ if (
473
+ _navigationIntent === _hydrationIntent &&
474
+ _currentPath === _initPath
475
+ ) {
336
476
  // Use the original (unwrapped) replace so isNavigating stays false during
337
477
  // the initial paint — the loading component must not flash over pre-rendered content.
338
478
  await _replace(_initPath)
339
479
  }
480
+
481
+ // An empty SPA shell has no server tree to retain. Middleware may also
482
+ // redirect either while the initial chunk loads or while _replace runs,
483
+ // making the SSR tree stale. This decision deliberately lives outside
484
+ // the URL-stability guard above: a newer URL must not be overwritten, but
485
+ // its resolved route still needs to replace the old server-rendered tree.
486
+ const _requestedInitialPath = new URL(_initPath, window.location.origin).pathname
487
+ const _resolvedInitialPath = router.getCurrent().path
488
+ const _urlLeftInitialEntry = _currentPath !== _initPath
489
+ if (
490
+ !_hasInitialServerTree ||
491
+ !_serverTreeMatchesEntry ||
492
+ _urlLeftInitialEntry ||
493
+ _resolvedInitialPath !== _requestedInitialPath
494
+ ) {
495
+ if (
496
+ !_serverTreeMatchesEntry ||
497
+ _urlLeftInitialEntry ||
498
+ _resolvedInitialPath !== _requestedInitialPath
499
+ ) {
500
+ delete (globalThis).__CER_DATA__
501
+ }
502
+ if (
503
+ _navigationIntent === _hydrationIntent &&
504
+ _currentPagePath !== _resolvedInitialPath
505
+ ) {
506
+ await _loadPageForPath(_resolvedInitialPath)
507
+ }
508
+ _activateClientRouteRendering()
509
+ }
340
510
  // The client entry marks the already-rendered entry URL so generated
341
511
  // route middleware can skip the browser router's startup replay once.
342
512
  // Clear any leftover flag after the first hydrated route commits so later
@@ -1 +1 @@
1
- {"version":3,"file":"app-template.js","sourceRoot":"","sources":["../../src/runtime/app-template.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB;IACtC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+WR,CAAA;AACD,CAAC"}
1
+ {"version":3,"file":"app-template.js","sourceRoot":"","sources":["../../src/runtime/app-template.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CAAC,gBAAmC,EAAE;IAC5E,MAAM,kBAAkB,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC;SACnD,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,WAAW,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;SACvF,IAAI,CAAC,IAAI,CAAC,CAAA;IACb,OAAO;;;;EAIP,kBAAkB,GAAG,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkhBpD,CAAA;AACD,CAAC"}
@@ -25,4 +25,8 @@ export type { LocaleComposable } from './use-locale.js';
25
25
  export { queryContent, QueryBuilder } from './use-content.js';
26
26
  export { useContentSearch } from './use-content-search.js';
27
27
  export type { UseContentSearchReturn } from './use-content-search.js';
28
+ export { defineContentPageLoader, normalizeContentPath, useContentBreadcrumbs, useContentHeadings, useContentSeo, } from './use-content-page.js';
29
+ export type { ContentBreadcrumb, ContentBreadcrumbOptions, ContentPageData, ContentPageLoaderOptions, ContentSeoOptions, } from './use-content-page.js';
30
+ export { useActiveHeadings } from './use-active-headings.js';
31
+ export type { ActiveHeadingsOptions } from './use-active-headings.js';
28
32
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/composables/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAClG,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AACnG,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAC7G,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACzE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAC7G,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACvD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,YAAY,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/composables/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAClG,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AACnG,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAC7G,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AACzE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAC7G,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AACvD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,YAAY,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AACrE,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,aAAa,GACd,MAAM,uBAAuB,CAAA;AAC9B,YAAY,EACV,iBAAiB,EACjB,wBAAwB,EACxB,eAAe,EACf,wBAAwB,EACxB,iBAAiB,GAClB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,YAAY,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA"}
@@ -15,4 +15,6 @@ export { useState } from './use-state.js';
15
15
  export { useLocale } from './use-locale.js';
16
16
  export { queryContent, QueryBuilder } from './use-content.js';
17
17
  export { useContentSearch } from './use-content-search.js';
18
+ export { defineContentPageLoader, normalizeContentPath, useContentBreadcrumbs, useContentHeadings, useContentSeo, } from './use-content-page.js';
19
+ export { useActiveHeadings } from './use-active-headings.js';
18
20
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/runtime/composables/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAElG,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAEnG,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAEzC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/runtime/composables/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAElG,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAEnG,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAEzC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAE1D,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,aAAa,GACd,MAAM,uBAAuB,CAAA;AAQ9B,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA"}
@@ -0,0 +1,24 @@
1
+ import type { ContentHeading } from '../../types/content.js';
2
+ type HeadingSource = readonly ContentHeading[] | {
3
+ value: readonly ContentHeading[];
4
+ };
5
+ export interface ActiveHeadingsOptions {
6
+ /** DOM root containing the rendered headings. Defaults to document. */
7
+ root?: ParentNode | (() => ParentNode | null);
8
+ /** Sticky-header offset in pixels. Defaults to 0. */
9
+ offset?: number;
10
+ /** IntersectionObserver root, when observing inside a scroll container. */
11
+ observerRoot?: Element | null;
12
+ /** Override the observer margin. */
13
+ rootMargin?: string;
14
+ }
15
+ /**
16
+ * Tracks visible content headings with one IntersectionObserver. This avoids
17
+ * scroll-event layout reads and works with document, light-DOM, and shadow roots.
18
+ */
19
+ export declare function useActiveHeadings(source: HeadingSource, options?: ActiveHeadingsOptions): {
20
+ activeIds: any;
21
+ isActive: (id: string) => any;
22
+ };
23
+ export {};
24
+ //# sourceMappingURL=use-active-headings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-active-headings.d.ts","sourceRoot":"","sources":["../../../src/runtime/composables/use-active-headings.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAE5D,KAAK,aAAa,GAAG,SAAS,cAAc,EAAE,GAAG;IAAE,KAAK,EAAE,SAAS,cAAc,EAAE,CAAA;CAAE,CAAA;AAErF,MAAM,WAAW,qBAAqB;IACpC,uEAAuE;IACvE,IAAI,CAAC,EAAE,UAAU,GAAG,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,CAAA;IAC7C,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,2EAA2E;IAC3E,YAAY,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IAC7B,oCAAoC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAiBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,GAAE,qBAA0B;;mBA2FzE,MAAM;EAExB"}