@jasonshimmy/vite-plugin-cer-app 0.23.1 → 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 (397) 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/commands/preview.d.ts.map +1 -1
  18. package/dist/cli/commands/preview.js +37 -4
  19. package/dist/cli/commands/preview.js.map +1 -1
  20. package/dist/cli/create/index.d.ts +11 -1
  21. package/dist/cli/create/index.d.ts.map +1 -1
  22. package/dist/cli/create/index.js +135 -65
  23. package/dist/cli/create/index.js.map +1 -1
  24. package/dist/cli/create/templates/spa/package.json.tpl +5 -3
  25. package/dist/cli/create/templates/ssg/cer.config.ts.tpl +2 -0
  26. package/dist/cli/create/templates/ssg/package.json.tpl +5 -3
  27. package/dist/cli/create/templates/ssr/package.json.tpl +5 -3
  28. package/dist/cli/index.js +2 -0
  29. package/dist/cli/index.js.map +1 -1
  30. package/dist/index.d.ts +3 -1
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/plugin/build-ssg.d.ts +22 -4
  33. package/dist/plugin/build-ssg.d.ts.map +1 -1
  34. package/dist/plugin/build-ssg.js +273 -13
  35. package/dist/plugin/build-ssg.js.map +1 -1
  36. package/dist/plugin/content/parser.d.ts.map +1 -1
  37. package/dist/plugin/content/parser.js +54 -10
  38. package/dist/plugin/content/parser.js.map +1 -1
  39. package/dist/plugin/dev-server.d.ts +6 -1
  40. package/dist/plugin/dev-server.d.ts.map +1 -1
  41. package/dist/plugin/dev-server.js.map +1 -1
  42. package/dist/plugin/dts-generator.d.ts.map +1 -1
  43. package/dist/plugin/dts-generator.js +50 -8
  44. package/dist/plugin/dts-generator.js.map +1 -1
  45. package/dist/plugin/generated-dir.d.ts +2 -0
  46. package/dist/plugin/generated-dir.d.ts.map +1 -1
  47. package/dist/plugin/generated-dir.js +17 -6
  48. package/dist/plugin/generated-dir.js.map +1 -1
  49. package/dist/plugin/html-post-process.d.ts +35 -0
  50. package/dist/plugin/html-post-process.d.ts.map +1 -0
  51. package/dist/plugin/html-post-process.js +112 -0
  52. package/dist/plugin/html-post-process.js.map +1 -0
  53. package/dist/plugin/index.d.ts +9 -0
  54. package/dist/plugin/index.d.ts.map +1 -1
  55. package/dist/plugin/index.js +89 -14
  56. package/dist/plugin/index.js.map +1 -1
  57. package/dist/plugin/transforms/auto-import.d.ts.map +1 -1
  58. package/dist/plugin/transforms/auto-import.js +7 -0
  59. package/dist/plugin/transforms/auto-import.js.map +1 -1
  60. package/dist/plugin/transforms/prune-runtime-css.d.ts +8 -0
  61. package/dist/plugin/transforms/prune-runtime-css.d.ts.map +1 -0
  62. package/dist/plugin/transforms/prune-runtime-css.js +40 -0
  63. package/dist/plugin/transforms/prune-runtime-css.js.map +1 -0
  64. package/dist/runtime/app-template.d.ts +1 -4
  65. package/dist/runtime/app-template.d.ts.map +1 -1
  66. package/dist/runtime/app-template.js +211 -40
  67. package/dist/runtime/app-template.js.map +1 -1
  68. package/dist/runtime/composables/index.d.ts +4 -0
  69. package/dist/runtime/composables/index.d.ts.map +1 -1
  70. package/dist/runtime/composables/index.js +2 -0
  71. package/dist/runtime/composables/index.js.map +1 -1
  72. package/dist/runtime/composables/use-active-headings.d.ts +24 -0
  73. package/dist/runtime/composables/use-active-headings.d.ts.map +1 -0
  74. package/dist/runtime/composables/use-active-headings.js +112 -0
  75. package/dist/runtime/composables/use-active-headings.js.map +1 -0
  76. package/dist/runtime/composables/use-content-page.d.ts +45 -0
  77. package/dist/runtime/composables/use-content-page.d.ts.map +1 -0
  78. package/dist/runtime/composables/use-content-page.js +179 -0
  79. package/dist/runtime/composables/use-content-page.js.map +1 -0
  80. package/dist/runtime/composables/use-content-search.d.ts.map +1 -1
  81. package/dist/runtime/composables/use-content-search.js +1 -5
  82. package/dist/runtime/composables/use-content-search.js.map +1 -1
  83. package/dist/runtime/composables/use-fetch.d.ts +2 -1
  84. package/dist/runtime/composables/use-fetch.d.ts.map +1 -1
  85. package/dist/runtime/composables/use-fetch.js +112 -43
  86. package/dist/runtime/composables/use-fetch.js.map +1 -1
  87. package/dist/runtime/composables/use-head.d.ts.map +1 -1
  88. package/dist/runtime/composables/use-head.js +30 -6
  89. package/dist/runtime/composables/use-head.js.map +1 -1
  90. package/dist/runtime/composables/use-route.d.ts.map +1 -1
  91. package/dist/runtime/composables/use-route.js +39 -11
  92. package/dist/runtime/composables/use-route.js.map +1 -1
  93. package/dist/runtime/content/client.js +2 -2
  94. package/dist/runtime/content/client.js.map +1 -1
  95. package/dist/runtime/entry-server-template.d.ts +16 -1
  96. package/dist/runtime/entry-server-template.d.ts.map +1 -1
  97. package/dist/runtime/entry-server-template.js +120 -13
  98. package/dist/runtime/entry-server-template.js.map +1 -1
  99. package/dist/types/config.d.ts +53 -4
  100. package/dist/types/config.d.ts.map +1 -1
  101. package/dist/types/config.js.map +1 -1
  102. package/dist/types/middleware.d.ts +2 -2
  103. package/dist/types/middleware.d.ts.map +1 -1
  104. package/package.json +22 -19
  105. package/.github/copilot-instructions.md +0 -169
  106. package/.github/workflows/publish.yml +0 -257
  107. package/.nvmrc +0 -1
  108. package/CHANGELOG.md +0 -232
  109. package/CLAUDE.md +0 -113
  110. package/commits.txt +0 -1
  111. package/cypress.config.ts +0 -16
  112. package/docs/authentication.md +0 -285
  113. package/docs/cli.md +0 -324
  114. package/docs/components.md +0 -237
  115. package/docs/composables.md +0 -907
  116. package/docs/configuration.md +0 -667
  117. package/docs/content.md +0 -570
  118. package/docs/data-loading.md +0 -336
  119. package/docs/getting-started.md +0 -237
  120. package/docs/head-management.md +0 -212
  121. package/docs/i18n.md +0 -159
  122. package/docs/layouts.md +0 -224
  123. package/docs/middleware.md +0 -234
  124. package/docs/plugins.md +0 -170
  125. package/docs/rendering-modes.md +0 -377
  126. package/docs/routing.md +0 -485
  127. package/docs/server-api.md +0 -253
  128. package/docs/testing.md +0 -455
  129. package/docs/use-fetch.md +0 -183
  130. package/e2e/cypress/e2e/api.cy.ts +0 -123
  131. package/e2e/cypress/e2e/async-component.cy.ts +0 -27
  132. package/e2e/cypress/e2e/component-splitting.cy.ts +0 -50
  133. package/e2e/cypress/e2e/content.cy.ts +0 -425
  134. package/e2e/cypress/e2e/cookie.cy.ts +0 -85
  135. package/e2e/cypress/e2e/data.cy.ts +0 -158
  136. package/e2e/cypress/e2e/error-boundary.cy.ts +0 -88
  137. package/e2e/cypress/e2e/fouc.cy.ts +0 -254
  138. package/e2e/cypress/e2e/group-meta.cy.ts +0 -36
  139. package/e2e/cypress/e2e/head.cy.ts +0 -89
  140. package/e2e/cypress/e2e/i18n.cy.ts +0 -79
  141. package/e2e/cypress/e2e/interactive.cy.ts +0 -137
  142. package/e2e/cypress/e2e/isr-nested-runtime.cy.ts +0 -102
  143. package/e2e/cypress/e2e/jit-css-custom-colors.cy.ts +0 -43
  144. package/e2e/cypress/e2e/middleware-chain.cy.ts +0 -89
  145. package/e2e/cypress/e2e/middleware-status.cy.ts +0 -30
  146. package/e2e/cypress/e2e/middleware.cy.ts +0 -45
  147. package/e2e/cypress/e2e/navigate.cy.ts +0 -39
  148. package/e2e/cypress/e2e/observability.cy.ts +0 -77
  149. package/e2e/cypress/e2e/per-route-error.cy.ts +0 -42
  150. package/e2e/cypress/e2e/per-route-render.cy.ts +0 -70
  151. package/e2e/cypress/e2e/preview-hardening.cy.ts +0 -88
  152. package/e2e/cypress/e2e/routes.cy.ts +0 -128
  153. package/e2e/cypress/e2e/seo-meta.cy.ts +0 -108
  154. package/e2e/cypress/e2e/server-middleware.cy.ts +0 -46
  155. package/e2e/cypress/e2e/session-rotation.cy.ts +0 -25
  156. package/e2e/cypress/e2e/session.cy.ts +0 -73
  157. package/e2e/cypress/e2e/ssr-render-error.cy.ts +0 -68
  158. package/e2e/cypress/e2e/synthetic-404.cy.ts +0 -45
  159. package/e2e/cypress/e2e/use-page-data.cy.ts +0 -122
  160. package/e2e/cypress/e2e/use-state.cy.ts +0 -138
  161. package/e2e/cypress/support/commands.ts +0 -120
  162. package/e2e/cypress/support/e2e.ts +0 -10
  163. package/e2e/cypress/tsconfig.json +0 -14
  164. package/e2e/kitchen-sink/app/components/ks-badge.ts +0 -8
  165. package/e2e/kitchen-sink/app/composables/useKsCounter.ts +0 -9
  166. package/e2e/kitchen-sink/app/error.ts +0 -18
  167. package/e2e/kitchen-sink/app/layouts/admin.ts +0 -13
  168. package/e2e/kitchen-sink/app/layouts/default.ts +0 -25
  169. package/e2e/kitchen-sink/app/layouts/group.ts +0 -9
  170. package/e2e/kitchen-sink/app/layouts/minimal.ts +0 -7
  171. package/e2e/kitchen-sink/app/loading.ts +0 -9
  172. package/e2e/kitchen-sink/app/middleware/auth.ts +0 -9
  173. package/e2e/kitchen-sink/app/middleware/custom-log.ts +0 -4
  174. package/e2e/kitchen-sink/app/middleware/group-auth.ts +0 -7
  175. package/e2e/kitchen-sink/app/middleware/logger.ts +0 -14
  176. package/e2e/kitchen-sink/app/pages/(auth)/login.ts +0 -13
  177. package/e2e/kitchen-sink/app/pages/(auth)/protected.ts +0 -16
  178. package/e2e/kitchen-sink/app/pages/404.ts +0 -9
  179. package/e2e/kitchen-sink/app/pages/about.ts +0 -17
  180. package/e2e/kitchen-sink/app/pages/admin/_layout.ts +0 -1
  181. package/e2e/kitchen-sink/app/pages/admin/dashboard.ts +0 -11
  182. package/e2e/kitchen-sink/app/pages/async-component-error-test.ts +0 -18
  183. package/e2e/kitchen-sink/app/pages/async-component-test.ts +0 -18
  184. package/e2e/kitchen-sink/app/pages/blog/[slug].ts +0 -59
  185. package/e2e/kitchen-sink/app/pages/blog/index.ts +0 -51
  186. package/e2e/kitchen-sink/app/pages/content-blog.ts +0 -37
  187. package/e2e/kitchen-sink/app/pages/content-doc.ts +0 -42
  188. package/e2e/kitchen-sink/app/pages/content-fallback.ts +0 -36
  189. package/e2e/kitchen-sink/app/pages/content-guides.ts +0 -35
  190. package/e2e/kitchen-sink/app/pages/content-index.ts +0 -39
  191. package/e2e/kitchen-sink/app/pages/content-search.ts +0 -36
  192. package/e2e/kitchen-sink/app/pages/cookie-test.ts +0 -22
  193. package/e2e/kitchen-sink/app/pages/counter.ts +0 -17
  194. package/e2e/kitchen-sink/app/pages/group-auth-blocked.ts +0 -9
  195. package/e2e/kitchen-sink/app/pages/group-meta-test/_layout.ts +0 -6
  196. package/e2e/kitchen-sink/app/pages/group-meta-test/custom-mw.ts +0 -14
  197. package/e2e/kitchen-sink/app/pages/group-meta-test/page.ts +0 -9
  198. package/e2e/kitchen-sink/app/pages/group-meta-test/protected.ts +0 -8
  199. package/e2e/kitchen-sink/app/pages/head.ts +0 -20
  200. package/e2e/kitchen-sink/app/pages/i18n-test.ts +0 -14
  201. package/e2e/kitchen-sink/app/pages/index.ts +0 -27
  202. package/e2e/kitchen-sink/app/pages/isr-test.ts +0 -17
  203. package/e2e/kitchen-sink/app/pages/items/[id].ts +0 -20
  204. package/e2e/kitchen-sink/app/pages/jit-css-custom-colors-test.ts +0 -14
  205. package/e2e/kitchen-sink/app/pages/loader-error-test.ts +0 -13
  206. package/e2e/kitchen-sink/app/pages/loader-props-test.ts +0 -19
  207. package/e2e/kitchen-sink/app/pages/loader-response-error-test.ts +0 -13
  208. package/e2e/kitchen-sink/app/pages/middleware-chain-test.ts +0 -12
  209. package/e2e/kitchen-sink/app/pages/middleware-status-test.ts +0 -9
  210. package/e2e/kitchen-sink/app/pages/navigate-test.ts +0 -16
  211. package/e2e/kitchen-sink/app/pages/observability-test.ts +0 -25
  212. package/e2e/kitchen-sink/app/pages/per-route-error-test.error.ts +0 -13
  213. package/e2e/kitchen-sink/app/pages/per-route-error-test.ts +0 -15
  214. package/e2e/kitchen-sink/app/pages/plugin-dsd-test.ts +0 -10
  215. package/e2e/kitchen-sink/app/pages/render-error-test.ts +0 -12
  216. package/e2e/kitchen-sink/app/pages/render-server-test.ts +0 -12
  217. package/e2e/kitchen-sink/app/pages/render-spa-test.ts +0 -12
  218. package/e2e/kitchen-sink/app/pages/route-info.ts +0 -14
  219. package/e2e/kitchen-sink/app/pages/seo-test.ts +0 -23
  220. package/e2e/kitchen-sink/app/pages/session-rotation-test.ts +0 -25
  221. package/e2e/kitchen-sink/app/pages/use-state-test.ts +0 -37
  222. package/e2e/kitchen-sink/app/plugins/01.setup.ts +0 -7
  223. package/e2e/kitchen-sink/app/plugins/02.ks-plugin-components.ts +0 -27
  224. package/e2e/kitchen-sink/cer-auto-imports.d.ts +0 -51
  225. package/e2e/kitchen-sink/cer-env.d.ts +0 -35
  226. package/e2e/kitchen-sink/cer-tsconfig.json +0 -30
  227. package/e2e/kitchen-sink/cer.config.ts +0 -43
  228. package/e2e/kitchen-sink/content/01.guides/01.index.md +0 -8
  229. package/e2e/kitchen-sink/content/01.guides/02.intro.md +0 -8
  230. package/e2e/kitchen-sink/content/01.guides/10.advanced.md +0 -8
  231. package/e2e/kitchen-sink/content/blog/2026-04-01-hello.md +0 -26
  232. package/e2e/kitchen-sink/content/blog/2026-04-02-draft.md +0 -10
  233. package/e2e/kitchen-sink/content/blog/index.md +0 -8
  234. package/e2e/kitchen-sink/content/blog/no-frontmatter.md +0 -7
  235. package/e2e/kitchen-sink/content/docs/getting-started.md +0 -48
  236. package/e2e/kitchen-sink/content/index.md +0 -16
  237. package/e2e/kitchen-sink/server/api/echo.ts +0 -12
  238. package/e2e/kitchen-sink/server/api/health.ts +0 -3
  239. package/e2e/kitchen-sink/server/api/posts/[slug].ts +0 -11
  240. package/e2e/kitchen-sink/server/api/posts/index.ts +0 -5
  241. package/e2e/kitchen-sink/server/api/session.ts +0 -23
  242. package/e2e/kitchen-sink/server/data/posts.ts +0 -21
  243. package/e2e/kitchen-sink/server/middleware/01-headers.ts +0 -6
  244. package/e2e/kitchen-sink/server/middleware/02-status-test.ts +0 -10
  245. package/e2e/kitchen-sink/tsconfig.json +0 -3
  246. package/e2e/scripts/clean.mjs +0 -14
  247. package/eslint.config.ts +0 -22
  248. package/src/__tests__/cli/adapters/cloudflare-worker.integration.test.ts +0 -132
  249. package/src/__tests__/cli/adapters/cloudflare.test.ts +0 -332
  250. package/src/__tests__/cli/adapters/netlify-bridge.integration.test.ts +0 -139
  251. package/src/__tests__/cli/adapters/netlify.test.ts +0 -286
  252. package/src/__tests__/cli/adapters/vercel-launcher.integration.test.ts +0 -129
  253. package/src/__tests__/cli/adapters/vercel.test.ts +0 -263
  254. package/src/__tests__/cli/preview-hardening.test.ts +0 -265
  255. package/src/__tests__/cli/preview-isr.test.ts +0 -320
  256. package/src/__tests__/index.test.ts +0 -21
  257. package/src/__tests__/plugin/app-template.test.ts +0 -112
  258. package/src/__tests__/plugin/build-ssg-render.test.ts +0 -155
  259. package/src/__tests__/plugin/build-ssg.test.ts +0 -598
  260. package/src/__tests__/plugin/build-ssr.test.ts +0 -192
  261. package/src/__tests__/plugin/cer-app-plugin.test.ts +0 -552
  262. package/src/__tests__/plugin/content/emitter.test.ts +0 -117
  263. package/src/__tests__/plugin/content/loader.test.ts +0 -154
  264. package/src/__tests__/plugin/content/parser.test.ts +0 -381
  265. package/src/__tests__/plugin/content/path-utils.test.ts +0 -69
  266. package/src/__tests__/plugin/content/search.test.ts +0 -119
  267. package/src/__tests__/plugin/dev-server.test.ts +0 -813
  268. package/src/__tests__/plugin/dts-generator.test.ts +0 -394
  269. package/src/__tests__/plugin/entry-server-template.test.ts +0 -385
  270. package/src/__tests__/plugin/generated-dir.test.ts +0 -144
  271. package/src/__tests__/plugin/path-utils.test.ts +0 -411
  272. package/src/__tests__/plugin/resolve-config.test.ts +0 -200
  273. package/src/__tests__/plugin/scanner.test.ts +0 -186
  274. package/src/__tests__/plugin/transforms/auto-import.test.ts +0 -510
  275. package/src/__tests__/plugin/transforms/head-inject.test.ts +0 -178
  276. package/src/__tests__/plugin/virtual/composables.test.ts +0 -57
  277. package/src/__tests__/plugin/virtual/content-components.test.ts +0 -66
  278. package/src/__tests__/plugin/virtual/error.test.ts +0 -71
  279. package/src/__tests__/plugin/virtual/layouts.test.ts +0 -70
  280. package/src/__tests__/plugin/virtual/loading.test.ts +0 -72
  281. package/src/__tests__/plugin/virtual/middleware.test.ts +0 -83
  282. package/src/__tests__/plugin/virtual/plugins.test.ts +0 -129
  283. package/src/__tests__/plugin/virtual/routes.test.ts +0 -884
  284. package/src/__tests__/plugin/virtual/server-api.test.ts +0 -164
  285. package/src/__tests__/plugin/virtual/server-middleware.test.ts +0 -102
  286. package/src/__tests__/runtime/app-template.test.ts +0 -198
  287. package/src/__tests__/runtime/define-middleware.test.ts +0 -64
  288. package/src/__tests__/runtime/define-server-middleware.test.ts +0 -54
  289. package/src/__tests__/runtime/entry-client-template.test.ts +0 -61
  290. package/src/__tests__/runtime/isr-handler.test.ts +0 -338
  291. package/src/__tests__/runtime/oauth/handler.test.ts +0 -358
  292. package/src/__tests__/runtime/oauth/providers.test.ts +0 -47
  293. package/src/__tests__/runtime/oauth-index.test.ts +0 -43
  294. package/src/__tests__/runtime/use-auth.test.ts +0 -169
  295. package/src/__tests__/runtime/use-content-search-composable.test.ts +0 -405
  296. package/src/__tests__/runtime/use-content-search.test.ts +0 -163
  297. package/src/__tests__/runtime/use-content.test.ts +0 -226
  298. package/src/__tests__/runtime/use-cookie.test.ts +0 -277
  299. package/src/__tests__/runtime/use-fetch-component.test.ts +0 -214
  300. package/src/__tests__/runtime/use-fetch.test.ts +0 -377
  301. package/src/__tests__/runtime/use-head.test.ts +0 -266
  302. package/src/__tests__/runtime/use-inject-client.test.ts +0 -67
  303. package/src/__tests__/runtime/use-inject.test.ts +0 -66
  304. package/src/__tests__/runtime/use-locale.test.ts +0 -152
  305. package/src/__tests__/runtime/use-navigate.test.ts +0 -121
  306. package/src/__tests__/runtime/use-page-data.test.ts +0 -298
  307. package/src/__tests__/runtime/use-route.test.ts +0 -156
  308. package/src/__tests__/runtime/use-runtime-config.test.ts +0 -182
  309. package/src/__tests__/runtime/use-seo-meta.test.ts +0 -109
  310. package/src/__tests__/runtime/use-session.test.ts +0 -320
  311. package/src/__tests__/runtime/use-state.test.ts +0 -340
  312. package/src/__tests__/types/config.test.ts +0 -18
  313. package/src/cli/adapters/cloudflare.ts +0 -335
  314. package/src/cli/adapters/netlify.ts +0 -326
  315. package/src/cli/adapters/vercel.ts +0 -311
  316. package/src/cli/commands/adapt.ts +0 -84
  317. package/src/cli/commands/build.ts +0 -165
  318. package/src/cli/commands/dev.ts +0 -125
  319. package/src/cli/commands/generate.ts +0 -91
  320. package/src/cli/commands/preview-isr.ts +0 -172
  321. package/src/cli/commands/preview.ts +0 -489
  322. package/src/cli/create/index.ts +0 -275
  323. package/src/cli/create/templates/shared/.gitignore.tpl +0 -25
  324. package/src/cli/create/templates/shared/app/layouts/default.ts.tpl +0 -15
  325. package/src/cli/create/templates/shared/app/pages/index.ts.tpl +0 -8
  326. package/src/cli/create/templates/shared/index.html.tpl +0 -12
  327. package/src/cli/create/templates/shared/tsconfig.json.tpl +0 -6
  328. package/src/cli/create/templates/spa/cer.config.ts.tpl +0 -6
  329. package/src/cli/create/templates/spa/package.json.tpl +0 -18
  330. package/src/cli/create/templates/ssg/cer.config.ts.tpl +0 -10
  331. package/src/cli/create/templates/ssg/package.json.tpl +0 -19
  332. package/src/cli/create/templates/ssr/cer.config.ts.tpl +0 -6
  333. package/src/cli/create/templates/ssr/package.json.tpl +0 -18
  334. package/src/cli/index.ts +0 -22
  335. package/src/index.ts +0 -20
  336. package/src/plugin/build-ssg.ts +0 -336
  337. package/src/plugin/build-ssr.ts +0 -134
  338. package/src/plugin/content/emitter.ts +0 -50
  339. package/src/plugin/content/index.ts +0 -233
  340. package/src/plugin/content/parser.ts +0 -259
  341. package/src/plugin/content/path-utils.ts +0 -55
  342. package/src/plugin/content/scanner.ts +0 -26
  343. package/src/plugin/content/search.ts +0 -28
  344. package/src/plugin/dev-server.ts +0 -377
  345. package/src/plugin/dts-generator.ts +0 -273
  346. package/src/plugin/generated-dir.ts +0 -121
  347. package/src/plugin/index.ts +0 -553
  348. package/src/plugin/path-utils.ts +0 -186
  349. package/src/plugin/scanner.ts +0 -65
  350. package/src/plugin/transforms/auto-import.ts +0 -206
  351. package/src/plugin/transforms/head-inject.ts +0 -161
  352. package/src/plugin/virtual/composables.ts +0 -28
  353. package/src/plugin/virtual/content-components.ts +0 -83
  354. package/src/plugin/virtual/error.ts +0 -34
  355. package/src/plugin/virtual/layouts.ts +0 -41
  356. package/src/plugin/virtual/loading.ts +0 -32
  357. package/src/plugin/virtual/middleware.ts +0 -45
  358. package/src/plugin/virtual/plugins.ts +0 -46
  359. package/src/plugin/virtual/routes.ts +0 -514
  360. package/src/plugin/virtual/server-api.ts +0 -85
  361. package/src/plugin/virtual/server-middleware.ts +0 -44
  362. package/src/runtime/app-template.ts +0 -380
  363. package/src/runtime/composables/define-middleware.ts +0 -17
  364. package/src/runtime/composables/define-server-middleware.ts +0 -18
  365. package/src/runtime/composables/index.ts +0 -27
  366. package/src/runtime/composables/use-auth.ts +0 -125
  367. package/src/runtime/composables/use-content-search.ts +0 -205
  368. package/src/runtime/composables/use-content.ts +0 -146
  369. package/src/runtime/composables/use-cookie.ts +0 -135
  370. package/src/runtime/composables/use-fetch.ts +0 -438
  371. package/src/runtime/composables/use-head.ts +0 -212
  372. package/src/runtime/composables/use-inject.ts +0 -49
  373. package/src/runtime/composables/use-locale.ts +0 -109
  374. package/src/runtime/composables/use-navigate.ts +0 -58
  375. package/src/runtime/composables/use-page-data.ts +0 -93
  376. package/src/runtime/composables/use-route.ts +0 -71
  377. package/src/runtime/composables/use-runtime-config.ts +0 -123
  378. package/src/runtime/composables/use-seo-meta.ts +0 -80
  379. package/src/runtime/composables/use-session.ts +0 -186
  380. package/src/runtime/composables/use-state.ts +0 -92
  381. package/src/runtime/content/client.ts +0 -168
  382. package/src/runtime/entry-client-template.ts +0 -39
  383. package/src/runtime/entry-server-template.ts +0 -493
  384. package/src/runtime/isr-handler.ts +0 -184
  385. package/src/runtime/oauth/handler.ts +0 -407
  386. package/src/runtime/oauth/index.ts +0 -49
  387. package/src/runtime/oauth/providers.ts +0 -38
  388. package/src/types/api.ts +0 -40
  389. package/src/types/config.ts +0 -371
  390. package/src/types/content.ts +0 -66
  391. package/src/types/index.ts +0 -7
  392. package/src/types/middleware.ts +0 -63
  393. package/src/types/page.ts +0 -117
  394. package/src/types/plugin.ts +0 -34
  395. package/tsconfig.build.json +0 -10
  396. package/tsconfig.json +0 -19
  397. package/vitest.config.ts +0 -33
