emdash 0.0.0-b → 0.0.2

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 (661) hide show
  1. package/README.md +87 -43
  2. package/dist/adapters-BLMa4JGD.d.mts +106 -0
  3. package/dist/adapters-BLMa4JGD.d.mts.map +1 -0
  4. package/dist/apply-Bjfq_b4-.mjs +1293 -0
  5. package/dist/apply-Bjfq_b4-.mjs.map +1 -0
  6. package/dist/astro/index.d.mts +51 -0
  7. package/dist/astro/index.d.mts.map +1 -0
  8. package/dist/astro/index.mjs +1336 -0
  9. package/dist/astro/index.mjs.map +1 -0
  10. package/dist/astro/middleware/auth.d.mts +31 -0
  11. package/dist/astro/middleware/auth.d.mts.map +1 -0
  12. package/dist/astro/middleware/auth.mjs +654 -0
  13. package/dist/astro/middleware/auth.mjs.map +1 -0
  14. package/dist/astro/middleware/redirect.d.mts +22 -0
  15. package/dist/astro/middleware/redirect.d.mts.map +1 -0
  16. package/dist/astro/middleware/redirect.mjs +63 -0
  17. package/dist/astro/middleware/redirect.mjs.map +1 -0
  18. package/dist/astro/middleware/request-context.d.mts +18 -0
  19. package/dist/astro/middleware/request-context.d.mts.map +1 -0
  20. package/dist/astro/middleware/request-context.mjs +1310 -0
  21. package/dist/astro/middleware/request-context.mjs.map +1 -0
  22. package/dist/astro/middleware/setup.d.mts +20 -0
  23. package/dist/astro/middleware/setup.d.mts.map +1 -0
  24. package/dist/astro/middleware/setup.mjs +47 -0
  25. package/dist/astro/middleware/setup.mjs.map +1 -0
  26. package/dist/astro/middleware.d.mts +13 -0
  27. package/dist/astro/middleware.d.mts.map +1 -0
  28. package/dist/astro/middleware.mjs +1613 -0
  29. package/dist/astro/middleware.mjs.map +1 -0
  30. package/dist/astro/types.d.mts +250 -0
  31. package/dist/astro/types.d.mts.map +1 -0
  32. package/dist/astro/types.mjs +1 -0
  33. package/dist/base64-MBPo9ozB.mjs +59 -0
  34. package/dist/base64-MBPo9ozB.mjs.map +1 -0
  35. package/dist/byline-CL847F26.mjs +213 -0
  36. package/dist/byline-CL847F26.mjs.map +1 -0
  37. package/dist/bylines-C2a-2TGt.mjs +136 -0
  38. package/dist/bylines-C2a-2TGt.mjs.map +1 -0
  39. package/dist/chunk-ClPoSABd.mjs +21 -0
  40. package/dist/cli/index.d.mts +1 -0
  41. package/dist/cli/index.mjs +3909 -0
  42. package/dist/cli/index.mjs.map +1 -0
  43. package/dist/client/cf-access.d.mts +60 -0
  44. package/dist/client/cf-access.d.mts.map +1 -0
  45. package/dist/client/cf-access.mjs +179 -0
  46. package/dist/client/cf-access.mjs.map +1 -0
  47. package/dist/client/index.d.mts +398 -0
  48. package/dist/client/index.d.mts.map +1 -0
  49. package/dist/client/index.mjs +346 -0
  50. package/dist/client/index.mjs.map +1 -0
  51. package/dist/config-CKE8p9xM.mjs +55 -0
  52. package/dist/config-CKE8p9xM.mjs.map +1 -0
  53. package/dist/connection-B4zVnQIa.mjs +40 -0
  54. package/dist/connection-B4zVnQIa.mjs.map +1 -0
  55. package/dist/content-D6C2WsZC.mjs +824 -0
  56. package/dist/content-D6C2WsZC.mjs.map +1 -0
  57. package/dist/db/index.d.mts +4 -0
  58. package/dist/db/index.mjs +62 -0
  59. package/dist/db/index.mjs.map +1 -0
  60. package/dist/db/libsql.d.mts +11 -0
  61. package/dist/db/libsql.d.mts.map +1 -0
  62. package/dist/db/libsql.mjs +17 -0
  63. package/dist/db/libsql.mjs.map +1 -0
  64. package/dist/db/postgres.d.mts +11 -0
  65. package/dist/db/postgres.d.mts.map +1 -0
  66. package/dist/db/postgres.mjs +30 -0
  67. package/dist/db/postgres.mjs.map +1 -0
  68. package/dist/db/sqlite.d.mts +11 -0
  69. package/dist/db/sqlite.d.mts.map +1 -0
  70. package/dist/db/sqlite.mjs +16 -0
  71. package/dist/db/sqlite.mjs.map +1 -0
  72. package/dist/default-Cyi4aAxu.mjs +81 -0
  73. package/dist/default-Cyi4aAxu.mjs.map +1 -0
  74. package/dist/dialect-helpers-B9uSp2GJ.mjs +90 -0
  75. package/dist/dialect-helpers-B9uSp2GJ.mjs.map +1 -0
  76. package/dist/error-Cxz0tQeO.mjs +27 -0
  77. package/dist/error-Cxz0tQeO.mjs.map +1 -0
  78. package/dist/index-C1xF3OGh.d.mts +4527 -0
  79. package/dist/index-C1xF3OGh.d.mts.map +1 -0
  80. package/dist/index.d.mts +16 -0
  81. package/dist/index.mjs +30 -0
  82. package/dist/load-yOOlckBj.mjs +28 -0
  83. package/dist/load-yOOlckBj.mjs.map +1 -0
  84. package/dist/loader-fz8Q_3EO.mjs +447 -0
  85. package/dist/loader-fz8Q_3EO.mjs.map +1 -0
  86. package/dist/manifest-schema-Dcl0R6nM.mjs +184 -0
  87. package/dist/manifest-schema-Dcl0R6nM.mjs.map +1 -0
  88. package/dist/media/index.d.mts +26 -0
  89. package/dist/media/index.d.mts.map +1 -0
  90. package/dist/media/index.mjs +55 -0
  91. package/dist/media/index.mjs.map +1 -0
  92. package/dist/media/local-runtime.d.mts +39 -0
  93. package/dist/media/local-runtime.d.mts.map +1 -0
  94. package/dist/media/local-runtime.mjs +133 -0
  95. package/dist/media/local-runtime.mjs.map +1 -0
  96. package/dist/media-DqHVh136.mjs +200 -0
  97. package/dist/media-DqHVh136.mjs.map +1 -0
  98. package/dist/mode-C2EzN1uE.mjs +23 -0
  99. package/dist/mode-C2EzN1uE.mjs.map +1 -0
  100. package/dist/page/index.d.mts +140 -0
  101. package/dist/page/index.d.mts.map +1 -0
  102. package/dist/page/index.mjs +416 -0
  103. package/dist/page/index.mjs.map +1 -0
  104. package/dist/placeholder-CmGAmqeO.d.mts +276 -0
  105. package/dist/placeholder-CmGAmqeO.d.mts.map +1 -0
  106. package/dist/placeholder-SmpOx-_v.mjs +243 -0
  107. package/dist/placeholder-SmpOx-_v.mjs.map +1 -0
  108. package/dist/plugin-utils.d.mts +58 -0
  109. package/dist/plugin-utils.d.mts.map +1 -0
  110. package/dist/plugin-utils.mjs +78 -0
  111. package/dist/plugin-utils.mjs.map +1 -0
  112. package/dist/plugins/adapt-sandbox-entry.d.mts +22 -0
  113. package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -0
  114. package/dist/plugins/adapt-sandbox-entry.mjs +113 -0
  115. package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -0
  116. package/dist/query-CS_iSj34.mjs +460 -0
  117. package/dist/query-CS_iSj34.mjs.map +1 -0
  118. package/dist/redirect-DIfIni3r.mjs +329 -0
  119. package/dist/redirect-DIfIni3r.mjs.map +1 -0
  120. package/dist/registry-D_w5HW4G.mjs +863 -0
  121. package/dist/registry-D_w5HW4G.mjs.map +1 -0
  122. package/dist/request-context.d.mts +49 -0
  123. package/dist/request-context.d.mts.map +1 -0
  124. package/dist/request-context.mjs +43 -0
  125. package/dist/request-context.mjs.map +1 -0
  126. package/dist/runner-C0hCbYnD.mjs +1412 -0
  127. package/dist/runner-C0hCbYnD.mjs.map +1 -0
  128. package/dist/runner-EAtf0ZIe.d.mts +27 -0
  129. package/dist/runner-EAtf0ZIe.d.mts.map +1 -0
  130. package/dist/runtime.d.mts +26 -0
  131. package/dist/runtime.d.mts.map +1 -0
  132. package/dist/runtime.mjs +42 -0
  133. package/dist/runtime.mjs.map +1 -0
  134. package/dist/search-DG603UrT.mjs +9211 -0
  135. package/dist/search-DG603UrT.mjs.map +1 -0
  136. package/dist/seed/index.d.mts +3 -0
  137. package/dist/seed/index.mjs +15 -0
  138. package/dist/seo/index.d.mts +70 -0
  139. package/dist/seo/index.d.mts.map +1 -0
  140. package/dist/seo/index.mjs +70 -0
  141. package/dist/seo/index.mjs.map +1 -0
  142. package/dist/storage/local.d.mts +39 -0
  143. package/dist/storage/local.d.mts.map +1 -0
  144. package/dist/storage/local.mjs +166 -0
  145. package/dist/storage/local.mjs.map +1 -0
  146. package/dist/storage/s3.d.mts +32 -0
  147. package/dist/storage/s3.d.mts.map +1 -0
  148. package/dist/storage/s3.mjs +175 -0
  149. package/dist/storage/s3.mjs.map +1 -0
  150. package/dist/tokens-DpgrkrXK.mjs +171 -0
  151. package/dist/tokens-DpgrkrXK.mjs.map +1 -0
  152. package/dist/transport-BFGblqwG.d.mts +42 -0
  153. package/dist/transport-BFGblqwG.d.mts.map +1 -0
  154. package/dist/transport-yxiQsi8I.mjs +418 -0
  155. package/dist/transport-yxiQsi8I.mjs.map +1 -0
  156. package/dist/types-BRuPJGdV.d.mts +102 -0
  157. package/dist/types-BRuPJGdV.d.mts.map +1 -0
  158. package/dist/types-C4-fAxN3.d.mts +182 -0
  159. package/dist/types-C4-fAxN3.d.mts.map +1 -0
  160. package/dist/types-CMMN0pNg.mjs +31 -0
  161. package/dist/types-CMMN0pNg.mjs.map +1 -0
  162. package/dist/types-CUBbjgmP.mjs +16 -0
  163. package/dist/types-CUBbjgmP.mjs.map +1 -0
  164. package/dist/types-DRjfYOEv.d.mts +426 -0
  165. package/dist/types-DRjfYOEv.d.mts.map +1 -0
  166. package/dist/types-DY5zk5HN.mjs +73 -0
  167. package/dist/types-DY5zk5HN.mjs.map +1 -0
  168. package/dist/types-DaNLHo_T.d.mts +184 -0
  169. package/dist/types-DaNLHo_T.d.mts.map +1 -0
  170. package/dist/types-DvhsUmSJ.d.mts +1111 -0
  171. package/dist/types-DvhsUmSJ.d.mts.map +1 -0
  172. package/dist/validate-CpBtVMsD.d.mts +378 -0
  173. package/dist/validate-CpBtVMsD.d.mts.map +1 -0
  174. package/dist/validate-CqRJb_xU.mjs +97 -0
  175. package/dist/validate-CqRJb_xU.mjs.map +1 -0
  176. package/dist/validate-O7PWmlnq.mjs +328 -0
  177. package/dist/validate-O7PWmlnq.mjs.map +1 -0
  178. package/locals.d.ts +46 -0
  179. package/package.json +233 -19
  180. package/src/api/authorize.ts +63 -0
  181. package/src/api/csrf.ts +48 -0
  182. package/src/api/error.ts +99 -0
  183. package/src/api/errors.ts +445 -0
  184. package/src/api/escape.ts +9 -0
  185. package/src/api/handlers/api-tokens.ts +240 -0
  186. package/src/api/handlers/comments.ts +314 -0
  187. package/src/api/handlers/content.ts +1315 -0
  188. package/src/api/handlers/dashboard.ts +205 -0
  189. package/src/api/handlers/device-flow.ts +684 -0
  190. package/src/api/handlers/index.ts +163 -0
  191. package/src/api/handlers/manifest.ts +158 -0
  192. package/src/api/handlers/marketplace.ts +930 -0
  193. package/src/api/handlers/media.ts +207 -0
  194. package/src/api/handlers/menus.ts +493 -0
  195. package/src/api/handlers/oauth-authorization.ts +429 -0
  196. package/src/api/handlers/oauth-clients.ts +349 -0
  197. package/src/api/handlers/oauth-user-lookup.ts +39 -0
  198. package/src/api/handlers/plugins.ts +254 -0
  199. package/src/api/handlers/redirects.ts +360 -0
  200. package/src/api/handlers/revision.ts +145 -0
  201. package/src/api/handlers/schema.ts +534 -0
  202. package/src/api/handlers/sections.ts +289 -0
  203. package/src/api/handlers/seo.ts +115 -0
  204. package/src/api/handlers/settings.ts +49 -0
  205. package/src/api/handlers/snapshot.ts +350 -0
  206. package/src/api/handlers/taxonomies.ts +523 -0
  207. package/src/api/index.ts +6 -0
  208. package/src/api/openapi/document.ts +2368 -0
  209. package/src/api/openapi/index.ts +1 -0
  210. package/src/api/parse.ts +139 -0
  211. package/src/api/redirect.ts +14 -0
  212. package/src/api/rev.ts +67 -0
  213. package/src/api/schemas/auth.ts +112 -0
  214. package/src/api/schemas/bylines.ts +85 -0
  215. package/src/api/schemas/comments.ts +117 -0
  216. package/src/api/schemas/common.ts +89 -0
  217. package/src/api/schemas/content.ts +191 -0
  218. package/src/api/schemas/import.ts +52 -0
  219. package/src/api/schemas/index.ts +17 -0
  220. package/src/api/schemas/media.ts +116 -0
  221. package/src/api/schemas/menus.ts +111 -0
  222. package/src/api/schemas/redirects.ts +155 -0
  223. package/src/api/schemas/schema.ts +203 -0
  224. package/src/api/schemas/search.ts +63 -0
  225. package/src/api/schemas/sections.ts +67 -0
  226. package/src/api/schemas/settings.ts +63 -0
  227. package/src/api/schemas/setup.ts +37 -0
  228. package/src/api/schemas/taxonomies.ts +113 -0
  229. package/src/api/schemas/users.ts +96 -0
  230. package/src/api/schemas/widgets.ts +80 -0
  231. package/src/api/site-url.ts +25 -0
  232. package/src/api/types.ts +82 -0
  233. package/src/astro/index.ts +27 -0
  234. package/src/astro/integration/index.ts +303 -0
  235. package/src/astro/integration/routes.ts +834 -0
  236. package/src/astro/integration/runtime.ts +338 -0
  237. package/src/astro/integration/virtual-modules.ts +469 -0
  238. package/src/astro/integration/vite-config.ts +335 -0
  239. package/src/astro/middleware/auth.ts +743 -0
  240. package/src/astro/middleware/redirect.ts +89 -0
  241. package/src/astro/middleware/request-context.ts +129 -0
  242. package/src/astro/middleware/setup.ts +89 -0
  243. package/src/astro/middleware.ts +398 -0
  244. package/src/astro/routes/PluginRegistry.tsx +15 -0
  245. package/src/astro/routes/admin.astro +81 -0
  246. package/src/astro/routes/api/admin/allowed-domains/[domain].ts +112 -0
  247. package/src/astro/routes/api/admin/allowed-domains/index.ts +108 -0
  248. package/src/astro/routes/api/admin/api-tokens/[id].ts +40 -0
  249. package/src/astro/routes/api/admin/api-tokens/index.ts +68 -0
  250. package/src/astro/routes/api/admin/bylines/[id]/index.ts +87 -0
  251. package/src/astro/routes/api/admin/bylines/index.ts +72 -0
  252. package/src/astro/routes/api/admin/comments/[id]/status.ts +116 -0
  253. package/src/astro/routes/api/admin/comments/[id].ts +64 -0
  254. package/src/astro/routes/api/admin/comments/bulk.ts +42 -0
  255. package/src/astro/routes/api/admin/comments/counts.ts +30 -0
  256. package/src/astro/routes/api/admin/comments/index.ts +46 -0
  257. package/src/astro/routes/api/admin/hooks/exclusive/[hookName].ts +91 -0
  258. package/src/astro/routes/api/admin/hooks/exclusive/index.ts +51 -0
  259. package/src/astro/routes/api/admin/oauth-clients/[id].ts +110 -0
  260. package/src/astro/routes/api/admin/oauth-clients/index.ts +71 -0
  261. package/src/astro/routes/api/admin/plugins/[id]/disable.ts +39 -0
  262. package/src/astro/routes/api/admin/plugins/[id]/enable.ts +39 -0
  263. package/src/astro/routes/api/admin/plugins/[id]/index.ts +38 -0
  264. package/src/astro/routes/api/admin/plugins/[id]/uninstall.ts +48 -0
  265. package/src/astro/routes/api/admin/plugins/[id]/update.ts +59 -0
  266. package/src/astro/routes/api/admin/plugins/index.ts +32 -0
  267. package/src/astro/routes/api/admin/plugins/marketplace/[id]/icon.ts +61 -0
  268. package/src/astro/routes/api/admin/plugins/marketplace/[id]/index.ts +33 -0
  269. package/src/astro/routes/api/admin/plugins/marketplace/[id]/install.ts +62 -0
  270. package/src/astro/routes/api/admin/plugins/marketplace/index.ts +38 -0
  271. package/src/astro/routes/api/admin/plugins/updates.ts +28 -0
  272. package/src/astro/routes/api/admin/themes/marketplace/[id]/index.ts +33 -0
  273. package/src/astro/routes/api/admin/themes/marketplace/[id]/thumbnail.ts +61 -0
  274. package/src/astro/routes/api/admin/themes/marketplace/index.ts +45 -0
  275. package/src/astro/routes/api/admin/users/[id]/disable.ts +69 -0
  276. package/src/astro/routes/api/admin/users/[id]/enable.ts +48 -0
  277. package/src/astro/routes/api/admin/users/[id]/index.ts +146 -0
  278. package/src/astro/routes/api/admin/users/[id]/send-recovery.ts +72 -0
  279. package/src/astro/routes/api/admin/users/index.ts +66 -0
  280. package/src/astro/routes/api/auth/dev-bypass.ts +139 -0
  281. package/src/astro/routes/api/auth/invite/accept.ts +52 -0
  282. package/src/astro/routes/api/auth/invite/complete.ts +84 -0
  283. package/src/astro/routes/api/auth/invite/index.ts +99 -0
  284. package/src/astro/routes/api/auth/logout.ts +40 -0
  285. package/src/astro/routes/api/auth/magic-link/send.ts +89 -0
  286. package/src/astro/routes/api/auth/magic-link/verify.ts +71 -0
  287. package/src/astro/routes/api/auth/me.ts +60 -0
  288. package/src/astro/routes/api/auth/oauth/[provider]/callback.ts +219 -0
  289. package/src/astro/routes/api/auth/oauth/[provider].ts +119 -0
  290. package/src/astro/routes/api/auth/passkey/[id].ts +124 -0
  291. package/src/astro/routes/api/auth/passkey/index.ts +54 -0
  292. package/src/astro/routes/api/auth/passkey/options.ts +82 -0
  293. package/src/astro/routes/api/auth/passkey/register/options.ts +86 -0
  294. package/src/astro/routes/api/auth/passkey/register/verify.ts +115 -0
  295. package/src/astro/routes/api/auth/passkey/verify.ts +66 -0
  296. package/src/astro/routes/api/auth/signup/complete.ts +85 -0
  297. package/src/astro/routes/api/auth/signup/request.ts +77 -0
  298. package/src/astro/routes/api/auth/signup/verify.ts +53 -0
  299. package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +312 -0
  300. package/src/astro/routes/api/content/[collection]/[id]/compare.ts +28 -0
  301. package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +54 -0
  302. package/src/astro/routes/api/content/[collection]/[id]/duplicate.ts +61 -0
  303. package/src/astro/routes/api/content/[collection]/[id]/permanent.ts +33 -0
  304. package/src/astro/routes/api/content/[collection]/[id]/preview-url.ts +107 -0
  305. package/src/astro/routes/api/content/[collection]/[id]/publish.ts +56 -0
  306. package/src/astro/routes/api/content/[collection]/[id]/restore.ts +54 -0
  307. package/src/astro/routes/api/content/[collection]/[id]/revisions.ts +31 -0
  308. package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +101 -0
  309. package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +140 -0
  310. package/src/astro/routes/api/content/[collection]/[id]/translations.ts +30 -0
  311. package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +56 -0
  312. package/src/astro/routes/api/content/[collection]/[id].ts +137 -0
  313. package/src/astro/routes/api/content/[collection]/index.ts +59 -0
  314. package/src/astro/routes/api/content/[collection]/trash.ts +33 -0
  315. package/src/astro/routes/api/dashboard.ts +32 -0
  316. package/src/astro/routes/api/dev/emails.ts +36 -0
  317. package/src/astro/routes/api/import/probe.ts +47 -0
  318. package/src/astro/routes/api/import/wordpress/analyze.ts +510 -0
  319. package/src/astro/routes/api/import/wordpress/execute.ts +283 -0
  320. package/src/astro/routes/api/import/wordpress/media.ts +338 -0
  321. package/src/astro/routes/api/import/wordpress/prepare.ts +181 -0
  322. package/src/astro/routes/api/import/wordpress/rewrite-urls.ts +393 -0
  323. package/src/astro/routes/api/import/wordpress-plugin/analyze.ts +111 -0
  324. package/src/astro/routes/api/import/wordpress-plugin/callback.ts +58 -0
  325. package/src/astro/routes/api/import/wordpress-plugin/execute.ts +347 -0
  326. package/src/astro/routes/api/manifest.ts +62 -0
  327. package/src/astro/routes/api/mcp.ts +124 -0
  328. package/src/astro/routes/api/media/[id]/confirm.ts +93 -0
  329. package/src/astro/routes/api/media/[id].ts +145 -0
  330. package/src/astro/routes/api/media/file/[key].ts +79 -0
  331. package/src/astro/routes/api/media/providers/[providerId]/[itemId].ts +86 -0
  332. package/src/astro/routes/api/media/providers/[providerId]/index.ts +111 -0
  333. package/src/astro/routes/api/media/providers/index.ts +30 -0
  334. package/src/astro/routes/api/media/upload-url.ts +137 -0
  335. package/src/astro/routes/api/media.ts +190 -0
  336. package/src/astro/routes/api/menus/[name]/items.ts +87 -0
  337. package/src/astro/routes/api/menus/[name]/reorder.ts +33 -0
  338. package/src/astro/routes/api/menus/[name].ts +65 -0
  339. package/src/astro/routes/api/menus/index.ts +47 -0
  340. package/src/astro/routes/api/oauth/authorize.ts +412 -0
  341. package/src/astro/routes/api/oauth/device/authorize.ts +45 -0
  342. package/src/astro/routes/api/oauth/device/code.ts +51 -0
  343. package/src/astro/routes/api/oauth/device/token.ts +69 -0
  344. package/src/astro/routes/api/oauth/token/refresh.ts +38 -0
  345. package/src/astro/routes/api/oauth/token/revoke.ts +38 -0
  346. package/src/astro/routes/api/oauth/token.ts +184 -0
  347. package/src/astro/routes/api/openapi.json.ts +32 -0
  348. package/src/astro/routes/api/plugins/[pluginId]/[...path].ts +92 -0
  349. package/src/astro/routes/api/redirects/404s/index.ts +72 -0
  350. package/src/astro/routes/api/redirects/404s/summary.ts +33 -0
  351. package/src/astro/routes/api/redirects/[id].ts +84 -0
  352. package/src/astro/routes/api/redirects/index.ts +52 -0
  353. package/src/astro/routes/api/revisions/[revisionId]/index.ts +29 -0
  354. package/src/astro/routes/api/revisions/[revisionId]/restore.ts +58 -0
  355. package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +76 -0
  356. package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +52 -0
  357. package/src/astro/routes/api/schema/collections/[slug]/fields/reorder.ts +32 -0
  358. package/src/astro/routes/api/schema/collections/[slug]/index.ts +80 -0
  359. package/src/astro/routes/api/schema/collections/index.ts +47 -0
  360. package/src/astro/routes/api/schema/index.ts +109 -0
  361. package/src/astro/routes/api/schema/orphans/[slug].ts +36 -0
  362. package/src/astro/routes/api/schema/orphans/index.ts +26 -0
  363. package/src/astro/routes/api/search/enable.ts +64 -0
  364. package/src/astro/routes/api/search/index.ts +55 -0
  365. package/src/astro/routes/api/search/rebuild.ts +72 -0
  366. package/src/astro/routes/api/search/stats.ts +35 -0
  367. package/src/astro/routes/api/search/suggest.ts +53 -0
  368. package/src/astro/routes/api/sections/[slug].ts +84 -0
  369. package/src/astro/routes/api/sections/index.ts +52 -0
  370. package/src/astro/routes/api/settings/email.ts +150 -0
  371. package/src/astro/routes/api/settings.ts +67 -0
  372. package/src/astro/routes/api/setup/admin-verify.ts +100 -0
  373. package/src/astro/routes/api/setup/admin.ts +94 -0
  374. package/src/astro/routes/api/setup/dev-bypass.ts +199 -0
  375. package/src/astro/routes/api/setup/dev-reset.ts +40 -0
  376. package/src/astro/routes/api/setup/index.ts +126 -0
  377. package/src/astro/routes/api/setup/status.ts +122 -0
  378. package/src/astro/routes/api/snapshot.ts +75 -0
  379. package/src/astro/routes/api/taxonomies/[name]/terms/[slug].ts +95 -0
  380. package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +69 -0
  381. package/src/astro/routes/api/taxonomies/index.ts +59 -0
  382. package/src/astro/routes/api/themes/preview.ts +77 -0
  383. package/src/astro/routes/api/typegen.ts +114 -0
  384. package/src/astro/routes/api/well-known/auth.ts +68 -0
  385. package/src/astro/routes/api/well-known/oauth-authorization-server.ts +44 -0
  386. package/src/astro/routes/api/well-known/oauth-protected-resource.ts +37 -0
  387. package/src/astro/routes/api/widget-areas/[name]/reorder.ts +68 -0
  388. package/src/astro/routes/api/widget-areas/[name]/widgets/[id].ts +127 -0
  389. package/src/astro/routes/api/widget-areas/[name]/widgets.ts +80 -0
  390. package/src/astro/routes/api/widget-areas/[name].ts +87 -0
  391. package/src/astro/routes/api/widget-areas/index.ts +99 -0
  392. package/src/astro/routes/api/widget-components.ts +22 -0
  393. package/src/astro/routes/robots.txt.ts +77 -0
  394. package/src/astro/routes/sitemap.xml.ts +97 -0
  395. package/src/astro/storage/adapters.ts +74 -0
  396. package/src/astro/storage/index.ts +19 -0
  397. package/src/astro/storage/types.ts +60 -0
  398. package/src/astro/types.ts +346 -0
  399. package/src/auth/api-tokens.ts +25 -0
  400. package/src/auth/challenge-store.ts +80 -0
  401. package/src/auth/mode.ts +96 -0
  402. package/src/auth/oauth-state-store.ts +96 -0
  403. package/src/auth/passkey-config.ts +27 -0
  404. package/src/auth/rate-limit.ts +158 -0
  405. package/src/auth/scopes.ts +33 -0
  406. package/src/auth/types.ts +104 -0
  407. package/src/aws-sdk.d.ts +100 -0
  408. package/src/bylines/index.ts +237 -0
  409. package/src/cleanup.ts +153 -0
  410. package/src/cli/client-factory.ts +100 -0
  411. package/src/cli/commands/auth.ts +46 -0
  412. package/src/cli/commands/bundle-utils.ts +247 -0
  413. package/src/cli/commands/bundle.ts +609 -0
  414. package/src/cli/commands/content.ts +442 -0
  415. package/src/cli/commands/dev.ts +191 -0
  416. package/src/cli/commands/doctor.ts +211 -0
  417. package/src/cli/commands/export-seed.ts +630 -0
  418. package/src/cli/commands/import/wordpress.ts +1056 -0
  419. package/src/cli/commands/init.ts +192 -0
  420. package/src/cli/commands/login.ts +547 -0
  421. package/src/cli/commands/media.ts +165 -0
  422. package/src/cli/commands/menu.ts +67 -0
  423. package/src/cli/commands/plugin-init.ts +291 -0
  424. package/src/cli/commands/plugin-validate.ts +31 -0
  425. package/src/cli/commands/plugin.ts +33 -0
  426. package/src/cli/commands/publish.ts +697 -0
  427. package/src/cli/commands/schema.ts +233 -0
  428. package/src/cli/commands/search-cmd.ts +54 -0
  429. package/src/cli/commands/seed.ts +286 -0
  430. package/src/cli/commands/taxonomy.ts +128 -0
  431. package/src/cli/commands/types.ts +68 -0
  432. package/src/cli/credentials.ts +236 -0
  433. package/src/cli/index.ts +70 -0
  434. package/src/cli/output.ts +75 -0
  435. package/src/cli/wxr/parser.ts +969 -0
  436. package/src/client/cf-access.ts +193 -0
  437. package/src/client/index.ts +854 -0
  438. package/src/client/portable-text.ts +413 -0
  439. package/src/client/transport.ts +200 -0
  440. package/src/comments/moderator.ts +46 -0
  441. package/src/comments/notifications.ts +144 -0
  442. package/src/comments/query.ts +105 -0
  443. package/src/comments/service.ts +213 -0
  444. package/src/components/Break.astro +45 -0
  445. package/src/components/Button.astro +71 -0
  446. package/src/components/Buttons.astro +49 -0
  447. package/src/components/Code.astro +59 -0
  448. package/src/components/Columns.astro +59 -0
  449. package/src/components/CommentForm.astro +315 -0
  450. package/src/components/Comments.astro +232 -0
  451. package/src/components/Cover.astro +128 -0
  452. package/src/components/EmDashBodyEnd.astro +32 -0
  453. package/src/components/EmDashBodyStart.astro +32 -0
  454. package/src/components/EmDashHead.astro +53 -0
  455. package/src/components/EmDashImage.astro +178 -0
  456. package/src/components/EmDashMedia.astro +167 -0
  457. package/src/components/Embed.astro +128 -0
  458. package/src/components/File.astro +122 -0
  459. package/src/components/Gallery.astro +93 -0
  460. package/src/components/HtmlBlock.astro +33 -0
  461. package/src/components/Image.astro +178 -0
  462. package/src/components/InlineEditor.astro +27 -0
  463. package/src/components/InlinePortableTextEditor.tsx +1905 -0
  464. package/src/components/LiveSearch.astro +614 -0
  465. package/src/components/PortableText.astro +51 -0
  466. package/src/components/Pullquote.astro +51 -0
  467. package/src/components/Table.astro +108 -0
  468. package/src/components/WidgetArea.astro +22 -0
  469. package/src/components/WidgetRenderer.astro +72 -0
  470. package/src/components/index.ts +116 -0
  471. package/src/components/marks/Link.astro +31 -0
  472. package/src/components/marks/StrikeThrough.astro +7 -0
  473. package/src/components/marks/Subscript.astro +7 -0
  474. package/src/components/marks/Superscript.astro +7 -0
  475. package/src/components/marks/Underline.astro +7 -0
  476. package/src/components/widgets/Archives.astro +65 -0
  477. package/src/components/widgets/Categories.astro +35 -0
  478. package/src/components/widgets/RecentPosts.astro +51 -0
  479. package/src/components/widgets/Search.astro +18 -0
  480. package/src/components/widgets/Tags.astro +38 -0
  481. package/src/content/converters/index.ts +9 -0
  482. package/src/content/converters/portable-text-to-prosemirror.ts +385 -0
  483. package/src/content/converters/prosemirror-to-portable-text.ts +413 -0
  484. package/src/content/converters/types.ts +120 -0
  485. package/src/content/index.ts +5 -0
  486. package/src/database/connection.ts +67 -0
  487. package/src/database/dialect-helpers.ts +138 -0
  488. package/src/database/index.ts +5 -0
  489. package/src/database/migrations/001_initial.ts +170 -0
  490. package/src/database/migrations/002_media_status.ts +26 -0
  491. package/src/database/migrations/003_schema_registry.ts +79 -0
  492. package/src/database/migrations/004_plugins.ts +62 -0
  493. package/src/database/migrations/005_menus.ts +67 -0
  494. package/src/database/migrations/006_taxonomy_defs.ts +51 -0
  495. package/src/database/migrations/007_widgets.ts +42 -0
  496. package/src/database/migrations/008_auth.ts +194 -0
  497. package/src/database/migrations/009_user_disabled.ts +27 -0
  498. package/src/database/migrations/011_sections.ts +65 -0
  499. package/src/database/migrations/012_search.ts +25 -0
  500. package/src/database/migrations/013_scheduled_publishing.ts +51 -0
  501. package/src/database/migrations/014_draft_revisions.ts +72 -0
  502. package/src/database/migrations/015_indexes.ts +82 -0
  503. package/src/database/migrations/016_api_tokens.ts +89 -0
  504. package/src/database/migrations/017_authorization_codes.ts +45 -0
  505. package/src/database/migrations/018_seo.ts +56 -0
  506. package/src/database/migrations/019_i18n.ts +618 -0
  507. package/src/database/migrations/020_collection_url_pattern.ts +23 -0
  508. package/src/database/migrations/021_remove_section_categories.ts +43 -0
  509. package/src/database/migrations/022_marketplace_plugin_state.ts +46 -0
  510. package/src/database/migrations/023_plugin_metadata.ts +33 -0
  511. package/src/database/migrations/024_media_placeholders.ts +32 -0
  512. package/src/database/migrations/025_oauth_clients.ts +28 -0
  513. package/src/database/migrations/026_cron_tasks.ts +49 -0
  514. package/src/database/migrations/027_comments.ts +87 -0
  515. package/src/database/migrations/028_drop_author_url.ts +9 -0
  516. package/src/database/migrations/029_redirects.ts +67 -0
  517. package/src/database/migrations/030_widen_scheduled_index.ts +48 -0
  518. package/src/database/migrations/031_bylines.ts +90 -0
  519. package/src/database/migrations/032_rate_limits.ts +39 -0
  520. package/src/database/migrations/runner.ts +170 -0
  521. package/src/database/repositories/audit.ts +294 -0
  522. package/src/database/repositories/byline.ts +387 -0
  523. package/src/database/repositories/comment.ts +458 -0
  524. package/src/database/repositories/content.ts +1144 -0
  525. package/src/database/repositories/index.ts +30 -0
  526. package/src/database/repositories/media.ts +347 -0
  527. package/src/database/repositories/options.ts +150 -0
  528. package/src/database/repositories/plugin-storage.ts +373 -0
  529. package/src/database/repositories/redirect.ts +480 -0
  530. package/src/database/repositories/revision.ts +200 -0
  531. package/src/database/repositories/seo.ts +176 -0
  532. package/src/database/repositories/taxonomy.ts +294 -0
  533. package/src/database/repositories/types.ts +132 -0
  534. package/src/database/repositories/user.ts +258 -0
  535. package/src/database/transaction.ts +54 -0
  536. package/src/database/types.ts +501 -0
  537. package/src/database/validate.ts +138 -0
  538. package/src/db/adapters.ts +125 -0
  539. package/src/db/index.ts +37 -0
  540. package/src/db/libsql.ts +23 -0
  541. package/src/db/postgres.ts +30 -0
  542. package/src/db/sqlite.ts +27 -0
  543. package/src/emdash-runtime.ts +2096 -0
  544. package/src/fields/boolean.ts +34 -0
  545. package/src/fields/datetime.ts +44 -0
  546. package/src/fields/file.ts +41 -0
  547. package/src/fields/image.ts +34 -0
  548. package/src/fields/index.ts +42 -0
  549. package/src/fields/integer.ts +50 -0
  550. package/src/fields/json.ts +37 -0
  551. package/src/fields/multiselect.ts +48 -0
  552. package/src/fields/number.ts +52 -0
  553. package/src/fields/portable-text.ts +33 -0
  554. package/src/fields/reference.ts +29 -0
  555. package/src/fields/richtext.ts +31 -0
  556. package/src/fields/select.ts +46 -0
  557. package/src/fields/slug.ts +38 -0
  558. package/src/fields/text.ts +55 -0
  559. package/src/fields/textarea.ts +52 -0
  560. package/src/fields/types.ts +64 -0
  561. package/src/i18n/config.ts +68 -0
  562. package/src/import/index.ts +90 -0
  563. package/src/import/menus.ts +436 -0
  564. package/src/import/registry.ts +111 -0
  565. package/src/import/sections.ts +103 -0
  566. package/src/import/settings.ts +281 -0
  567. package/src/import/sources/wordpress-plugin.ts +641 -0
  568. package/src/import/sources/wordpress-rest.ts +191 -0
  569. package/src/import/sources/wxr.ts +330 -0
  570. package/src/import/ssrf.ts +260 -0
  571. package/src/import/types.ts +418 -0
  572. package/src/import/utils.ts +412 -0
  573. package/src/index.ts +481 -0
  574. package/src/loader.ts +770 -0
  575. package/src/mcp/server.ts +1463 -0
  576. package/src/media/index.ts +32 -0
  577. package/src/media/local-runtime.ts +213 -0
  578. package/src/media/local.ts +46 -0
  579. package/src/media/normalize.ts +190 -0
  580. package/src/media/placeholder.ts +150 -0
  581. package/src/media/provider-loader.ts +78 -0
  582. package/src/media/types.ts +279 -0
  583. package/src/menus/index.ts +324 -0
  584. package/src/menus/types.ts +112 -0
  585. package/src/page/context.ts +93 -0
  586. package/src/page/fragments.ts +89 -0
  587. package/src/page/index.ts +58 -0
  588. package/src/page/jsonld.ts +94 -0
  589. package/src/page/metadata.ts +185 -0
  590. package/src/page/seo-contributions.ts +136 -0
  591. package/src/plugin-utils.ts +80 -0
  592. package/src/plugins/adapt-sandbox-entry.ts +207 -0
  593. package/src/plugins/context.ts +833 -0
  594. package/src/plugins/cron.ts +361 -0
  595. package/src/plugins/define-plugin.ts +259 -0
  596. package/src/plugins/email-console.ts +73 -0
  597. package/src/plugins/email.ts +209 -0
  598. package/src/plugins/hooks.ts +1273 -0
  599. package/src/plugins/index.ts +193 -0
  600. package/src/plugins/manager.ts +595 -0
  601. package/src/plugins/manifest-schema.ts +230 -0
  602. package/src/plugins/marketplace.ts +460 -0
  603. package/src/plugins/request-meta.ts +139 -0
  604. package/src/plugins/routes.ts +302 -0
  605. package/src/plugins/sandbox/index.ts +18 -0
  606. package/src/plugins/sandbox/noop.ts +76 -0
  607. package/src/plugins/sandbox/types.ts +173 -0
  608. package/src/plugins/scheduler/node.ts +122 -0
  609. package/src/plugins/scheduler/piggyback.ts +71 -0
  610. package/src/plugins/scheduler/types.ts +27 -0
  611. package/src/plugins/state.ts +208 -0
  612. package/src/plugins/storage-indexes.ts +326 -0
  613. package/src/plugins/storage-query.ts +240 -0
  614. package/src/plugins/types.ts +1284 -0
  615. package/src/preview/helpers.ts +27 -0
  616. package/src/preview/index.ts +40 -0
  617. package/src/preview/tokens.ts +279 -0
  618. package/src/preview/urls.ts +118 -0
  619. package/src/query.ts +674 -0
  620. package/src/redirects/patterns.ts +224 -0
  621. package/src/request-context.ts +67 -0
  622. package/src/runtime.ts +21 -0
  623. package/src/schema/index.ts +29 -0
  624. package/src/schema/query.ts +44 -0
  625. package/src/schema/registry.ts +965 -0
  626. package/src/schema/types.ts +276 -0
  627. package/src/schema/zod-generator.ts +413 -0
  628. package/src/search/fts-manager.ts +452 -0
  629. package/src/search/index.ts +26 -0
  630. package/src/search/query.ts +396 -0
  631. package/src/search/text-extraction.ts +162 -0
  632. package/src/search/types.ts +114 -0
  633. package/src/sections/index.ts +226 -0
  634. package/src/sections/types.ts +86 -0
  635. package/src/seed/apply.ts +1141 -0
  636. package/src/seed/default.ts +86 -0
  637. package/src/seed/index.ts +28 -0
  638. package/src/seed/load.ts +35 -0
  639. package/src/seed/types.ts +341 -0
  640. package/src/seed/validate.ts +642 -0
  641. package/src/seo/index.ts +179 -0
  642. package/src/settings/index.ts +203 -0
  643. package/src/settings/types.ts +58 -0
  644. package/src/storage/index.ts +28 -0
  645. package/src/storage/local.ts +249 -0
  646. package/src/storage/s3.ts +263 -0
  647. package/src/storage/types.ts +204 -0
  648. package/src/taxonomies/index.ts +309 -0
  649. package/src/taxonomies/types.ts +61 -0
  650. package/src/ui.ts +75 -0
  651. package/src/utils/base64.ts +73 -0
  652. package/src/utils/hash.ts +36 -0
  653. package/src/utils/sanitize.ts +20 -0
  654. package/src/utils/slugify.ts +29 -0
  655. package/src/utils/url.ts +48 -0
  656. package/src/virtual-modules.d.ts +111 -0
  657. package/src/visual-editing/editable.ts +108 -0
  658. package/src/visual-editing/toolbar.ts +1229 -0
  659. package/src/widgets/components.ts +105 -0
  660. package/src/widgets/index.ts +131 -0
  661. package/src/widgets/types.ts +81 -0
