@growth-labs/cms 0.1.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 (1093) hide show
  1. package/README.md +165 -0
  2. package/dist/engine/activity-log.d.ts +17 -0
  3. package/dist/engine/activity-log.d.ts.map +1 -0
  4. package/dist/engine/activity-log.js +17 -0
  5. package/dist/engine/activity-log.js.map +1 -0
  6. package/dist/engine/ai-prompts.d.ts +57 -0
  7. package/dist/engine/ai-prompts.d.ts.map +1 -0
  8. package/dist/engine/ai-prompts.js +90 -0
  9. package/dist/engine/ai-prompts.js.map +1 -0
  10. package/dist/engine/ai-writeback.d.ts +36 -0
  11. package/dist/engine/ai-writeback.d.ts.map +1 -0
  12. package/dist/engine/ai-writeback.js +45 -0
  13. package/dist/engine/ai-writeback.js.map +1 -0
  14. package/dist/engine/api-keys.d.ts +76 -0
  15. package/dist/engine/api-keys.d.ts.map +1 -0
  16. package/dist/engine/api-keys.js +165 -0
  17. package/dist/engine/api-keys.js.map +1 -0
  18. package/dist/engine/content-insights.d.ts +36 -0
  19. package/dist/engine/content-insights.d.ts.map +1 -0
  20. package/dist/engine/content-insights.js +114 -0
  21. package/dist/engine/content-insights.js.map +1 -0
  22. package/dist/engine/contributors.d.ts +25 -0
  23. package/dist/engine/contributors.d.ts.map +1 -0
  24. package/dist/engine/contributors.js +59 -0
  25. package/dist/engine/contributors.js.map +1 -0
  26. package/dist/engine/cron.d.ts +15 -0
  27. package/dist/engine/cron.d.ts.map +1 -0
  28. package/dist/engine/cron.js +33 -0
  29. package/dist/engine/cron.js.map +1 -0
  30. package/dist/engine/d1.d.ts +16 -0
  31. package/dist/engine/d1.d.ts.map +1 -0
  32. package/dist/engine/d1.js +13 -0
  33. package/dist/engine/d1.js.map +1 -0
  34. package/dist/engine/foundry-dispatch.d.ts +52 -0
  35. package/dist/engine/foundry-dispatch.d.ts.map +1 -0
  36. package/dist/engine/foundry-dispatch.js +290 -0
  37. package/dist/engine/foundry-dispatch.js.map +1 -0
  38. package/dist/engine/import-parsers.d.ts +11 -0
  39. package/dist/engine/import-parsers.d.ts.map +1 -0
  40. package/dist/engine/import-parsers.js +373 -0
  41. package/dist/engine/import-parsers.js.map +1 -0
  42. package/dist/engine/index.d.ts +28 -0
  43. package/dist/engine/index.d.ts.map +1 -0
  44. package/dist/engine/index.js +57 -0
  45. package/dist/engine/index.js.map +1 -0
  46. package/dist/engine/invites.d.ts +78 -0
  47. package/dist/engine/invites.d.ts.map +1 -0
  48. package/dist/engine/invites.js +158 -0
  49. package/dist/engine/invites.js.map +1 -0
  50. package/dist/engine/members.d.ts +59 -0
  51. package/dist/engine/members.d.ts.map +1 -0
  52. package/dist/engine/members.js +124 -0
  53. package/dist/engine/members.js.map +1 -0
  54. package/dist/engine/membership-rules.d.ts +25 -0
  55. package/dist/engine/membership-rules.d.ts.map +1 -0
  56. package/dist/engine/membership-rules.js +44 -0
  57. package/dist/engine/membership-rules.js.map +1 -0
  58. package/dist/engine/og-render.d.ts +40 -0
  59. package/dist/engine/og-render.d.ts.map +1 -0
  60. package/dist/engine/og-render.js +26 -0
  61. package/dist/engine/og-render.js.map +1 -0
  62. package/dist/engine/publish-guard.d.ts +58 -0
  63. package/dist/engine/publish-guard.d.ts.map +1 -0
  64. package/dist/engine/publish-guard.js +80 -0
  65. package/dist/engine/publish-guard.js.map +1 -0
  66. package/dist/engine/publisher.d.ts +171 -0
  67. package/dist/engine/publisher.d.ts.map +1 -0
  68. package/dist/engine/publisher.js +597 -0
  69. package/dist/engine/publisher.js.map +1 -0
  70. package/dist/engine/revisions.d.ts +39 -0
  71. package/dist/engine/revisions.d.ts.map +1 -0
  72. package/dist/engine/revisions.js +203 -0
  73. package/dist/engine/revisions.js.map +1 -0
  74. package/dist/engine/sanitize.d.ts +52 -0
  75. package/dist/engine/sanitize.d.ts.map +1 -0
  76. package/dist/engine/sanitize.js +155 -0
  77. package/dist/engine/sanitize.js.map +1 -0
  78. package/dist/engine/seed-membership.d.ts +29 -0
  79. package/dist/engine/seed-membership.d.ts.map +1 -0
  80. package/dist/engine/seed-membership.js +65 -0
  81. package/dist/engine/seed-membership.js.map +1 -0
  82. package/dist/engine/seo.d.ts +20 -0
  83. package/dist/engine/seo.d.ts.map +1 -0
  84. package/dist/engine/seo.js +50 -0
  85. package/dist/engine/seo.js.map +1 -0
  86. package/dist/engine/slug-redirects.d.ts +8 -0
  87. package/dist/engine/slug-redirects.d.ts.map +1 -0
  88. package/dist/engine/slug-redirects.js +26 -0
  89. package/dist/engine/slug-redirects.js.map +1 -0
  90. package/dist/engine/slug.d.ts +6 -0
  91. package/dist/engine/slug.d.ts.map +1 -0
  92. package/dist/engine/slug.js +28 -0
  93. package/dist/engine/slug.js.map +1 -0
  94. package/dist/engine/soft-delete.d.ts +8 -0
  95. package/dist/engine/soft-delete.d.ts.map +1 -0
  96. package/dist/engine/soft-delete.js +28 -0
  97. package/dist/engine/soft-delete.js.map +1 -0
  98. package/dist/engine/tags.d.ts +14 -0
  99. package/dist/engine/tags.d.ts.map +1 -0
  100. package/dist/engine/tags.js +79 -0
  101. package/dist/engine/tags.js.map +1 -0
  102. package/dist/engine/topics.d.ts +10 -0
  103. package/dist/engine/topics.d.ts.map +1 -0
  104. package/dist/engine/topics.js +140 -0
  105. package/dist/engine/topics.js.map +1 -0
  106. package/dist/engine/url-guard.d.ts +12 -0
  107. package/dist/engine/url-guard.d.ts.map +1 -0
  108. package/dist/engine/url-guard.js +129 -0
  109. package/dist/engine/url-guard.js.map +1 -0
  110. package/dist/engine/validator/checks/bare-url-not-autolinked.d.ts +20 -0
  111. package/dist/engine/validator/checks/bare-url-not-autolinked.d.ts.map +1 -0
  112. package/dist/engine/validator/checks/bare-url-not-autolinked.js +54 -0
  113. package/dist/engine/validator/checks/bare-url-not-autolinked.js.map +1 -0
  114. package/dist/engine/validator/checks/broken-footnote-label.d.ts +16 -0
  115. package/dist/engine/validator/checks/broken-footnote-label.d.ts.map +1 -0
  116. package/dist/engine/validator/checks/broken-footnote-label.js +17 -0
  117. package/dist/engine/validator/checks/broken-footnote-label.js.map +1 -0
  118. package/dist/engine/validator/checks/double-encoded-entities.d.ts +18 -0
  119. package/dist/engine/validator/checks/double-encoded-entities.d.ts.map +1 -0
  120. package/dist/engine/validator/checks/double-encoded-entities.js +23 -0
  121. package/dist/engine/validator/checks/double-encoded-entities.js.map +1 -0
  122. package/dist/engine/validator/checks/empty-alt-text.d.ts +14 -0
  123. package/dist/engine/validator/checks/empty-alt-text.d.ts.map +1 -0
  124. package/dist/engine/validator/checks/empty-alt-text.js +23 -0
  125. package/dist/engine/validator/checks/empty-alt-text.js.map +1 -0
  126. package/dist/engine/validator/checks/heading-hierarchy-skip.d.ts +11 -0
  127. package/dist/engine/validator/checks/heading-hierarchy-skip.d.ts.map +1 -0
  128. package/dist/engine/validator/checks/heading-hierarchy-skip.js +20 -0
  129. package/dist/engine/validator/checks/heading-hierarchy-skip.js.map +1 -0
  130. package/dist/engine/validator/checks/html-comment-leak.d.ts +20 -0
  131. package/dist/engine/validator/checks/html-comment-leak.d.ts.map +1 -0
  132. package/dist/engine/validator/checks/html-comment-leak.js +30 -0
  133. package/dist/engine/validator/checks/html-comment-leak.js.map +1 -0
  134. package/dist/engine/validator/checks/iframe-missing-dims-and-wrapper.d.ts +12 -0
  135. package/dist/engine/validator/checks/iframe-missing-dims-and-wrapper.d.ts.map +1 -0
  136. package/dist/engine/validator/checks/iframe-missing-dims-and-wrapper.js +17 -0
  137. package/dist/engine/validator/checks/iframe-missing-dims-and-wrapper.js.map +1 -0
  138. package/dist/engine/validator/checks/invisible-control-chars.d.ts +24 -0
  139. package/dist/engine/validator/checks/invisible-control-chars.d.ts.map +1 -0
  140. package/dist/engine/validator/checks/invisible-control-chars.js +30 -0
  141. package/dist/engine/validator/checks/invisible-control-chars.js.map +1 -0
  142. package/dist/engine/validator/checks/paywall-marker-leak.d.ts +17 -0
  143. package/dist/engine/validator/checks/paywall-marker-leak.d.ts.map +1 -0
  144. package/dist/engine/validator/checks/paywall-marker-leak.js +22 -0
  145. package/dist/engine/validator/checks/paywall-marker-leak.js.map +1 -0
  146. package/dist/engine/validator/checks/raw-block-html.d.ts +28 -0
  147. package/dist/engine/validator/checks/raw-block-html.d.ts.map +1 -0
  148. package/dist/engine/validator/checks/raw-block-html.js +38 -0
  149. package/dist/engine/validator/checks/raw-block-html.js.map +1 -0
  150. package/dist/engine/validator/checks/stale-body-html.d.ts +28 -0
  151. package/dist/engine/validator/checks/stale-body-html.d.ts.map +1 -0
  152. package/dist/engine/validator/checks/stale-body-html.js +15 -0
  153. package/dist/engine/validator/checks/stale-body-html.js.map +1 -0
  154. package/dist/engine/validator/checks/unresolved-footnote-anchor.d.ts +11 -0
  155. package/dist/engine/validator/checks/unresolved-footnote-anchor.d.ts.map +1 -0
  156. package/dist/engine/validator/checks/unresolved-footnote-anchor.js +48 -0
  157. package/dist/engine/validator/checks/unresolved-footnote-anchor.js.map +1 -0
  158. package/dist/engine/validator/checks/word-gdocs-paste-artifacts.d.ts +23 -0
  159. package/dist/engine/validator/checks/word-gdocs-paste-artifacts.d.ts.map +1 -0
  160. package/dist/engine/validator/checks/word-gdocs-paste-artifacts.js +47 -0
  161. package/dist/engine/validator/checks/word-gdocs-paste-artifacts.js.map +1 -0
  162. package/dist/engine/validator/index.d.ts +75 -0
  163. package/dist/engine/validator/index.d.ts.map +1 -0
  164. package/dist/engine/validator/index.js +313 -0
  165. package/dist/engine/validator/index.js.map +1 -0
  166. package/dist/engine/validator/scan.d.ts +28 -0
  167. package/dist/engine/validator/scan.d.ts.map +1 -0
  168. package/dist/engine/validator/scan.js +97 -0
  169. package/dist/engine/validator/scan.js.map +1 -0
  170. package/dist/engine/validator/types.d.ts +50 -0
  171. package/dist/engine/validator/types.d.ts.map +1 -0
  172. package/dist/engine/validator/types.js +51 -0
  173. package/dist/engine/validator/types.js.map +1 -0
  174. package/dist/engine/webhook-signer.d.ts +39 -0
  175. package/dist/engine/webhook-signer.d.ts.map +1 -0
  176. package/dist/engine/webhook-signer.js +117 -0
  177. package/dist/engine/webhook-signer.js.map +1 -0
  178. package/dist/engine/webhooks.d.ts +75 -0
  179. package/dist/engine/webhooks.d.ts.map +1 -0
  180. package/dist/engine/webhooks.js +139 -0
  181. package/dist/engine/webhooks.js.map +1 -0
  182. package/dist/index.d.ts +5 -0
  183. package/dist/index.d.ts.map +1 -0
  184. package/dist/index.js +40 -0
  185. package/dist/index.js.map +1 -0
  186. package/dist/integration/index.d.ts +6 -0
  187. package/dist/integration/index.d.ts.map +1 -0
  188. package/dist/integration/index.js +294 -0
  189. package/dist/integration/index.js.map +1 -0
  190. package/dist/integration/options.d.ts +105 -0
  191. package/dist/integration/options.d.ts.map +1 -0
  192. package/dist/integration/options.js +25 -0
  193. package/dist/integration/options.js.map +1 -0
  194. package/dist/integration/vite-plugin.d.ts +4 -0
  195. package/dist/integration/vite-plugin.d.ts.map +1 -0
  196. package/dist/integration/vite-plugin.js +37 -0
  197. package/dist/integration/vite-plugin.js.map +1 -0
  198. package/dist/providers/index.d.ts +3 -0
  199. package/dist/providers/index.d.ts.map +1 -0
  200. package/dist/providers/index.js +3 -0
  201. package/dist/providers/index.js.map +1 -0
  202. package/dist/providers/null.d.ts +9 -0
  203. package/dist/providers/null.d.ts.map +1 -0
  204. package/dist/providers/null.js +144 -0
  205. package/dist/providers/null.js.map +1 -0
  206. package/dist/providers/types.d.ts +277 -0
  207. package/dist/providers/types.d.ts.map +1 -0
  208. package/dist/providers/types.js +2 -0
  209. package/dist/providers/types.js.map +1 -0
  210. package/dist/routes/ai.d.ts +25 -0
  211. package/dist/routes/ai.d.ts.map +1 -0
  212. package/dist/routes/ai.js +381 -0
  213. package/dist/routes/ai.js.map +1 -0
  214. package/dist/routes/analytics.d.ts +15 -0
  215. package/dist/routes/analytics.d.ts.map +1 -0
  216. package/dist/routes/analytics.js +61 -0
  217. package/dist/routes/analytics.js.map +1 -0
  218. package/dist/routes/api-keys.d.ts +13 -0
  219. package/dist/routes/api-keys.d.ts.map +1 -0
  220. package/dist/routes/api-keys.js +109 -0
  221. package/dist/routes/api-keys.js.map +1 -0
  222. package/dist/routes/authors.d.ts +19 -0
  223. package/dist/routes/authors.d.ts.map +1 -0
  224. package/dist/routes/authors.js +202 -0
  225. package/dist/routes/authors.js.map +1 -0
  226. package/dist/routes/authz-matrix.d.ts +78 -0
  227. package/dist/routes/authz-matrix.d.ts.map +1 -0
  228. package/dist/routes/authz-matrix.js +170 -0
  229. package/dist/routes/authz-matrix.js.map +1 -0
  230. package/dist/routes/calendar.d.ts +19 -0
  231. package/dist/routes/calendar.d.ts.map +1 -0
  232. package/dist/routes/calendar.js +89 -0
  233. package/dist/routes/calendar.js.map +1 -0
  234. package/dist/routes/config.d.ts +70 -0
  235. package/dist/routes/config.d.ts.map +1 -0
  236. package/dist/routes/config.js +23 -0
  237. package/dist/routes/config.js.map +1 -0
  238. package/dist/routes/content-insights.d.ts +18 -0
  239. package/dist/routes/content-insights.d.ts.map +1 -0
  240. package/dist/routes/content-insights.js +137 -0
  241. package/dist/routes/content-insights.js.map +1 -0
  242. package/dist/routes/content.d.ts +145 -0
  243. package/dist/routes/content.d.ts.map +1 -0
  244. package/dist/routes/content.js +1374 -0
  245. package/dist/routes/content.js.map +1 -0
  246. package/dist/routes/context.d.ts +104 -0
  247. package/dist/routes/context.d.ts.map +1 -0
  248. package/dist/routes/context.js +26 -0
  249. package/dist/routes/context.js.map +1 -0
  250. package/dist/routes/cron.d.ts +8 -0
  251. package/dist/routes/cron.d.ts.map +1 -0
  252. package/dist/routes/cron.js +20 -0
  253. package/dist/routes/cron.js.map +1 -0
  254. package/dist/routes/dashboard.d.ts +12 -0
  255. package/dist/routes/dashboard.d.ts.map +1 -0
  256. package/dist/routes/dashboard.js +113 -0
  257. package/dist/routes/dashboard.js.map +1 -0
  258. package/dist/routes/imports.d.ts +10 -0
  259. package/dist/routes/imports.d.ts.map +1 -0
  260. package/dist/routes/imports.js +149 -0
  261. package/dist/routes/imports.js.map +1 -0
  262. package/dist/routes/index.d.ts +75 -0
  263. package/dist/routes/index.d.ts.map +1 -0
  264. package/dist/routes/index.js +141 -0
  265. package/dist/routes/index.js.map +1 -0
  266. package/dist/routes/media-lib.d.ts +75 -0
  267. package/dist/routes/media-lib.d.ts.map +1 -0
  268. package/dist/routes/media-lib.js +305 -0
  269. package/dist/routes/media-lib.js.map +1 -0
  270. package/dist/routes/media.d.ts +32 -0
  271. package/dist/routes/media.d.ts.map +1 -0
  272. package/dist/routes/media.js +756 -0
  273. package/dist/routes/media.js.map +1 -0
  274. package/dist/routes/preview.d.ts +19 -0
  275. package/dist/routes/preview.d.ts.map +1 -0
  276. package/dist/routes/preview.js +150 -0
  277. package/dist/routes/preview.js.map +1 -0
  278. package/dist/routes/rbac-invites.d.ts +31 -0
  279. package/dist/routes/rbac-invites.d.ts.map +1 -0
  280. package/dist/routes/rbac-invites.js +174 -0
  281. package/dist/routes/rbac-invites.js.map +1 -0
  282. package/dist/routes/rbac.d.ts +12 -0
  283. package/dist/routes/rbac.d.ts.map +1 -0
  284. package/dist/routes/rbac.js +126 -0
  285. package/dist/routes/rbac.js.map +1 -0
  286. package/dist/routes/shell.d.ts +22 -0
  287. package/dist/routes/shell.d.ts.map +1 -0
  288. package/dist/routes/shell.js +123 -0
  289. package/dist/routes/shell.js.map +1 -0
  290. package/dist/routes/subscriptions.d.ts +21 -0
  291. package/dist/routes/subscriptions.d.ts.map +1 -0
  292. package/dist/routes/subscriptions.js +127 -0
  293. package/dist/routes/subscriptions.js.map +1 -0
  294. package/dist/routes/tags.d.ts +23 -0
  295. package/dist/routes/tags.d.ts.map +1 -0
  296. package/dist/routes/tags.js +68 -0
  297. package/dist/routes/tags.js.map +1 -0
  298. package/dist/routes/topics.d.ts +12 -0
  299. package/dist/routes/topics.d.ts.map +1 -0
  300. package/dist/routes/topics.js +49 -0
  301. package/dist/routes/topics.js.map +1 -0
  302. package/dist/routes/webhooks.d.ts +31 -0
  303. package/dist/routes/webhooks.d.ts.map +1 -0
  304. package/dist/routes/webhooks.js +173 -0
  305. package/dist/routes/webhooks.js.map +1 -0
  306. package/dist/schema/index.d.ts +4 -0
  307. package/dist/schema/index.d.ts.map +1 -0
  308. package/dist/schema/index.js +6 -0
  309. package/dist/schema/index.js.map +1 -0
  310. package/dist/schema/insights-ingest.d.ts +959 -0
  311. package/dist/schema/insights-ingest.d.ts.map +1 -0
  312. package/dist/schema/insights-ingest.js +112 -0
  313. package/dist/schema/insights-ingest.js.map +1 -0
  314. package/dist/schema/migrations.d.ts +63 -0
  315. package/dist/schema/migrations.d.ts.map +1 -0
  316. package/dist/schema/migrations.js +589 -0
  317. package/dist/schema/migrations.js.map +1 -0
  318. package/dist/schema/tables.d.ts +11 -0
  319. package/dist/schema/tables.d.ts.map +1 -0
  320. package/dist/schema/tables.js +56 -0
  321. package/dist/schema/tables.js.map +1 -0
  322. package/dist/schema/types.d.ts +476 -0
  323. package/dist/schema/types.d.ts.map +1 -0
  324. package/dist/schema/types.js +37 -0
  325. package/dist/schema/types.js.map +1 -0
  326. package/dist/ui/api/_authz.d.ts +6 -0
  327. package/dist/ui/api/_authz.d.ts.map +1 -0
  328. package/dist/ui/api/_authz.js +74 -0
  329. package/dist/ui/api/_authz.js.map +1 -0
  330. package/dist/ui/api/_content-config.d.ts +22 -0
  331. package/dist/ui/api/_content-config.d.ts.map +1 -0
  332. package/dist/ui/api/_content-config.js +50 -0
  333. package/dist/ui/api/_content-config.js.map +1 -0
  334. package/dist/ui/api/activity.d.ts +3 -0
  335. package/dist/ui/api/activity.d.ts.map +1 -0
  336. package/dist/ui/api/activity.js +28 -0
  337. package/dist/ui/api/activity.js.map +1 -0
  338. package/dist/ui/api/analytics.d.ts +3 -0
  339. package/dist/ui/api/analytics.d.ts.map +1 -0
  340. package/dist/ui/api/analytics.js +36 -0
  341. package/dist/ui/api/analytics.js.map +1 -0
  342. package/dist/ui/api/authors/[id].d.ts +4 -0
  343. package/dist/ui/api/authors/[id].d.ts.map +1 -0
  344. package/dist/ui/api/authors/[id].js +17 -0
  345. package/dist/ui/api/authors/[id].js.map +1 -0
  346. package/dist/ui/api/authors.d.ts +4 -0
  347. package/dist/ui/api/authors.d.ts.map +1 -0
  348. package/dist/ui/api/authors.js +12 -0
  349. package/dist/ui/api/authors.js.map +1 -0
  350. package/dist/ui/api/calendar.d.ts +3 -0
  351. package/dist/ui/api/calendar.d.ts.map +1 -0
  352. package/dist/ui/api/calendar.js +16 -0
  353. package/dist/ui/api/calendar.js.map +1 -0
  354. package/dist/ui/api/content/[id]/ai/headlines.d.ts +3 -0
  355. package/dist/ui/api/content/[id]/ai/headlines.d.ts.map +1 -0
  356. package/dist/ui/api/content/[id]/ai/headlines.js +7 -0
  357. package/dist/ui/api/content/[id]/ai/headlines.js.map +1 -0
  358. package/dist/ui/api/content/[id]/ai/meta-description.d.ts +3 -0
  359. package/dist/ui/api/content/[id]/ai/meta-description.d.ts.map +1 -0
  360. package/dist/ui/api/content/[id]/ai/meta-description.js +6 -0
  361. package/dist/ui/api/content/[id]/ai/meta-description.js.map +1 -0
  362. package/dist/ui/api/content/[id]/ai/og-image.d.ts +3 -0
  363. package/dist/ui/api/content/[id]/ai/og-image.d.ts.map +1 -0
  364. package/dist/ui/api/content/[id]/ai/og-image.js +7 -0
  365. package/dist/ui/api/content/[id]/ai/og-image.js.map +1 -0
  366. package/dist/ui/api/content/[id]/ai/proofread.d.ts +3 -0
  367. package/dist/ui/api/content/[id]/ai/proofread.d.ts.map +1 -0
  368. package/dist/ui/api/content/[id]/ai/proofread.js +7 -0
  369. package/dist/ui/api/content/[id]/ai/proofread.js.map +1 -0
  370. package/dist/ui/api/content/[id]/ai/takeaways.d.ts +3 -0
  371. package/dist/ui/api/content/[id]/ai/takeaways.d.ts.map +1 -0
  372. package/dist/ui/api/content/[id]/ai/takeaways.js +6 -0
  373. package/dist/ui/api/content/[id]/ai/takeaways.js.map +1 -0
  374. package/dist/ui/api/content/[id]/contributors.d.ts +4 -0
  375. package/dist/ui/api/content/[id]/contributors.d.ts.map +1 -0
  376. package/dist/ui/api/content/[id]/contributors.js +8 -0
  377. package/dist/ui/api/content/[id]/contributors.js.map +1 -0
  378. package/dist/ui/api/content/[id]/preview-token.d.ts +3 -0
  379. package/dist/ui/api/content/[id]/preview-token.d.ts.map +1 -0
  380. package/dist/ui/api/content/[id]/preview-token.js +16 -0
  381. package/dist/ui/api/content/[id]/preview-token.js.map +1 -0
  382. package/dist/ui/api/content/[id]/revisions/[rev]/restore.d.ts +3 -0
  383. package/dist/ui/api/content/[id]/revisions/[rev]/restore.d.ts.map +1 -0
  384. package/dist/ui/api/content/[id]/revisions/[rev]/restore.js +7 -0
  385. package/dist/ui/api/content/[id]/revisions/[rev]/restore.js.map +1 -0
  386. package/dist/ui/api/content/[id]/revisions/[rev].d.ts +3 -0
  387. package/dist/ui/api/content/[id]/revisions/[rev].d.ts.map +1 -0
  388. package/dist/ui/api/content/[id]/revisions/[rev].js +6 -0
  389. package/dist/ui/api/content/[id]/revisions/[rev].js.map +1 -0
  390. package/dist/ui/api/content/[id]/revisions.d.ts +3 -0
  391. package/dist/ui/api/content/[id]/revisions.d.ts.map +1 -0
  392. package/dist/ui/api/content/[id]/revisions.js +6 -0
  393. package/dist/ui/api/content/[id]/revisions.js.map +1 -0
  394. package/dist/ui/api/content/[id]/seo-score.d.ts +3 -0
  395. package/dist/ui/api/content/[id]/seo-score.d.ts.map +1 -0
  396. package/dist/ui/api/content/[id]/seo-score.js +7 -0
  397. package/dist/ui/api/content/[id]/seo-score.js.map +1 -0
  398. package/dist/ui/api/content/[id].d.ts +5 -0
  399. package/dist/ui/api/content/[id].d.ts.map +1 -0
  400. package/dist/ui/api/content/[id].js +17 -0
  401. package/dist/ui/api/content/[id].js.map +1 -0
  402. package/dist/ui/api/content/bulk.d.ts +3 -0
  403. package/dist/ui/api/content/bulk.d.ts.map +1 -0
  404. package/dist/ui/api/content/bulk.js +7 -0
  405. package/dist/ui/api/content/bulk.js.map +1 -0
  406. package/dist/ui/api/content/counts.d.ts +3 -0
  407. package/dist/ui/api/content/counts.d.ts.map +1 -0
  408. package/dist/ui/api/content/counts.js +8 -0
  409. package/dist/ui/api/content/counts.js.map +1 -0
  410. package/dist/ui/api/content/foundry-callback.d.ts +3 -0
  411. package/dist/ui/api/content/foundry-callback.d.ts.map +1 -0
  412. package/dist/ui/api/content/foundry-callback.js +8 -0
  413. package/dist/ui/api/content/foundry-callback.js.map +1 -0
  414. package/dist/ui/api/content/import/confirm.d.ts +3 -0
  415. package/dist/ui/api/content/import/confirm.d.ts.map +1 -0
  416. package/dist/ui/api/content/import/confirm.js +11 -0
  417. package/dist/ui/api/content/import/confirm.js.map +1 -0
  418. package/dist/ui/api/content/import/parse.d.ts +3 -0
  419. package/dist/ui/api/content/import/parse.d.ts.map +1 -0
  420. package/dist/ui/api/content/import/parse.js +11 -0
  421. package/dist/ui/api/content/import/parse.js.map +1 -0
  422. package/dist/ui/api/content/insights-ingest.d.ts +3 -0
  423. package/dist/ui/api/content/insights-ingest.d.ts.map +1 -0
  424. package/dist/ui/api/content/insights-ingest.js +15 -0
  425. package/dist/ui/api/content/insights-ingest.js.map +1 -0
  426. package/dist/ui/api/content-insights/dismiss.d.ts +3 -0
  427. package/dist/ui/api/content-insights/dismiss.d.ts.map +1 -0
  428. package/dist/ui/api/content-insights/dismiss.js +16 -0
  429. package/dist/ui/api/content-insights/dismiss.js.map +1 -0
  430. package/dist/ui/api/content-insights/index.d.ts +3 -0
  431. package/dist/ui/api/content-insights/index.d.ts.map +1 -0
  432. package/dist/ui/api/content-insights/index.js +12 -0
  433. package/dist/ui/api/content-insights/index.js.map +1 -0
  434. package/dist/ui/api/content-insights/undismiss.d.ts +3 -0
  435. package/dist/ui/api/content-insights/undismiss.d.ts.map +1 -0
  436. package/dist/ui/api/content-insights/undismiss.js +16 -0
  437. package/dist/ui/api/content-insights/undismiss.js.map +1 -0
  438. package/dist/ui/api/content.d.ts +4 -0
  439. package/dist/ui/api/content.d.ts.map +1 -0
  440. package/dist/ui/api/content.js +16 -0
  441. package/dist/ui/api/content.js.map +1 -0
  442. package/dist/ui/api/dashboard.d.ts +3 -0
  443. package/dist/ui/api/dashboard.d.ts.map +1 -0
  444. package/dist/ui/api/dashboard.js +22 -0
  445. package/dist/ui/api/dashboard.js.map +1 -0
  446. package/dist/ui/api/me.d.ts +3 -0
  447. package/dist/ui/api/me.d.ts.map +1 -0
  448. package/dist/ui/api/me.js +18 -0
  449. package/dist/ui/api/me.js.map +1 -0
  450. package/dist/ui/api/media/[id].d.ts +3 -0
  451. package/dist/ui/api/media/[id].d.ts.map +1 -0
  452. package/dist/ui/api/media/[id].js +17 -0
  453. package/dist/ui/api/media/[id].js.map +1 -0
  454. package/dist/ui/api/media/images.d.ts +3 -0
  455. package/dist/ui/api/media/images.d.ts.map +1 -0
  456. package/dist/ui/api/media/images.js +6 -0
  457. package/dist/ui/api/media/images.js.map +1 -0
  458. package/dist/ui/api/media/library/[id].d.ts +3 -0
  459. package/dist/ui/api/media/library/[id].d.ts.map +1 -0
  460. package/dist/ui/api/media/library/[id].js +6 -0
  461. package/dist/ui/api/media/library/[id].js.map +1 -0
  462. package/dist/ui/api/media/library.d.ts +3 -0
  463. package/dist/ui/api/media/library.d.ts.map +1 -0
  464. package/dist/ui/api/media/library.js +17 -0
  465. package/dist/ui/api/media/library.js.map +1 -0
  466. package/dist/ui/api/media/podcast/abort.d.ts +3 -0
  467. package/dist/ui/api/media/podcast/abort.d.ts.map +1 -0
  468. package/dist/ui/api/media/podcast/abort.js +4 -0
  469. package/dist/ui/api/media/podcast/abort.js.map +1 -0
  470. package/dist/ui/api/media/podcast/complete.d.ts +3 -0
  471. package/dist/ui/api/media/podcast/complete.d.ts.map +1 -0
  472. package/dist/ui/api/media/podcast/complete.js +4 -0
  473. package/dist/ui/api/media/podcast/complete.js.map +1 -0
  474. package/dist/ui/api/media/podcast/init.d.ts +3 -0
  475. package/dist/ui/api/media/podcast/init.d.ts.map +1 -0
  476. package/dist/ui/api/media/podcast/init.js +4 -0
  477. package/dist/ui/api/media/podcast/init.js.map +1 -0
  478. package/dist/ui/api/media/podcast/part.d.ts +3 -0
  479. package/dist/ui/api/media/podcast/part.d.ts.map +1 -0
  480. package/dist/ui/api/media/podcast/part.js +4 -0
  481. package/dist/ui/api/media/podcast/part.js.map +1 -0
  482. package/dist/ui/api/media/podcast.d.ts +3 -0
  483. package/dist/ui/api/media/podcast.d.ts.map +1 -0
  484. package/dist/ui/api/media/podcast.js +6 -0
  485. package/dist/ui/api/media/podcast.js.map +1 -0
  486. package/dist/ui/api/media/videos/abort.d.ts +3 -0
  487. package/dist/ui/api/media/videos/abort.d.ts.map +1 -0
  488. package/dist/ui/api/media/videos/abort.js +6 -0
  489. package/dist/ui/api/media/videos/abort.js.map +1 -0
  490. package/dist/ui/api/media/videos/complete.d.ts +3 -0
  491. package/dist/ui/api/media/videos/complete.d.ts.map +1 -0
  492. package/dist/ui/api/media/videos/complete.js +6 -0
  493. package/dist/ui/api/media/videos/complete.js.map +1 -0
  494. package/dist/ui/api/media/videos/init.d.ts +3 -0
  495. package/dist/ui/api/media/videos/init.d.ts.map +1 -0
  496. package/dist/ui/api/media/videos/init.js +6 -0
  497. package/dist/ui/api/media/videos/init.js.map +1 -0
  498. package/dist/ui/api/media/videos/part.d.ts +3 -0
  499. package/dist/ui/api/media/videos/part.d.ts.map +1 -0
  500. package/dist/ui/api/media/videos/part.js +6 -0
  501. package/dist/ui/api/media/videos/part.js.map +1 -0
  502. package/dist/ui/api/notifications.d.ts +4 -0
  503. package/dist/ui/api/notifications.d.ts.map +1 -0
  504. package/dist/ui/api/notifications.js +20 -0
  505. package/dist/ui/api/notifications.js.map +1 -0
  506. package/dist/ui/api/search.d.ts +3 -0
  507. package/dist/ui/api/search.d.ts.map +1 -0
  508. package/dist/ui/api/search.js +18 -0
  509. package/dist/ui/api/search.js.map +1 -0
  510. package/dist/ui/api/settings/api-keys/[id].d.ts +3 -0
  511. package/dist/ui/api/settings/api-keys/[id].d.ts.map +1 -0
  512. package/dist/ui/api/settings/api-keys/[id].js +22 -0
  513. package/dist/ui/api/settings/api-keys/[id].js.map +1 -0
  514. package/dist/ui/api/settings/api-keys.d.ts +4 -0
  515. package/dist/ui/api/settings/api-keys.d.ts.map +1 -0
  516. package/dist/ui/api/settings/api-keys.js +19 -0
  517. package/dist/ui/api/settings/api-keys.js.map +1 -0
  518. package/dist/ui/api/settings/domains.d.ts +3 -0
  519. package/dist/ui/api/settings/domains.d.ts.map +1 -0
  520. package/dist/ui/api/settings/domains.js +32 -0
  521. package/dist/ui/api/settings/domains.js.map +1 -0
  522. package/dist/ui/api/settings/integrations.d.ts +3 -0
  523. package/dist/ui/api/settings/integrations.d.ts.map +1 -0
  524. package/dist/ui/api/settings/integrations.js +32 -0
  525. package/dist/ui/api/settings/integrations.js.map +1 -0
  526. package/dist/ui/api/settings/members/[userId].d.ts +4 -0
  527. package/dist/ui/api/settings/members/[userId].d.ts.map +1 -0
  528. package/dist/ui/api/settings/members/[userId].js +26 -0
  529. package/dist/ui/api/settings/members/[userId].js.map +1 -0
  530. package/dist/ui/api/settings/members/invite.d.ts +3 -0
  531. package/dist/ui/api/settings/members/invite.d.ts.map +1 -0
  532. package/dist/ui/api/settings/members/invite.js +21 -0
  533. package/dist/ui/api/settings/members/invite.js.map +1 -0
  534. package/dist/ui/api/settings/members.d.ts +3 -0
  535. package/dist/ui/api/settings/members.d.ts.map +1 -0
  536. package/dist/ui/api/settings/members.js +17 -0
  537. package/dist/ui/api/settings/members.js.map +1 -0
  538. package/dist/ui/api/settings/webhooks/[id]/test.d.ts +3 -0
  539. package/dist/ui/api/settings/webhooks/[id]/test.d.ts.map +1 -0
  540. package/dist/ui/api/settings/webhooks/[id]/test.js +24 -0
  541. package/dist/ui/api/settings/webhooks/[id]/test.js.map +1 -0
  542. package/dist/ui/api/settings/webhooks/[id].d.ts +3 -0
  543. package/dist/ui/api/settings/webhooks/[id].d.ts.map +1 -0
  544. package/dist/ui/api/settings/webhooks/[id].js +23 -0
  545. package/dist/ui/api/settings/webhooks/[id].js.map +1 -0
  546. package/dist/ui/api/settings/webhooks.d.ts +4 -0
  547. package/dist/ui/api/settings/webhooks.d.ts.map +1 -0
  548. package/dist/ui/api/settings/webhooks.js +21 -0
  549. package/dist/ui/api/settings/webhooks.js.map +1 -0
  550. package/dist/ui/api/subscriptions.d.ts +4 -0
  551. package/dist/ui/api/subscriptions.d.ts.map +1 -0
  552. package/dist/ui/api/subscriptions.js +47 -0
  553. package/dist/ui/api/subscriptions.js.map +1 -0
  554. package/dist/ui/api/tags/[id].d.ts +4 -0
  555. package/dist/ui/api/tags/[id].d.ts.map +1 -0
  556. package/dist/ui/api/tags/[id].js +18 -0
  557. package/dist/ui/api/tags/[id].js.map +1 -0
  558. package/dist/ui/api/tags/index.d.ts +4 -0
  559. package/dist/ui/api/tags/index.d.ts.map +1 -0
  560. package/dist/ui/api/tags/index.js +13 -0
  561. package/dist/ui/api/tags/index.js.map +1 -0
  562. package/dist/ui/api/topics/[id].d.ts +3 -0
  563. package/dist/ui/api/topics/[id].d.ts.map +1 -0
  564. package/dist/ui/api/topics/[id].js +15 -0
  565. package/dist/ui/api/topics/[id].js.map +1 -0
  566. package/dist/ui/api/topics/index.d.ts +4 -0
  567. package/dist/ui/api/topics/index.d.ts.map +1 -0
  568. package/dist/ui/api/topics/index.js +12 -0
  569. package/dist/ui/api/topics/index.js.map +1 -0
  570. package/dist/ui/api/workspace-settings.d.ts +4 -0
  571. package/dist/ui/api/workspace-settings.d.ts.map +1 -0
  572. package/dist/ui/api/workspace-settings.js +20 -0
  573. package/dist/ui/api/workspace-settings.js.map +1 -0
  574. package/dist/ui/client/boot-state.d.ts +15 -0
  575. package/dist/ui/client/boot-state.d.ts.map +1 -0
  576. package/dist/ui/client/boot-state.js +36 -0
  577. package/dist/ui/client/boot-state.js.map +1 -0
  578. package/dist/ui/client/mount.d.ts +3 -0
  579. package/dist/ui/client/mount.d.ts.map +1 -0
  580. package/dist/ui/client/mount.js +37 -0
  581. package/dist/ui/client/mount.js.map +1 -0
  582. package/dist/ui/commands.d.ts +23 -0
  583. package/dist/ui/commands.d.ts.map +1 -0
  584. package/dist/ui/commands.js +48 -0
  585. package/dist/ui/commands.js.map +1 -0
  586. package/dist/ui/components/CmsApp.d.ts +16 -0
  587. package/dist/ui/components/CmsApp.d.ts.map +1 -0
  588. package/dist/ui/components/CmsApp.js +74 -0
  589. package/dist/ui/components/CmsApp.js.map +1 -0
  590. package/dist/ui/components/CommandPalette.d.ts +7 -0
  591. package/dist/ui/components/CommandPalette.d.ts.map +1 -0
  592. package/dist/ui/components/CommandPalette.js +61 -0
  593. package/dist/ui/components/CommandPalette.js.map +1 -0
  594. package/dist/ui/components/NoAccessScreen.d.ts +2 -0
  595. package/dist/ui/components/NoAccessScreen.d.ts.map +1 -0
  596. package/dist/ui/components/NoAccessScreen.js +42 -0
  597. package/dist/ui/components/NoAccessScreen.js.map +1 -0
  598. package/dist/ui/components/ShareModal.d.ts +27 -0
  599. package/dist/ui/components/ShareModal.d.ts.map +1 -0
  600. package/dist/ui/components/ShareModal.js +208 -0
  601. package/dist/ui/components/ShareModal.js.map +1 -0
  602. package/dist/ui/components/SharePickers.d.ts +39 -0
  603. package/dist/ui/components/SharePickers.d.ts.map +1 -0
  604. package/dist/ui/components/SharePickers.js +352 -0
  605. package/dist/ui/components/SharePickers.js.map +1 -0
  606. package/dist/ui/components/ShareStatsPanel.d.ts +22 -0
  607. package/dist/ui/components/ShareStatsPanel.d.ts.map +1 -0
  608. package/dist/ui/components/ShareStatsPanel.js +317 -0
  609. package/dist/ui/components/ShareStatsPanel.js.map +1 -0
  610. package/dist/ui/components/Sidebar.d.ts +7 -0
  611. package/dist/ui/components/Sidebar.d.ts.map +1 -0
  612. package/dist/ui/components/Sidebar.js +20 -0
  613. package/dist/ui/components/Sidebar.js.map +1 -0
  614. package/dist/ui/components/SiteSwitcher.d.ts +4 -0
  615. package/dist/ui/components/SiteSwitcher.d.ts.map +1 -0
  616. package/dist/ui/components/SiteSwitcher.js +35 -0
  617. package/dist/ui/components/SiteSwitcher.js.map +1 -0
  618. package/dist/ui/components/Topbar.d.ts +9 -0
  619. package/dist/ui/components/Topbar.d.ts.map +1 -0
  620. package/dist/ui/components/Topbar.js +20 -0
  621. package/dist/ui/components/Topbar.js.map +1 -0
  622. package/dist/ui/editor/AiAssistPanel.d.ts +8 -0
  623. package/dist/ui/editor/AiAssistPanel.d.ts.map +1 -0
  624. package/dist/ui/editor/AiAssistPanel.js +221 -0
  625. package/dist/ui/editor/AiAssistPanel.js.map +1 -0
  626. package/dist/ui/editor/ContentForm.d.ts +46 -0
  627. package/dist/ui/editor/ContentForm.d.ts.map +1 -0
  628. package/dist/ui/editor/ContentForm.js +821 -0
  629. package/dist/ui/editor/ContentForm.js.map +1 -0
  630. package/dist/ui/editor/Rte.d.ts +16 -0
  631. package/dist/ui/editor/Rte.d.ts.map +1 -0
  632. package/dist/ui/editor/Rte.js +272 -0
  633. package/dist/ui/editor/Rte.js.map +1 -0
  634. package/dist/ui/editor/ai-assist.d.ts +43 -0
  635. package/dist/ui/editor/ai-assist.d.ts.map +1 -0
  636. package/dist/ui/editor/ai-assist.js +114 -0
  637. package/dist/ui/editor/ai-assist.js.map +1 -0
  638. package/dist/ui/editor/autosave.d.ts +18 -0
  639. package/dist/ui/editor/autosave.d.ts.map +1 -0
  640. package/dist/ui/editor/autosave.js +23 -0
  641. package/dist/ui/editor/autosave.js.map +1 -0
  642. package/dist/ui/editor/content-payload.d.ts +19 -0
  643. package/dist/ui/editor/content-payload.d.ts.map +1 -0
  644. package/dist/ui/editor/content-payload.js +97 -0
  645. package/dist/ui/editor/content-payload.js.map +1 -0
  646. package/dist/ui/editor/editor-media-upload.d.ts +6 -0
  647. package/dist/ui/editor/editor-media-upload.d.ts.map +1 -0
  648. package/dist/ui/editor/editor-media-upload.js +20 -0
  649. package/dist/ui/editor/editor-media-upload.js.map +1 -0
  650. package/dist/ui/editor/serialize.d.ts +6 -0
  651. package/dist/ui/editor/serialize.d.ts.map +1 -0
  652. package/dist/ui/editor/serialize.js +479 -0
  653. package/dist/ui/editor/serialize.js.map +1 -0
  654. package/dist/ui/editor/tweet-embed.d.ts +4 -0
  655. package/dist/ui/editor/tweet-embed.d.ts.map +1 -0
  656. package/dist/ui/editor/tweet-embed.js +49 -0
  657. package/dist/ui/editor/tweet-embed.js.map +1 -0
  658. package/dist/ui/hash-router.d.ts +5 -0
  659. package/dist/ui/hash-router.d.ts.map +1 -0
  660. package/dist/ui/hash-router.js +25 -0
  661. package/dist/ui/hash-router.js.map +1 -0
  662. package/dist/ui/icons.d.ts +32 -0
  663. package/dist/ui/icons.d.ts.map +1 -0
  664. package/dist/ui/icons.js +86 -0
  665. package/dist/ui/icons.js.map +1 -0
  666. package/dist/ui/inspector/Field.d.ts +12 -0
  667. package/dist/ui/inspector/Field.d.ts.map +1 -0
  668. package/dist/ui/inspector/Field.js +8 -0
  669. package/dist/ui/inspector/Field.js.map +1 -0
  670. package/dist/ui/inspector/FoundryTab.d.ts +9 -0
  671. package/dist/ui/inspector/FoundryTab.d.ts.map +1 -0
  672. package/dist/ui/inspector/FoundryTab.js +362 -0
  673. package/dist/ui/inspector/FoundryTab.js.map +1 -0
  674. package/dist/ui/inspector/HistoryTab.d.ts +7 -0
  675. package/dist/ui/inspector/HistoryTab.d.ts.map +1 -0
  676. package/dist/ui/inspector/HistoryTab.js +289 -0
  677. package/dist/ui/inspector/HistoryTab.js.map +1 -0
  678. package/dist/ui/inspector/Inspector.d.ts +13 -0
  679. package/dist/ui/inspector/Inspector.d.ts.map +1 -0
  680. package/dist/ui/inspector/Inspector.js +163 -0
  681. package/dist/ui/inspector/Inspector.js.map +1 -0
  682. package/dist/ui/inspector/OrganizeTab.d.ts +15 -0
  683. package/dist/ui/inspector/OrganizeTab.d.ts.map +1 -0
  684. package/dist/ui/inspector/OrganizeTab.js +319 -0
  685. package/dist/ui/inspector/OrganizeTab.js.map +1 -0
  686. package/dist/ui/inspector/PublishTab.d.ts +18 -0
  687. package/dist/ui/inspector/PublishTab.d.ts.map +1 -0
  688. package/dist/ui/inspector/PublishTab.js +339 -0
  689. package/dist/ui/inspector/PublishTab.js.map +1 -0
  690. package/dist/ui/inspector/Section.d.ts +10 -0
  691. package/dist/ui/inspector/Section.d.ts.map +1 -0
  692. package/dist/ui/inspector/Section.js +40 -0
  693. package/dist/ui/inspector/Section.js.map +1 -0
  694. package/dist/ui/inspector/SeoTab.d.ts +19 -0
  695. package/dist/ui/inspector/SeoTab.d.ts.map +1 -0
  696. package/dist/ui/inspector/SeoTab.js +328 -0
  697. package/dist/ui/inspector/SeoTab.js.map +1 -0
  698. package/dist/ui/inspector/foundry-stages.d.ts +36 -0
  699. package/dist/ui/inspector/foundry-stages.d.ts.map +1 -0
  700. package/dist/ui/inspector/foundry-stages.js +101 -0
  701. package/dist/ui/inspector/foundry-stages.js.map +1 -0
  702. package/dist/ui/inspector/inspector-data.d.ts +80 -0
  703. package/dist/ui/inspector/inspector-data.d.ts.map +1 -0
  704. package/dist/ui/inspector/inspector-data.js +172 -0
  705. package/dist/ui/inspector/inspector-data.js.map +1 -0
  706. package/dist/ui/inspector/organize-data.d.ts +23 -0
  707. package/dist/ui/inspector/organize-data.d.ts.map +1 -0
  708. package/dist/ui/inspector/organize-data.js +28 -0
  709. package/dist/ui/inspector/organize-data.js.map +1 -0
  710. package/dist/ui/inspector/revision-diff.d.ts +49 -0
  711. package/dist/ui/inspector/revision-diff.d.ts.map +1 -0
  712. package/dist/ui/inspector/revision-diff.js +166 -0
  713. package/dist/ui/inspector/revision-diff.js.map +1 -0
  714. package/dist/ui/inspector/seo-helpers.d.ts +37 -0
  715. package/dist/ui/inspector/seo-helpers.d.ts.map +1 -0
  716. package/dist/ui/inspector/seo-helpers.js +37 -0
  717. package/dist/ui/inspector/seo-helpers.js.map +1 -0
  718. package/dist/ui/inspector/tab-visibility.d.ts +14 -0
  719. package/dist/ui/inspector/tab-visibility.d.ts.map +1 -0
  720. package/dist/ui/inspector/tab-visibility.js +28 -0
  721. package/dist/ui/inspector/tab-visibility.js.map +1 -0
  722. package/dist/ui/nav.d.ts +16 -0
  723. package/dist/ui/nav.d.ts.map +1 -0
  724. package/dist/ui/nav.js +33 -0
  725. package/dist/ui/nav.js.map +1 -0
  726. package/dist/ui/pages/admin.astro +32 -0
  727. package/dist/ui/preview/draft-page.d.ts +37 -0
  728. package/dist/ui/preview/draft-page.d.ts.map +1 -0
  729. package/dist/ui/preview/draft-page.js +212 -0
  730. package/dist/ui/preview/draft-page.js.map +1 -0
  731. package/dist/ui/preview/preview-layout.d.ts +23 -0
  732. package/dist/ui/preview/preview-layout.d.ts.map +1 -0
  733. package/dist/ui/preview/preview-layout.js +30 -0
  734. package/dist/ui/preview/preview-layout.js.map +1 -0
  735. package/dist/ui/screens/AnalyticsScreen.d.ts +2 -0
  736. package/dist/ui/screens/AnalyticsScreen.d.ts.map +1 -0
  737. package/dist/ui/screens/AnalyticsScreen.js +408 -0
  738. package/dist/ui/screens/AnalyticsScreen.js.map +1 -0
  739. package/dist/ui/screens/AuthorsScreen.d.ts +2 -0
  740. package/dist/ui/screens/AuthorsScreen.d.ts.map +1 -0
  741. package/dist/ui/screens/AuthorsScreen.js +225 -0
  742. package/dist/ui/screens/AuthorsScreen.js.map +1 -0
  743. package/dist/ui/screens/CalendarScreen.d.ts +6 -0
  744. package/dist/ui/screens/CalendarScreen.d.ts.map +1 -0
  745. package/dist/ui/screens/CalendarScreen.js +327 -0
  746. package/dist/ui/screens/CalendarScreen.js.map +1 -0
  747. package/dist/ui/screens/ContentInsightsScreen.d.ts +2 -0
  748. package/dist/ui/screens/ContentInsightsScreen.d.ts.map +1 -0
  749. package/dist/ui/screens/ContentInsightsScreen.js +129 -0
  750. package/dist/ui/screens/ContentInsightsScreen.js.map +1 -0
  751. package/dist/ui/screens/ContentRoute.d.ts +2 -0
  752. package/dist/ui/screens/ContentRoute.d.ts.map +1 -0
  753. package/dist/ui/screens/ContentRoute.js +32 -0
  754. package/dist/ui/screens/ContentRoute.js.map +1 -0
  755. package/dist/ui/screens/DashboardScreen.d.ts +6 -0
  756. package/dist/ui/screens/DashboardScreen.d.ts.map +1 -0
  757. package/dist/ui/screens/DashboardScreen.js +273 -0
  758. package/dist/ui/screens/DashboardScreen.js.map +1 -0
  759. package/dist/ui/screens/EditorScreen.d.ts +7 -0
  760. package/dist/ui/screens/EditorScreen.d.ts.map +1 -0
  761. package/dist/ui/screens/EditorScreen.js +426 -0
  762. package/dist/ui/screens/EditorScreen.js.map +1 -0
  763. package/dist/ui/screens/LibraryScreen.d.ts +6 -0
  764. package/dist/ui/screens/LibraryScreen.d.ts.map +1 -0
  765. package/dist/ui/screens/LibraryScreen.js +580 -0
  766. package/dist/ui/screens/LibraryScreen.js.map +1 -0
  767. package/dist/ui/screens/MediaScreen.d.ts +2 -0
  768. package/dist/ui/screens/MediaScreen.d.ts.map +1 -0
  769. package/dist/ui/screens/MediaScreen.js +173 -0
  770. package/dist/ui/screens/MediaScreen.js.map +1 -0
  771. package/dist/ui/screens/SettingsScreen.d.ts +4 -0
  772. package/dist/ui/screens/SettingsScreen.d.ts.map +1 -0
  773. package/dist/ui/screens/SettingsScreen.js +751 -0
  774. package/dist/ui/screens/SettingsScreen.js.map +1 -0
  775. package/dist/ui/screens/SocialShareScreen.d.ts +2 -0
  776. package/dist/ui/screens/SocialShareScreen.d.ts.map +1 -0
  777. package/dist/ui/screens/SocialShareScreen.js +224 -0
  778. package/dist/ui/screens/SocialShareScreen.js.map +1 -0
  779. package/dist/ui/screens/SubscriptionsScreen.d.ts +2 -0
  780. package/dist/ui/screens/SubscriptionsScreen.d.ts.map +1 -0
  781. package/dist/ui/screens/SubscriptionsScreen.js +441 -0
  782. package/dist/ui/screens/SubscriptionsScreen.js.map +1 -0
  783. package/dist/ui/screens/TopicsScreen.d.ts +2 -0
  784. package/dist/ui/screens/TopicsScreen.d.ts.map +1 -0
  785. package/dist/ui/screens/TopicsScreen.js +360 -0
  786. package/dist/ui/screens/TopicsScreen.js.map +1 -0
  787. package/dist/ui/screens/analytics-data.d.ts +19 -0
  788. package/dist/ui/screens/analytics-data.d.ts.map +1 -0
  789. package/dist/ui/screens/analytics-data.js +42 -0
  790. package/dist/ui/screens/analytics-data.js.map +1 -0
  791. package/dist/ui/screens/calendar-data.d.ts +45 -0
  792. package/dist/ui/screens/calendar-data.d.ts.map +1 -0
  793. package/dist/ui/screens/calendar-data.js +70 -0
  794. package/dist/ui/screens/calendar-data.js.map +1 -0
  795. package/dist/ui/screens/content-insights-data.d.ts +54 -0
  796. package/dist/ui/screens/content-insights-data.d.ts.map +1 -0
  797. package/dist/ui/screens/content-insights-data.js +82 -0
  798. package/dist/ui/screens/content-insights-data.js.map +1 -0
  799. package/dist/ui/screens/content-view.d.ts +21 -0
  800. package/dist/ui/screens/content-view.d.ts.map +1 -0
  801. package/dist/ui/screens/content-view.js +17 -0
  802. package/dist/ui/screens/content-view.js.map +1 -0
  803. package/dist/ui/screens/library-data.d.ts +76 -0
  804. package/dist/ui/screens/library-data.d.ts.map +1 -0
  805. package/dist/ui/screens/library-data.js +116 -0
  806. package/dist/ui/screens/library-data.js.map +1 -0
  807. package/dist/ui/screens/media-upload.d.ts +19 -0
  808. package/dist/ui/screens/media-upload.d.ts.map +1 -0
  809. package/dist/ui/screens/media-upload.js +187 -0
  810. package/dist/ui/screens/media-upload.js.map +1 -0
  811. package/dist/ui/screens/public-url.d.ts +24 -0
  812. package/dist/ui/screens/public-url.d.ts.map +1 -0
  813. package/dist/ui/screens/public-url.js +74 -0
  814. package/dist/ui/screens/public-url.js.map +1 -0
  815. package/dist/ui/screens/registry.d.ts +3 -0
  816. package/dist/ui/screens/registry.d.ts.map +1 -0
  817. package/dist/ui/screens/registry.js +38 -0
  818. package/dist/ui/screens/registry.js.map +1 -0
  819. package/dist/ui/screens/render-state.d.ts +105 -0
  820. package/dist/ui/screens/render-state.d.ts.map +1 -0
  821. package/dist/ui/screens/render-state.js +127 -0
  822. package/dist/ui/screens/render-state.js.map +1 -0
  823. package/dist/ui/screens/settings-data.d.ts +55 -0
  824. package/dist/ui/screens/settings-data.d.ts.map +1 -0
  825. package/dist/ui/screens/settings-data.js +89 -0
  826. package/dist/ui/screens/settings-data.js.map +1 -0
  827. package/dist/ui/screens/settings-panels-data.d.ts +58 -0
  828. package/dist/ui/screens/settings-panels-data.d.ts.map +1 -0
  829. package/dist/ui/screens/settings-panels-data.js +88 -0
  830. package/dist/ui/screens/settings-panels-data.js.map +1 -0
  831. package/dist/ui/screens/social-share-data.d.ts +307 -0
  832. package/dist/ui/screens/social-share-data.d.ts.map +1 -0
  833. package/dist/ui/screens/social-share-data.js +447 -0
  834. package/dist/ui/screens/social-share-data.js.map +1 -0
  835. package/dist/ui/screens/topics-data.d.ts +38 -0
  836. package/dist/ui/screens/topics-data.d.ts.map +1 -0
  837. package/dist/ui/screens/topics-data.js +50 -0
  838. package/dist/ui/screens/topics-data.js.map +1 -0
  839. package/dist/ui/styles/broadsheet.css +394 -0
  840. package/dist/ui/theme.d.ts +23 -0
  841. package/dist/ui/theme.d.ts.map +1 -0
  842. package/dist/ui/theme.js +87 -0
  843. package/dist/ui/theme.js.map +1 -0
  844. package/dist/ui/tweaks.d.ts +7 -0
  845. package/dist/ui/tweaks.d.ts.map +1 -0
  846. package/dist/ui/tweaks.js +31 -0
  847. package/dist/ui/tweaks.js.map +1 -0
  848. package/dist/ui/use-hash-router.d.ts +6 -0
  849. package/dist/ui/use-hash-router.d.ts.map +1 -0
  850. package/dist/ui/use-hash-router.js +15 -0
  851. package/dist/ui/use-hash-router.js.map +1 -0
  852. package/dist/ui/use-tweaks.d.ts +6 -0
  853. package/dist/ui/use-tweaks.d.ts.map +1 -0
  854. package/dist/ui/use-tweaks.js +24 -0
  855. package/dist/ui/use-tweaks.js.map +1 -0
  856. package/dist/ui/workspace-context.d.ts +34 -0
  857. package/dist/ui/workspace-context.d.ts.map +1 -0
  858. package/dist/ui/workspace-context.js +32 -0
  859. package/dist/ui/workspace-context.js.map +1 -0
  860. package/migrations/0001_create_cms_tables.sql +200 -0
  861. package/migrations/0002_review_softdelete_board.sql +112 -0
  862. package/migrations/0003_content_contributors.sql +16 -0
  863. package/migrations/0004_seo_faq_columns.sql +6 -0
  864. package/migrations/0005_revision_delta_columns.sql +5 -0
  865. package/migrations/0006_processing_trigger_token.sql +4 -0
  866. package/migrations/0007_content_slug_redirects.sql +9 -0
  867. package/migrations/0008_workspace_settings.sql +17 -0
  868. package/migrations/0009_workspace_memberships.sql +36 -0
  869. package/migrations/0010_api_keys_webhooks.sql +21 -0
  870. package/migrations/0011_notifications_activity.sql +22 -0
  871. package/migrations/0012_content_imports.sql +10 -0
  872. package/migrations/0013_media_normalization.sql +4 -0
  873. package/migrations/0014_api_key_prefix.sql +3 -0
  874. package/migrations/0015_cms_topics.sql +7 -0
  875. package/migrations/0016_content_insights.sql +53 -0
  876. package/package.json +82 -0
  877. package/src/engine/activity-log.ts +39 -0
  878. package/src/engine/ai-prompts.ts +124 -0
  879. package/src/engine/ai-writeback.ts +62 -0
  880. package/src/engine/api-keys.ts +239 -0
  881. package/src/engine/content-insights.ts +198 -0
  882. package/src/engine/contributors.ts +95 -0
  883. package/src/engine/cron.ts +62 -0
  884. package/src/engine/d1.ts +29 -0
  885. package/src/engine/foundry-dispatch.ts +417 -0
  886. package/src/engine/import-parsers.ts +478 -0
  887. package/src/engine/index.ts +230 -0
  888. package/src/engine/invites.ts +271 -0
  889. package/src/engine/members.ts +216 -0
  890. package/src/engine/membership-rules.ts +63 -0
  891. package/src/engine/og-render.ts +59 -0
  892. package/src/engine/publish-guard.ts +123 -0
  893. package/src/engine/publisher.ts +1032 -0
  894. package/src/engine/revisions.ts +292 -0
  895. package/src/engine/sanitize.ts +183 -0
  896. package/src/engine/seed-membership.ts +92 -0
  897. package/src/engine/seo.ts +72 -0
  898. package/src/engine/slug-redirects.ts +34 -0
  899. package/src/engine/slug.ts +33 -0
  900. package/src/engine/soft-delete.ts +42 -0
  901. package/src/engine/tags.ts +95 -0
  902. package/src/engine/topics.ts +158 -0
  903. package/src/engine/url-guard.ts +136 -0
  904. package/src/engine/validator/checks/bare-url-not-autolinked.ts +78 -0
  905. package/src/engine/validator/checks/broken-footnote-label.ts +33 -0
  906. package/src/engine/validator/checks/double-encoded-entities.ts +46 -0
  907. package/src/engine/validator/checks/empty-alt-text.ts +35 -0
  908. package/src/engine/validator/checks/heading-hierarchy-skip.ts +33 -0
  909. package/src/engine/validator/checks/html-comment-leak.ts +58 -0
  910. package/src/engine/validator/checks/iframe-missing-dims-and-wrapper.ts +34 -0
  911. package/src/engine/validator/checks/invisible-control-chars.ts +58 -0
  912. package/src/engine/validator/checks/paywall-marker-leak.ts +43 -0
  913. package/src/engine/validator/checks/raw-block-html.ts +65 -0
  914. package/src/engine/validator/checks/stale-body-html.ts +39 -0
  915. package/src/engine/validator/checks/unresolved-footnote-anchor.ts +61 -0
  916. package/src/engine/validator/checks/word-gdocs-paste-artifacts.ts +72 -0
  917. package/src/engine/validator/index.ts +385 -0
  918. package/src/engine/validator/scan.ts +103 -0
  919. package/src/engine/validator/types.ts +114 -0
  920. package/src/engine/webhook-signer.ts +139 -0
  921. package/src/engine/webhooks.ts +224 -0
  922. package/src/index.ts +79 -0
  923. package/src/integration/index.ts +298 -0
  924. package/src/integration/options.ts +30 -0
  925. package/src/integration/vite-plugin.ts +37 -0
  926. package/src/providers/index.ts +2 -0
  927. package/src/providers/null.ts +160 -0
  928. package/src/providers/types.ts +284 -0
  929. package/src/routes/ai.ts +461 -0
  930. package/src/routes/analytics.ts +78 -0
  931. package/src/routes/api-keys.ts +133 -0
  932. package/src/routes/authors.ts +282 -0
  933. package/src/routes/authz-matrix.ts +239 -0
  934. package/src/routes/calendar.ts +127 -0
  935. package/src/routes/config.ts +99 -0
  936. package/src/routes/content-insights.ts +159 -0
  937. package/src/routes/content.ts +1753 -0
  938. package/src/routes/context.ts +146 -0
  939. package/src/routes/cron.ts +27 -0
  940. package/src/routes/dashboard.ts +174 -0
  941. package/src/routes/imports.ts +190 -0
  942. package/src/routes/index.ts +295 -0
  943. package/src/routes/media-lib.ts +405 -0
  944. package/src/routes/media.ts +944 -0
  945. package/src/routes/preview.ts +182 -0
  946. package/src/routes/rbac-invites.ts +220 -0
  947. package/src/routes/rbac.ts +155 -0
  948. package/src/routes/shell.ts +163 -0
  949. package/src/routes/subscriptions.ts +167 -0
  950. package/src/routes/tags.ts +93 -0
  951. package/src/routes/topics.ts +58 -0
  952. package/src/routes/webhooks.ts +233 -0
  953. package/src/schema/index.ts +45 -0
  954. package/src/schema/insights-ingest.ts +126 -0
  955. package/src/schema/migrations.ts +599 -0
  956. package/src/schema/tables.ts +59 -0
  957. package/src/schema/types.ts +576 -0
  958. package/src/ui/api/_authz.ts +100 -0
  959. package/src/ui/api/_content-config.ts +75 -0
  960. package/src/ui/api/activity.ts +33 -0
  961. package/src/ui/api/analytics.ts +42 -0
  962. package/src/ui/api/authors/[id].ts +23 -0
  963. package/src/ui/api/authors.ts +19 -0
  964. package/src/ui/api/calendar.ts +21 -0
  965. package/src/ui/api/content/[id]/ai/headlines.ts +10 -0
  966. package/src/ui/api/content/[id]/ai/meta-description.ts +11 -0
  967. package/src/ui/api/content/[id]/ai/og-image.ts +10 -0
  968. package/src/ui/api/content/[id]/ai/proofread.ts +10 -0
  969. package/src/ui/api/content/[id]/ai/takeaways.ts +11 -0
  970. package/src/ui/api/content/[id]/contributors.ts +13 -0
  971. package/src/ui/api/content/[id]/preview-token.ts +21 -0
  972. package/src/ui/api/content/[id]/revisions/[rev]/restore.ts +12 -0
  973. package/src/ui/api/content/[id]/revisions/[rev].ts +11 -0
  974. package/src/ui/api/content/[id]/revisions.ts +9 -0
  975. package/src/ui/api/content/[id]/seo-score.ts +10 -0
  976. package/src/ui/api/content/[id].ts +23 -0
  977. package/src/ui/api/content/bulk.ts +10 -0
  978. package/src/ui/api/content/counts.ts +11 -0
  979. package/src/ui/api/content/foundry-callback.ts +11 -0
  980. package/src/ui/api/content/import/confirm.ts +16 -0
  981. package/src/ui/api/content/import/parse.ts +16 -0
  982. package/src/ui/api/content/insights-ingest.ts +24 -0
  983. package/src/ui/api/content-insights/dismiss.ts +23 -0
  984. package/src/ui/api/content-insights/index.ts +21 -0
  985. package/src/ui/api/content-insights/undismiss.ts +23 -0
  986. package/src/ui/api/content.ts +21 -0
  987. package/src/ui/api/dashboard.ts +28 -0
  988. package/src/ui/api/me.ts +23 -0
  989. package/src/ui/api/media/[id].ts +22 -0
  990. package/src/ui/api/media/images.ts +9 -0
  991. package/src/ui/api/media/library/[id].ts +9 -0
  992. package/src/ui/api/media/library.ts +22 -0
  993. package/src/ui/api/media/podcast/abort.ts +6 -0
  994. package/src/ui/api/media/podcast/complete.ts +6 -0
  995. package/src/ui/api/media/podcast/init.ts +6 -0
  996. package/src/ui/api/media/podcast/part.ts +6 -0
  997. package/src/ui/api/media/podcast.ts +9 -0
  998. package/src/ui/api/media/videos/abort.ts +9 -0
  999. package/src/ui/api/media/videos/complete.ts +9 -0
  1000. package/src/ui/api/media/videos/init.ts +9 -0
  1001. package/src/ui/api/media/videos/part.ts +9 -0
  1002. package/src/ui/api/notifications.ts +26 -0
  1003. package/src/ui/api/search.ts +23 -0
  1004. package/src/ui/api/settings/api-keys/[id].ts +28 -0
  1005. package/src/ui/api/settings/api-keys.ts +25 -0
  1006. package/src/ui/api/settings/domains.ts +37 -0
  1007. package/src/ui/api/settings/integrations.ts +40 -0
  1008. package/src/ui/api/settings/members/[userId].ts +33 -0
  1009. package/src/ui/api/settings/members/invite.ts +27 -0
  1010. package/src/ui/api/settings/members.ts +23 -0
  1011. package/src/ui/api/settings/webhooks/[id]/test.ts +30 -0
  1012. package/src/ui/api/settings/webhooks/[id].ts +29 -0
  1013. package/src/ui/api/settings/webhooks.ts +27 -0
  1014. package/src/ui/api/subscriptions.ts +56 -0
  1015. package/src/ui/api/tags/[id].ts +24 -0
  1016. package/src/ui/api/tags/index.ts +18 -0
  1017. package/src/ui/api/topics/[id].ts +20 -0
  1018. package/src/ui/api/topics/index.ts +17 -0
  1019. package/src/ui/api/workspace-settings.ts +26 -0
  1020. package/src/ui/client/boot-state.ts +42 -0
  1021. package/src/ui/client/mount.tsx +41 -0
  1022. package/src/ui/commands.ts +62 -0
  1023. package/src/ui/components/CmsApp.tsx +149 -0
  1024. package/src/ui/components/CommandPalette.tsx +118 -0
  1025. package/src/ui/components/NoAccessScreen.tsx +79 -0
  1026. package/src/ui/components/ShareModal.tsx +650 -0
  1027. package/src/ui/components/SharePickers.tsx +790 -0
  1028. package/src/ui/components/ShareStatsPanel.tsx +721 -0
  1029. package/src/ui/components/Sidebar.tsx +86 -0
  1030. package/src/ui/components/SiteSwitcher.tsx +100 -0
  1031. package/src/ui/components/Topbar.tsx +93 -0
  1032. package/src/ui/editor/AiAssistPanel.tsx +407 -0
  1033. package/src/ui/editor/ContentForm.tsx +1462 -0
  1034. package/src/ui/editor/Rte.tsx +382 -0
  1035. package/src/ui/editor/ai-assist.ts +139 -0
  1036. package/src/ui/editor/autosave.ts +36 -0
  1037. package/src/ui/editor/content-payload.ts +125 -0
  1038. package/src/ui/editor/editor-media-upload.ts +26 -0
  1039. package/src/ui/editor/serialize.ts +522 -0
  1040. package/src/ui/editor/tweet-embed.ts +60 -0
  1041. package/src/ui/hash-router.ts +30 -0
  1042. package/src/ui/icons.tsx +208 -0
  1043. package/src/ui/inspector/Field.tsx +30 -0
  1044. package/src/ui/inspector/FoundryTab.tsx +613 -0
  1045. package/src/ui/inspector/HistoryTab.tsx +482 -0
  1046. package/src/ui/inspector/Inspector.tsx +328 -0
  1047. package/src/ui/inspector/OrganizeTab.tsx +534 -0
  1048. package/src/ui/inspector/PublishTab.tsx +626 -0
  1049. package/src/ui/inspector/Section.tsx +81 -0
  1050. package/src/ui/inspector/SeoTab.tsx +573 -0
  1051. package/src/ui/inspector/foundry-stages.ts +140 -0
  1052. package/src/ui/inspector/inspector-data.ts +232 -0
  1053. package/src/ui/inspector/organize-data.ts +51 -0
  1054. package/src/ui/inspector/revision-diff.ts +213 -0
  1055. package/src/ui/inspector/seo-helpers.ts +71 -0
  1056. package/src/ui/inspector/tab-visibility.ts +37 -0
  1057. package/src/ui/nav.ts +48 -0
  1058. package/src/ui/pages/admin.astro +32 -0
  1059. package/src/ui/preview/draft-page.tsx +395 -0
  1060. package/src/ui/preview/preview-layout.ts +49 -0
  1061. package/src/ui/screens/AnalyticsScreen.tsx +938 -0
  1062. package/src/ui/screens/AuthorsScreen.tsx +524 -0
  1063. package/src/ui/screens/CalendarScreen.tsx +694 -0
  1064. package/src/ui/screens/ContentInsightsScreen.tsx +417 -0
  1065. package/src/ui/screens/ContentRoute.tsx +35 -0
  1066. package/src/ui/screens/DashboardScreen.tsx +654 -0
  1067. package/src/ui/screens/EditorScreen.tsx +673 -0
  1068. package/src/ui/screens/LibraryScreen.tsx +1350 -0
  1069. package/src/ui/screens/MediaScreen.tsx +357 -0
  1070. package/src/ui/screens/SettingsScreen.tsx +1841 -0
  1071. package/src/ui/screens/SocialShareScreen.tsx +670 -0
  1072. package/src/ui/screens/SubscriptionsScreen.tsx +1240 -0
  1073. package/src/ui/screens/TopicsScreen.tsx +912 -0
  1074. package/src/ui/screens/analytics-data.ts +68 -0
  1075. package/src/ui/screens/calendar-data.ts +126 -0
  1076. package/src/ui/screens/content-insights-data.ts +127 -0
  1077. package/src/ui/screens/content-view.ts +30 -0
  1078. package/src/ui/screens/library-data.ts +177 -0
  1079. package/src/ui/screens/media-upload.ts +283 -0
  1080. package/src/ui/screens/public-url.ts +81 -0
  1081. package/src/ui/screens/registry.tsx +53 -0
  1082. package/src/ui/screens/render-state.ts +228 -0
  1083. package/src/ui/screens/settings-data.ts +140 -0
  1084. package/src/ui/screens/settings-panels-data.ts +142 -0
  1085. package/src/ui/screens/social-share-data.ts +753 -0
  1086. package/src/ui/screens/topics-data.ts +75 -0
  1087. package/src/ui/styles/broadsheet.css +394 -0
  1088. package/src/ui/theme.ts +104 -0
  1089. package/src/ui/tweaks.ts +37 -0
  1090. package/src/ui/use-hash-router.ts +17 -0
  1091. package/src/ui/use-tweaks.ts +31 -0
  1092. package/src/ui/workspace-context.tsx +62 -0
  1093. package/src/virtual.d.ts +4 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revisions.d.ts","sourceRoot":"","sources":["../../src/engine/revisions.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAGzC,oFAAoF;AACpF,MAAM,WAAW,sBAAsB;IACtC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IACvC,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,OAAO,EAAE,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAA;CAC3E;AAED,MAAM,WAAW,eAAe;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAClB;AA4BD,6EAA6E;AAC7E,wBAAsB,uBAAuB,CAC5C,EAAE,EAAE,UAAU,EACd,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,GAC3D,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAyCjC;AAED,wBAAsB,aAAa,CAAC,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAwBjG;AAED,wBAAsB,WAAW,CAChC,EAAE,EAAE,UAAU,EACd,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,OAAO,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,sBAAsB,CAAA;CAAE,GAAG,IAAI,CAAC,CAmC/E;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACpC,EAAE,EAAE,UAAU,EACd,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,GACtC,OAAO,CAAC,OAAO,CAAC,CAiHlB"}