@@ -1,336 +0,0 @@
1
- import { writeFile, mkdir, readFile } from 'node:fs/promises'
2
- import { existsSync } from 'node:fs'
3
- import { join } from 'pathe'
4
- import { createServer, type UserConfig } from 'vite'
5
- import type { ResolvedCerConfig } from './dev-server.js'
6
- import type { ContentItem } from '../types/content.js'
7
- import { buildSSR } from './build-ssr.js'
8
- import { buildRouteEntry } from './path-utils.js'
9
- import fg from 'fast-glob'
10
-
11
- interface SsgManifest {
12
- generatedAt: string
13
- paths: string[]
14
- errors: Array<{ path: string; error: string }>
15
- }
16
-
17
- const CONTENT_STORE_KEY = '__CER_CONTENT_STORE__'
18
-
19
-
20
- /**
21
- * Collects all static paths to generate.
22
- * For 'auto' mode: scans app/pages/ and collects only static (non-dynamic) routes
23
- * plus any dynamic routes that provide ssg.paths().
24
- * For explicit string[] mode: uses those paths directly.
25
- */
26
- /**
27
- * Expands a set of base paths into locale-prefixed variants when i18n is
28
- * configured. Skips expansion for `no_prefix` strategy.
29
- */
30
- function _expandWithLocales(
31
- paths: string[],
32
- i18n: ResolvedCerConfig['i18n'],
33
- ): string[] {
34
- if (!i18n || i18n.strategy === 'no_prefix') return paths
35
- const { locales, defaultLocale, strategy } = i18n
36
- const expanded: string[] = []
37
- for (const p of paths) {
38
- for (const locale of locales) {
39
- const isDefault = locale === defaultLocale
40
- if (isDefault && strategy === 'prefix_except_default') {
41
- expanded.push(p)
42
- } else {
43
- expanded.push(`/${locale}${p === '/' ? '' : p}`)
44
- }
45
- }
46
- }
47
- return [...new Set(expanded)]
48
- }
49
-
50
- async function collectSsgPaths(
51
- config: ResolvedCerConfig,
52
- viteUserConfig: UserConfig,
53
- ): Promise<string[]> {
54
- const ssgConfig = config.ssg
55
-
56
- if (Array.isArray(ssgConfig.routes) && ssgConfig.routes.length > 0) {
57
- return _expandWithLocales(ssgConfig.routes, config.i18n)
58
- }
59
-
60
- // Auto-discover paths
61
- const paths: string[] = ['/']
62
-
63
- if (!existsSync(config.pagesDir)) return paths
64
-
65
- const files = await fg('**/*.ts', {
66
- cwd: config.pagesDir,
67
- absolute: true,
68
- onlyFiles: true,
69
- })
70
-
71
- const staticFiles: string[] = []
72
- const dynamicFiles: Array<{
73
- file: string
74
- entry: ReturnType<typeof buildRouteEntry>
75
- usesQueryContent: boolean
76
- }> = []
77
-
78
- for (const file of files) {
79
- // Skip routes that declare render: 'server' or render: 'spa' — they are
80
- // either always-SSR or client-only and must not be pre-rendered.
81
- let src = ''
82
- try {
83
- src = await readFile(file, 'utf-8')
84
- const renderMatch = src.match(/render\s*:\s*['"]([^'"]+)['"]/)
85
- const renderMode = renderMatch ? renderMatch[1] : null
86
- if (renderMode === 'server' || renderMode === 'spa') continue
87
- } catch { /* ignore read errors */ }
88
-
89
- const entry = buildRouteEntry(file, config.pagesDir)
90
- const usesQueryContent = /\bqueryContent\s*\(/.test(src)
91
-
92
- if (!entry.isDynamic && !entry.isCatchAll) {
93
- staticFiles.push(file)
94
- if (entry.routePath !== '/') {
95
- paths.push(entry.routePath)
96
- }
97
- } else if (entry.isDynamic) {
98
- dynamicFiles.push({ file, entry, usesQueryContent })
99
- }
100
- }
101
-
102
- if (dynamicFiles.length > 0) {
103
- // Use a Vite SSR dev server to load page modules with auto-imports applied
104
- const viteServer = await createServer({
105
- ...viteUserConfig,
106
- root: config.root,
107
- server: { middlewareMode: true },
108
- appType: 'custom',
109
- logLevel: 'silent',
110
- })
111
-
112
- try {
113
- for (const { file, entry, usesQueryContent } of dynamicFiles) {
114
- try {
115
- const pageMod = await viteServer.ssrLoadModule(file)
116
- const pageMeta = pageMod.meta ?? pageMod.pageMeta
117
-
118
- if (pageMeta?.render === 'server' || pageMeta?.render === 'spa') continue
119
- if (pageMeta?.ssg?.paths) {
120
- const pathsResult = await pageMeta.ssg.paths()
121
- for (const ctx of pathsResult) {
122
- let resolvedPath = entry.routePath
123
- for (const [key, value] of Object.entries(ctx.params as Record<string, unknown>)) {
124
- resolvedPath = resolvedPath.replace(`:${key}*`, String(value))
125
- resolvedPath = resolvedPath.replace(`:${key}`, String(value))
126
- }
127
- paths.push(resolvedPath)
128
- }
129
- continue
130
- }
131
-
132
- if (entry.isCatchAll && usesQueryContent) {
133
- const contentStore = (globalThis as Record<string, unknown>)[CONTENT_STORE_KEY] as ContentItem[] | undefined
134
- const catchAllPaths = _collectCatchAllContentPaths(entry.routePath, contentStore ?? [])
135
- paths.push(...catchAllPaths)
136
- }
137
- } catch {
138
- console.warn(`[cer-app] Could not enumerate paths for ${file}`)
139
- }
140
- }
141
- } finally {
142
- await viteServer.close()
143
- }
144
- }
145
-
146
- // When i18n is configured, expand every collected path into locale-prefixed
147
- // variants so each locale gets its own pre-rendered HTML file.
148
- // strategy 'prefix' → /en/about, /fr/about
149
- // strategy 'prefix_except_default' → /about, /fr/about
150
- // strategy 'no_prefix' → no expansion (locale detected from header/cookie only)
151
- if (config.i18n && config.i18n.strategy !== 'no_prefix') {
152
- const { locales, defaultLocale, strategy } = config.i18n
153
- const expanded: string[] = []
154
- for (const p of paths) {
155
- for (const locale of locales) {
156
- const isDefault = locale === defaultLocale
157
- if (isDefault && strategy === 'prefix_except_default') {
158
- expanded.push(p)
159
- } else {
160
- expanded.push(`/${locale}${p === '/' ? '' : p}`)
161
- }
162
- }
163
- }
164
- return [...new Set(expanded)]
165
- }
166
-
167
- return [...new Set(paths)] // deduplicate
168
- }
169
-
170
- function _collectCatchAllContentPaths(routePath: string, store: ContentItem[]): string[] {
171
- if (store.length === 0) return []
172
-
173
- const prefix = routePath
174
- .replace(/:[^/]+\*$/, '')
175
- .replace(/\/+$/, '') || '/'
176
-
177
- return store
178
- .map((item) => item._path)
179
- .filter((contentPath) => {
180
- if (prefix === '/') return true
181
- return contentPath === prefix || contentPath.startsWith(prefix + '/')
182
- })
183
- }
184
-
185
- // Cache the server module across renderPath calls (loaded once per SSG run)
186
- let _serverMod: Record<string, unknown> | null = null
187
-
188
- /**
189
- * Renders a single path using the SSR server bundle and returns the HTML.
190
- *
191
- * The server bundle's handler already merges the SSR output with
192
- * dist/client/index.html internally (via the _mergeWithClientTemplate helper
193
- * it embeds at build time), so this function simply captures the response.
194
- */
195
- async function renderPath(
196
- path: string,
197
- serverBundlePath: string,
198
- ): Promise<string> {
199
- // Load server bundle once
200
- if (!_serverMod) {
201
- try {
202
- _serverMod = await import(serverBundlePath) as Record<string, unknown>
203
- } catch (err) {
204
- throw new Error(`Failed to load server bundle at ${serverBundlePath}: ${err}`)
205
- }
206
- }
207
-
208
- const handlerFn =
209
- (typeof _serverMod['handler'] === 'function' ? _serverMod['handler'] : null) ??
210
- (typeof (_serverMod['default'] as Record<string, unknown> | undefined)?.['handler'] === 'function'
211
- ? (_serverMod['default'] as Record<string, unknown>)['handler']
212
- : null)
213
-
214
- if (typeof handlerFn !== 'function') {
215
- console.warn(`[cer-app] No handler function found in server bundle for path: ${path}`)
216
- return ''
217
- }
218
-
219
- // Mock req/res for the Express-style handler.
220
- // The handler internally merges with dist/client/index.html, so we just
221
- // capture whatever it writes/ends with.
222
- const mockReq = { url: path, headers: {} }
223
- return new Promise<string>((resolve, reject) => {
224
- const chunks: string[] = []
225
- const mockRes = {
226
- setHeader: () => {},
227
- write: (chunk: string) => { chunks.push(chunk) },
228
- end: (body?: string) => resolve(chunks.join('') + (body ?? '')),
229
- }
230
- ;(handlerFn as (req: unknown, res: unknown) => Promise<void>)(mockReq, mockRes).catch(reject)
231
- })
232
- }
233
-
234
- /**
235
- * Writes the rendered HTML to the output directory.
236
- * path '/' -> dist/index.html
237
- * path '/about' -> dist/about/index.html
238
- * @internal exported for unit testing
239
- */
240
- export async function writeRenderedPath(
241
- path: string,
242
- html: string,
243
- distDir: string,
244
- ): Promise<void> {
245
- let outputPath: string
246
- if (path === '/') {
247
- outputPath = join(distDir, 'index.html')
248
- } else {
249
- // Normalize path and create directory
250
- const cleanPath = path.replace(/^\//, '').replace(/\/$/, '')
251
- outputPath = join(distDir, cleanPath, 'index.html')
252
- }
253
-
254
- await mkdir(join(outputPath, '..'), { recursive: true })
255
- await writeFile(outputPath, html, 'utf-8')
256
- }
257
-
258
- /**
259
- * Full SSG build pipeline:
260
- * 1. Run the SSR dual-build (client + server bundles)
261
- * 2. Enumerate all paths to generate
262
- * 3. Render each path using the server bundle
263
- * 4. Write HTML files to dist/
264
- * 5. Write ssg-manifest.json
265
- */
266
- export async function buildSSG(
267
- config: ResolvedCerConfig,
268
- viteUserConfig: UserConfig = {},
269
- ): Promise<void> {
270
- const distDir = join(config.root, 'dist')
271
- const serverDistDir = join(distDir, 'server')
272
- const serverBundlePath = join(serverDistDir, 'server.js')
273
-
274
- console.log('[cer-app] Starting SSG build...')
275
-
276
- // Step 1: Run the SSR build to produce client + server bundles
277
- await buildSSR(config, viteUserConfig)
278
-
279
- // Step 2: Collect paths to generate
280
- console.log('[cer-app] Collecting SSG paths...')
281
- const paths = await collectSsgPaths(config, viteUserConfig)
282
- console.log(`[cer-app] Found ${paths.length} path(s) to generate:`, paths)
283
-
284
- // Step 3+4: Render and write paths with bounded concurrency.
285
- // The server bundle uses per-request router instances (initRouter returns the
286
- // router; the factory passes it to createStreamingSSRHandler as { vnode, router })
287
- // so concurrent renders are safe — each request carries its own router with its
288
- // own URL state and never reads from the shared activeRouterProxy singleton.
289
- const concurrency = config.ssg?.concurrency ?? 4
290
- console.log(`[cer-app] Rendering ${paths.length} path(s) with concurrency ${concurrency}...`)
291
-
292
- const generatedPaths: string[] = []
293
- const errors: Array<{ path: string; error: string }> = []
294
-
295
- // Process paths in chunks of `concurrency` so we don't overwhelm the process
296
- // with hundreds of simultaneous renders on very large sites.
297
- for (let i = 0; i < paths.length; i += concurrency) {
298
- const chunk = paths.slice(i, i + concurrency)
299
- const results = await Promise.allSettled(
300
- chunk.map(async (path) => {
301
- console.log(`[cer-app] Generating: ${path}`)
302
- const html = await renderPath(path, serverBundlePath)
303
- await writeRenderedPath(path, html, distDir)
304
- return path
305
- }),
306
- )
307
- for (let j = 0; j < results.length; j++) {
308
- const result = results[j]
309
- if (result.status === 'fulfilled') {
310
- generatedPaths.push(result.value)
311
- } else {
312
- const errorMsg = String(result.reason)
313
- console.error(`[cer-app] Failed to generate ${chunk[j]}: ${errorMsg}`)
314
- errors.push({ path: chunk[j], error: errorMsg })
315
- }
316
- }
317
- }
318
-
319
- // Step 5: Write SSG manifest
320
- const manifest: SsgManifest = {
321
- generatedAt: new Date().toISOString(),
322
- paths: generatedPaths,
323
- errors,
324
- }
325
-
326
- const manifestPath = join(distDir, 'ssg-manifest.json')
327
- await mkdir(distDir, { recursive: true })
328
- await writeFile(manifestPath, JSON.stringify(manifest, null, 2), 'utf-8')
329
-
330
- console.log(`[cer-app] SSG build complete.`)
331
- console.log(` Generated ${generatedPaths.length} page(s).`)
332
- if (errors.length > 0) {
333
- console.warn(` ${errors.length} error(s) — see ${manifestPath} for details.`)
334
- }
335
- console.log(` Manifest: ${manifestPath}`)
336
- }
@@ -1,134 +0,0 @@
1
- import { build, type UserConfig } from 'vite'
2
- import { join, resolve } from 'pathe'
3
- import { existsSync, renameSync } from 'node:fs'
4
- import type { ResolvedCerConfig } from './dev-server.js'
5
- import { getGeneratedDir, writeGeneratedDir } from './generated-dir.js'
6
- import { ENTRY_SERVER_TEMPLATE } from '../runtime/entry-server-template.js'
7
-
8
- /**
9
- * Resolves the client build entry point for an SSR/SSG build.
10
- *
11
- * Priority order:
12
- * 1. `index.html` at the project root — consumer-provided HTML shell.
13
- * 2. `.cer/index.html` — auto-generated HTML shell (Nuxt-style magic).
14
- * 3. `app/entry-client.ts` — fallback for projects that manage HTML externally.
15
- * 4. `app/app.ts` — last resort (same bundle, no DSD hydration preamble).
16
- */
17
- export function resolveClientEntry(config: ResolvedCerConfig): string {
18
- const indexHtml = resolve(config.root, 'index.html')
19
- if (existsSync(indexHtml)) return indexHtml
20
- const cerIndexHtml = join(getGeneratedDir(config.root), 'index.html')
21
- if (existsSync(cerIndexHtml)) return cerIndexHtml
22
- const entryClient = resolve(config.srcDir, 'entry-client.ts')
23
- if (existsSync(entryClient)) return entryClient
24
- return resolve(config.srcDir, 'app.ts')
25
- }
26
-
27
- function generateServerEntryCode(): string {
28
- return ENTRY_SERVER_TEMPLATE
29
- }
30
-
31
- /**
32
- * Runs the dual (client + server) SSR build using Vite's programmatic API.
33
- *
34
- * 1. Client bundle: normal Vite build (outputs to dist/client)
35
- * 2. Server bundle: SSR build (outputs to dist/server), uses a generated entry
36
- */
37
- export async function buildSSR(
38
- config: ResolvedCerConfig,
39
- viteUserConfig: UserConfig = {},
40
- ): Promise<void> {
41
- const clientOutDir = join(config.root, 'dist/client')
42
- const serverOutDir = join(config.root, 'dist/server')
43
-
44
- // Write .cer/ generated files BEFORE resolving the client entry so that
45
- // .cer/index.html is on disk when resolveClientEntry checks for it.
46
- writeGeneratedDir(config)
47
-
48
- // Resolve the client entry — index.html is preferred so Vite writes a
49
- // processed index.html to dist/client/ for use as the SSG shell template.
50
- const clientEntry = resolveClientEntry(config)
51
-
52
- // Build the client bundle
53
- console.log('[cer-app] Building client bundle...')
54
- await build({
55
- ...viteUserConfig,
56
- root: config.root,
57
- build: {
58
- ...viteUserConfig.build,
59
- outDir: clientOutDir,
60
- ssrManifest: true,
61
- rollupOptions: {
62
- input: clientEntry,
63
- },
64
- },
65
- })
66
-
67
- // If the client entry was .cer/index.html, Vite outputs it as
68
- // dist/client/.cer/index.html (preserving relative path). The SSR server
69
- // template expects dist/client/index.html, so rename it into place.
70
- const generatedHtmlOut = join(clientOutDir, '.cer/index.html')
71
- const rootHtmlOut = join(clientOutDir, 'index.html')
72
- if (existsSync(generatedHtmlOut) && !existsSync(rootHtmlOut)) {
73
- renameSync(generatedHtmlOut, rootHtmlOut)
74
- }
75
-
76
- // Generate server entry source inline via a virtual plugin
77
- const serverEntryCode = generateServerEntryCode()
78
- const VIRTUAL_SERVER_ENTRY = 'virtual:cer-server-entry'
79
- const RESOLVED_SERVER_ENTRY = '\0virtual:cer-server-entry'
80
-
81
- // Build the server (SSR) bundle
82
- console.log('[cer-app] Building server bundle...')
83
- await build({
84
- ...viteUserConfig,
85
- root: config.root,
86
- plugins: [
87
- ...(viteUserConfig.plugins ?? []),
88
- {
89
- name: 'vite-plugin-cer-server-entry',
90
- enforce: 'pre' as const,
91
- resolveId(id: string) {
92
- if (id === VIRTUAL_SERVER_ENTRY) return RESOLVED_SERVER_ENTRY
93
- },
94
- load(id: string) {
95
- if (id === RESOLVED_SERVER_ENTRY) return serverEntryCode
96
- },
97
- },
98
- ],
99
- build: {
100
- ...viteUserConfig.build,
101
- outDir: serverOutDir,
102
- ssr: true,
103
- rollupOptions: {
104
- input: VIRTUAL_SERVER_ENTRY,
105
- output: {
106
- entryFileNames: 'server.js',
107
- },
108
- },
109
- },
110
- ssr: {
111
- // Keep vite-plugin-cer-app inlined so its virtual-module composables
112
- // (useRoute, useState, useFetch, etc.) are available in the server bundle.
113
- //
114
- // Do NOT add @jasonshimmy/custom-elements-runtime here. Inlining it
115
- // creates a second, isolated copy of the component registry (the module-
116
- // level Map in namespace-helpers). Third-party CER component libraries
117
- // (e.g. @jasonshimmy/cer-material) are external and resolve the runtime
118
- // from node_modules at runtime, giving them a *different* Map instance.
119
- // That means components registered by plugins never appear in the
120
- // renderer's registry → renderToStreamWithJITCSSDSD emits bare stubs
121
- // with no DSD → FOUC when the browser upgrades those elements.
122
- //
123
- // By keeping the runtime external both the server bundle and all
124
- // third-party plugins resolve it from node_modules at runtime, sharing
125
- // one Map and one registry, so DSD is generated for all registered
126
- // components regardless of which package called component().
127
- noExternal: ['@jasonshimmy/vite-plugin-cer-app'],
128
- },
129
- })
130
-
131
- console.log('[cer-app] SSR build complete.')
132
- console.log(` Client: ${clientOutDir}`)
133
- console.log(` Server: ${serverOutDir}`)
134
- }
@@ -1,50 +0,0 @@
1
- import { writeFileSync, mkdirSync } from 'node:fs'
2
- import { join, dirname } from 'pathe'
3
- import type { ContentItem, ContentMeta } from '../../types/content.js'
4
- import { toContentMeta } from './parser.js'
5
-
6
- /**
7
- * Converts a `_path` to the relative file path under `_content/`.
8
- *
9
- * Special case: `_path === '/'` writes to `_content/index.json` rather than
10
- * `_content/.json` (which would be invalid on most filesystems and confusing).
11
- */
12
- export function contentPathToFile(path: string): string {
13
- if (path === '/') return 'index.json'
14
- // Remove leading slash, append .json
15
- return path.slice(1) + '.json'
16
- }
17
-
18
- /**
19
- * Writes all content output files to `<outDir>/_content/`:
20
- *
21
- * - `manifest.json` — `ContentMeta[]` (no body, no toc, no excerpt)
22
- * - `search-index.json` — serialised MiniSearch index string
23
- * - `[path].json` — full `ContentItem` per document
24
- *
25
- * `router.base` is NOT prepended here — that is a client-side fetch concern.
26
- */
27
- export function emitContentFiles(
28
- items: ContentItem[],
29
- outDir: string,
30
- searchIndexJson: string,
31
- ): void {
32
- const contentDir = join(outDir, '_content')
33
- mkdirSync(contentDir, { recursive: true })
34
-
35
- // manifest.json — lean metadata only
36
- const manifest: ContentMeta[] = items.map(toContentMeta)
37
- writeFileSync(join(contentDir, 'manifest.json'), JSON.stringify(manifest), 'utf-8')
38
-
39
- // search-index.json
40
- writeFileSync(join(contentDir, 'search-index.json'), searchIndexJson, 'utf-8')
41
-
42
- // Per-document full JSON files
43
- for (const item of items) {
44
- const relFile = contentPathToFile(item._path)
45
- const absFile = join(contentDir, relFile)
46
- // Ensure subdirectory exists (e.g. _content/blog/ for _path: /blog/hello)
47
- mkdirSync(dirname(absFile), { recursive: true })
48
- writeFileSync(absFile, JSON.stringify(item), 'utf-8')
49
- }
50
- }