@jasonshimmy/vite-plugin-cer-app 0.23.2 → 0.25.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 (404) hide show
  1. package/dist/cli/adapters/netlify.js +4 -2
  2. package/dist/cli/adapters/netlify.js.map +1 -1
  3. package/dist/cli/checks/lighthouse.d.ts +26 -0
  4. package/dist/cli/checks/lighthouse.d.ts.map +1 -0
  5. package/dist/cli/checks/lighthouse.js +121 -0
  6. package/dist/cli/checks/lighthouse.js.map +1 -0
  7. package/dist/cli/checks/links.d.ts +12 -0
  8. package/dist/cli/checks/links.d.ts.map +1 -0
  9. package/dist/cli/checks/links.js +89 -0
  10. package/dist/cli/checks/links.js.map +1 -0
  11. package/dist/cli/checks/performance.d.ts +17 -0
  12. package/dist/cli/checks/performance.d.ts.map +1 -0
  13. package/dist/cli/checks/performance.js +61 -0
  14. package/dist/cli/checks/performance.js.map +1 -0
  15. package/dist/cli/commands/check.d.ts +3 -0
  16. package/dist/cli/commands/check.d.ts.map +1 -0
  17. package/dist/cli/commands/check.js +85 -0
  18. package/dist/cli/commands/check.js.map +1 -0
  19. package/dist/cli/commands/preview.d.ts.map +1 -1
  20. package/dist/cli/commands/preview.js +4 -2
  21. package/dist/cli/commands/preview.js.map +1 -1
  22. package/dist/cli/create/index.d.ts +11 -1
  23. package/dist/cli/create/index.d.ts.map +1 -1
  24. package/dist/cli/create/index.js +135 -65
  25. package/dist/cli/create/index.js.map +1 -1
  26. package/dist/cli/create/templates/spa/package.json.tpl +5 -3
  27. package/dist/cli/create/templates/ssg/cer.config.ts.tpl +2 -0
  28. package/dist/cli/create/templates/ssg/package.json.tpl +5 -3
  29. package/dist/cli/create/templates/ssr/package.json.tpl +5 -3
  30. package/dist/cli/index.js +2 -0
  31. package/dist/cli/index.js.map +1 -1
  32. package/dist/index.d.ts +4 -2
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/plugin/build-ssg.d.ts +22 -6
  35. package/dist/plugin/build-ssg.d.ts.map +1 -1
  36. package/dist/plugin/build-ssg.js +226 -17
  37. package/dist/plugin/build-ssg.js.map +1 -1
  38. package/dist/plugin/content/index.d.ts +1 -1
  39. package/dist/plugin/content/index.d.ts.map +1 -1
  40. package/dist/plugin/content/index.js +8 -8
  41. package/dist/plugin/content/index.js.map +1 -1
  42. package/dist/plugin/content/parser.d.ts +3 -3
  43. package/dist/plugin/content/parser.d.ts.map +1 -1
  44. package/dist/plugin/content/parser.js +103 -24
  45. package/dist/plugin/content/parser.js.map +1 -1
  46. package/dist/plugin/dev-server.d.ts +4 -1
  47. package/dist/plugin/dev-server.d.ts.map +1 -1
  48. package/dist/plugin/dev-server.js.map +1 -1
  49. package/dist/plugin/dts-generator.d.ts.map +1 -1
  50. package/dist/plugin/dts-generator.js +50 -8
  51. package/dist/plugin/dts-generator.js.map +1 -1
  52. package/dist/plugin/generated-dir.d.ts +2 -0
  53. package/dist/plugin/generated-dir.d.ts.map +1 -1
  54. package/dist/plugin/generated-dir.js +17 -6
  55. package/dist/plugin/generated-dir.js.map +1 -1
  56. package/dist/plugin/html-post-process.d.ts +7 -0
  57. package/dist/plugin/html-post-process.d.ts.map +1 -1
  58. package/dist/plugin/html-post-process.js +26 -0
  59. package/dist/plugin/html-post-process.js.map +1 -1
  60. package/dist/plugin/index.d.ts.map +1 -1
  61. package/dist/plugin/index.js +60 -13
  62. package/dist/plugin/index.js.map +1 -1
  63. package/dist/plugin/transforms/auto-import.d.ts.map +1 -1
  64. package/dist/plugin/transforms/auto-import.js +7 -0
  65. package/dist/plugin/transforms/auto-import.js.map +1 -1
  66. package/dist/plugin/transforms/prune-runtime-css.d.ts +8 -0
  67. package/dist/plugin/transforms/prune-runtime-css.d.ts.map +1 -0
  68. package/dist/plugin/transforms/prune-runtime-css.js +40 -0
  69. package/dist/plugin/transforms/prune-runtime-css.js.map +1 -0
  70. package/dist/runtime/app-template.d.ts +1 -1
  71. package/dist/runtime/app-template.d.ts.map +1 -1
  72. package/dist/runtime/app-template.js +206 -36
  73. package/dist/runtime/app-template.js.map +1 -1
  74. package/dist/runtime/composables/index.d.ts +4 -0
  75. package/dist/runtime/composables/index.d.ts.map +1 -1
  76. package/dist/runtime/composables/index.js +2 -0
  77. package/dist/runtime/composables/index.js.map +1 -1
  78. package/dist/runtime/composables/use-active-headings.d.ts +24 -0
  79. package/dist/runtime/composables/use-active-headings.d.ts.map +1 -0
  80. package/dist/runtime/composables/use-active-headings.js +112 -0
  81. package/dist/runtime/composables/use-active-headings.js.map +1 -0
  82. package/dist/runtime/composables/use-content-page.d.ts +45 -0
  83. package/dist/runtime/composables/use-content-page.d.ts.map +1 -0
  84. package/dist/runtime/composables/use-content-page.js +181 -0
  85. package/dist/runtime/composables/use-content-page.js.map +1 -0
  86. package/dist/runtime/composables/use-content-search.d.ts.map +1 -1
  87. package/dist/runtime/composables/use-content-search.js +1 -5
  88. package/dist/runtime/composables/use-content-search.js.map +1 -1
  89. package/dist/runtime/composables/use-fetch.d.ts +2 -1
  90. package/dist/runtime/composables/use-fetch.d.ts.map +1 -1
  91. package/dist/runtime/composables/use-fetch.js +112 -43
  92. package/dist/runtime/composables/use-fetch.js.map +1 -1
  93. package/dist/runtime/composables/use-route.d.ts.map +1 -1
  94. package/dist/runtime/composables/use-route.js +39 -11
  95. package/dist/runtime/composables/use-route.js.map +1 -1
  96. package/dist/runtime/content/client.js +2 -2
  97. package/dist/runtime/content/client.js.map +1 -1
  98. package/dist/runtime/entry-server-template.d.ts +16 -1
  99. package/dist/runtime/entry-server-template.d.ts.map +1 -1
  100. package/dist/runtime/entry-server-template.js +120 -13
  101. package/dist/runtime/entry-server-template.js.map +1 -1
  102. package/dist/types/config.d.ts +45 -4
  103. package/dist/types/config.d.ts.map +1 -1
  104. package/dist/types/config.js.map +1 -1
  105. package/dist/types/content.d.ts +18 -1
  106. package/dist/types/content.d.ts.map +1 -1
  107. package/dist/types/middleware.d.ts +2 -2
  108. package/dist/types/middleware.d.ts.map +1 -1
  109. package/package.json +22 -19
  110. package/.github/copilot-instructions.md +0 -169
  111. package/.github/workflows/publish.yml +0 -257
  112. package/.nvmrc +0 -1
  113. package/CHANGELOG.md +0 -236
  114. package/CLAUDE.md +0 -113
  115. package/commits.txt +0 -1
  116. package/cypress.config.ts +0 -16
  117. package/docs/authentication.md +0 -285
  118. package/docs/cli.md +0 -324
  119. package/docs/components.md +0 -237
  120. package/docs/composables.md +0 -907
  121. package/docs/configuration.md +0 -696
  122. package/docs/content.md +0 -570
  123. package/docs/data-loading.md +0 -336
  124. package/docs/getting-started.md +0 -237
  125. package/docs/head-management.md +0 -212
  126. package/docs/i18n.md +0 -159
  127. package/docs/layouts.md +0 -224
  128. package/docs/middleware.md +0 -234
  129. package/docs/plugins.md +0 -170
  130. package/docs/rendering-modes.md +0 -377
  131. package/docs/routing.md +0 -485
  132. package/docs/server-api.md +0 -253
  133. package/docs/testing.md +0 -455
  134. package/docs/use-fetch.md +0 -183
  135. package/e2e/cypress/e2e/api.cy.ts +0 -123
  136. package/e2e/cypress/e2e/async-component.cy.ts +0 -27
  137. package/e2e/cypress/e2e/component-splitting.cy.ts +0 -50
  138. package/e2e/cypress/e2e/content.cy.ts +0 -425
  139. package/e2e/cypress/e2e/cookie.cy.ts +0 -85
  140. package/e2e/cypress/e2e/data.cy.ts +0 -158
  141. package/e2e/cypress/e2e/error-boundary.cy.ts +0 -88
  142. package/e2e/cypress/e2e/fouc.cy.ts +0 -254
  143. package/e2e/cypress/e2e/group-meta.cy.ts +0 -36
  144. package/e2e/cypress/e2e/head.cy.ts +0 -89
  145. package/e2e/cypress/e2e/i18n.cy.ts +0 -79
  146. package/e2e/cypress/e2e/interactive.cy.ts +0 -137
  147. package/e2e/cypress/e2e/isr-nested-runtime.cy.ts +0 -102
  148. package/e2e/cypress/e2e/jit-css-custom-colors.cy.ts +0 -43
  149. package/e2e/cypress/e2e/middleware-chain.cy.ts +0 -89
  150. package/e2e/cypress/e2e/middleware-status.cy.ts +0 -30
  151. package/e2e/cypress/e2e/middleware.cy.ts +0 -45
  152. package/e2e/cypress/e2e/navigate.cy.ts +0 -39
  153. package/e2e/cypress/e2e/observability.cy.ts +0 -77
  154. package/e2e/cypress/e2e/per-route-error.cy.ts +0 -42
  155. package/e2e/cypress/e2e/per-route-render.cy.ts +0 -70
  156. package/e2e/cypress/e2e/preview-hardening.cy.ts +0 -88
  157. package/e2e/cypress/e2e/routes.cy.ts +0 -128
  158. package/e2e/cypress/e2e/seo-meta.cy.ts +0 -108
  159. package/e2e/cypress/e2e/server-middleware.cy.ts +0 -46
  160. package/e2e/cypress/e2e/session-rotation.cy.ts +0 -25
  161. package/e2e/cypress/e2e/session.cy.ts +0 -73
  162. package/e2e/cypress/e2e/ssr-render-error.cy.ts +0 -68
  163. package/e2e/cypress/e2e/synthetic-404.cy.ts +0 -45
  164. package/e2e/cypress/e2e/use-page-data.cy.ts +0 -122
  165. package/e2e/cypress/e2e/use-state.cy.ts +0 -138
  166. package/e2e/cypress/support/commands.ts +0 -120
  167. package/e2e/cypress/support/e2e.ts +0 -10
  168. package/e2e/cypress/tsconfig.json +0 -14
  169. package/e2e/kitchen-sink/app/components/ks-badge.ts +0 -8
  170. package/e2e/kitchen-sink/app/composables/useKsCounter.ts +0 -9
  171. package/e2e/kitchen-sink/app/error.ts +0 -18
  172. package/e2e/kitchen-sink/app/layouts/admin.ts +0 -13
  173. package/e2e/kitchen-sink/app/layouts/default.ts +0 -25
  174. package/e2e/kitchen-sink/app/layouts/group.ts +0 -9
  175. package/e2e/kitchen-sink/app/layouts/minimal.ts +0 -7
  176. package/e2e/kitchen-sink/app/loading.ts +0 -9
  177. package/e2e/kitchen-sink/app/middleware/auth.ts +0 -9
  178. package/e2e/kitchen-sink/app/middleware/custom-log.ts +0 -4
  179. package/e2e/kitchen-sink/app/middleware/group-auth.ts +0 -7
  180. package/e2e/kitchen-sink/app/middleware/logger.ts +0 -14
  181. package/e2e/kitchen-sink/app/pages/(auth)/login.ts +0 -13
  182. package/e2e/kitchen-sink/app/pages/(auth)/protected.ts +0 -16
  183. package/e2e/kitchen-sink/app/pages/404.ts +0 -9
  184. package/e2e/kitchen-sink/app/pages/about.ts +0 -17
  185. package/e2e/kitchen-sink/app/pages/admin/_layout.ts +0 -1
  186. package/e2e/kitchen-sink/app/pages/admin/dashboard.ts +0 -11
  187. package/e2e/kitchen-sink/app/pages/async-component-error-test.ts +0 -18
  188. package/e2e/kitchen-sink/app/pages/async-component-test.ts +0 -18
  189. package/e2e/kitchen-sink/app/pages/blog/[slug].ts +0 -59
  190. package/e2e/kitchen-sink/app/pages/blog/index.ts +0 -51
  191. package/e2e/kitchen-sink/app/pages/content-blog.ts +0 -37
  192. package/e2e/kitchen-sink/app/pages/content-doc.ts +0 -42
  193. package/e2e/kitchen-sink/app/pages/content-fallback.ts +0 -36
  194. package/e2e/kitchen-sink/app/pages/content-guides.ts +0 -35
  195. package/e2e/kitchen-sink/app/pages/content-index.ts +0 -39
  196. package/e2e/kitchen-sink/app/pages/content-search.ts +0 -36
  197. package/e2e/kitchen-sink/app/pages/cookie-test.ts +0 -22
  198. package/e2e/kitchen-sink/app/pages/counter.ts +0 -17
  199. package/e2e/kitchen-sink/app/pages/group-auth-blocked.ts +0 -9
  200. package/e2e/kitchen-sink/app/pages/group-meta-test/_layout.ts +0 -6
  201. package/e2e/kitchen-sink/app/pages/group-meta-test/custom-mw.ts +0 -14
  202. package/e2e/kitchen-sink/app/pages/group-meta-test/page.ts +0 -9
  203. package/e2e/kitchen-sink/app/pages/group-meta-test/protected.ts +0 -8
  204. package/e2e/kitchen-sink/app/pages/head.ts +0 -20
  205. package/e2e/kitchen-sink/app/pages/i18n-test.ts +0 -14
  206. package/e2e/kitchen-sink/app/pages/index.ts +0 -27
  207. package/e2e/kitchen-sink/app/pages/isr-test.ts +0 -17
  208. package/e2e/kitchen-sink/app/pages/items/[id].ts +0 -20
  209. package/e2e/kitchen-sink/app/pages/jit-css-custom-colors-test.ts +0 -14
  210. package/e2e/kitchen-sink/app/pages/loader-error-test.ts +0 -13
  211. package/e2e/kitchen-sink/app/pages/loader-props-test.ts +0 -19
  212. package/e2e/kitchen-sink/app/pages/loader-response-error-test.ts +0 -13
  213. package/e2e/kitchen-sink/app/pages/middleware-chain-test.ts +0 -12
  214. package/e2e/kitchen-sink/app/pages/middleware-status-test.ts +0 -9
  215. package/e2e/kitchen-sink/app/pages/navigate-test.ts +0 -16
  216. package/e2e/kitchen-sink/app/pages/observability-test.ts +0 -25
  217. package/e2e/kitchen-sink/app/pages/per-route-error-test.error.ts +0 -13
  218. package/e2e/kitchen-sink/app/pages/per-route-error-test.ts +0 -15
  219. package/e2e/kitchen-sink/app/pages/plugin-dsd-test.ts +0 -10
  220. package/e2e/kitchen-sink/app/pages/render-error-test.ts +0 -12
  221. package/e2e/kitchen-sink/app/pages/render-server-test.ts +0 -12
  222. package/e2e/kitchen-sink/app/pages/render-spa-test.ts +0 -12
  223. package/e2e/kitchen-sink/app/pages/route-info.ts +0 -14
  224. package/e2e/kitchen-sink/app/pages/seo-test.ts +0 -23
  225. package/e2e/kitchen-sink/app/pages/session-rotation-test.ts +0 -25
  226. package/e2e/kitchen-sink/app/pages/use-state-test.ts +0 -37
  227. package/e2e/kitchen-sink/app/plugins/01.setup.ts +0 -7
  228. package/e2e/kitchen-sink/app/plugins/02.ks-plugin-components.ts +0 -27
  229. package/e2e/kitchen-sink/cer-auto-imports.d.ts +0 -51
  230. package/e2e/kitchen-sink/cer-env.d.ts +0 -35
  231. package/e2e/kitchen-sink/cer-tsconfig.json +0 -30
  232. package/e2e/kitchen-sink/cer.config.ts +0 -43
  233. package/e2e/kitchen-sink/content/01.guides/01.index.md +0 -8
  234. package/e2e/kitchen-sink/content/01.guides/02.intro.md +0 -8
  235. package/e2e/kitchen-sink/content/01.guides/10.advanced.md +0 -8
  236. package/e2e/kitchen-sink/content/blog/2026-04-01-hello.md +0 -26
  237. package/e2e/kitchen-sink/content/blog/2026-04-02-draft.md +0 -10
  238. package/e2e/kitchen-sink/content/blog/index.md +0 -8
  239. package/e2e/kitchen-sink/content/blog/no-frontmatter.md +0 -7
  240. package/e2e/kitchen-sink/content/docs/getting-started.md +0 -48
  241. package/e2e/kitchen-sink/content/index.md +0 -16
  242. package/e2e/kitchen-sink/server/api/echo.ts +0 -12
  243. package/e2e/kitchen-sink/server/api/health.ts +0 -3
  244. package/e2e/kitchen-sink/server/api/posts/[slug].ts +0 -11
  245. package/e2e/kitchen-sink/server/api/posts/index.ts +0 -5
  246. package/e2e/kitchen-sink/server/api/session.ts +0 -23
  247. package/e2e/kitchen-sink/server/data/posts.ts +0 -21
  248. package/e2e/kitchen-sink/server/middleware/01-headers.ts +0 -6
  249. package/e2e/kitchen-sink/server/middleware/02-status-test.ts +0 -10
  250. package/e2e/kitchen-sink/tsconfig.json +0 -3
  251. package/e2e/scripts/clean.mjs +0 -14
  252. package/eslint.config.ts +0 -22
  253. package/src/__tests__/cli/adapters/cloudflare-worker.integration.test.ts +0 -132
  254. package/src/__tests__/cli/adapters/cloudflare.test.ts +0 -332
  255. package/src/__tests__/cli/adapters/netlify-bridge.integration.test.ts +0 -139
  256. package/src/__tests__/cli/adapters/netlify.test.ts +0 -286
  257. package/src/__tests__/cli/adapters/vercel-launcher.integration.test.ts +0 -129
  258. package/src/__tests__/cli/adapters/vercel.test.ts +0 -263
  259. package/src/__tests__/cli/preview-hardening.test.ts +0 -265
  260. package/src/__tests__/cli/preview-isr.test.ts +0 -320
  261. package/src/__tests__/index.test.ts +0 -21
  262. package/src/__tests__/plugin/app-template.test.ts +0 -166
  263. package/src/__tests__/plugin/build-ssg-render.test.ts +0 -155
  264. package/src/__tests__/plugin/build-ssg.test.ts +0 -598
  265. package/src/__tests__/plugin/build-ssr.test.ts +0 -192
  266. package/src/__tests__/plugin/cer-app-plugin.test.ts +0 -552
  267. package/src/__tests__/plugin/content/emitter.test.ts +0 -117
  268. package/src/__tests__/plugin/content/loader.test.ts +0 -154
  269. package/src/__tests__/plugin/content/parser.test.ts +0 -381
  270. package/src/__tests__/plugin/content/path-utils.test.ts +0 -69
  271. package/src/__tests__/plugin/content/search.test.ts +0 -119
  272. package/src/__tests__/plugin/dev-server.test.ts +0 -813
  273. package/src/__tests__/plugin/dts-generator.test.ts +0 -394
  274. package/src/__tests__/plugin/entry-server-template.test.ts +0 -385
  275. package/src/__tests__/plugin/generated-dir.test.ts +0 -144
  276. package/src/__tests__/plugin/html-post-process.test.ts +0 -146
  277. package/src/__tests__/plugin/path-utils.test.ts +0 -411
  278. package/src/__tests__/plugin/resolve-config.test.ts +0 -233
  279. package/src/__tests__/plugin/scanner.test.ts +0 -186
  280. package/src/__tests__/plugin/transforms/auto-import.test.ts +0 -510
  281. package/src/__tests__/plugin/transforms/head-inject.test.ts +0 -178
  282. package/src/__tests__/plugin/virtual/composables.test.ts +0 -57
  283. package/src/__tests__/plugin/virtual/content-components.test.ts +0 -66
  284. package/src/__tests__/plugin/virtual/error.test.ts +0 -71
  285. package/src/__tests__/plugin/virtual/layouts.test.ts +0 -70
  286. package/src/__tests__/plugin/virtual/loading.test.ts +0 -72
  287. package/src/__tests__/plugin/virtual/middleware.test.ts +0 -83
  288. package/src/__tests__/plugin/virtual/plugins.test.ts +0 -129
  289. package/src/__tests__/plugin/virtual/routes.test.ts +0 -884
  290. package/src/__tests__/plugin/virtual/server-api.test.ts +0 -164
  291. package/src/__tests__/plugin/virtual/server-middleware.test.ts +0 -102
  292. package/src/__tests__/runtime/app-template.test.ts +0 -208
  293. package/src/__tests__/runtime/define-middleware.test.ts +0 -64
  294. package/src/__tests__/runtime/define-server-middleware.test.ts +0 -54
  295. package/src/__tests__/runtime/entry-client-template.test.ts +0 -61
  296. package/src/__tests__/runtime/isr-handler.test.ts +0 -338
  297. package/src/__tests__/runtime/oauth/handler.test.ts +0 -358
  298. package/src/__tests__/runtime/oauth/providers.test.ts +0 -47
  299. package/src/__tests__/runtime/oauth-index.test.ts +0 -43
  300. package/src/__tests__/runtime/use-auth.test.ts +0 -169
  301. package/src/__tests__/runtime/use-content-search-composable.test.ts +0 -405
  302. package/src/__tests__/runtime/use-content-search.test.ts +0 -163
  303. package/src/__tests__/runtime/use-content.test.ts +0 -226
  304. package/src/__tests__/runtime/use-cookie.test.ts +0 -277
  305. package/src/__tests__/runtime/use-fetch-component.test.ts +0 -214
  306. package/src/__tests__/runtime/use-fetch.test.ts +0 -377
  307. package/src/__tests__/runtime/use-head.test.ts +0 -311
  308. package/src/__tests__/runtime/use-inject-client.test.ts +0 -67
  309. package/src/__tests__/runtime/use-inject.test.ts +0 -66
  310. package/src/__tests__/runtime/use-locale.test.ts +0 -152
  311. package/src/__tests__/runtime/use-navigate.test.ts +0 -121
  312. package/src/__tests__/runtime/use-page-data.test.ts +0 -298
  313. package/src/__tests__/runtime/use-route.test.ts +0 -156
  314. package/src/__tests__/runtime/use-runtime-config.test.ts +0 -182
  315. package/src/__tests__/runtime/use-seo-meta.test.ts +0 -109
  316. package/src/__tests__/runtime/use-session.test.ts +0 -320
  317. package/src/__tests__/runtime/use-state.test.ts +0 -340
  318. package/src/__tests__/types/config.test.ts +0 -18
  319. package/src/cli/adapters/cloudflare.ts +0 -335
  320. package/src/cli/adapters/netlify.ts +0 -326
  321. package/src/cli/adapters/vercel.ts +0 -311
  322. package/src/cli/commands/adapt.ts +0 -84
  323. package/src/cli/commands/build.ts +0 -165
  324. package/src/cli/commands/dev.ts +0 -125
  325. package/src/cli/commands/generate.ts +0 -91
  326. package/src/cli/commands/preview-isr.ts +0 -172
  327. package/src/cli/commands/preview.ts +0 -523
  328. package/src/cli/create/index.ts +0 -275
  329. package/src/cli/create/templates/shared/.gitignore.tpl +0 -25
  330. package/src/cli/create/templates/shared/app/layouts/default.ts.tpl +0 -15
  331. package/src/cli/create/templates/shared/app/pages/index.ts.tpl +0 -8
  332. package/src/cli/create/templates/shared/index.html.tpl +0 -12
  333. package/src/cli/create/templates/shared/tsconfig.json.tpl +0 -6
  334. package/src/cli/create/templates/spa/cer.config.ts.tpl +0 -6
  335. package/src/cli/create/templates/spa/package.json.tpl +0 -18
  336. package/src/cli/create/templates/ssg/cer.config.ts.tpl +0 -10
  337. package/src/cli/create/templates/ssg/package.json.tpl +0 -19
  338. package/src/cli/create/templates/ssr/cer.config.ts.tpl +0 -6
  339. package/src/cli/create/templates/ssr/package.json.tpl +0 -18
  340. package/src/cli/index.ts +0 -22
  341. package/src/index.ts +0 -20
  342. package/src/plugin/build-ssg.ts +0 -403
  343. package/src/plugin/build-ssr.ts +0 -134
  344. package/src/plugin/content/emitter.ts +0 -50
  345. package/src/plugin/content/index.ts +0 -233
  346. package/src/plugin/content/parser.ts +0 -259
  347. package/src/plugin/content/path-utils.ts +0 -55
  348. package/src/plugin/content/scanner.ts +0 -26
  349. package/src/plugin/content/search.ts +0 -28
  350. package/src/plugin/dev-server.ts +0 -379
  351. package/src/plugin/dts-generator.ts +0 -273
  352. package/src/plugin/generated-dir.ts +0 -121
  353. package/src/plugin/html-post-process.ts +0 -96
  354. package/src/plugin/index.ts +0 -584
  355. package/src/plugin/path-utils.ts +0 -186
  356. package/src/plugin/scanner.ts +0 -65
  357. package/src/plugin/transforms/auto-import.ts +0 -206
  358. package/src/plugin/transforms/head-inject.ts +0 -161
  359. package/src/plugin/virtual/composables.ts +0 -28
  360. package/src/plugin/virtual/content-components.ts +0 -83
  361. package/src/plugin/virtual/error.ts +0 -34
  362. package/src/plugin/virtual/layouts.ts +0 -41
  363. package/src/plugin/virtual/loading.ts +0 -32
  364. package/src/plugin/virtual/middleware.ts +0 -45
  365. package/src/plugin/virtual/plugins.ts +0 -46
  366. package/src/plugin/virtual/routes.ts +0 -514
  367. package/src/plugin/virtual/server-api.ts +0 -85
  368. package/src/plugin/virtual/server-middleware.ts +0 -44
  369. package/src/runtime/app-template.ts +0 -377
  370. package/src/runtime/composables/define-middleware.ts +0 -17
  371. package/src/runtime/composables/define-server-middleware.ts +0 -18
  372. package/src/runtime/composables/index.ts +0 -27
  373. package/src/runtime/composables/use-auth.ts +0 -125
  374. package/src/runtime/composables/use-content-search.ts +0 -205
  375. package/src/runtime/composables/use-content.ts +0 -146
  376. package/src/runtime/composables/use-cookie.ts +0 -135
  377. package/src/runtime/composables/use-fetch.ts +0 -438
  378. package/src/runtime/composables/use-head.ts +0 -234
  379. package/src/runtime/composables/use-inject.ts +0 -49
  380. package/src/runtime/composables/use-locale.ts +0 -109
  381. package/src/runtime/composables/use-navigate.ts +0 -58
  382. package/src/runtime/composables/use-page-data.ts +0 -93
  383. package/src/runtime/composables/use-route.ts +0 -71
  384. package/src/runtime/composables/use-runtime-config.ts +0 -123
  385. package/src/runtime/composables/use-seo-meta.ts +0 -80
  386. package/src/runtime/composables/use-session.ts +0 -186
  387. package/src/runtime/composables/use-state.ts +0 -92
  388. package/src/runtime/content/client.ts +0 -168
  389. package/src/runtime/entry-client-template.ts +0 -39
  390. package/src/runtime/entry-server-template.ts +0 -493
  391. package/src/runtime/isr-handler.ts +0 -184
  392. package/src/runtime/oauth/handler.ts +0 -407
  393. package/src/runtime/oauth/index.ts +0 -49
  394. package/src/runtime/oauth/providers.ts +0 -38
  395. package/src/types/api.ts +0 -40
  396. package/src/types/config.ts +0 -379
  397. package/src/types/content.ts +0 -66
  398. package/src/types/index.ts +0 -7
  399. package/src/types/middleware.ts +0 -63
  400. package/src/types/page.ts +0 -117
  401. package/src/types/plugin.ts +0 -34
  402. package/tsconfig.build.json +0 -10
  403. package/tsconfig.json +0 -19
  404. package/vitest.config.ts +0 -33
