@geekity/cms 0.3.0 → 0.4.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 (637) hide show
  1. package/README.md +2091 -214
  2. package/admin/components/fields.njk +165 -0
  3. package/admin/layouts/base.njk +1 -1
  4. package/admin/layouts/settings-page.njk +26 -0
  5. package/admin/layouts/shell.njk +17 -3
  6. package/admin/pages/account/forgot.njk +47 -0
  7. package/admin/pages/account/login.njk +26 -0
  8. package/admin/pages/account/reset.njk +38 -0
  9. package/admin/pages/account/setup.njk +28 -0
  10. package/admin/pages/appearance/themes.njk +69 -0
  11. package/admin/pages/comments/all.njk +133 -0
  12. package/admin/{layouts/dashboard.njk → pages/dashboard/home.njk} +8 -15
  13. package/admin/{layouts/document-conflict.njk → pages/documents/conflict.njk} +1 -0
  14. package/admin/pages/documents/editor.njk +196 -0
  15. package/admin/{layouts/document-list.njk → pages/documents/list.njk} +19 -2
  16. package/admin/pages/documents/taxonomy.njk +95 -0
  17. package/admin/pages/federation/followers.njk +238 -0
  18. package/admin/pages/media/library.njk +160 -0
  19. package/admin/pages/messages/all.njk +110 -0
  20. package/admin/{layouts → pages}/placeholder.njk +5 -1
  21. package/admin/pages/settings/discussion.njk +99 -0
  22. package/admin/pages/settings/email.njk +203 -0
  23. package/admin/pages/settings/federation.njk +75 -0
  24. package/admin/pages/settings/general.njk +29 -0
  25. package/admin/pages/settings/permalinks.njk +50 -0
  26. package/admin/pages/settings/reading.njk +72 -0
  27. package/admin/pages/users/edit.njk +239 -0
  28. package/admin/pages/users/list.njk +48 -0
  29. package/admin/pages/users/new.njk +41 -0
  30. package/admin/static/admin.css +498 -3
  31. package/admin/static/copy.js +52 -0
  32. package/admin/static/editor.js +16 -16
  33. package/admin/static/slug.js +61 -0
  34. package/dist/admin/accounts.d.ts +413 -0
  35. package/dist/admin/accounts.d.ts.map +1 -0
  36. package/dist/admin/accounts.js +680 -0
  37. package/dist/admin/accounts.js.map +1 -0
  38. package/dist/admin/appearance.d.ts +80 -0
  39. package/dist/admin/appearance.d.ts.map +1 -0
  40. package/dist/admin/appearance.js +136 -0
  41. package/dist/admin/appearance.js.map +1 -0
  42. package/dist/admin/comments.d.ts +90 -0
  43. package/dist/admin/comments.d.ts.map +1 -0
  44. package/dist/admin/comments.js +244 -0
  45. package/dist/admin/comments.js.map +1 -0
  46. package/dist/admin/credentials.d.ts +26 -2
  47. package/dist/admin/credentials.d.ts.map +1 -1
  48. package/dist/admin/credentials.js +35 -2
  49. package/dist/admin/credentials.js.map +1 -1
  50. package/dist/admin/documents.d.ts +127 -10
  51. package/dist/admin/documents.d.ts.map +1 -1
  52. package/dist/admin/documents.js +360 -41
  53. package/dist/admin/documents.js.map +1 -1
  54. package/dist/admin/federation.d.ts +151 -50
  55. package/dist/admin/federation.d.ts.map +1 -1
  56. package/dist/admin/federation.js +225 -93
  57. package/dist/admin/federation.js.map +1 -1
  58. package/dist/admin/formatting.d.ts +20 -0
  59. package/dist/admin/formatting.d.ts.map +1 -0
  60. package/dist/admin/formatting.js +72 -0
  61. package/dist/admin/formatting.js.map +1 -0
  62. package/dist/admin/headers.d.ts +65 -0
  63. package/dist/admin/headers.d.ts.map +1 -0
  64. package/dist/admin/headers.js +104 -0
  65. package/dist/admin/headers.js.map +1 -0
  66. package/dist/admin/index.d.ts +38 -12
  67. package/dist/admin/index.d.ts.map +1 -1
  68. package/dist/admin/index.js +25 -7
  69. package/dist/admin/index.js.map +1 -1
  70. package/dist/admin/media.d.ts +168 -0
  71. package/dist/admin/media.d.ts.map +1 -0
  72. package/dist/admin/media.js +295 -0
  73. package/dist/admin/media.js.map +1 -0
  74. package/dist/admin/menu.d.ts +79 -0
  75. package/dist/admin/menu.d.ts.map +1 -0
  76. package/dist/admin/menu.js +126 -0
  77. package/dist/admin/menu.js.map +1 -0
  78. package/dist/admin/messages.d.ts +80 -0
  79. package/dist/admin/messages.d.ts.map +1 -0
  80. package/dist/admin/messages.js +152 -0
  81. package/dist/admin/messages.js.map +1 -0
  82. package/dist/admin/preview.d.ts.map +1 -1
  83. package/dist/admin/preview.js +31 -7
  84. package/dist/admin/preview.js.map +1 -1
  85. package/dist/admin/recovery.d.ts +92 -0
  86. package/dist/admin/recovery.d.ts.map +1 -0
  87. package/dist/admin/recovery.js +229 -0
  88. package/dist/admin/recovery.js.map +1 -0
  89. package/dist/admin/routes.d.ts +0 -20
  90. package/dist/admin/routes.d.ts.map +1 -1
  91. package/dist/admin/routes.js +155 -105
  92. package/dist/admin/routes.js.map +1 -1
  93. package/dist/admin/settings-discussion.d.ts +37 -0
  94. package/dist/admin/settings-discussion.d.ts.map +1 -0
  95. package/dist/admin/settings-discussion.js +117 -0
  96. package/dist/admin/settings-discussion.js.map +1 -0
  97. package/dist/admin/settings-email.d.ts +54 -0
  98. package/dist/admin/settings-email.d.ts.map +1 -0
  99. package/dist/admin/settings-email.js +189 -0
  100. package/dist/admin/settings-email.js.map +1 -0
  101. package/dist/admin/settings-federation.d.ts +39 -0
  102. package/dist/admin/settings-federation.d.ts.map +1 -0
  103. package/dist/admin/settings-federation.js +103 -0
  104. package/dist/admin/settings-federation.js.map +1 -0
  105. package/dist/admin/settings-general.d.ts +12 -0
  106. package/dist/admin/settings-general.d.ts.map +1 -0
  107. package/dist/admin/settings-general.js +48 -0
  108. package/dist/admin/settings-general.js.map +1 -0
  109. package/dist/admin/settings-page.d.ts +102 -0
  110. package/dist/admin/settings-page.d.ts.map +1 -0
  111. package/dist/admin/settings-page.js +126 -0
  112. package/dist/admin/settings-page.js.map +1 -0
  113. package/dist/admin/settings-pages.d.ts +19 -0
  114. package/dist/admin/settings-pages.d.ts.map +1 -0
  115. package/dist/admin/settings-pages.js +33 -0
  116. package/dist/admin/settings-pages.js.map +1 -0
  117. package/dist/admin/settings-permalinks.d.ts +16 -0
  118. package/dist/admin/settings-permalinks.d.ts.map +1 -0
  119. package/dist/admin/settings-permalinks.js +32 -0
  120. package/dist/admin/settings-permalinks.js.map +1 -0
  121. package/dist/admin/settings-reading.d.ts +33 -0
  122. package/dist/admin/settings-reading.d.ts.map +1 -0
  123. package/dist/admin/settings-reading.js +48 -0
  124. package/dist/admin/settings-reading.js.map +1 -0
  125. package/dist/admin/settings.d.ts +325 -96
  126. package/dist/admin/settings.d.ts.map +1 -1
  127. package/dist/admin/settings.js +650 -308
  128. package/dist/admin/settings.js.map +1 -1
  129. package/dist/admin/store.d.ts +606 -152
  130. package/dist/admin/store.d.ts.map +1 -1
  131. package/dist/admin/store.js +863 -268
  132. package/dist/admin/store.js.map +1 -1
  133. package/dist/admin/taxonomy.d.ts +114 -0
  134. package/dist/admin/taxonomy.d.ts.map +1 -0
  135. package/dist/admin/taxonomy.js +289 -0
  136. package/dist/admin/taxonomy.js.map +1 -0
  137. package/dist/admin/templates.d.ts +44 -14
  138. package/dist/admin/templates.d.ts.map +1 -1
  139. package/dist/admin/templates.js +44 -14
  140. package/dist/admin/templates.js.map +1 -1
  141. package/dist/admin/throttle.d.ts +84 -0
  142. package/dist/admin/throttle.d.ts.map +1 -0
  143. package/dist/admin/throttle.js +143 -0
  144. package/dist/admin/throttle.js.map +1 -0
  145. package/dist/admin/uploads.d.ts +28 -2
  146. package/dist/admin/uploads.d.ts.map +1 -1
  147. package/dist/admin/uploads.js +43 -4
  148. package/dist/admin/uploads.js.map +1 -1
  149. package/dist/admin/users.d.ts +100 -13
  150. package/dist/admin/users.d.ts.map +1 -1
  151. package/dist/admin/users.js +412 -39
  152. package/dist/admin/users.js.map +1 -1
  153. package/dist/cache.d.ts +141 -0
  154. package/dist/cache.d.ts.map +1 -0
  155. package/dist/cache.js +207 -0
  156. package/dist/cache.js.map +1 -0
  157. package/dist/cli.d.ts +14 -2
  158. package/dist/cli.d.ts.map +1 -1
  159. package/dist/cli.js +424 -21
  160. package/dist/cli.js.map +1 -1
  161. package/dist/comments/akismet.d.ts +130 -0
  162. package/dist/comments/akismet.d.ts.map +1 -0
  163. package/dist/comments/akismet.js +274 -0
  164. package/dist/comments/akismet.js.map +1 -0
  165. package/dist/comments/conversation.d.ts +29 -0
  166. package/dist/comments/conversation.d.ts.map +1 -0
  167. package/dist/comments/conversation.js +60 -0
  168. package/dist/comments/conversation.js.map +1 -0
  169. package/dist/comments/form.d.ts +75 -0
  170. package/dist/comments/form.d.ts.map +1 -0
  171. package/dist/comments/form.js +64 -0
  172. package/dist/comments/form.js.map +1 -0
  173. package/dist/comments/index.d.ts +15 -0
  174. package/dist/comments/index.d.ts.map +1 -0
  175. package/dist/comments/index.js +9 -0
  176. package/dist/comments/index.js.map +1 -0
  177. package/dist/comments/markdown.d.ts +8 -0
  178. package/dist/comments/markdown.d.ts.map +1 -0
  179. package/dist/comments/markdown.js +85 -0
  180. package/dist/comments/markdown.js.map +1 -0
  181. package/dist/comments/moderate.d.ts +71 -0
  182. package/dist/comments/moderate.d.ts.map +1 -0
  183. package/dist/comments/moderate.js +88 -0
  184. package/dist/comments/moderate.js.map +1 -0
  185. package/dist/comments/policy.d.ts +57 -0
  186. package/dist/comments/policy.d.ts.map +1 -0
  187. package/dist/comments/policy.js +80 -0
  188. package/dist/comments/policy.js.map +1 -0
  189. package/dist/comments/records.d.ts +266 -0
  190. package/dist/comments/records.d.ts.map +1 -0
  191. package/dist/comments/records.js +487 -0
  192. package/dist/comments/records.js.map +1 -0
  193. package/dist/comments/routes.d.ts +58 -0
  194. package/dist/comments/routes.d.ts.map +1 -0
  195. package/dist/comments/routes.js +177 -0
  196. package/dist/comments/routes.js.map +1 -0
  197. package/dist/comments/submission.d.ts +263 -0
  198. package/dist/comments/submission.d.ts.map +1 -0
  199. package/dist/comments/submission.js +241 -0
  200. package/dist/comments/submission.js.map +1 -0
  201. package/dist/config.d.ts +190 -5
  202. package/dist/config.d.ts.map +1 -1
  203. package/dist/config.js +118 -6
  204. package/dist/config.js.map +1 -1
  205. package/dist/contact/delivery.d.ts +60 -0
  206. package/dist/contact/delivery.d.ts.map +1 -0
  207. package/dist/contact/delivery.js +87 -0
  208. package/dist/contact/delivery.js.map +1 -0
  209. package/dist/contact/form.d.ts +130 -0
  210. package/dist/contact/form.d.ts.map +1 -0
  211. package/dist/contact/form.js +163 -0
  212. package/dist/contact/form.js.map +1 -0
  213. package/dist/contact/index.d.ts +17 -0
  214. package/dist/contact/index.d.ts.map +1 -0
  215. package/dist/contact/index.js +13 -0
  216. package/dist/contact/index.js.map +1 -0
  217. package/dist/contact/records.d.ts +124 -0
  218. package/dist/contact/records.d.ts.map +1 -0
  219. package/dist/contact/records.js +218 -0
  220. package/dist/contact/records.js.map +1 -0
  221. package/dist/contact/routes.d.ts +17 -0
  222. package/dist/contact/routes.d.ts.map +1 -0
  223. package/dist/contact/routes.js +127 -0
  224. package/dist/contact/routes.js.map +1 -0
  225. package/dist/contact/submission.d.ts +103 -0
  226. package/dist/contact/submission.d.ts.map +1 -0
  227. package/dist/contact/submission.js +166 -0
  228. package/dist/contact/submission.js.map +1 -0
  229. package/dist/content/document.d.ts +7 -2
  230. package/dist/content/document.d.ts.map +1 -1
  231. package/dist/content/document.js +1 -0
  232. package/dist/content/document.js.map +1 -1
  233. package/dist/content/index.d.ts +7 -2
  234. package/dist/content/index.d.ts.map +1 -1
  235. package/dist/content/index.js +4 -1
  236. package/dist/content/index.js.map +1 -1
  237. package/dist/content/markdown.d.ts.map +1 -1
  238. package/dist/content/markdown.js +24 -2
  239. package/dist/content/markdown.js.map +1 -1
  240. package/dist/content/parser.d.ts.map +1 -1
  241. package/dist/content/parser.js +11 -4
  242. package/dist/content/parser.js.map +1 -1
  243. package/dist/content/save.d.ts +5 -0
  244. package/dist/content/save.d.ts.map +1 -1
  245. package/dist/content/save.js +44 -1
  246. package/dist/content/save.js.map +1 -1
  247. package/dist/content/schedule.d.ts +125 -0
  248. package/dist/content/schedule.d.ts.map +1 -0
  249. package/dist/content/schedule.js +207 -0
  250. package/dist/content/schedule.js.map +1 -0
  251. package/dist/content/search.d.ts +64 -0
  252. package/dist/content/search.d.ts.map +1 -0
  253. package/dist/content/search.js +136 -0
  254. package/dist/content/search.js.map +1 -0
  255. package/dist/content/store.d.ts +202 -7
  256. package/dist/content/store.d.ts.map +1 -1
  257. package/dist/content/store.js +374 -67
  258. package/dist/content/store.js.map +1 -1
  259. package/dist/content/sync.d.ts +7 -1
  260. package/dist/content/sync.d.ts.map +1 -1
  261. package/dist/content/sync.js +18 -10
  262. package/dist/content/sync.js.map +1 -1
  263. package/dist/content/time.d.ts +56 -0
  264. package/dist/content/time.d.ts.map +1 -0
  265. package/dist/content/time.js +141 -0
  266. package/dist/content/time.js.map +1 -0
  267. package/dist/content/writer.d.ts.map +1 -1
  268. package/dist/content/writer.js +3 -0
  269. package/dist/content/writer.js.map +1 -1
  270. package/dist/env.d.ts +58 -4
  271. package/dist/env.d.ts.map +1 -1
  272. package/dist/federation/actor.d.ts +95 -41
  273. package/dist/federation/actor.d.ts.map +1 -1
  274. package/dist/federation/actor.js +180 -53
  275. package/dist/federation/actor.js.map +1 -1
  276. package/dist/federation/article.d.ts +44 -17
  277. package/dist/federation/article.d.ts.map +1 -1
  278. package/dist/federation/article.js +98 -46
  279. package/dist/federation/article.js.map +1 -1
  280. package/dist/federation/delivery.d.ts +63 -15
  281. package/dist/federation/delivery.d.ts.map +1 -1
  282. package/dist/federation/delivery.js +154 -80
  283. package/dist/federation/delivery.js.map +1 -1
  284. package/dist/federation/federation.d.ts +22 -17
  285. package/dist/federation/federation.d.ts.map +1 -1
  286. package/dist/federation/federation.js +98 -77
  287. package/dist/federation/federation.js.map +1 -1
  288. package/dist/federation/followers.d.ts +3 -2
  289. package/dist/federation/followers.d.ts.map +1 -1
  290. package/dist/federation/followers.js +6 -5
  291. package/dist/federation/followers.js.map +1 -1
  292. package/dist/federation/import-wordpress.d.ts +128 -0
  293. package/dist/federation/import-wordpress.d.ts.map +1 -0
  294. package/dist/federation/import-wordpress.js +426 -0
  295. package/dist/federation/import-wordpress.js.map +1 -0
  296. package/dist/federation/inbox.d.ts +36 -13
  297. package/dist/federation/inbox.d.ts.map +1 -1
  298. package/dist/federation/inbox.js +120 -49
  299. package/dist/federation/inbox.js.map +1 -1
  300. package/dist/federation/index.d.ts +22 -10
  301. package/dist/federation/index.d.ts.map +1 -1
  302. package/dist/federation/index.js +13 -8
  303. package/dist/federation/index.js.map +1 -1
  304. package/dist/federation/keys.d.ts +98 -20
  305. package/dist/federation/keys.d.ts.map +1 -1
  306. package/dist/federation/keys.js +269 -39
  307. package/dist/federation/keys.js.map +1 -1
  308. package/dist/federation/mount.d.ts +42 -10
  309. package/dist/federation/mount.d.ts.map +1 -1
  310. package/dist/federation/mount.js +266 -26
  311. package/dist/federation/mount.js.map +1 -1
  312. package/dist/federation/paths.d.ts +23 -35
  313. package/dist/federation/paths.d.ts.map +1 -1
  314. package/dist/federation/paths.js +26 -39
  315. package/dist/federation/paths.js.map +1 -1
  316. package/dist/federation/records.d.ts +223 -0
  317. package/dist/federation/records.d.ts.map +1 -0
  318. package/dist/federation/records.js +506 -0
  319. package/dist/federation/records.js.map +1 -0
  320. package/dist/federation/relays.d.ts +114 -0
  321. package/dist/federation/relays.d.ts.map +1 -0
  322. package/dist/federation/relays.js +290 -0
  323. package/dist/federation/relays.js.map +1 -0
  324. package/dist/federation/replies.d.ts +80 -0
  325. package/dist/federation/replies.d.ts.map +1 -0
  326. package/dist/federation/replies.js +166 -0
  327. package/dist/federation/replies.js.map +1 -0
  328. package/dist/federation/wordpress.d.ts +131 -0
  329. package/dist/federation/wordpress.d.ts.map +1 -0
  330. package/dist/federation/wordpress.js +341 -0
  331. package/dist/federation/wordpress.js.map +1 -0
  332. package/dist/files/atomic.d.ts +103 -0
  333. package/dist/files/atomic.d.ts.map +1 -0
  334. package/dist/files/atomic.js +150 -0
  335. package/dist/files/atomic.js.map +1 -0
  336. package/dist/files/index.d.ts +3 -0
  337. package/dist/files/index.d.ts.map +1 -0
  338. package/dist/files/index.js +2 -0
  339. package/dist/files/index.js.map +1 -0
  340. package/dist/forms/protection.d.ts +85 -0
  341. package/dist/forms/protection.d.ts.map +1 -0
  342. package/dist/forms/protection.js +116 -0
  343. package/dist/forms/protection.js.map +1 -0
  344. package/dist/images/icons.d.ts +59 -0
  345. package/dist/images/icons.d.ts.map +1 -0
  346. package/dist/images/icons.js +131 -0
  347. package/dist/images/icons.js.map +1 -0
  348. package/dist/images/index.d.ts +7 -0
  349. package/dist/images/index.d.ts.map +1 -0
  350. package/dist/images/index.js +4 -0
  351. package/dist/images/index.js.map +1 -0
  352. package/dist/images/markup.d.ts +47 -0
  353. package/dist/images/markup.d.ts.map +1 -0
  354. package/dist/images/markup.js +175 -0
  355. package/dist/images/markup.js.map +1 -0
  356. package/dist/images/paths.d.ts +34 -0
  357. package/dist/images/paths.d.ts.map +1 -0
  358. package/dist/images/paths.js +41 -0
  359. package/dist/images/paths.js.map +1 -0
  360. package/dist/images/variants.d.ts +104 -0
  361. package/dist/images/variants.d.ts.map +1 -0
  362. package/dist/images/variants.js +320 -0
  363. package/dist/images/variants.js.map +1 -0
  364. package/dist/index.d.ts +123 -19
  365. package/dist/index.d.ts.map +1 -1
  366. package/dist/index.js +327 -25
  367. package/dist/index.js.map +1 -1
  368. package/dist/init.d.ts +18 -0
  369. package/dist/init.d.ts.map +1 -1
  370. package/dist/init.js +34 -3
  371. package/dist/init.js.map +1 -1
  372. package/dist/mail/brevo.d.ts +35 -0
  373. package/dist/mail/brevo.d.ts.map +1 -0
  374. package/dist/mail/brevo.js +85 -0
  375. package/dist/mail/brevo.js.map +1 -0
  376. package/dist/mail/credentials.d.ts +62 -0
  377. package/dist/mail/credentials.d.ts.map +1 -0
  378. package/dist/mail/credentials.js +86 -0
  379. package/dist/mail/credentials.js.map +1 -0
  380. package/dist/mail/index.d.ts +15 -0
  381. package/dist/mail/index.d.ts.map +1 -0
  382. package/dist/mail/index.js +8 -0
  383. package/dist/mail/index.js.map +1 -0
  384. package/dist/mail/memory.d.ts +35 -0
  385. package/dist/mail/memory.d.ts.map +1 -0
  386. package/dist/mail/memory.js +29 -0
  387. package/dist/mail/memory.js.map +1 -0
  388. package/dist/mail/provider.d.ts +80 -0
  389. package/dist/mail/provider.d.ts.map +1 -0
  390. package/dist/mail/provider.js +23 -0
  391. package/dist/mail/provider.js.map +1 -0
  392. package/dist/mail/service.d.ts +156 -0
  393. package/dist/mail/service.d.ts.map +1 -0
  394. package/dist/mail/service.js +265 -0
  395. package/dist/mail/service.js.map +1 -0
  396. package/dist/mail/smtp.d.ts +39 -0
  397. package/dist/mail/smtp.d.ts.map +1 -0
  398. package/dist/mail/smtp.js +58 -0
  399. package/dist/mail/smtp.js.map +1 -0
  400. package/dist/mail/templates.d.ts +91 -0
  401. package/dist/mail/templates.d.ts.map +1 -0
  402. package/dist/mail/templates.js +69 -0
  403. package/dist/mail/templates.js.map +1 -0
  404. package/dist/notifications/comments.d.ts +66 -0
  405. package/dist/notifications/comments.d.ts.map +1 -0
  406. package/dist/notifications/comments.js +151 -0
  407. package/dist/notifications/comments.js.map +1 -0
  408. package/dist/notifications/digest.d.ts +135 -0
  409. package/dist/notifications/digest.d.ts.map +1 -0
  410. package/dist/notifications/digest.js +287 -0
  411. package/dist/notifications/digest.js.map +1 -0
  412. package/dist/notifications/index.d.ts +13 -0
  413. package/dist/notifications/index.d.ts.map +1 -0
  414. package/dist/notifications/index.js +8 -0
  415. package/dist/notifications/index.js.map +1 -0
  416. package/dist/notifications/links.d.ts +60 -0
  417. package/dist/notifications/links.d.ts.map +1 -0
  418. package/dist/notifications/links.js +63 -0
  419. package/dist/notifications/links.js.map +1 -0
  420. package/dist/notifications/optouts.d.ts +48 -0
  421. package/dist/notifications/optouts.d.ts.map +1 -0
  422. package/dist/notifications/optouts.js +93 -0
  423. package/dist/notifications/optouts.js.map +1 -0
  424. package/dist/notifications/preferences.d.ts +158 -0
  425. package/dist/notifications/preferences.d.ts.map +1 -0
  426. package/dist/notifications/preferences.js +195 -0
  427. package/dist/notifications/preferences.js.map +1 -0
  428. package/dist/notifications/routes.d.ts +28 -0
  429. package/dist/notifications/routes.d.ts.map +1 -0
  430. package/dist/notifications/routes.js +184 -0
  431. package/dist/notifications/routes.js.map +1 -0
  432. package/dist/notifications/tokens.d.ts +60 -0
  433. package/dist/notifications/tokens.d.ts.map +1 -0
  434. package/dist/notifications/tokens.js +125 -0
  435. package/dist/notifications/tokens.js.map +1 -0
  436. package/dist/notify.d.ts +84 -0
  437. package/dist/notify.d.ts.map +1 -0
  438. package/dist/notify.js +149 -0
  439. package/dist/notify.js.map +1 -0
  440. package/dist/web/archive.d.ts +49 -0
  441. package/dist/web/archive.d.ts.map +1 -0
  442. package/dist/web/archive.js +59 -0
  443. package/dist/web/archive.js.map +1 -0
  444. package/dist/web/assets.d.ts +6 -5
  445. package/dist/web/assets.d.ts.map +1 -1
  446. package/dist/web/assets.js +5 -7
  447. package/dist/web/assets.js.map +1 -1
  448. package/dist/web/authors.d.ts +143 -0
  449. package/dist/web/authors.d.ts.map +1 -0
  450. package/dist/web/authors.js +178 -0
  451. package/dist/web/authors.js.map +1 -0
  452. package/dist/web/comments.d.ts +60 -0
  453. package/dist/web/comments.d.ts.map +1 -0
  454. package/dist/web/comments.js +207 -0
  455. package/dist/web/comments.js.map +1 -0
  456. package/dist/web/context.d.ts +162 -28
  457. package/dist/web/context.d.ts.map +1 -1
  458. package/dist/web/context.js +123 -26
  459. package/dist/web/context.js.map +1 -1
  460. package/dist/web/conversation.d.ts +209 -0
  461. package/dist/web/conversation.d.ts.map +1 -0
  462. package/dist/web/conversation.js +557 -0
  463. package/dist/web/conversation.js.map +1 -0
  464. package/dist/web/documents.d.ts +36 -6
  465. package/dist/web/documents.d.ts.map +1 -1
  466. package/dist/web/documents.js +52 -10
  467. package/dist/web/documents.js.map +1 -1
  468. package/dist/web/feed-atom.d.ts +22 -0
  469. package/dist/web/feed-atom.d.ts.map +1 -0
  470. package/dist/web/feed-atom.js +83 -0
  471. package/dist/web/feed-atom.js.map +1 -0
  472. package/dist/web/feed-item.d.ts +145 -0
  473. package/dist/web/feed-item.d.ts.map +1 -0
  474. package/dist/web/feed-item.js +120 -0
  475. package/dist/web/feed-item.js.map +1 -0
  476. package/dist/web/feed-json.d.ts +79 -0
  477. package/dist/web/feed-json.d.ts.map +1 -0
  478. package/dist/web/feed-json.js +53 -0
  479. package/dist/web/feed-json.js.map +1 -0
  480. package/dist/web/feed-rss.d.ts +26 -0
  481. package/dist/web/feed-rss.d.ts.map +1 -0
  482. package/dist/web/feed-rss.js +203 -0
  483. package/dist/web/feed-rss.js.map +1 -0
  484. package/dist/web/feed-source.d.ts +244 -0
  485. package/dist/web/feed-source.d.ts.map +1 -0
  486. package/dist/web/feed-source.js +201 -0
  487. package/dist/web/feed-source.js.map +1 -0
  488. package/dist/web/feed-xml.d.ts +63 -0
  489. package/dist/web/feed-xml.d.ts.map +1 -0
  490. package/dist/web/feed-xml.js +116 -0
  491. package/dist/web/feed-xml.js.map +1 -0
  492. package/dist/web/feeds.d.ts +31 -96
  493. package/dist/web/feeds.d.ts.map +1 -1
  494. package/dist/web/feeds.js +94 -198
  495. package/dist/web/feeds.js.map +1 -1
  496. package/dist/web/health.d.ts +31 -0
  497. package/dist/web/health.d.ts.map +1 -0
  498. package/dist/web/health.js +44 -0
  499. package/dist/web/health.js.map +1 -0
  500. package/dist/web/index.d.ts +30 -10
  501. package/dist/web/index.d.ts.map +1 -1
  502. package/dist/web/index.js +18 -7
  503. package/dist/web/index.js.map +1 -1
  504. package/dist/web/navigation.d.ts +73 -0
  505. package/dist/web/navigation.d.ts.map +1 -0
  506. package/dist/web/navigation.js +110 -0
  507. package/dist/web/navigation.js.map +1 -0
  508. package/dist/web/negotiate.d.ts +9 -0
  509. package/dist/web/negotiate.d.ts.map +1 -1
  510. package/dist/web/negotiate.js +6 -1
  511. package/dist/web/negotiate.js.map +1 -1
  512. package/dist/web/recent.d.ts +43 -0
  513. package/dist/web/recent.d.ts.map +1 -0
  514. package/dist/web/recent.js +37 -0
  515. package/dist/web/recent.js.map +1 -0
  516. package/dist/web/render.d.ts +197 -9
  517. package/dist/web/render.d.ts.map +1 -1
  518. package/dist/web/render.js +334 -17
  519. package/dist/web/render.js.map +1 -1
  520. package/dist/web/routes.d.ts +25 -8
  521. package/dist/web/routes.d.ts.map +1 -1
  522. package/dist/web/routes.js +845 -93
  523. package/dist/web/routes.js.map +1 -1
  524. package/dist/web/sanitize.d.ts +19 -0
  525. package/dist/web/sanitize.d.ts.map +1 -0
  526. package/dist/web/sanitize.js +272 -0
  527. package/dist/web/sanitize.js.map +1 -0
  528. package/dist/web/search.d.ts +79 -0
  529. package/dist/web/search.d.ts.map +1 -0
  530. package/dist/web/search.js +94 -0
  531. package/dist/web/search.js.map +1 -0
  532. package/dist/web/sitemap.d.ts +120 -0
  533. package/dist/web/sitemap.d.ts.map +1 -0
  534. package/dist/web/sitemap.js +199 -0
  535. package/dist/web/sitemap.js.map +1 -0
  536. package/dist/web/taxonomy.d.ts +152 -0
  537. package/dist/web/taxonomy.d.ts.map +1 -0
  538. package/dist/web/taxonomy.js +237 -0
  539. package/dist/web/taxonomy.js.map +1 -0
  540. package/dist/web/templates.d.ts +54 -16
  541. package/dist/web/templates.d.ts.map +1 -1
  542. package/dist/web/templates.js +109 -28
  543. package/dist/web/templates.js.map +1 -1
  544. package/dist/web/themes.d.ts +205 -0
  545. package/dist/web/themes.d.ts.map +1 -0
  546. package/dist/web/themes.js +277 -0
  547. package/dist/web/themes.js.map +1 -0
  548. package/dist/webmention/discovery.d.ts +51 -0
  549. package/dist/webmention/discovery.d.ts.map +1 -0
  550. package/dist/webmention/discovery.js +176 -0
  551. package/dist/webmention/discovery.js.map +1 -0
  552. package/dist/webmention/html.d.ts +71 -0
  553. package/dist/webmention/html.d.ts.map +1 -0
  554. package/dist/webmention/html.js +285 -0
  555. package/dist/webmention/html.js.map +1 -0
  556. package/dist/webmention/index.d.ts +12 -0
  557. package/dist/webmention/index.d.ts.map +1 -0
  558. package/dist/webmention/index.js +8 -0
  559. package/dist/webmention/index.js.map +1 -0
  560. package/dist/webmention/links.d.ts +18 -0
  561. package/dist/webmention/links.d.ts.map +1 -0
  562. package/dist/webmention/links.js +64 -0
  563. package/dist/webmention/links.js.map +1 -0
  564. package/dist/webmention/microformats.d.ts +93 -0
  565. package/dist/webmention/microformats.d.ts.map +1 -0
  566. package/dist/webmention/microformats.js +376 -0
  567. package/dist/webmention/microformats.js.map +1 -0
  568. package/dist/webmention/receive.d.ts +141 -0
  569. package/dist/webmention/receive.d.ts.map +1 -0
  570. package/dist/webmention/receive.js +264 -0
  571. package/dist/webmention/receive.js.map +1 -0
  572. package/dist/webmention/routes.d.ts +37 -0
  573. package/dist/webmention/routes.d.ts.map +1 -0
  574. package/dist/webmention/routes.js +75 -0
  575. package/dist/webmention/routes.js.map +1 -0
  576. package/dist/webmention/service.d.ts +94 -0
  577. package/dist/webmention/service.d.ts.map +1 -0
  578. package/dist/webmention/service.js +207 -0
  579. package/dist/webmention/service.js.map +1 -0
  580. package/package.json +11 -6
  581. package/templates/site/content/_data/site.json +1 -0
  582. package/templates/site/content/posts/2026-01-01-hello-world.md +5 -3
  583. package/templates/site/geekity.config.ts +11 -1
  584. package/templates/site/tsconfig.json +1 -1
  585. package/themes/default/README.md +1096 -50
  586. package/themes/default/layouts/404.njk +2 -3
  587. package/themes/default/layouts/author.njk +37 -0
  588. package/themes/default/layouts/base.njk +172 -31
  589. package/themes/default/layouts/category.njk +27 -0
  590. package/themes/default/layouts/front-page.njk +57 -0
  591. package/themes/default/layouts/home.njk +17 -1
  592. package/themes/default/layouts/page.njk +57 -5
  593. package/themes/default/layouts/post.njk +78 -19
  594. package/themes/default/layouts/search.njk +57 -0
  595. package/themes/default/layouts/tag.njk +3 -6
  596. package/themes/default/mail/comment-digest.html.njk +37 -0
  597. package/themes/default/mail/comment-digest.subject.njk +3 -0
  598. package/themes/default/mail/comment-digest.txt.njk +40 -0
  599. package/themes/default/mail/comment-pending.html.njk +27 -0
  600. package/themes/default/mail/comment-pending.subject.njk +2 -0
  601. package/themes/default/mail/comment-pending.txt.njk +24 -0
  602. package/themes/default/mail/comment-reply.html.njk +21 -0
  603. package/themes/default/mail/comment-reply.subject.njk +2 -0
  604. package/themes/default/mail/comment-reply.txt.njk +22 -0
  605. package/themes/default/mail/contact-message.html.njk +24 -0
  606. package/themes/default/mail/contact-message.subject.njk +5 -0
  607. package/themes/default/mail/contact-message.txt.njk +20 -0
  608. package/themes/default/mail/password-changed.html.njk +18 -0
  609. package/themes/default/mail/password-changed.subject.njk +2 -0
  610. package/themes/default/mail/password-changed.txt.njk +17 -0
  611. package/themes/default/mail/password-reset.html.njk +22 -0
  612. package/themes/default/mail/password-reset.subject.njk +2 -0
  613. package/themes/default/mail/password-reset.txt.njk +18 -0
  614. package/themes/default/mail/test.html.njk +14 -0
  615. package/themes/default/mail/test.subject.njk +2 -0
  616. package/themes/default/mail/test.txt.njk +12 -0
  617. package/themes/default/partials/archive.njk +27 -0
  618. package/themes/default/partials/bio.njk +77 -0
  619. package/themes/default/partials/comment-form.njk +109 -0
  620. package/themes/default/partials/contact-form.njk +88 -0
  621. package/themes/default/partials/conversation.njk +139 -0
  622. package/themes/default/partials/feeds.njk +26 -0
  623. package/themes/default/partials/jsonld.njk +120 -0
  624. package/themes/default/partials/pagination.njk +12 -6
  625. package/themes/default/partials/post-list.njk +51 -18
  626. package/themes/default/partials/search-form.njk +17 -0
  627. package/themes/default/partials/tags.njk +26 -5
  628. package/themes/default/static/highlight.js +4 -0
  629. package/themes/default/static/style.css +1119 -194
  630. package/themes/default/theme.json +5 -0
  631. package/admin/layouts/document-editor.njk +0 -167
  632. package/admin/layouts/federation.njk +0 -145
  633. package/admin/layouts/login.njk +0 -23
  634. package/admin/layouts/settings.njk +0 -116
  635. package/admin/layouts/setup.njk +0 -27
  636. package/admin/layouts/users.njk +0 -91
  637. /package/admin/{layouts/_flash.njk → components/flash.njk} +0 -0