@@ -0,0 +1,203 @@
1
+ // Revision engine — createRevisionWithDelta / listRevisions / getRevision / restoreRevision.
2
+ //
3
+ // Backs the History tab (spec §4 "ContentRevisionPayload"). Builds on the
4
+ // existing content_revisions table (0001 baseline) + the 0005 delta columns
5
+ // (words_added, words_removed, tag). Snapshot shape is formalized as
6
+ // ContentRevisionPayload, aligned to getContentSnapshot's output.
7
+ import { countWords, getContentItem, getContentSnapshot, updateContentItem } from './publisher.js';
8
+ function bodyWordCount(payload) {
9
+ const md = payload?.content && typeof payload.content.body_markdown === 'string'
10
+ ? payload.content.body_markdown
11
+ : '';
12
+ return countWords(md);
13
+ }
14
+ async function latestRevisionPayload(db, contentId) {
15
+ const row = await db
16
+ .prepare('SELECT payload_json FROM content_revisions WHERE content_id = ? ORDER BY created_at DESC, rowid DESC LIMIT 1')
17
+ .bind(contentId)
18
+ .first();
19
+ if (!row)
20
+ return null;
21
+ try {
22
+ return JSON.parse(row.payload_json);
23
+ }
24
+ catch {
25
+ return null;
26
+ }
27
+ }
28
+ /** Snapshot the item now, computing word deltas vs the previous revision. */
29
+ export async function createRevisionWithDelta(db, contentId, opts = {}) {
30
+ const snapshot = (await getContentSnapshot(db, contentId));
31
+ if (!snapshot)
32
+ return null;
33
+ const prev = await latestRevisionPayload(db, contentId);
34
+ const prevWc = bodyWordCount(prev);
35
+ const nextWc = bodyWordCount(snapshot);
36
+ const wordsAdded = Math.max(0, nextWc - prevWc);
37
+ const wordsRemoved = Math.max(0, prevWc - nextWc);
38
+ const id = crypto.randomUUID();
39
+ await db
40
+ .prepare('INSERT INTO content_revisions (id, content_id, payload_json, created_at, created_by, words_added, words_removed, tag) VALUES (?, ?, ?, unixepoch(), ?, ?, ?, ?)')
41
+ .bind(id, contentId, JSON.stringify(snapshot), opts.createdBy ?? null, wordsAdded, wordsRemoved, opts.tag ?? null)
42
+ .run();
43
+ // NOTE: this is the autosave/History trigger (fired on a debounce while
44
+ // editing a draft, and by restoreRevision). It must NOT move
45
+ // content_items.published_revision_id — that pointer tracks the PUBLISHED
46
+ // snapshot and is only advanced by the publish path (createRevision in
47
+ // publisher.ts).
48
+ const row = await db
49
+ .prepare('SELECT created_at FROM content_revisions WHERE id = ?')
50
+ .bind(id)
51
+ .first();
52
+ return {
53
+ id,
54
+ contentId,
55
+ createdAt: row?.created_at ?? 0,
56
+ createdBy: opts.createdBy ?? null,
57
+ wordsAdded,
58
+ wordsRemoved,
59
+ tag: opts.tag ?? null,
60
+ };
61
+ }
62
+ export async function listRevisions(db, contentId) {
63
+ const result = await db
64
+ .prepare('SELECT id, content_id, created_at, created_by, words_added, words_removed, tag FROM content_revisions WHERE content_id = ? ORDER BY created_at DESC, rowid DESC')
65
+ .bind(contentId)
66
+ .all();
67
+ return (result.results || []).map((r) => ({
68
+ id: r.id,
69
+ contentId: r.content_id,
70
+ createdAt: r.created_at,
71
+ createdBy: r.created_by,
72
+ wordsAdded: r.words_added,
73
+ wordsRemoved: r.words_removed,
74
+ tag: r.tag,
75
+ }));
76
+ }
77
+ export async function getRevision(db, contentId, revisionId) {
78
+ const row = await db
79
+ .prepare('SELECT id, content_id, payload_json, created_at, created_by, words_added, words_removed, tag FROM content_revisions WHERE id = ? AND content_id = ? LIMIT 1')
80
+ .bind(revisionId, contentId)
81
+ .first();
82
+ if (!row)
83
+ return null;
84
+ let payload;
85
+ try {
86
+ payload = JSON.parse(row.payload_json);
87
+ }
88
+ catch {
89
+ return null;
90
+ }
91
+ return {
92
+ summary: {
93
+ id: row.id,
94
+ contentId: row.content_id,
95
+ createdAt: row.created_at,
96
+ createdBy: row.created_by,
97
+ wordsAdded: row.words_added,
98
+ wordsRemoved: row.words_removed,
99
+ tag: row.tag,
100
+ },
101
+ payload,
102
+ };
103
+ }
104
+ /**
105
+ * Restore: replay the revision's item+body+tags+relations through updateContentItem,
106
+ * then snapshot the restore as a new revision tagged 'restore'.
107
+ */
108
+ export async function restoreRevision(db, contentId, revisionId, opts = {}) {
109
+ const target = await getRevision(db, contentId, revisionId);
110
+ if (!target)
111
+ return false;
112
+ const existing = await getContentItem(db, contentId);
113
+ if (!existing)
114
+ return false;
115
+ const item = target.payload.item;
116
+ const content = target.payload.content;
117
+ // Map the snapshot's snake_case row back onto the updateContentItem camelCase input.
118
+ const body = content;
119
+ // Editor takeaways are stored as a JSON-encoded string array on article_content.
120
+ // updateContentItem takes them as a string[] via content.editorTakeaways, so
121
+ // parse the snapshot's stored JSON back into an array for a faithful restore.
122
+ function parseTakeaways(raw) {
123
+ if (!raw)
124
+ return null;
125
+ try {
126
+ const parsed = JSON.parse(raw);
127
+ return Array.isArray(parsed) ? parsed : null;
128
+ }
129
+ catch {
130
+ return null;
131
+ }
132
+ }
133
+ const restoredTakeaways = parseTakeaways(body?.editor_takeaways);
134
+ // Restore intentionally rolls back CONTENT fields (title/body/tags/relations/
135
+ // featured/seo/hero/etc.) to the snapshot, but NOT publication state
136
+ // (status / publish_at / published_at / published_revision_id) — that is by
137
+ // design: restoring an old draft must not silently re-publish or un-publish.
138
+ await updateContentItem(db, contentId, {
139
+ title: item.title ?? existing.title,
140
+ featured: Boolean(item.featured),
141
+ seoTitle: item.seo_title ?? null,
142
+ description: item.description ?? null,
143
+ excerpt: item.excerpt ?? null,
144
+ byline: item.byline ?? null,
145
+ primaryCategory: item.channel ?? null,
146
+ primaryTopic: item.primary_topic ?? null,
147
+ visibility: item.visibility ?? existing.visibility,
148
+ authorId: item.author_id ?? null,
149
+ heroImageId: item.hero_image_id ?? null,
150
+ heroImageAlt: item.hero_image_alt ?? null,
151
+ heroImageCaption: item.hero_image_caption ?? null,
152
+ socialImageId: item.social_image_id ?? null,
153
+ canonicalUrl: item.canonical_url ?? null,
154
+ // SEO focus keyword is part of the snapshot — restore it too.
155
+ seoFocusKeyword: item.seo_focus_keyword ?? null,
156
+ tags: target.payload.tags,
157
+ relations: target.payload.related.map((r) => ({
158
+ relatedId: r.related_id,
159
+ rank: r.rank,
160
+ reason: r.reason,
161
+ })),
162
+ content: existing.type === 'article' || existing.type === 'newsletter'
163
+ ? {
164
+ bodyMarkdown: body?.body_markdown ?? '',
165
+ bodyHtml: body?.body_html ?? null,
166
+ subtitle: body?.subtitle ?? null,
167
+ // Editor takeaways were captured in the snapshot — roll them back.
168
+ editorTakeaways: restoredTakeaways,
169
+ }
170
+ : existing.type === 'video'
171
+ ? {
172
+ script: body?.script ?? '',
173
+ videoId: body?.video_id ?? '',
174
+ durationSeconds: body?.duration_seconds ?? null,
175
+ thumbnailImageId: body?.thumbnail_image_id ?? null,
176
+ }
177
+ : {
178
+ transcript: body?.transcript ?? '',
179
+ audioR2Key: body?.audio_r2_key ?? '',
180
+ durationSeconds: body?.duration_seconds ?? null,
181
+ },
182
+ });
183
+ // updateContentItem does not carry seo_score / ai_og_image_id (these are set
184
+ // by SEO scoring + AI-OG generation, not the editor form) or faq_json. They
185
+ // ARE captured in the snapshot, so restore them directly for fidelity — a
186
+ // restore must reproduce the snapshot, not silently drop SEO/AI metadata.
187
+ await db
188
+ .prepare('UPDATE content_items SET seo_score = ?, ai_og_image_id = ?, updated_at = unixepoch() WHERE id = ?')
189
+ .bind(item.seo_score ?? null, item.ai_og_image_id ?? null, contentId)
190
+ .run();
191
+ if (existing.type === 'article' || existing.type === 'newsletter') {
192
+ await db
193
+ .prepare('UPDATE article_content SET faq_json = ? WHERE content_id = ?')
194
+ .bind(body?.faq_json ?? null, contentId)
195
+ .run();
196
+ }
197
+ await createRevisionWithDelta(db, contentId, {
198
+ createdBy: opts.createdBy ?? null,
199
+ tag: 'restore',
200
+ });
201
+ return true;
202
+ }
203
+ //# sourceMappingURL=revisions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revisions.js","sourceRoot":"","sources":["../../src/engine/revisions.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,EAAE;AACF,0EAA0E;AAC1E,4EAA4E;AAC5E,qEAAqE;AACrE,kEAAkE;AAGlE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAoBlG,SAAS,aAAa,CAAC,OAAsC;IAC5D,MAAM,EAAE,GACP,OAAO,EAAE,OAAO,IAAI,OAAO,OAAO,CAAC,OAAO,CAAC,aAAa,KAAK,QAAQ;QACpE,CAAC,CAAE,OAAO,CAAC,OAAO,CAAC,aAAwB;QAC3C,CAAC,CAAC,EAAE,CAAA;IACN,OAAO,UAAU,CAAC,EAAE,CAAC,CAAA;AACtB,CAAC;AAED,KAAK,UAAU,qBAAqB,CACnC,EAAc,EACd,SAAiB;IAEjB,MAAM,GAAG,GAAG,MAAM,EAAE;SAClB,OAAO,CACP,8GAA8G,CAC9G;SACA,IAAI,CAAC,SAAS,CAAC;SACf,KAAK,EAA4B,CAAA;IACnC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAA;IACrB,IAAI,CAAC;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAA2B,CAAA;IAC9D,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAA;IACZ,CAAC;AACF,CAAC;AAED,6EAA6E;AAC7E,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC5C,EAAc,EACd,SAAiB,EACjB,OAA2D,EAAE;IAE7D,MAAM,QAAQ,GAAG,CAAC,MAAM,kBAAkB,CAAC,EAAE,EAAE,SAAS,CAAC,CAAkC,CAAA;IAC3F,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAA;IAC1B,MAAM,IAAI,GAAG,MAAM,qBAAqB,CAAC,EAAE,EAAE,SAAS,CAAC,CAAA;IACvD,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAA;IAClC,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAA;IACtC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;IAC/C,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;IACjD,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,EAAE,CAAA;IAC9B,MAAM,EAAE;SACN,OAAO,CACP,iKAAiK,CACjK;SACA,IAAI,CACJ,EAAE,EACF,SAAS,EACT,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EACxB,IAAI,CAAC,SAAS,IAAI,IAAI,EACtB,UAAU,EACV,YAAY,EACZ,IAAI,CAAC,GAAG,IAAI,IAAI,CAChB;SACA,GAAG,EAAE,CAAA;IACP,wEAAwE;IACxE,6DAA6D;IAC7D,0EAA0E;IAC1E,uEAAuE;IACvE,iBAAiB;IACjB,MAAM,GAAG,GAAG,MAAM,EAAE;SAClB,OAAO,CAAC,uDAAuD,CAAC;SAChE,IAAI,CAAC,EAAE,CAAC;SACR,KAAK,EAA0B,CAAA;IACjC,OAAO;QACN,EAAE;QACF,SAAS;QACT,SAAS,EAAE,GAAG,EAAE,UAAU,IAAI,CAAC;QAC/B,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI;QACjC,UAAU;QACV,YAAY;QACZ,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,IAAI;KACrB,CAAA;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,EAAc,EAAE,SAAiB;IACpE,MAAM,MAAM,GAAG,MAAM,EAAE;SACrB,OAAO,CACP,iKAAiK,CACjK;SACA,IAAI,CAAC,SAAS,CAAC;SACf,GAAG,EAQA,CAAA;IACL,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACzC,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,SAAS,EAAE,CAAC,CAAC,UAAU;QACvB,SAAS,EAAE,CAAC,CAAC,UAAU;QACvB,SAAS,EAAE,CAAC,CAAC,UAAU;QACvB,UAAU,EAAE,CAAC,CAAC,WAAW;QACzB,YAAY,EAAE,CAAC,CAAC,aAAa;QAC7B,GAAG,EAAE,CAAC,CAAC,GAAG;KACV,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,EAAc,EACd,SAAiB,EACjB,UAAkB;IAElB,MAAM,GAAG,GAAG,MAAM,EAAE;SAClB,OAAO,CACP,6JAA6J,CAC7J;SACA,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC;SAC3B,KAAK,EASF,CAAA;IACL,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAA;IACrB,IAAI,OAA+B,CAAA;IACnC,IAAI,CAAC;QACJ,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAA2B,CAAA;IACjE,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAA;IACZ,CAAC;IACD,OAAO;QACN,OAAO,EAAE;YACR,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,SAAS,EAAE,GAAG,CAAC,UAAU;YACzB,SAAS,EAAE,GAAG,CAAC,UAAU;YACzB,SAAS,EAAE,GAAG,CAAC,UAAU;YACzB,UAAU,EAAE,GAAG,CAAC,WAAW;YAC3B,YAAY,EAAE,GAAG,CAAC,aAAa;YAC/B,GAAG,EAAE,GAAG,CAAC,GAAG;SACZ;QACD,OAAO;KACP,CAAA;AACF,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACpC,EAAc,EACd,SAAiB,EACjB,UAAkB,EAClB,OAAsC,EAAE;IAExC,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAA;IAC3D,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAA;IACzB,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,EAAE,EAAE,SAAS,CAAC,CAAA;IACpD,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAA;IAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,IAA+B,CAAA;IAC3D,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAyC,CAAA;IACxE,qFAAqF;IACrF,MAAM,IAAI,GAAG,OAYL,CAAA;IAER,iFAAiF;IACjF,6EAA6E;IAC7E,8EAA8E;IAC9E,SAAS,cAAc,CAAC,GAA8B;QACrD,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAA;QACrB,IAAI,CAAC;YACJ,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YAC9B,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAE,MAAmB,CAAC,CAAC,CAAC,IAAI,CAAA;QAC3D,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,IAAI,CAAA;QACZ,CAAC;IACF,CAAC;IACD,MAAM,iBAAiB,GAAG,cAAc,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAA;IAChE,8EAA8E;IAC9E,qEAAqE;IACrE,4EAA4E;IAC5E,6EAA6E;IAC7E,MAAM,iBAAiB,CAAC,EAAE,EAAE,SAAS,EAAE;QACtC,KAAK,EAAG,IAAI,CAAC,KAAgB,IAAI,QAAQ,CAAC,KAAK;QAC/C,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;QAChC,QAAQ,EAAG,IAAI,CAAC,SAA2B,IAAI,IAAI;QACnD,WAAW,EAAG,IAAI,CAAC,WAA6B,IAAI,IAAI;QACxD,OAAO,EAAG,IAAI,CAAC,OAAyB,IAAI,IAAI;QAChD,MAAM,EAAG,IAAI,CAAC,MAAwB,IAAI,IAAI;QAC9C,eAAe,EAAG,IAAI,CAAC,OAAyB,IAAI,IAAI;QACxD,YAAY,EAAG,IAAI,CAAC,aAA+B,IAAI,IAAI;QAC3D,UAAU,EAAG,IAAI,CAAC,UAAiC,IAAI,QAAQ,CAAC,UAAU;QAC1E,QAAQ,EAAG,IAAI,CAAC,SAA2B,IAAI,IAAI;QACnD,WAAW,EAAG,IAAI,CAAC,aAA+B,IAAI,IAAI;QAC1D,YAAY,EAAG,IAAI,CAAC,cAAgC,IAAI,IAAI;QAC5D,gBAAgB,EAAG,IAAI,CAAC,kBAAoC,IAAI,IAAI;QACpE,aAAa,EAAG,IAAI,CAAC,eAAiC,IAAI,IAAI;QAC9D,YAAY,EAAG,IAAI,CAAC,aAA+B,IAAI,IAAI;QAC3D,8DAA8D;QAC9D,eAAe,EAAG,IAAI,CAAC,iBAAmC,IAAI,IAAI;QAClE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI;QACzB,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC7C,SAAS,EAAE,CAAC,CAAC,UAAU;YACvB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,MAAM,EAAE,CAAC,CAAC,MAAM;SAChB,CAAC,CAAC;QACH,OAAO,EACN,QAAQ,CAAC,IAAI,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,KAAK,YAAY;YAC5D,CAAC,CAAC;gBACA,YAAY,EAAE,IAAI,EAAE,aAAa,IAAI,EAAE;gBACvC,QAAQ,EAAE,IAAI,EAAE,SAAS,IAAI,IAAI;gBACjC,QAAQ,EAAE,IAAI,EAAE,QAAQ,IAAI,IAAI;gBAChC,mEAAmE;gBACnE,eAAe,EAAE,iBAAiB;aAClC;YACF,CAAC,CAAC,QAAQ,CAAC,IAAI,KAAK,OAAO;gBAC1B,CAAC,CAAC;oBACA,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,EAAE;oBAC1B,OAAO,EAAE,IAAI,EAAE,QAAQ,IAAI,EAAE;oBAC7B,eAAe,EAAE,IAAI,EAAE,gBAAgB,IAAI,IAAI;oBAC/C,gBAAgB,EAAE,IAAI,EAAE,kBAAkB,IAAI,IAAI;iBAClD;gBACF,CAAC,CAAC;oBACA,UAAU,EAAE,IAAI,EAAE,UAAU,IAAI,EAAE;oBAClC,UAAU,EAAE,IAAI,EAAE,YAAY,IAAI,EAAE;oBACpC,eAAe,EAAE,IAAI,EAAE,gBAAgB,IAAI,IAAI;iBAC/C;KACL,CAAC,CAAA;IAEF,6EAA6E;IAC7E,4EAA4E;IAC5E,0EAA0E;IAC1E,0EAA0E;IAC1E,MAAM,EAAE;SACN,OAAO,CACP,mGAAmG,CACnG;SACA,IAAI,CACH,IAAI,CAAC,SAA2B,IAAI,IAAI,EACxC,IAAI,CAAC,cAAgC,IAAI,IAAI,EAC9C,SAAS,CACT;SACA,GAAG,EAAE,CAAA;IAEP,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QACnE,MAAM,EAAE;aACN,OAAO,CAAC,8DAA8D,CAAC;aACvE,IAAI,CAAC,IAAI,EAAE,QAAQ,IAAI,IAAI,EAAE,SAAS,CAAC;aACvC,GAAG,EAAE,CAAA;IACR,CAAC;IAED,MAAM,uBAAuB,CAAC,EAAE,EAAE,SAAS,EAAE;QAC5C,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI;QACjC,GAAG,EAAE,SAAS;KACd,CAAC,CAAA;IACF,OAAO,IAAI,CAAA;AACZ,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Phase 1 strip: drop the leading backslash before any character that
3
+ * is not a legitimate markdown escape. Mirror of
4
+ * {@link checkBackslashOverEscape}'s detector.
5
+ *
6
+ * Also drops HTML-entity-encoded backslashes (`\`, `\`,
7
+ * `\`) that bypass the literal-backslash strip.
8
+ */
9
+ export declare function stripOverEscapes(value: string): string;
10
+ /**
11
+ * Phase 1 strip (heading-scoped): decode HTML entities only inside
12
+ * heading lines. Entities inside paragraph prose are intentionally
13
+ * left alone — they're sometimes part of legitimate publication
14
+ * names (`Tools & Trade`).
15
+ */
16
+ export declare function decodeHeadingEntities(value: string): string;
17
+ export interface SanitizeOptions {
18
+ /**
19
+ * When true, the speaker-aware passes leave podcast/video speaker
20
+ * prefixes alone. Default true (the safe option for all callers).
21
+ */
22
+ preserveSpeakerPrefixes: boolean;
23
+ }
24
+ export declare const DEFAULT_SANITIZE_OPTIONS: SanitizeOptions;
25
+ /**
26
+ * Phase 2 strip composition. Order matters in a few places — see the
27
+ * inline comments. The composition is idempotent.
28
+ *
29
+ * Order:
30
+ * 1. Word/Gdocs paste artifacts (strip BEFORE we look for HTML
31
+ * comments, because Word paste residue is itself a comment).
32
+ * 2. HTML comment leak (whitelisted-only).
33
+ * 3. Paywall marker leak (defensive — even though the splitter
34
+ * should have eaten these already).
35
+ * 4. Double-encoded entities (`"` → `"` — must run
36
+ * BEFORE the heading entity decode so it sees the decoded form).
37
+ * 5. Backslash over-escape (Phase 1 strip). CODE-AWARE: fenced and
38
+ * inline code regions are protected.
39
+ * 6. Heading-entity decode (Phase 1 strip).
40
+ * 7. Broken footnote label `[[N]](#a)` → `[N](#a)`.
41
+ * 8. Invisible control chars (last — they're invisible in raw text
42
+ * so order vs other passes doesn't matter, but doing it last
43
+ * means subsequent regex passes can't get tripped up by them).
44
+ * 9. `<br>` lines → blank line (raw-block-html repair).
45
+ */
46
+ export declare function sanitizeBody(value: string, _options?: SanitizeOptions): string;
47
+ /**
48
+ * Convenience export — the renderer side of the same module. Returns
49
+ * the input cleaned via every pass once.
50
+ */
51
+ export declare const sanitize: typeof sanitizeBody;
52
+ //# sourceMappingURL=sanitize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/engine/sanitize.ts"],"names":[],"mappings":"AAwCA;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOtD;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAmB3D;AAMD,MAAM,WAAW,eAAe;IAC/B;;;OAGG;IACH,uBAAuB,EAAE,OAAO,CAAA;CAChC;AAED,eAAO,MAAM,wBAAwB,EAAE,eAEtC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAC3B,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,eAA0C,GAClD,MAAM,CAYR;AA0CD;;;GAGG;AACH,eAAO,MAAM,QAAQ,qBAAe,CAAA"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * sanitize.ts
3
+ *
4
+ * Shared L2 sanitization passes that run AFTER the validator has emitted
5
+ * its report. A site's renderers (article, podcast, video) consume these
6
+ * so they never drift on what counts as "safe stored body".
7
+ *
8
+ * Ported verbatim from fulcrum-labs/fronts src/lib/content-sanitize.ts
9
+ * (inventory §1: extract — the sanitize helper). Each pass is pure and
10
+ * composable; the default {@link sanitizeBody} orchestration is
11
+ * idempotent. It reuses the validator checks' `repair` functions so the
12
+ * detector and the fixer can never diverge.
13
+ *
14
+ * Negative invariants:
15
+ * - Fenced code blocks are preserved unchanged.
16
+ * - Inline code spans are preserved unchanged.
17
+ * - URLs inside `[label](url)` are preserved unchanged.
18
+ * - Podcast/video speaker prefixes (`Alice:`, `[00:01:23] Bob:`) are
19
+ * preserved unchanged — no pass strips the colon or numeric label.
20
+ * - Legitimate markdown escapes (`\*emphasis\*`, `\[brackets\]`) are
21
+ * preserved unchanged.
22
+ */
23
+ import { repair as repairBrokenFootnoteLabel } from './validator/checks/broken-footnote-label.js';
24
+ import { repair as repairDoubleEncodedEntities } from './validator/checks/double-encoded-entities.js';
25
+ import { repair as repairHtmlCommentLeak } from './validator/checks/html-comment-leak.js';
26
+ import { repair as repairInvisibleControl } from './validator/checks/invisible-control-chars.js';
27
+ import { repair as repairPaywallMarker } from './validator/checks/paywall-marker-leak.js';
28
+ import { repair as repairRawBlockHtml } from './validator/checks/raw-block-html.js';
29
+ import { repair as repairWordGdocs } from './validator/checks/word-gdocs-paste-artifacts.js';
30
+ /* -------------------------------------------------------------------------- */
31
+ /* Mirror with validator */
32
+ /* -------------------------------------------------------------------------- */
33
+ /**
34
+ * Mirror of the legit-escape set in `./validator/index.ts`. If you
35
+ * change one, change the other.
36
+ */
37
+ const LEGIT_ESCAPE_CHARS = '*_[]{}|`#+!>\\-';
38
+ /**
39
+ * Phase 1 strip: drop the leading backslash before any character that
40
+ * is not a legitimate markdown escape. Mirror of
41
+ * {@link checkBackslashOverEscape}'s detector.
42
+ *
43
+ * Also drops HTML-entity-encoded backslashes (`&#92;`, `&#x5C;`,
44
+ * `&bsol;`) that bypass the literal-backslash strip.
45
+ */
46
+ export function stripOverEscapes(value) {
47
+ const literal = value.replace(/\\(.)/g, (match, ch) => LEGIT_ESCAPE_CHARS.includes(ch) ? match : ch);
48
+ return literal.replace(/(?:&#92;|&#x5[Cc];|&bsol;)(.)/g, (match, ch) => LEGIT_ESCAPE_CHARS.includes(ch) ? match : ch);
49
+ }
50
+ /**
51
+ * Phase 1 strip (heading-scoped): decode HTML entities only inside
52
+ * heading lines. Entities inside paragraph prose are intentionally
53
+ * left alone — they're sometimes part of legitimate publication
54
+ * names (`Tools &amp; Trade`).
55
+ */
56
+ export function decodeHeadingEntities(value) {
57
+ const ENTITY_MAP = {
58
+ '&quot;': '"',
59
+ '&apos;': "'",
60
+ '&#39;': "'",
61
+ '&amp;': '&',
62
+ '&lt;': '<',
63
+ '&gt;': '>',
64
+ };
65
+ return value
66
+ .split('\n')
67
+ .map((line) => {
68
+ if (!/^\s*#{1,6}\s+/.test(line))
69
+ return line;
70
+ return line.replace(/&(?:quot|apos|amp|lt|gt|#\d+);/g, (entity) => ENTITY_MAP[entity] ?? entity);
71
+ })
72
+ .join('\n');
73
+ }
74
+ export const DEFAULT_SANITIZE_OPTIONS = {
75
+ preserveSpeakerPrefixes: true,
76
+ };
77
+ /**
78
+ * Phase 2 strip composition. Order matters in a few places — see the
79
+ * inline comments. The composition is idempotent.
80
+ *
81
+ * Order:
82
+ * 1. Word/Gdocs paste artifacts (strip BEFORE we look for HTML
83
+ * comments, because Word paste residue is itself a comment).
84
+ * 2. HTML comment leak (whitelisted-only).
85
+ * 3. Paywall marker leak (defensive — even though the splitter
86
+ * should have eaten these already).
87
+ * 4. Double-encoded entities (`&amp;quot;` → `&quot;` — must run
88
+ * BEFORE the heading entity decode so it sees the decoded form).
89
+ * 5. Backslash over-escape (Phase 1 strip). CODE-AWARE: fenced and
90
+ * inline code regions are protected.
91
+ * 6. Heading-entity decode (Phase 1 strip).
92
+ * 7. Broken footnote label `[[N]](#a)` → `[N](#a)`.
93
+ * 8. Invisible control chars (last — they're invisible in raw text
94
+ * so order vs other passes doesn't matter, but doing it last
95
+ * means subsequent regex passes can't get tripped up by them).
96
+ * 9. `<br>` lines → blank line (raw-block-html repair).
97
+ */
98
+ export function sanitizeBody(value, _options = DEFAULT_SANITIZE_OPTIONS) {
99
+ let out = value;
100
+ out = repairWordGdocs(out);
101
+ out = repairHtmlCommentLeak(out);
102
+ out = repairPaywallMarker(out);
103
+ out = repairDoubleEncodedEntities(out);
104
+ out = stripOverEscapesPreservingCode(out);
105
+ out = decodeHeadingEntities(out);
106
+ out = repairBrokenFootnoteLabel(out);
107
+ out = repairInvisibleControl(out);
108
+ out = repairRawBlockHtml(out);
109
+ return out;
110
+ }
111
+ /**
112
+ * Code-aware variant of {@link stripOverEscapes}. Fenced (` ``` `) and
113
+ * inline (` ` `) code regions are extracted, the strip runs on the
114
+ * surrounding prose, and the code regions are spliced back in
115
+ * verbatim. This preserves intentional escape sequences in code
116
+ * examples (`'\, \.'` etc.) while still cleaning prose.
117
+ */
118
+ function stripOverEscapesPreservingCode(value) {
119
+ const segments = [];
120
+ const fenceRe = /(^|\n)([ \t]*)(`{3,}|~{3,})[^\n]*\n[\s\S]*?\n\2\3/g;
121
+ const inlineRe = /`[^`\n]+`/g;
122
+ const protectedSpans = [];
123
+ for (const m of value.matchAll(fenceRe)) {
124
+ protectedSpans.push({
125
+ start: m.index ?? 0,
126
+ end: (m.index ?? 0) + m[0].length,
127
+ });
128
+ }
129
+ for (const m of value.matchAll(inlineRe)) {
130
+ const start = m.index ?? 0;
131
+ const end = start + m[0].length;
132
+ if (protectedSpans.some((s) => start >= s.start && end <= s.end))
133
+ continue;
134
+ protectedSpans.push({ start, end });
135
+ }
136
+ protectedSpans.sort((a, b) => a.start - b.start);
137
+ let cursor = 0;
138
+ for (const span of protectedSpans) {
139
+ if (span.start > cursor) {
140
+ segments.push({ kind: 'prose', text: value.slice(cursor, span.start) });
141
+ }
142
+ segments.push({ kind: 'code', text: value.slice(span.start, span.end) });
143
+ cursor = span.end;
144
+ }
145
+ if (cursor < value.length) {
146
+ segments.push({ kind: 'prose', text: value.slice(cursor) });
147
+ }
148
+ return segments.map((s) => (s.kind === 'prose' ? stripOverEscapes(s.text) : s.text)).join('');
149
+ }
150
+ /**
151
+ * Convenience export — the renderer side of the same module. Returns
152
+ * the input cleaned via every pass once.
153
+ */
154
+ export const sanitize = sanitizeBody;
155
+ //# sourceMappingURL=sanitize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../../src/engine/sanitize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { CmsRole } from '../schema/types.js';
2
+ import type { D1Database } from './d1.js';
3
+ export interface SeedMembershipInput {
4
+ workspaceId: string;
5
+ /**
6
+ * The REAL OpenAuth subject from the Fulcrum issuer — MUST start with
7
+ * 'user:'. Never pass a locally-minted or placeholder id here.
8
+ */
9
+ subject: string;
10
+ email: string;
11
+ name: string | null;
12
+ role: CmsRole;
13
+ }
14
+ /**
15
+ * Seed a workspace membership from a known real OpenAuth subject.
16
+ *
17
+ * Validates that the subject starts with 'user:' (rejects placeholder ids).
18
+ * Upserts `masthead_users` (id = subject) and `workspace_memberships` with
19
+ * `accepted_at` set — a seeded member is pre-accepted (no invite required).
20
+ *
21
+ * Idempotent: safe to run multiple times; the second call updates in place.
22
+ *
23
+ * Throws if:
24
+ * - subject does not start with 'user:' (placeholder guard)
25
+ * - a different id already holds the same email (UNIQUE collision on
26
+ * masthead_users.email — surfaces as an error, never a silent 500)
27
+ */
28
+ export declare function seedMembership(db: D1Database, input: SeedMembershipInput): Promise<void>;
29
+ //# sourceMappingURL=seed-membership.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seed-membership.d.ts","sourceRoot":"","sources":["../../src/engine/seed-membership.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAOzC,MAAM,WAAW,mBAAmB;IACnC,WAAW,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,IAAI,EAAE,OAAO,CAAA;CACb;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,cAAc,CAAC,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAiC9F"}
@@ -0,0 +1,65 @@
1
+ // seed-membership.ts — Parameterized membership pre-seed helper (P7 Task 6).
2
+ //
3
+ // PRE-SEED IS AN OPERATOR/CUTOVER STEP.
4
+ //
5
+ // Look up each person's REAL subject in the Fulcrum issuer D1 by email —
6
+ // subjects are minted + stable in the issuer before first login. NEVER
7
+ // hardcode subjects or emails; pass them at call time.
8
+ //
9
+ // A placeholder id → no membership match → 403 on every request.
10
+ // A placeholder email on the UNIQUE masthead_users.email column → 500 on the
11
+ // real person's first login (the exact inbox-platform bug, §16 risk 10).
12
+ //
13
+ // Usage (at cutover, after looking up real subjects in the issuer D1):
14
+ //
15
+ // await seedMembership(db, { workspaceId: 'ws-prod', subject: 'user:<real-uuid>', email, name, role: 'owner' })
16
+ //
17
+ // This helper is idempotent: calling it twice with the same (workspaceId,
18
+ // subject) pair updates the membership and user profile in place — it does NOT
19
+ // insert a duplicate or fail silently.
20
+ import { upsertMastheadUser } from './members.js';
21
+ // ---------------------------------------------------------------------------
22
+ // seedMembership
23
+ // ---------------------------------------------------------------------------
24
+ /**
25
+ * Seed a workspace membership from a known real OpenAuth subject.
26
+ *
27
+ * Validates that the subject starts with 'user:' (rejects placeholder ids).
28
+ * Upserts `masthead_users` (id = subject) and `workspace_memberships` with
29
+ * `accepted_at` set — a seeded member is pre-accepted (no invite required).
30
+ *
31
+ * Idempotent: safe to run multiple times; the second call updates in place.
32
+ *
33
+ * Throws if:
34
+ * - subject does not start with 'user:' (placeholder guard)
35
+ * - a different id already holds the same email (UNIQUE collision on
36
+ * masthead_users.email — surfaces as an error, never a silent 500)
37
+ */
38
+ export async function seedMembership(db, input) {
39
+ if (!input.subject?.startsWith('user:')) {
40
+ throw new Error(`seedMembership: subject must start with 'user:' — received: ${JSON.stringify(input.subject)}. ` +
41
+ 'Look up the real subject in the Fulcrum issuer D1 by email before seeding. ' +
42
+ 'A placeholder id causes 403 on every request (§16 risk 10).');
43
+ }
44
+ const now = Math.floor(Date.now() / 1000);
45
+ // Upsert masthead_users — will throw a UNIQUE constraint error if a
46
+ // DIFFERENT id already holds this email (the §16 risk-10 collision surface).
47
+ // We deliberately do NOT silence that error here.
48
+ await upsertMastheadUser(db, {
49
+ id: input.subject,
50
+ email: input.email,
51
+ name: input.name,
52
+ image: null,
53
+ });
54
+ // Upsert the membership row with accepted_at set (pre-accepted seed).
55
+ await db
56
+ .prepare(`INSERT INTO workspace_memberships (workspace_id, user_id, role, invited_by, accepted_at, created_at, updated_at)
57
+ VALUES (?, ?, ?, NULL, ?, ?, ?)
58
+ ON CONFLICT(workspace_id, user_id) DO UPDATE SET
59
+ role = excluded.role,
60
+ accepted_at = COALESCE(workspace_memberships.accepted_at, excluded.accepted_at),
61
+ updated_at = excluded.updated_at`)
62
+ .bind(input.workspaceId, input.subject, input.role, now, now, now)
63
+ .run();
64
+ }
65
+ //# sourceMappingURL=seed-membership.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seed-membership.js","sourceRoot":"","sources":["../../src/engine/seed-membership.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,EAAE;AACF,wCAAwC;AACxC,EAAE;AACF,yEAAyE;AACzE,uEAAuE;AACvE,uDAAuD;AACvD,EAAE;AACF,mEAAmE;AACnE,+EAA+E;AAC/E,2EAA2E;AAC3E,EAAE;AACF,uEAAuE;AACvE,EAAE;AACF,kHAAkH;AAClH,EAAE;AACF,0EAA0E;AAC1E,+EAA+E;AAC/E,uCAAuC;AAIvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAkBjD,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,EAAc,EAAE,KAA0B;IAC9E,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CACd,+DAA+D,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI;YAC/F,6EAA6E;YAC7E,6DAA6D,CAC9D,CAAA;IACF,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAA;IAEzC,oEAAoE;IACpE,6EAA6E;IAC7E,kDAAkD;IAClD,MAAM,kBAAkB,CAAC,EAAE,EAAE;QAC5B,EAAE,EAAE,KAAK,CAAC,OAAO;QACjB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,KAAK,EAAE,IAAI;KACX,CAAC,CAAA;IAEF,sEAAsE;IACtE,MAAM,EAAE;SACN,OAAO,CACP;;;;;uCAKoC,CACpC;SACA,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;SACjE,GAAG,EAAE,CAAA;AACR,CAAC"}
@@ -0,0 +1,20 @@
1
+ export interface SeoScoreInput {
2
+ title: string;
3
+ seoTitle?: string | null;
4
+ description?: string | null;
5
+ focusKeyword?: string | null;
6
+ bodyMarkdown?: string | null;
7
+ }
8
+ export interface SeoCheck {
9
+ id: string;
10
+ label: string;
11
+ pass: boolean;
12
+ hint: string;
13
+ }
14
+ export interface SeoScoreResult {
15
+ score: number;
16
+ checks: SeoCheck[];
17
+ }
18
+ /** The in-package default SeoProvider scorer: 5 checks × 20 pts (spec §8). */
19
+ export declare function scoreDraft(input: SeoScoreInput): SeoScoreResult;
20
+ //# sourceMappingURL=seo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seo.d.ts","sourceRoot":"","sources":["../../src/engine/seo.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,OAAO,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,QAAQ,EAAE,CAAA;CAClB;AAQD,8EAA8E;AAC9E,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,GAAG,cAAc,CA0C/D"}
@@ -0,0 +1,50 @@
1
+ import { countWords } from './publisher.js';
2
+ const MIN_DESC = 50;
3
+ const MAX_DESC = 160;
4
+ const MIN_TITLE = 15;
5
+ const MAX_TITLE = 60;
6
+ const MIN_BODY_WORDS = 300;
7
+ /** The in-package default SeoProvider scorer: 5 checks × 20 pts (spec §8). */
8
+ export function scoreDraft(input) {
9
+ const title = (input.seoTitle || input.title || '').trim();
10
+ const description = (input.description || '').trim();
11
+ const keyword = (input.focusKeyword || '').trim().toLowerCase();
12
+ const bodyWords = countWords(input.bodyMarkdown || '');
13
+ const lcTitle = title.toLowerCase();
14
+ const lcBody = (input.bodyMarkdown || '').toLowerCase();
15
+ const checks = [
16
+ {
17
+ id: 'title-length',
18
+ label: 'Title length',
19
+ pass: title.length >= MIN_TITLE && title.length <= MAX_TITLE,
20
+ hint: `Keep the title between ${MIN_TITLE} and ${MAX_TITLE} characters.`,
21
+ },
22
+ {
23
+ id: 'meta-description',
24
+ label: 'Meta description',
25
+ pass: description.length >= MIN_DESC && description.length <= MAX_DESC,
26
+ hint: `Write a meta description ${MIN_DESC}–${MAX_DESC} characters long.`,
27
+ },
28
+ {
29
+ id: 'keyword-in-title',
30
+ label: 'Focus keyword in title',
31
+ pass: keyword.length > 0 && lcTitle.includes(keyword),
32
+ hint: 'Include the focus keyword in the title.',
33
+ },
34
+ {
35
+ id: 'keyword-in-body',
36
+ label: 'Focus keyword in body',
37
+ pass: keyword.length > 0 && lcBody.includes(keyword),
38
+ hint: 'Mention the focus keyword in the body.',
39
+ },
40
+ {
41
+ id: 'body-length',
42
+ label: 'Body length',
43
+ pass: bodyWords >= MIN_BODY_WORDS,
44
+ hint: `Write at least ${MIN_BODY_WORDS} words (currently ${bodyWords}).`,
45
+ },
46
+ ];
47
+ const score = checks.reduce((sum, c) => sum + (c.pass ? 20 : 0), 0);
48
+ return { score, checks };
49
+ }
50
+ //# sourceMappingURL=seo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seo.js","sourceRoot":"","sources":["../../src/engine/seo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAsB3C,MAAM,QAAQ,GAAG,EAAE,CAAA;AACnB,MAAM,QAAQ,GAAG,GAAG,CAAA;AACpB,MAAM,SAAS,GAAG,EAAE,CAAA;AACpB,MAAM,SAAS,GAAG,EAAE,CAAA;AACpB,MAAM,cAAc,GAAG,GAAG,CAAA;AAE1B,8EAA8E;AAC9E,MAAM,UAAU,UAAU,CAAC,KAAoB;IAC9C,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAC1D,MAAM,WAAW,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IACpD,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAC/D,MAAM,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC,CAAA;IACtD,MAAM,OAAO,GAAG,KAAK,CAAC,WAAW,EAAE,CAAA;IACnC,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAA;IAEvD,MAAM,MAAM,GAAe;QAC1B;YACC,EAAE,EAAE,cAAc;YAClB,KAAK,EAAE,cAAc;YACrB,IAAI,EAAE,KAAK,CAAC,MAAM,IAAI,SAAS,IAAI,KAAK,CAAC,MAAM,IAAI,SAAS;YAC5D,IAAI,EAAE,0BAA0B,SAAS,QAAQ,SAAS,cAAc;SACxE;QACD;YACC,EAAE,EAAE,kBAAkB;YACtB,KAAK,EAAE,kBAAkB;YACzB,IAAI,EAAE,WAAW,CAAC,MAAM,IAAI,QAAQ,IAAI,WAAW,CAAC,MAAM,IAAI,QAAQ;YACtE,IAAI,EAAE,4BAA4B,QAAQ,IAAI,QAAQ,mBAAmB;SACzE;QACD;YACC,EAAE,EAAE,kBAAkB;YACtB,KAAK,EAAE,wBAAwB;YAC/B,IAAI,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;YACrD,IAAI,EAAE,yCAAyC;SAC/C;QACD;YACC,EAAE,EAAE,iBAAiB;YACrB,KAAK,EAAE,uBAAuB;YAC9B,IAAI,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;YACpD,IAAI,EAAE,wCAAwC;SAC9C;QACD;YACC,EAAE,EAAE,aAAa;YACjB,KAAK,EAAE,aAAa;YACpB,IAAI,EAAE,SAAS,IAAI,cAAc;YACjC,IAAI,EAAE,kBAAkB,cAAc,qBAAqB,SAAS,IAAI;SACxE;KACD,CAAA;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACnE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAA;AACzB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { D1Database } from './d1.js';
2
+ /**
3
+ * Record `oldSlug` as a redirect pointing at `contentId`.
4
+ * Idempotent: if `old_slug` is already in the table the row is silently kept
5
+ * as-is (INSERT … ON CONFLICT(old_slug) DO NOTHING).
6
+ */
7
+ export declare function recordSlugRedirect(db: D1Database, oldSlug: string, contentId: string): Promise<void>;
8
+ //# sourceMappingURL=slug-redirects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slug-redirects.d.ts","sourceRoot":"","sources":["../../src/engine/slug-redirects.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEzC;;;;GAIG;AACH,wBAAsB,kBAAkB,CACvC,EAAE,EAAE,UAAU,EACd,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CASf"}