@@ -0,0 +1,413 @@
1
+ /**
2
+ * Portable Text <-> Markdown conversion layer.
3
+ *
4
+ * Three tiers of block handling:
5
+ * Tier 1: Standard PT blocks <-> standard Markdown (headings, paragraphs, lists, etc.)
6
+ * Tier 2: EmDash custom blocks <-> Markdown directives (future)
7
+ * Tier 3: Unknown blocks <-> opaque HTML comment fences (preserved, not editable)
8
+ */
9
+
10
+ // ---------------------------------------------------------------------------
11
+ // Types
12
+ // ---------------------------------------------------------------------------
13
+
14
+ /** Minimal Portable Text block shape */
15
+ export interface PortableTextBlock {
16
+ _type: string;
17
+ _key?: string;
18
+ style?: string;
19
+ level?: number;
20
+ listItem?: string;
21
+ markDefs?: MarkDef[];
22
+ children?: PortableTextSpan[];
23
+ [key: string]: unknown;
24
+ }
25
+
26
+ interface PortableTextSpan {
27
+ _type: string;
28
+ _key?: string;
29
+ text?: string;
30
+ marks?: string[];
31
+ [key: string]: unknown;
32
+ }
33
+
34
+ interface MarkDef {
35
+ _key: string;
36
+ _type: string;
37
+ href?: string;
38
+ [key: string]: unknown;
39
+ }
40
+
41
+ interface ParsedInline {
42
+ spans: PortableTextSpan[];
43
+ markDefs: MarkDef[];
44
+ }
45
+
46
+ // ---------------------------------------------------------------------------
47
+ // PT -> Markdown
48
+ // ---------------------------------------------------------------------------
49
+
50
+ /**
51
+ * Convert Portable Text blocks to Markdown.
52
+ * Unknown block types are serialized as opaque fences.
53
+ */
54
+ export function portableTextToMarkdown(blocks: PortableTextBlock[]): string {
55
+ const lines: string[] = [];
56
+ let prevWasList = false;
57
+
58
+ for (let i = 0; i < blocks.length; i++) {
59
+ const block = blocks[i];
60
+
61
+ if (block._type === "block") {
62
+ const isList = !!block.listItem;
63
+
64
+ // Blank line between non-contiguous block types
65
+ if (i > 0 && (!isList || !prevWasList)) {
66
+ lines.push("");
67
+ }
68
+
69
+ lines.push(renderStandardBlock(block));
70
+ prevWasList = isList;
71
+ } else if (block._type === "code") {
72
+ if (i > 0) lines.push("");
73
+ const lang = (block.language as string) || "";
74
+ const code = (block.code as string) || "";
75
+ lines.push("```" + lang);
76
+ lines.push(code);
77
+ lines.push("```");
78
+ prevWasList = false;
79
+ } else if (block._type === "image") {
80
+ if (i > 0) lines.push("");
81
+ const alt = (block.alt as string) || "";
82
+ const url = (block.asset as { url?: string })?.url || "";
83
+ lines.push(`![${alt}](${url})`);
84
+ prevWasList = false;
85
+ } else {
86
+ // Tier 3: Unknown block -> opaque fence
87
+ if (i > 0) lines.push("");
88
+ lines.push(`<!--ec:block ${JSON.stringify(block)} -->`);
89
+ prevWasList = false;
90
+ }
91
+ }
92
+
93
+ return lines.join("\n") + "\n";
94
+ }
95
+
96
+ function renderStandardBlock(block: PortableTextBlock): string {
97
+ const text = renderSpans(block.children ?? [], block.markDefs ?? []);
98
+
99
+ // List items
100
+ if (block.listItem) {
101
+ const indent = " ".repeat(Math.max(0, (block.level ?? 1) - 1));
102
+ const marker = block.listItem === "number" ? "1." : "-";
103
+ return `${indent}${marker} ${text}`;
104
+ }
105
+
106
+ // Headings
107
+ if (block.style && block.style.startsWith("h")) {
108
+ const level = parseInt(block.style.substring(1), 10);
109
+ if (level >= 1 && level <= 6) {
110
+ return `${"#".repeat(level)} ${text}`;
111
+ }
112
+ }
113
+
114
+ // Blockquote
115
+ if (block.style === "blockquote") {
116
+ return `> ${text}`;
117
+ }
118
+
119
+ return text;
120
+ }
121
+
122
+ function renderSpans(spans: PortableTextSpan[], markDefs: MarkDef[]): string {
123
+ let result = "";
124
+
125
+ for (const span of spans) {
126
+ if (span._type !== "span") continue;
127
+
128
+ let text = span.text ?? "";
129
+ const marks = span.marks ?? [];
130
+
131
+ for (const mark of marks) {
132
+ const def = markDefs.find((d) => d._key === mark);
133
+ if (def) {
134
+ if (def._type === "link") {
135
+ text = `[${text}](${def.href ?? ""})`;
136
+ }
137
+ } else {
138
+ switch (mark) {
139
+ case "strong":
140
+ text = `**${text}**`;
141
+ break;
142
+ case "em":
143
+ text = `_${text}_`;
144
+ break;
145
+ case "code":
146
+ text = `\`${text}\``;
147
+ break;
148
+ case "strike-through":
149
+ case "strikethrough":
150
+ text = `~~${text}~~`;
151
+ break;
152
+ }
153
+ }
154
+ }
155
+
156
+ result += text;
157
+ }
158
+
159
+ return result;
160
+ }
161
+
162
+ // ---------------------------------------------------------------------------
163
+ // Markdown -> PT
164
+ // ---------------------------------------------------------------------------
165
+
166
+ // Regex patterns for markdown parsing
167
+ const OPAQUE_FENCE_PATTERN = /^<!--ec:block (.+) -->$/;
168
+ const HEADING_PATTERN = /^(#{1,6})\s+(.+)$/;
169
+ const UNORDERED_LIST_PATTERN = /^(\s*)[-*+]\s+(.+)$/;
170
+ const ORDERED_LIST_PATTERN = /^(\s*)\d+\.\s+(.+)$/;
171
+ const IMAGE_PATTERN = /^!\[([^\]]*)\]\(([^)]+)\)$/;
172
+ const INLINE_MARKDOWN_PATTERN =
173
+ /(\*\*(.+?)\*\*)|(_(.+?)_)|(`(.+?)`)|(\[(.+?)\]\((.+?)\))|(~~(.+?)~~)/g;
174
+
175
+ /**
176
+ * Convert Markdown to Portable Text blocks.
177
+ * Opaque fences (<!--ec:block ... -->) are deserialized and spliced back in.
178
+ */
179
+ export function markdownToPortableText(markdown: string): PortableTextBlock[] {
180
+ const blocks: PortableTextBlock[] = [];
181
+ const lines = markdown.split("\n");
182
+ let i = 0;
183
+
184
+ while (i < lines.length) {
185
+ const line = lines[i];
186
+
187
+ // Opaque fence
188
+ const opaqueMatch = line.match(OPAQUE_FENCE_PATTERN);
189
+ if (opaqueMatch) {
190
+ try {
191
+ blocks.push(JSON.parse(opaqueMatch[1]) as PortableTextBlock);
192
+ } catch {
193
+ blocks.push(makeBlock(line));
194
+ }
195
+ i++;
196
+ continue;
197
+ }
198
+
199
+ // Code fence
200
+ if (line.startsWith("```")) {
201
+ const lang = line.slice(3).trim();
202
+ const codeLines: string[] = [];
203
+ i++;
204
+ while (i < lines.length && !lines[i].startsWith("```")) {
205
+ codeLines.push(lines[i]);
206
+ i++;
207
+ }
208
+ blocks.push({
209
+ _type: "code",
210
+ _key: generateKey(),
211
+ language: lang || undefined,
212
+ code: codeLines.join("\n"),
213
+ });
214
+ i++; // skip closing ```
215
+ continue;
216
+ }
217
+
218
+ // Blank line
219
+ if (line.trim() === "") {
220
+ i++;
221
+ continue;
222
+ }
223
+
224
+ // Heading
225
+ const headingMatch = line.match(HEADING_PATTERN);
226
+ if (headingMatch) {
227
+ blocks.push(makeBlock(headingMatch[2], `h${headingMatch[1].length}`));
228
+ i++;
229
+ continue;
230
+ }
231
+
232
+ // Blockquote
233
+ if (line.startsWith("> ")) {
234
+ blocks.push(makeBlock(line.slice(2), "blockquote"));
235
+ i++;
236
+ continue;
237
+ }
238
+
239
+ // Unordered list
240
+ const ulMatch = line.match(UNORDERED_LIST_PATTERN);
241
+ if (ulMatch) {
242
+ const level = Math.floor(ulMatch[1].length / 2) + 1;
243
+ blocks.push(makeListBlock(ulMatch[2], "bullet", level));
244
+ i++;
245
+ continue;
246
+ }
247
+
248
+ // Ordered list
249
+ const olMatch = line.match(ORDERED_LIST_PATTERN);
250
+ if (olMatch) {
251
+ const level = Math.floor(olMatch[1].length / 2) + 1;
252
+ blocks.push(makeListBlock(olMatch[2], "number", level));
253
+ i++;
254
+ continue;
255
+ }
256
+
257
+ // Image
258
+ const imgMatch = line.match(IMAGE_PATTERN);
259
+ if (imgMatch) {
260
+ blocks.push({
261
+ _type: "image",
262
+ _key: generateKey(),
263
+ alt: imgMatch[1],
264
+ asset: { url: imgMatch[2] },
265
+ });
266
+ i++;
267
+ continue;
268
+ }
269
+
270
+ // Paragraph
271
+ blocks.push(makeBlock(line));
272
+ i++;
273
+ }
274
+
275
+ return blocks;
276
+ }
277
+
278
+ // ---------------------------------------------------------------------------
279
+ // Block builders
280
+ // ---------------------------------------------------------------------------
281
+
282
+ function makeBlock(text: string, style: string = "normal"): PortableTextBlock {
283
+ const { spans, markDefs } = parseInline(text);
284
+ return { _type: "block", _key: generateKey(), style, markDefs, children: spans };
285
+ }
286
+
287
+ function makeListBlock(text: string, listItem: string, level: number): PortableTextBlock {
288
+ const { spans, markDefs } = parseInline(text);
289
+ return {
290
+ _type: "block",
291
+ _key: generateKey(),
292
+ style: "normal",
293
+ listItem,
294
+ level,
295
+ markDefs,
296
+ children: spans,
297
+ };
298
+ }
299
+
300
+ /**
301
+ * Parse inline markdown (bold, italic, code, links, strikethrough) into PT spans + markDefs.
302
+ */
303
+ function parseInline(text: string): ParsedInline {
304
+ const spans: PortableTextSpan[] = [];
305
+ const markDefs: MarkDef[] = [];
306
+ const regex = INLINE_MARKDOWN_PATTERN;
307
+
308
+ let lastIndex = 0;
309
+ let match: RegExpExecArray | null;
310
+
311
+ while ((match = regex.exec(text)) !== null) {
312
+ if (match.index > lastIndex) {
313
+ spans.push({
314
+ _type: "span",
315
+ _key: generateKey(),
316
+ text: text.slice(lastIndex, match.index),
317
+ marks: [],
318
+ });
319
+ }
320
+
321
+ if (match[2] != null) {
322
+ spans.push({ _type: "span", _key: generateKey(), text: match[2], marks: ["strong"] });
323
+ } else if (match[4] != null) {
324
+ spans.push({ _type: "span", _key: generateKey(), text: match[4], marks: ["em"] });
325
+ } else if (match[6] != null) {
326
+ spans.push({ _type: "span", _key: generateKey(), text: match[6], marks: ["code"] });
327
+ } else if (match[8] != null && match[9] != null) {
328
+ const key = generateKey();
329
+ markDefs.push({ _key: key, _type: "link", href: match[9] });
330
+ spans.push({ _type: "span", _key: generateKey(), text: match[8], marks: [key] });
331
+ } else if (match[11] != null) {
332
+ spans.push({
333
+ _type: "span",
334
+ _key: generateKey(),
335
+ text: match[11],
336
+ marks: ["strike-through"],
337
+ });
338
+ }
339
+
340
+ lastIndex = match.index + match[0].length;
341
+ }
342
+
343
+ if (lastIndex < text.length) {
344
+ spans.push({ _type: "span", _key: generateKey(), text: text.slice(lastIndex), marks: [] });
345
+ }
346
+
347
+ if (spans.length === 0) {
348
+ spans.push({ _type: "span", _key: generateKey(), text, marks: [] });
349
+ }
350
+
351
+ return { spans, markDefs };
352
+ }
353
+
354
+ // ---------------------------------------------------------------------------
355
+ // Key generation
356
+ // ---------------------------------------------------------------------------
357
+
358
+ let keyCounter = 0;
359
+
360
+ function generateKey(): string {
361
+ return `k${(keyCounter++).toString(36)}`;
362
+ }
363
+
364
+ /** Reset key counter (useful for testing) */
365
+ export function resetKeyCounter(): void {
366
+ keyCounter = 0;
367
+ }
368
+
369
+ // ---------------------------------------------------------------------------
370
+ // Schema-aware conversion helpers
371
+ // ---------------------------------------------------------------------------
372
+
373
+ export interface FieldSchema {
374
+ slug: string;
375
+ type: string;
376
+ }
377
+
378
+ /**
379
+ * Convert content data for reading: PT fields -> markdown strings.
380
+ * Only converts fields with type "portableText" that contain arrays.
381
+ */
382
+ export function convertDataForRead(
383
+ data: Record<string, unknown>,
384
+ fields: FieldSchema[],
385
+ raw: boolean = false,
386
+ ): Record<string, unknown> {
387
+ if (raw) return data;
388
+
389
+ const result = { ...data };
390
+ for (const field of fields) {
391
+ if (field.type === "portableText" && Array.isArray(result[field.slug])) {
392
+ result[field.slug] = portableTextToMarkdown(result[field.slug] as PortableTextBlock[]);
393
+ }
394
+ }
395
+ return result;
396
+ }
397
+
398
+ /**
399
+ * Convert content data for writing: markdown strings -> PT arrays.
400
+ * Only converts fields with type "portableText" that contain strings.
401
+ */
402
+ export function convertDataForWrite(
403
+ data: Record<string, unknown>,
404
+ fields: FieldSchema[],
405
+ ): Record<string, unknown> {
406
+ const result = { ...data };
407
+ for (const field of fields) {
408
+ if (field.type === "portableText" && typeof result[field.slug] === "string") {
409
+ result[field.slug] = markdownToPortableText(result[field.slug] as string);
410
+ }
411
+ }
412
+ return result;
413
+ }
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Transport layer for the EmDash client.
3
+ *
4
+ * Implements a composable interceptor pipeline that modifies requests
5
+ * and responses. The client calls `transport.fetch(request)` — everything
6
+ * else (auth, CSRF, retry) is handled by interceptors.
7
+ */
8
+
9
+ // Regex patterns for transport utilities
10
+ const COOKIE_NAME_VALUE_PATTERN = /^([^;]+)/;
11
+
12
+ /**
13
+ * An interceptor can modify the request, call next(), inspect
14
+ * the response, and optionally retry.
15
+ */
16
+ export type Interceptor = (
17
+ request: Request,
18
+ next: (request: Request) => Promise<Response>,
19
+ ) => Promise<Response>;
20
+
21
+ export interface TransportOptions {
22
+ interceptors?: Interceptor[];
23
+ }
24
+
25
+ function baseFetch(request: Request): Promise<Response> {
26
+ return globalThis.fetch(request);
27
+ }
28
+
29
+ /**
30
+ * Creates a fetch function that runs requests through an interceptor pipeline.
31
+ */
32
+ export function createTransport(options: TransportOptions = {}): {
33
+ fetch: (request: Request) => Promise<Response>;
34
+ } {
35
+ const interceptors = options.interceptors ?? [];
36
+
37
+ // Build the chain once — interceptors don't change after construction
38
+ let chain: (request: Request) => Promise<Response> = baseFetch;
39
+ for (let i = interceptors.length - 1; i >= 0; i--) {
40
+ const interceptor = interceptors[i];
41
+ const next = chain;
42
+ chain = (req) => interceptor(req, next);
43
+ }
44
+
45
+ return { fetch: chain };
46
+ }
47
+
48
+ // ---------------------------------------------------------------------------
49
+ // Built-in interceptors
50
+ // ---------------------------------------------------------------------------
51
+
52
+ /**
53
+ * Adds X-EmDash-Request: 1 and Origin headers to mutation requests
54
+ * (POST, PUT, DELETE). The custom header satisfies EmDash's CSRF check;
55
+ * the Origin header satisfies Astro's built-in origin verification which
56
+ * rejects server-side POST requests that lack a matching Origin.
57
+ */
58
+ export function csrfInterceptor(): Interceptor {
59
+ const MUTATION_METHODS = new Set(["POST", "PUT", "DELETE", "PATCH"]);
60
+
61
+ return (request, next) => {
62
+ if (MUTATION_METHODS.has(request.method)) {
63
+ const headers = new Headers(request.headers);
64
+ headers.set("X-EmDash-Request", "1");
65
+ if (!headers.has("Origin")) {
66
+ const url = new URL(request.url);
67
+ headers.set("Origin", url.origin);
68
+ }
69
+ return next(new Request(request, { headers }));
70
+ }
71
+ return next(request);
72
+ };
73
+ }
74
+
75
+ /**
76
+ * Adds Authorization: Bearer header from a static token.
77
+ */
78
+ export function tokenInterceptor(token: string): Interceptor {
79
+ return (request, next) => {
80
+ const headers = new Headers(request.headers);
81
+ headers.set("Authorization", `Bearer ${token}`);
82
+ return next(new Request(request, { headers }));
83
+ };
84
+ }
85
+
86
+ /**
87
+ * Dev bypass interceptor. Calls the dev-bypass endpoint on first request
88
+ * to establish a session, then forwards the session cookie on subsequent
89
+ * requests.
90
+ */
91
+ export function devBypassInterceptor(baseUrl: string): Interceptor {
92
+ let sessionCookie: string | null = null;
93
+ let initializing: Promise<void> | null = null;
94
+
95
+ async function init(): Promise<void> {
96
+ const bypassUrl = new URL("/_emdash/api/auth/dev-bypass", baseUrl);
97
+ const res = await globalThis.fetch(bypassUrl, { redirect: "manual" });
98
+
99
+ // Extract session cookie from Set-Cookie header
100
+ const setCookie = res.headers.get("set-cookie");
101
+ if (setCookie) {
102
+ // Extract just the cookie name=value part
103
+ const match = setCookie.match(COOKIE_NAME_VALUE_PATTERN);
104
+ if (match) {
105
+ sessionCookie = match[1]!;
106
+ }
107
+ }
108
+
109
+ // Consume the response body
110
+ if (res.body) {
111
+ await res.text().catch(() => {});
112
+ }
113
+ }
114
+
115
+ return async (request, next) => {
116
+ // Ensure we've initialized (only once, even with concurrent requests)
117
+ if (!sessionCookie) {
118
+ if (!initializing) {
119
+ initializing = init();
120
+ }
121
+ await initializing;
122
+ }
123
+
124
+ if (sessionCookie) {
125
+ const headers = new Headers(request.headers);
126
+ const existing = headers.get("cookie");
127
+ headers.set("cookie", existing ? `${existing}; ${sessionCookie}` : sessionCookie);
128
+ return next(new Request(request, { headers }));
129
+ }
130
+
131
+ return next(request);
132
+ };
133
+ }
134
+
135
+ /**
136
+ * Auto-refreshes expired OAuth tokens on 401 responses.
137
+ * Requires a refresh token and the token endpoint URL.
138
+ */
139
+ export function refreshInterceptor(options: {
140
+ refreshToken: string;
141
+ tokenEndpoint: string;
142
+ onTokenRefreshed?: (accessToken: string, refreshToken: string, expiresAt: string) => void;
143
+ }): Interceptor {
144
+ let refreshing: Promise<string | null> | null = null;
145
+
146
+ async function refresh(): Promise<string | null> {
147
+ const res = await globalThis.fetch(options.tokenEndpoint, {
148
+ method: "POST",
149
+ headers: { "Content-Type": "application/json" },
150
+ body: JSON.stringify({
151
+ grant_type: "refresh_token",
152
+ refresh_token: options.refreshToken,
153
+ }),
154
+ });
155
+
156
+ if (!res.ok) return null;
157
+
158
+ const data = (await res.json()) as {
159
+ access_token: string;
160
+ refresh_token?: string;
161
+ expires_in?: number;
162
+ };
163
+ const expiresAt = data.expires_in
164
+ ? new Date(Date.now() + data.expires_in * 1000).toISOString()
165
+ : new Date(Date.now() + 3600_000).toISOString();
166
+
167
+ if (options.onTokenRefreshed) {
168
+ options.onTokenRefreshed(
169
+ data.access_token,
170
+ data.refresh_token ?? options.refreshToken,
171
+ expiresAt,
172
+ );
173
+ }
174
+
175
+ return data.access_token;
176
+ }
177
+
178
+ return async (request, next) => {
179
+ const response = await next(request);
180
+
181
+ if (response.status === 401) {
182
+ // Try to refresh
183
+ if (!refreshing) {
184
+ refreshing = refresh().finally(() => {
185
+ refreshing = null;
186
+ });
187
+ }
188
+
189
+ const newToken = await refreshing;
190
+ if (newToken) {
191
+ // Retry with new token
192
+ const headers = new Headers(request.headers);
193
+ headers.set("Authorization", `Bearer ${newToken}`);
194
+ return next(new Request(request, { headers }));
195
+ }
196
+ }
197
+
198
+ return response;
199
+ };
200
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Built-in Default Comment Moderator
3
+ *
4
+ * Registers comment:moderate as an exclusive hook.
5
+ * Implements the 4-step decision logic:
6
+ * 1. Auto-approve authenticated CMS users (if configured)
7
+ * 2. If moderation is "none" → approved
8
+ * 3. If moderation is "first_time" and returning commenter → approved
9
+ * 4. Otherwise → pending
10
+ *
11
+ * This moderator does not read `metadata` — it only uses collection settings
12
+ * and prior approval count. Plugin moderators (AI, Akismet) replace this.
13
+ */
14
+
15
+ import type { CommentModerateEvent, ModerationDecision, PluginContext } from "../plugins/types.js";
16
+
17
+ /** Plugin ID for the built-in default comment moderator */
18
+ export const DEFAULT_COMMENT_MODERATOR_PLUGIN_ID = "emdash-default-comment-moderator";
19
+
20
+ /**
21
+ * The comment:moderate handler for the built-in default moderator.
22
+ */
23
+ export async function defaultCommentModerate(
24
+ event: CommentModerateEvent,
25
+ _ctx: PluginContext,
26
+ ): Promise<ModerationDecision> {
27
+ const { comment, collectionSettings, priorApprovedCount } = event;
28
+
29
+ // 1. Auto-approve authenticated CMS users if configured
30
+ if (collectionSettings.commentsAutoApproveUsers && comment.authorUserId) {
31
+ return { status: "approved", reason: "Authenticated CMS user" };
32
+ }
33
+
34
+ // 2. If moderation is "none" → approved
35
+ if (collectionSettings.commentsModeration === "none") {
36
+ return { status: "approved", reason: "Moderation disabled" };
37
+ }
38
+
39
+ // 3. If moderation is "first_time" and returning commenter → approved
40
+ if (collectionSettings.commentsModeration === "first_time" && priorApprovedCount > 0) {
41
+ return { status: "approved", reason: "Returning commenter" };
42
+ }
43
+
44
+ // 4. Otherwise → pending
45
+ return { status: "pending", reason: "Held for review" };
46
+ }