@@ -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"}
@@ -0,0 +1,112 @@
1
+ import { nextTick, ref, useOnConnected, watch } from '@jasonshimmy/custom-elements-runtime';
2
+ function sourceValue(source) {
3
+ return Array.isArray(source)
4
+ ? source
5
+ : source.value;
6
+ }
7
+ function resolveRoot(root) {
8
+ if (typeof root === 'function')
9
+ return root();
10
+ return root ?? (typeof document !== 'undefined' ? document : null);
11
+ }
12
+ function escapeAttribute(value) {
13
+ return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
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 function useActiveHeadings(source, options = {}) {
20
+ const activeIds = ref([]);
21
+ const intersecting = new Set();
22
+ const headingTops = new Map();
23
+ useOnConnected(() => {
24
+ let observer = null;
25
+ let observationRevision = 0;
26
+ let disposed = false;
27
+ const observe = () => {
28
+ observer?.disconnect();
29
+ intersecting.clear();
30
+ headingTops.clear();
31
+ activeIds.value = [];
32
+ const headings = sourceValue(source);
33
+ const root = resolveRoot(options.root);
34
+ if (!root || headings.length === 0)
35
+ return;
36
+ // Establish a useful state immediately. IntersectionObserver callbacks
37
+ // are asynchronous, and on an entry navigation every heading may begin
38
+ // below the narrowed activation band even though the first section is
39
+ // the section the reader is approaching.
40
+ activeIds.value = [headings[0].id];
41
+ if (typeof IntersectionObserver === 'undefined') {
42
+ return;
43
+ }
44
+ observer = new IntersectionObserver((entries) => {
45
+ for (const entry of entries) {
46
+ const id = entry.target.id;
47
+ if (!id)
48
+ continue;
49
+ const top = entry.boundingClientRect?.top;
50
+ if (Number.isFinite(top))
51
+ headingTops.set(id, top);
52
+ if (entry.isIntersecting)
53
+ intersecting.add(id);
54
+ else
55
+ intersecting.delete(id);
56
+ }
57
+ const orderedIds = sourceValue(source).map((heading) => heading.id);
58
+ const visibleIds = orderedIds.filter((id) => intersecting.has(id));
59
+ if (visibleIds.length > 0) {
60
+ activeIds.value = visibleIds;
61
+ return;
62
+ }
63
+ // When the activation band lies in the gap between headings, keep the
64
+ // most recently passed section selected. At the top of the article,
65
+ // where no heading has crossed the sticky-header line, select the first
66
+ // section instead of presenting an unexplained empty state.
67
+ const activationTop = options.offset ?? 0;
68
+ let fallback = orderedIds[0];
69
+ for (const id of orderedIds) {
70
+ const top = headingTops.get(id);
71
+ if (top !== undefined && top <= activationTop)
72
+ fallback = id;
73
+ }
74
+ activeIds.value = fallback ? [fallback] : [];
75
+ }, {
76
+ root: options.observerRoot ?? null,
77
+ rootMargin: options.rootMargin ?? `-${options.offset ?? 0}px 0px -60% 0px`,
78
+ threshold: [0, 1],
79
+ });
80
+ for (const heading of headings) {
81
+ const element = root.querySelector(`[id="${escapeAttribute(heading.id)}"]`);
82
+ if (element)
83
+ observer.observe(element);
84
+ }
85
+ };
86
+ const scheduleObserve = () => {
87
+ const revision = ++observationRevision;
88
+ // A child receives its new heading props while the parent page is still
89
+ // being patched. Waiting for the runtime's DOM queue prevents querying
90
+ // the outgoing article and permanently observing stale heading nodes.
91
+ void nextTick().then(() => {
92
+ if (!disposed && revision === observationRevision)
93
+ observe();
94
+ });
95
+ };
96
+ scheduleObserve();
97
+ const stop = watch(() => sourceValue(source), scheduleObserve);
98
+ return () => {
99
+ disposed = true;
100
+ observationRevision += 1;
101
+ stop?.();
102
+ observer?.disconnect();
103
+ intersecting.clear();
104
+ headingTops.clear();
105
+ };
106
+ });
107
+ return {
108
+ activeIds,
109
+ isActive: (id) => activeIds.value.includes(id),
110
+ };
111
+ }
112
+ //# sourceMappingURL=use-active-headings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-active-headings.js","sourceRoot":"","sources":["../../../src/runtime/composables/use-active-headings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import type { ContentHeading, ContentItem } from '../../types/content.js';
2
+ import type { PageLoaderContext } from '../../types/page.js';
3
+ export interface ContentPageData {
4
+ doc: ContentItem | null;
5
+ existingPaths: string[];
6
+ }
7
+ export interface ContentBreadcrumb {
8
+ label: string;
9
+ path: string;
10
+ icon: string;
11
+ key: string;
12
+ isLast: boolean;
13
+ hasPage: boolean;
14
+ }
15
+ export interface ContentBreadcrumbOptions {
16
+ rootLabel?: string;
17
+ rootIcon?: string;
18
+ formatLabel?: (segment: string) => string;
19
+ }
20
+ export interface ContentPageLoaderOptions {
21
+ /** Catch-all route parameter name. Defaults to `all`. */
22
+ param?: string;
23
+ }
24
+ export interface ContentSeoOptions {
25
+ doc: ContentItem | null;
26
+ path: string;
27
+ siteUrl: string;
28
+ siteName?: string;
29
+ image?: string;
30
+ breadcrumbs?: ContentBreadcrumb[];
31
+ /** Path depth at which Open Graph pages become articles. Defaults to 2. */
32
+ articleDepth?: number;
33
+ notFoundTitle?: string;
34
+ }
35
+ /** Normalize a route/catch-all value into the content layer's absolute path form. */
36
+ export declare function normalizeContentPath(value: string | undefined | null): string;
37
+ /** Create a catch-all content loader with document and ancestor-page data. */
38
+ export declare function defineContentPageLoader(options?: ContentPageLoaderOptions): ({ params }: PageLoaderContext) => Promise<ContentPageData>;
39
+ /** Build accessible breadcrumb data from a content path and known ancestor pages. */
40
+ export declare function useContentBreadcrumbs(path: string, doc: ContentItem | null, existingPaths?: readonly string[], options?: ContentBreadcrumbOptions): ContentBreadcrumb[];
41
+ /** Return the document headings appropriate for a table of contents. */
42
+ export declare function useContentHeadings(doc: Pick<ContentItem, 'toc'> | null | undefined, depths?: readonly ContentHeading['depth'][]): ContentHeading[];
43
+ /** Apply consistent content title, canonical, social, robots, and JSON-LD metadata. */
44
+ export declare function useContentSeo(options: ContentSeoOptions): void;
45
+ //# sourceMappingURL=use-content-page.d.ts.map