@@ -0,0 +1,69 @@
1
+ import { createTemplateEnvironment, useThemeDirs } from '../web/templates.js';
2
+ import { findThemeFile } from '../web/themes.js';
3
+ /** Which files a named message is built from, relative to a theme directory. */
4
+ export function mailTemplateFiles(name) {
5
+ return {
6
+ subject: `mail/${name}.subject.njk`,
7
+ text: `mail/${name}.txt.njk`,
8
+ html: `mail/${name}.html.njk`,
9
+ };
10
+ }
11
+ /** Build the mail templates for one site. */
12
+ export function createMailTemplates(options) {
13
+ // The same environment the theme is rendered through, so a message has the
14
+ // same `date`, `url` and `absoluteUrl` filters a page does and a site does
15
+ // not have to learn a second set of rules to write one.
16
+ const environment = createTemplateEnvironment({
17
+ themeDirs: options.themes.current().dirs,
18
+ baseUrl: options.baseUrl,
19
+ ...(options.noCache === undefined ? {} : { noCache: options.noCache }),
20
+ });
21
+ // The same again with autoescaping off, for the two halves of a message that
22
+ // are not HTML. Built here rather than by unescaping afterwards, because
23
+ // there is no way to tell an `&` the template meant from one it did not.
24
+ const plainEnvironment = createTemplateEnvironment({
25
+ themeDirs: options.themes.current().dirs,
26
+ baseUrl: options.baseUrl,
27
+ autoescape: false,
28
+ ...(options.noCache === undefined ? {} : { noCache: options.noCache }),
29
+ });
30
+ /**
31
+ * The theme this message is being written in, with both environments pointed
32
+ * at it.
33
+ *
34
+ * Asked per message rather than held, for the reason a page asks per render:
35
+ * a theme chosen a minute ago is the one the next message should come from.
36
+ * The directories it hands back are what `present` then asks about, so which
37
+ * halves of a message exist is the same question as which file a render
38
+ * would read.
39
+ */
40
+ function themeDirs() {
41
+ const dirs = options.themes.current().dirs;
42
+ useThemeDirs(environment, dirs);
43
+ useThemeDirs(plainEnvironment, dirs);
44
+ return dirs;
45
+ }
46
+ return {
47
+ environment,
48
+ plainEnvironment,
49
+ render(name, context = {}) {
50
+ const files = mailTemplateFiles(name);
51
+ const searchPath = themeDirs();
52
+ /** Whether any theme on the search path has that template. */
53
+ const present = (template) => findThemeFile(searchPath, template) !== undefined;
54
+ if (!present(files.text)) {
55
+ throw new Error(`There is no mail template ${files.text} in the site theme or in the packaged one.`);
56
+ }
57
+ return {
58
+ // A subject is a header, and a header is one line: whatever the
59
+ // template did with whitespace, what goes out is a single line.
60
+ subject: present(files.subject)
61
+ ? plainEnvironment.render(files.subject, context).replace(/\s+/g, ' ').trim()
62
+ : '',
63
+ text: plainEnvironment.render(files.text, context),
64
+ ...(present(files.html) ? { html: environment.render(files.html, context) } : {}),
65
+ };
66
+ },
67
+ };
68
+ }
69
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/mail/templates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import type { AdminStore, PostComment } from '../admin/store.ts';
2
+ import type { ResolvedConfig } from '../config.ts';
3
+ import type { ContentStore } from '../content/store.ts';
4
+ import type { MailService } from '../mail/service.ts';
5
+ /**
6
+ * The two messages a comment sets off, and the rules about who gets them.
7
+ *
8
+ * Both go through the mail service and nothing else (TASK-53), so a site with
9
+ * no provider sends nothing and every path through here still works. Neither
10
+ * is awaited by the request that caused it: a comment is stored, a page is
11
+ * redirected to, and the message goes out behind that.
12
+ *
13
+ * **The moderation notice.** A comment or a webmention has entered the queue,
14
+ * so everyone who has an address and has not turned the notice off is told,
15
+ * with the words themselves and three signed links that approve, file as spam
16
+ * or delete it without a login. It goes out for `pending` and nothing else,
17
+ * which is the whole of the "not for spam" rule: a comment Akismet filed as
18
+ * spam is nobody's decision to make today, and one it said to discard was
19
+ * never stored at all.
20
+ *
21
+ * **The reply notice.** Somebody ticked "tell me about replies" when they
22
+ * commented, and a reply to that comment has just been approved. That is the
23
+ * only moment it goes: an unapproved reply is not something a stranger should
24
+ * be emailed the text of, and a moderator should be able to delete a nasty one
25
+ * before anybody hears about it.
26
+ *
27
+ * Three things stop it. The address is missing, the address has unsubscribed,
28
+ * or the reply is by the very person who would be told — nobody needs an email
29
+ * about their own words.
30
+ */
31
+ /** The message an admin gets when something is waiting. */
32
+ export declare const COMMENT_PENDING_TEMPLATE = "comment-pending";
33
+ /** The message a commenter gets when a reply to them is approved. */
34
+ export declare const COMMENT_REPLY_TEMPLATE = "comment-reply";
35
+ /** The event name the users screen switches, from the registry. */
36
+ export declare const COMMENTS_NOTIFICATION = "comments";
37
+ /** What {@link createCommentNotifier} needs. */
38
+ export interface CreateCommentNotifierOptions {
39
+ /** The comment index, which is what a parent comment is looked up in. */
40
+ admin: AdminStore;
41
+ /** The content index, for the post's title. */
42
+ store: ContentStore;
43
+ /** The one door out for email. */
44
+ mail: MailService;
45
+ /**
46
+ * Config after defaults: the base URL the links are absolute against, the
47
+ * data directory the signing secret and the opt-outs live in, and the clock.
48
+ */
49
+ config: Pick<ResolvedConfig, 'baseUrl' | 'dataDir' | 'now'>;
50
+ }
51
+ /** Tells people about comments. Never throws, and never waits on a provider. */
52
+ export interface CommentNotifier {
53
+ /**
54
+ * A comment has been stored. Tells the moderators when, and only when, it is
55
+ * waiting for one of them.
56
+ */
57
+ pending(comment: PostComment): void;
58
+ /**
59
+ * A comment has been approved. Tells whoever it answers, when they asked to
60
+ * be told and are still listening.
61
+ */
62
+ replyApproved(reply: PostComment): void;
63
+ }
64
+ /** Build the notifier for one site. */
65
+ export declare function createCommentNotifier(options: CreateCommentNotifierOptions): CommentNotifier;
66
+ //# sourceMappingURL=comments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comments.d.ts","sourceRoot":"","sources":["../../src/notifications/comments.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAKtD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,2DAA2D;AAC3D,eAAO,MAAM,wBAAwB,oBAAoB,CAAC;AAE1D,qEAAqE;AACrE,eAAO,MAAM,sBAAsB,kBAAkB,CAAC;AAEtD,mEAAmE;AACnE,eAAO,MAAM,qBAAqB,aAAa,CAAC;AAEhD,gDAAgD;AAChD,MAAM,WAAW,4BAA4B;IAC3C,yEAAyE;IACzE,KAAK,EAAE,UAAU,CAAC;IAClB,+CAA+C;IAC/C,KAAK,EAAE,YAAY,CAAC;IACpB,kCAAkC;IAClC,IAAI,EAAE,WAAW,CAAC;IAClB;;;OAGG;IACH,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,GAAG,SAAS,GAAG,KAAK,CAAC,CAAC;CAC7D;AAED,gFAAgF;AAChF,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IACpC;;;OAGG;IACH,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;CACzC;AAED,uCAAuC;AACvC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,GAAG,eAAe,CA6G5F"}
@@ -0,0 +1,151 @@
1
+ import { listUsers } from '../admin/accounts.js';
2
+ import { commentAnchor } from '../web/conversation.js';
3
+ import { MODERATION_ACTIONS } from '../comments/moderate.js';
4
+ import { moderationLink, unsubscribeLink } from './links.js';
5
+ import { hasOptedOut } from './optouts.js';
6
+ import { isBatchedMode, notificationMode, notificationRecipients } from './preferences.js';
7
+ /**
8
+ * The two messages a comment sets off, and the rules about who gets them.
9
+ *
10
+ * Both go through the mail service and nothing else (TASK-53), so a site with
11
+ * no provider sends nothing and every path through here still works. Neither
12
+ * is awaited by the request that caused it: a comment is stored, a page is
13
+ * redirected to, and the message goes out behind that.
14
+ *
15
+ * **The moderation notice.** A comment or a webmention has entered the queue,
16
+ * so everyone who has an address and has not turned the notice off is told,
17
+ * with the words themselves and three signed links that approve, file as spam
18
+ * or delete it without a login. It goes out for `pending` and nothing else,
19
+ * which is the whole of the "not for spam" rule: a comment Akismet filed as
20
+ * spam is nobody's decision to make today, and one it said to discard was
21
+ * never stored at all.
22
+ *
23
+ * **The reply notice.** Somebody ticked "tell me about replies" when they
24
+ * commented, and a reply to that comment has just been approved. That is the
25
+ * only moment it goes: an unapproved reply is not something a stranger should
26
+ * be emailed the text of, and a moderator should be able to delete a nasty one
27
+ * before anybody hears about it.
28
+ *
29
+ * Three things stop it. The address is missing, the address has unsubscribed,
30
+ * or the reply is by the very person who would be told — nobody needs an email
31
+ * about their own words.
32
+ */
33
+ /** The message an admin gets when something is waiting. */
34
+ export const COMMENT_PENDING_TEMPLATE = 'comment-pending';
35
+ /** The message a commenter gets when a reply to them is approved. */
36
+ export const COMMENT_REPLY_TEMPLATE = 'comment-reply';
37
+ /** The event name the users screen switches, from the registry. */
38
+ export const COMMENTS_NOTIFICATION = 'comments';
39
+ /** Build the notifier for one site. */
40
+ export function createCommentNotifier(options) {
41
+ const { admin, store, mail, config } = options;
42
+ /** The post a comment is on, as a message names it. */
43
+ function postOf(comment) {
44
+ const document = store.getBySlug(comment.slug);
45
+ return {
46
+ title: document?.title ?? comment.slug,
47
+ url: absolute(comment.permalink, config.baseUrl),
48
+ };
49
+ }
50
+ /** What a message says about the comment itself. */
51
+ function commentIn(comment) {
52
+ return {
53
+ author: comment.author.name,
54
+ // The website they gave, which is a thing a moderator judges a comment
55
+ // by. Never their email: the message goes to a moderator, but it also
56
+ // goes through a third party's servers, and the address is not needed to
57
+ // decide anything.
58
+ website: comment.author.url,
59
+ source: comment.source,
60
+ kind: comment.kind,
61
+ text: comment.content.markdown,
62
+ html: comment.content.html,
63
+ submitted: comment.submitted,
64
+ // Where it came from, for a webmention: the page that linked here.
65
+ url: comment.url,
66
+ };
67
+ }
68
+ return {
69
+ pending(comment) {
70
+ if (comment.status !== 'pending')
71
+ return;
72
+ // Asked before anything else, so a site that sends no mail never mints a
73
+ // signing secret it would have no use for.
74
+ if (!mail.configured())
75
+ return;
76
+ // Everybody who wants the notice as it happens. A user on an hourly or
77
+ // daily digest is deliberately not written to here: the whole of what
78
+ // choosing a window means is that this moment is not one of the moments
79
+ // they hear about (TASK-60), and `createCommentDigest` writes to them
80
+ // instead, from the queue as it stands when their window comes up.
81
+ const recipients = notificationRecipients(listUsers(config.dataDir), COMMENTS_NOTIFICATION).filter((recipient) => !isBatchedMode(notificationMode(recipient.user, COMMENTS_NOTIFICATION)));
82
+ if (recipients.length === 0)
83
+ return;
84
+ const context = { dataDir: config.dataDir, baseUrl: config.baseUrl, now: config.now() };
85
+ const actions = MODERATION_ACTIONS.map((action) => ({
86
+ action,
87
+ label: action === 'approve' ? 'Approve' : action === 'spam' ? 'Spam' : 'Delete',
88
+ url: moderationLink(context, comment.id, action),
89
+ }));
90
+ const data = {
91
+ comment: commentIn(comment),
92
+ post: postOf(comment),
93
+ actions,
94
+ queueUrl: absolute('/admin/comments', config.baseUrl),
95
+ };
96
+ for (const recipient of recipients) {
97
+ // One message each rather than one with everybody on it: a moderator's
98
+ // address is not something to show the other moderators, and a message
99
+ // per person is what lets a later version say something different to
100
+ // each of them.
101
+ void mail.send({ to: recipient.email, template: COMMENT_PENDING_TEMPLATE, data });
102
+ }
103
+ },
104
+ replyApproved(reply) {
105
+ if (reply.status !== 'approved' || reply.inReplyTo === null)
106
+ return;
107
+ if (!mail.configured())
108
+ return;
109
+ const parent = admin.getComment(reply.inReplyTo);
110
+ if (parent === undefined || !parent.notify)
111
+ return;
112
+ const address = parent.author.email;
113
+ if (address === null || address === '')
114
+ return;
115
+ // Nobody wants an email about their own reply, and a thread of two
116
+ // people talking would otherwise send one on every message.
117
+ if (address.toLowerCase() === (reply.author.email ?? '').toLowerCase())
118
+ return;
119
+ if (hasOptedOut(config.dataDir, address))
120
+ return;
121
+ const context = { dataDir: config.dataDir, baseUrl: config.baseUrl, now: config.now() };
122
+ const post = postOf(reply);
123
+ void mail.send({
124
+ to: address,
125
+ template: COMMENT_REPLY_TEMPLATE,
126
+ data: {
127
+ reply: {
128
+ ...commentIn(reply),
129
+ url: reply.url ?? `${post.url}#${commentAnchor(reply.id)}`,
130
+ },
131
+ comment: {
132
+ ...commentIn(parent),
133
+ url: parent.url ?? `${post.url}#${commentAnchor(parent.id)}`,
134
+ },
135
+ post,
136
+ unsubscribeUrl: unsubscribeLink(context, address),
137
+ },
138
+ });
139
+ },
140
+ };
141
+ }
142
+ /** A site-root path as an absolute URL. */
143
+ function absolute(pathname, baseUrl) {
144
+ try {
145
+ return new URL(pathname, baseUrl).href;
146
+ }
147
+ catch {
148
+ return pathname;
149
+ }
150
+ }
151
+ //# sourceMappingURL=comments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comments.js","sourceRoot":"","sources":["../../src/notifications/comments.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,135 @@
1
+ import type { AdminStore } from '../admin/store.ts';
2
+ import type { ResolvedConfig } from '../config.ts';
3
+ import type { ContentStore } from '../content/store.ts';
4
+ import type { MailService } from '../mail/service.ts';
5
+ /**
6
+ * One message a window instead of one message a comment.
7
+ *
8
+ * TASK-55 emails every moderator the moment something enters the queue, which
9
+ * is right for a quiet site and wrong for a spam wave that Akismet let
10
+ * through. A user who has chosen `hourly` or `daily` on `/admin/users` is sent
11
+ * nothing when a comment arrives; instead this sends them one message per
12
+ * window listing everything still waiting, each item with its own approve,
13
+ * spam and delete links.
14
+ *
15
+ * Three decisions hold the whole thing up:
16
+ *
17
+ * - **A digest is derived, not queued.** It is built from what
18
+ * `admin.listComments({ status: 'pending' })` says right now, so an item
19
+ * somebody approved before the run is simply absent and there is no queue to
20
+ * keep true across a restart, a crash or a `geekity rebuild`. Nothing has to
21
+ * remember what it meant to send.
22
+ * - **The only new state is when each user was last written to**, and it lives
23
+ * in `data/notification-digests.json` rather than in the database, because
24
+ * decision-9 says the database may be deleted whenever the site is stopped —
25
+ * and a forgotten timestamp would mean either a window silently skipped or a
26
+ * digest sent twice. It is its own file rather than a field in
27
+ * `data/users.json` because that file is the answer to "who may sign in",
28
+ * and a timestamp the sender rewrites every hour is bookkeeping rather than
29
+ * anything about the person.
30
+ * - **Nothing is sent for an empty queue, and an empty run records nothing.**
31
+ * A user with nothing waiting is never emailed, and because their timestamp
32
+ * does not move, the first thing that does arrive goes out on the very next
33
+ * tick rather than waiting out a window that had nothing in it. The promise
34
+ * a mode makes is "at most one message per window", and that is kept.
35
+ */
36
+ /** The message a batched user gets: everything still waiting, in one. */
37
+ export declare const COMMENT_DIGEST_TEMPLATE = "comment-digest";
38
+ /** The file, relative to `dataDir`. */
39
+ export declare const DIGEST_TIMES_FILE = "notification-digests.json";
40
+ /** Nobody but the site's own user reads it. */
41
+ export declare const DIGEST_TIMES_FILE_MODE = 384;
42
+ /**
43
+ * How often the timer looks.
44
+ *
45
+ * A minute. The tick is not the window — each user's own mode decides whether
46
+ * they are due — so this only sets how promptly a window that has come up is
47
+ * noticed, and a minute's lag on an hourly digest is nothing while a busier
48
+ * tick would be a query a minute for no one.
49
+ */
50
+ export declare const DIGEST_TICK_MS: number;
51
+ /**
52
+ * The most items one digest lists.
53
+ *
54
+ * A cap rather than "everything", because "everything" during a spam wave is a
55
+ * message with thousands of entries and three signed links each, which no mail
56
+ * provider would take and nobody could read. What is over the cap is counted
57
+ * in a line at the bottom pointing at the moderation queue, and the next
58
+ * window lists the next hundred.
59
+ */
60
+ export declare const DIGEST_MAX_ITEMS = 100;
61
+ /** Where the digest times live for a given data directory. */
62
+ export declare function digestTimesFile(dataDir: string): string;
63
+ /**
64
+ * When each user last had a digest of each event, as
65
+ * `{ [event]: { [userId]: instant } }`.
66
+ *
67
+ * Keyed by event as well as by user because the registry may grow a second
68
+ * batched notice, and the two would then be on windows of their own. A file
69
+ * that is missing, damaged or the wrong shape reads as nobody having had
70
+ * anything — the same direction {@link readCommentOptOuts} fails in, and for
71
+ * the same reason: the cost is a duplicate digest, and the alternative is a
72
+ * site whose timer throws over a stray comma.
73
+ */
74
+ export declare function readDigestTimes(dataDir: string): Record<string, Record<string, string>>;
75
+ /**
76
+ * Write down that these users have just been sent a digest of this event.
77
+ *
78
+ * The read is inside the write, so two runs at once cannot lose one another's
79
+ * timestamps.
80
+ */
81
+ export declare function recordDigestTimes(dataDir: string, event: string, users: readonly number[], at: Date): Promise<void>;
82
+ /**
83
+ * The timer the digest waits on, injected so a test can fire it rather than
84
+ * wait for it. The shape {@link ScheduleTimers} has, for the same reason: a
85
+ * repeating tick, unreferenced so it never holds the process open on its own.
86
+ */
87
+ export interface NotificationTimers {
88
+ set(callback: () => void, everyMs: number): unknown;
89
+ clear(handle: unknown): void;
90
+ }
91
+ /** The real one. */
92
+ export declare const systemNotificationTimers: NotificationTimers;
93
+ /** Where a digest run reports what it could not do. `console` will do. */
94
+ export interface DigestLogger {
95
+ warn(message: string): void;
96
+ }
97
+ /** What {@link createCommentDigest} needs. */
98
+ export interface CreateCommentDigestOptions {
99
+ /** The comment index, which is what "still pending" is asked of. */
100
+ admin: AdminStore;
101
+ /** The content index, for the posts the items are on. */
102
+ store: ContentStore;
103
+ /** The one door out for email. */
104
+ mail: MailService;
105
+ /**
106
+ * Config after defaults: the base URL the links are absolute against, the
107
+ * data directory the signing secret and the record live in, and the clock.
108
+ */
109
+ config: Pick<ResolvedConfig, 'baseUrl' | 'dataDir' | 'now'>;
110
+ /** The timer to tick on. Defaults to {@link systemNotificationTimers}. */
111
+ timers?: NotificationTimers | undefined;
112
+ /** How often it ticks. Defaults to {@link DIGEST_TICK_MS}. */
113
+ tickMs?: number | undefined;
114
+ /** The most items one message lists. Defaults to {@link DIGEST_MAX_ITEMS}. */
115
+ maxItems?: number | undefined;
116
+ /** Where failures are reported. Defaults to `console`. */
117
+ logger?: DigestLogger | undefined;
118
+ }
119
+ /** Sends the batched notices. Never throws, and never waits on a provider. */
120
+ export interface CommentDigest {
121
+ /**
122
+ * Send a digest to every user who is due one and has something waiting.
123
+ * Resolves with how many messages were handed to the mail service.
124
+ */
125
+ run(): Promise<number>;
126
+ /** Start ticking. Safe twice. */
127
+ start(): void;
128
+ /** Stop ticking. Safe before starting and safe twice. */
129
+ stop(): void;
130
+ /** Resolve once the run in flight, if there is one, has finished. */
131
+ settled(): Promise<void>;
132
+ }
133
+ /** Build the digest sender for one site. */
134
+ export declare function createCommentDigest(options: CreateCommentDigestOptions): CommentDigest;
135
+ //# sourceMappingURL=digest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"digest.d.ts","sourceRoot":"","sources":["../../src/notifications/digest.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,mBAAmB,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAUtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,yEAAyE;AACzE,eAAO,MAAM,uBAAuB,mBAAmB,CAAC;AAExD,uCAAuC;AACvC,eAAO,MAAM,iBAAiB,8BAA8B,CAAC;AAE7D,+CAA+C;AAC/C,eAAO,MAAM,sBAAsB,MAAQ,CAAC;AAE5C;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,QAAY,CAAC;AAExC;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAEpC,8DAA8D;AAC9D,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAEvF;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,EAAE,EAAE,IAAI,GACP,OAAO,CAAC,IAAI,CAAC,CAaf;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IACpD,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9B;AAED,oBAAoB;AACpB,eAAO,MAAM,wBAAwB,EAAE,kBAStC,CAAC;AAEF,0EAA0E;AAC1E,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,8CAA8C;AAC9C,MAAM,WAAW,0BAA0B;IACzC,oEAAoE;IACpE,KAAK,EAAE,UAAU,CAAC;IAClB,yDAAyD;IACzD,KAAK,EAAE,YAAY,CAAC;IACpB,kCAAkC;IAClC,IAAI,EAAE,WAAW,CAAC;IAClB;;;OAGG;IACH,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,GAAG,SAAS,GAAG,KAAK,CAAC,CAAC;IAC5D,0EAA0E;IAC1E,MAAM,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACxC,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,0DAA0D;IAC1D,MAAM,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;CACnC;AAED,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACvB,iCAAiC;IACjC,KAAK,IAAI,IAAI,CAAC;IACd,yDAAyD;IACzD,IAAI,IAAI,IAAI,CAAC;IACb,qEAAqE;IACrE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,4CAA4C;AAC5C,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,aAAa,CA0ItF"}