@geekity/cms 0.3.0 → 0.5.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 (660) hide show
  1. package/README.md +2217 -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/{layouts/document-editor.njk → pages/documents/editor.njk} +75 -59
  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/federation/settings.njk +77 -0
  19. package/admin/pages/media/library.njk +160 -0
  20. package/admin/pages/messages/all.njk +110 -0
  21. package/admin/pages/navigation/menus.njk +129 -0
  22. package/admin/{layouts → pages}/placeholder.njk +5 -1
  23. package/admin/pages/settings/discussion.njk +99 -0
  24. package/admin/pages/settings/email.njk +203 -0
  25. package/admin/pages/settings/general.njk +29 -0
  26. package/admin/pages/settings/permalinks.njk +50 -0
  27. package/admin/pages/settings/reading.njk +64 -0
  28. package/admin/pages/tools/content-index.njk +89 -0
  29. package/admin/pages/users/edit.njk +239 -0
  30. package/admin/pages/users/list.njk +51 -0
  31. package/admin/pages/users/new.njk +41 -0
  32. package/admin/static/admin.css +558 -3
  33. package/admin/static/copy.js +52 -0
  34. package/admin/static/editor.js +16 -16
  35. package/admin/static/slug.js +61 -0
  36. package/dist/access-log.d.ts +44 -0
  37. package/dist/access-log.d.ts.map +1 -0
  38. package/dist/access-log.js +71 -0
  39. package/dist/access-log.js.map +1 -0
  40. package/dist/admin/accounts.d.ts +413 -0
  41. package/dist/admin/accounts.d.ts.map +1 -0
  42. package/dist/admin/accounts.js +680 -0
  43. package/dist/admin/accounts.js.map +1 -0
  44. package/dist/admin/appearance.d.ts +80 -0
  45. package/dist/admin/appearance.d.ts.map +1 -0
  46. package/dist/admin/appearance.js +136 -0
  47. package/dist/admin/appearance.js.map +1 -0
  48. package/dist/admin/comments.d.ts +90 -0
  49. package/dist/admin/comments.d.ts.map +1 -0
  50. package/dist/admin/comments.js +244 -0
  51. package/dist/admin/comments.js.map +1 -0
  52. package/dist/admin/credentials.d.ts +26 -2
  53. package/dist/admin/credentials.d.ts.map +1 -1
  54. package/dist/admin/credentials.js +35 -2
  55. package/dist/admin/credentials.js.map +1 -1
  56. package/dist/admin/documents.d.ts +117 -10
  57. package/dist/admin/documents.d.ts.map +1 -1
  58. package/dist/admin/documents.js +328 -41
  59. package/dist/admin/documents.js.map +1 -1
  60. package/dist/admin/federation.d.ts +161 -50
  61. package/dist/admin/federation.d.ts.map +1 -1
  62. package/dist/admin/federation.js +235 -93
  63. package/dist/admin/federation.js.map +1 -1
  64. package/dist/admin/formatting.d.ts +20 -0
  65. package/dist/admin/formatting.d.ts.map +1 -0
  66. package/dist/admin/formatting.js +72 -0
  67. package/dist/admin/formatting.js.map +1 -0
  68. package/dist/admin/headers.d.ts +65 -0
  69. package/dist/admin/headers.d.ts.map +1 -0
  70. package/dist/admin/headers.js +104 -0
  71. package/dist/admin/headers.js.map +1 -0
  72. package/dist/admin/index.d.ts +38 -12
  73. package/dist/admin/index.d.ts.map +1 -1
  74. package/dist/admin/index.js +25 -7
  75. package/dist/admin/index.js.map +1 -1
  76. package/dist/admin/media.d.ts +168 -0
  77. package/dist/admin/media.d.ts.map +1 -0
  78. package/dist/admin/media.js +295 -0
  79. package/dist/admin/media.js.map +1 -0
  80. package/dist/admin/menu.d.ts +79 -0
  81. package/dist/admin/menu.d.ts.map +1 -0
  82. package/dist/admin/menu.js +143 -0
  83. package/dist/admin/menu.js.map +1 -0
  84. package/dist/admin/messages.d.ts +80 -0
  85. package/dist/admin/messages.d.ts.map +1 -0
  86. package/dist/admin/messages.js +152 -0
  87. package/dist/admin/messages.js.map +1 -0
  88. package/dist/admin/navigation.d.ts +155 -0
  89. package/dist/admin/navigation.d.ts.map +1 -0
  90. package/dist/admin/navigation.js +292 -0
  91. package/dist/admin/navigation.js.map +1 -0
  92. package/dist/admin/preview.d.ts.map +1 -1
  93. package/dist/admin/preview.js +31 -7
  94. package/dist/admin/preview.js.map +1 -1
  95. package/dist/admin/recovery.d.ts +92 -0
  96. package/dist/admin/recovery.d.ts.map +1 -0
  97. package/dist/admin/recovery.js +229 -0
  98. package/dist/admin/recovery.js.map +1 -0
  99. package/dist/admin/routes.d.ts +0 -20
  100. package/dist/admin/routes.d.ts.map +1 -1
  101. package/dist/admin/routes.js +164 -105
  102. package/dist/admin/routes.js.map +1 -1
  103. package/dist/admin/session.d.ts +17 -3
  104. package/dist/admin/session.d.ts.map +1 -1
  105. package/dist/admin/session.js +19 -5
  106. package/dist/admin/session.js.map +1 -1
  107. package/dist/admin/settings-discussion.d.ts +37 -0
  108. package/dist/admin/settings-discussion.d.ts.map +1 -0
  109. package/dist/admin/settings-discussion.js +117 -0
  110. package/dist/admin/settings-discussion.js.map +1 -0
  111. package/dist/admin/settings-email.d.ts +54 -0
  112. package/dist/admin/settings-email.d.ts.map +1 -0
  113. package/dist/admin/settings-email.js +189 -0
  114. package/dist/admin/settings-email.js.map +1 -0
  115. package/dist/admin/settings-federation.d.ts +48 -0
  116. package/dist/admin/settings-federation.d.ts.map +1 -0
  117. package/dist/admin/settings-federation.js +123 -0
  118. package/dist/admin/settings-federation.js.map +1 -0
  119. package/dist/admin/settings-general.d.ts +12 -0
  120. package/dist/admin/settings-general.d.ts.map +1 -0
  121. package/dist/admin/settings-general.js +48 -0
  122. package/dist/admin/settings-general.js.map +1 -0
  123. package/dist/admin/settings-page.d.ts +119 -0
  124. package/dist/admin/settings-page.d.ts.map +1 -0
  125. package/dist/admin/settings-page.js +132 -0
  126. package/dist/admin/settings-page.js.map +1 -0
  127. package/dist/admin/settings-pages.d.ts +30 -0
  128. package/dist/admin/settings-pages.d.ts.map +1 -0
  129. package/dist/admin/settings-pages.js +43 -0
  130. package/dist/admin/settings-pages.js.map +1 -0
  131. package/dist/admin/settings-permalinks.d.ts +16 -0
  132. package/dist/admin/settings-permalinks.d.ts.map +1 -0
  133. package/dist/admin/settings-permalinks.js +32 -0
  134. package/dist/admin/settings-permalinks.js.map +1 -0
  135. package/dist/admin/settings-reading.d.ts +34 -0
  136. package/dist/admin/settings-reading.d.ts.map +1 -0
  137. package/dist/admin/settings-reading.js +49 -0
  138. package/dist/admin/settings-reading.js.map +1 -0
  139. package/dist/admin/settings.d.ts +339 -96
  140. package/dist/admin/settings.d.ts.map +1 -1
  141. package/dist/admin/settings.js +600 -308
  142. package/dist/admin/settings.js.map +1 -1
  143. package/dist/admin/store.d.ts +606 -152
  144. package/dist/admin/store.d.ts.map +1 -1
  145. package/dist/admin/store.js +863 -268
  146. package/dist/admin/store.js.map +1 -1
  147. package/dist/admin/taxonomy.d.ts +114 -0
  148. package/dist/admin/taxonomy.d.ts.map +1 -0
  149. package/dist/admin/taxonomy.js +289 -0
  150. package/dist/admin/taxonomy.js.map +1 -0
  151. package/dist/admin/templates.d.ts +46 -14
  152. package/dist/admin/templates.d.ts.map +1 -1
  153. package/dist/admin/templates.js +46 -14
  154. package/dist/admin/templates.js.map +1 -1
  155. package/dist/admin/throttle.d.ts +84 -0
  156. package/dist/admin/throttle.d.ts.map +1 -0
  157. package/dist/admin/throttle.js +143 -0
  158. package/dist/admin/throttle.js.map +1 -0
  159. package/dist/admin/tools.d.ts +111 -0
  160. package/dist/admin/tools.d.ts.map +1 -0
  161. package/dist/admin/tools.js +182 -0
  162. package/dist/admin/tools.js.map +1 -0
  163. package/dist/admin/uploads.d.ts +28 -2
  164. package/dist/admin/uploads.d.ts.map +1 -1
  165. package/dist/admin/uploads.js +43 -4
  166. package/dist/admin/uploads.js.map +1 -1
  167. package/dist/admin/users.d.ts +100 -13
  168. package/dist/admin/users.d.ts.map +1 -1
  169. package/dist/admin/users.js +412 -39
  170. package/dist/admin/users.js.map +1 -1
  171. package/dist/cache.d.ts +141 -0
  172. package/dist/cache.d.ts.map +1 -0
  173. package/dist/cache.js +207 -0
  174. package/dist/cache.js.map +1 -0
  175. package/dist/cli.d.ts +14 -2
  176. package/dist/cli.d.ts.map +1 -1
  177. package/dist/cli.js +429 -21
  178. package/dist/cli.js.map +1 -1
  179. package/dist/comments/akismet.d.ts +130 -0
  180. package/dist/comments/akismet.d.ts.map +1 -0
  181. package/dist/comments/akismet.js +274 -0
  182. package/dist/comments/akismet.js.map +1 -0
  183. package/dist/comments/conversation.d.ts +29 -0
  184. package/dist/comments/conversation.d.ts.map +1 -0
  185. package/dist/comments/conversation.js +60 -0
  186. package/dist/comments/conversation.js.map +1 -0
  187. package/dist/comments/form.d.ts +123 -0
  188. package/dist/comments/form.d.ts.map +1 -0
  189. package/dist/comments/form.js +79 -0
  190. package/dist/comments/form.js.map +1 -0
  191. package/dist/comments/index.d.ts +16 -0
  192. package/dist/comments/index.d.ts.map +1 -0
  193. package/dist/comments/index.js +10 -0
  194. package/dist/comments/index.js.map +1 -0
  195. package/dist/comments/markdown.d.ts +8 -0
  196. package/dist/comments/markdown.d.ts.map +1 -0
  197. package/dist/comments/markdown.js +85 -0
  198. package/dist/comments/markdown.js.map +1 -0
  199. package/dist/comments/moderate.d.ts +71 -0
  200. package/dist/comments/moderate.d.ts.map +1 -0
  201. package/dist/comments/moderate.js +88 -0
  202. package/dist/comments/moderate.js.map +1 -0
  203. package/dist/comments/policy.d.ts +57 -0
  204. package/dist/comments/policy.d.ts.map +1 -0
  205. package/dist/comments/policy.js +80 -0
  206. package/dist/comments/policy.js.map +1 -0
  207. package/dist/comments/records.d.ts +266 -0
  208. package/dist/comments/records.d.ts.map +1 -0
  209. package/dist/comments/records.js +487 -0
  210. package/dist/comments/records.js.map +1 -0
  211. package/dist/comments/routes.d.ts +60 -0
  212. package/dist/comments/routes.d.ts.map +1 -0
  213. package/dist/comments/routes.js +212 -0
  214. package/dist/comments/routes.js.map +1 -0
  215. package/dist/comments/submission.d.ts +297 -0
  216. package/dist/comments/submission.d.ts.map +1 -0
  217. package/dist/comments/submission.js +280 -0
  218. package/dist/comments/submission.js.map +1 -0
  219. package/dist/comments/viewer.d.ts +21 -0
  220. package/dist/comments/viewer.d.ts.map +1 -0
  221. package/dist/comments/viewer.js +45 -0
  222. package/dist/comments/viewer.js.map +1 -0
  223. package/dist/config.d.ts +225 -5
  224. package/dist/config.d.ts.map +1 -1
  225. package/dist/config.js +121 -6
  226. package/dist/config.js.map +1 -1
  227. package/dist/contact/delivery.d.ts +60 -0
  228. package/dist/contact/delivery.d.ts.map +1 -0
  229. package/dist/contact/delivery.js +87 -0
  230. package/dist/contact/delivery.js.map +1 -0
  231. package/dist/contact/form.d.ts +130 -0
  232. package/dist/contact/form.d.ts.map +1 -0
  233. package/dist/contact/form.js +163 -0
  234. package/dist/contact/form.js.map +1 -0
  235. package/dist/contact/index.d.ts +17 -0
  236. package/dist/contact/index.d.ts.map +1 -0
  237. package/dist/contact/index.js +13 -0
  238. package/dist/contact/index.js.map +1 -0
  239. package/dist/contact/records.d.ts +124 -0
  240. package/dist/contact/records.d.ts.map +1 -0
  241. package/dist/contact/records.js +218 -0
  242. package/dist/contact/records.js.map +1 -0
  243. package/dist/contact/routes.d.ts +17 -0
  244. package/dist/contact/routes.d.ts.map +1 -0
  245. package/dist/contact/routes.js +127 -0
  246. package/dist/contact/routes.js.map +1 -0
  247. package/dist/contact/submission.d.ts +103 -0
  248. package/dist/contact/submission.d.ts.map +1 -0
  249. package/dist/contact/submission.js +166 -0
  250. package/dist/contact/submission.js.map +1 -0
  251. package/dist/content/document.d.ts +7 -2
  252. package/dist/content/document.d.ts.map +1 -1
  253. package/dist/content/document.js +1 -0
  254. package/dist/content/document.js.map +1 -1
  255. package/dist/content/index.d.ts +7 -2
  256. package/dist/content/index.d.ts.map +1 -1
  257. package/dist/content/index.js +4 -1
  258. package/dist/content/index.js.map +1 -1
  259. package/dist/content/markdown.d.ts.map +1 -1
  260. package/dist/content/markdown.js +24 -2
  261. package/dist/content/markdown.js.map +1 -1
  262. package/dist/content/parser.d.ts.map +1 -1
  263. package/dist/content/parser.js +11 -4
  264. package/dist/content/parser.js.map +1 -1
  265. package/dist/content/save.d.ts +5 -0
  266. package/dist/content/save.d.ts.map +1 -1
  267. package/dist/content/save.js +44 -1
  268. package/dist/content/save.js.map +1 -1
  269. package/dist/content/schedule.d.ts +125 -0
  270. package/dist/content/schedule.d.ts.map +1 -0
  271. package/dist/content/schedule.js +207 -0
  272. package/dist/content/schedule.js.map +1 -0
  273. package/dist/content/search.d.ts +64 -0
  274. package/dist/content/search.d.ts.map +1 -0
  275. package/dist/content/search.js +136 -0
  276. package/dist/content/search.js.map +1 -0
  277. package/dist/content/store.d.ts +220 -7
  278. package/dist/content/store.d.ts.map +1 -1
  279. package/dist/content/store.js +392 -67
  280. package/dist/content/store.js.map +1 -1
  281. package/dist/content/sync.d.ts +7 -1
  282. package/dist/content/sync.d.ts.map +1 -1
  283. package/dist/content/sync.js +18 -10
  284. package/dist/content/sync.js.map +1 -1
  285. package/dist/content/time.d.ts +56 -0
  286. package/dist/content/time.d.ts.map +1 -0
  287. package/dist/content/time.js +141 -0
  288. package/dist/content/time.js.map +1 -0
  289. package/dist/content/writer.d.ts.map +1 -1
  290. package/dist/content/writer.js +3 -0
  291. package/dist/content/writer.js.map +1 -1
  292. package/dist/env.d.ts +70 -5
  293. package/dist/env.d.ts.map +1 -1
  294. package/dist/federation/actor.d.ts +95 -41
  295. package/dist/federation/actor.d.ts.map +1 -1
  296. package/dist/federation/actor.js +180 -53
  297. package/dist/federation/actor.js.map +1 -1
  298. package/dist/federation/article.d.ts +44 -17
  299. package/dist/federation/article.d.ts.map +1 -1
  300. package/dist/federation/article.js +98 -46
  301. package/dist/federation/article.js.map +1 -1
  302. package/dist/federation/delivery.d.ts +63 -15
  303. package/dist/federation/delivery.d.ts.map +1 -1
  304. package/dist/federation/delivery.js +154 -80
  305. package/dist/federation/delivery.js.map +1 -1
  306. package/dist/federation/federation.d.ts +22 -17
  307. package/dist/federation/federation.d.ts.map +1 -1
  308. package/dist/federation/federation.js +98 -77
  309. package/dist/federation/federation.js.map +1 -1
  310. package/dist/federation/followers.d.ts +3 -2
  311. package/dist/federation/followers.d.ts.map +1 -1
  312. package/dist/federation/followers.js +6 -5
  313. package/dist/federation/followers.js.map +1 -1
  314. package/dist/federation/import-wordpress.d.ts +128 -0
  315. package/dist/federation/import-wordpress.d.ts.map +1 -0
  316. package/dist/federation/import-wordpress.js +426 -0
  317. package/dist/federation/import-wordpress.js.map +1 -0
  318. package/dist/federation/inbox.d.ts +36 -13
  319. package/dist/federation/inbox.d.ts.map +1 -1
  320. package/dist/federation/inbox.js +120 -49
  321. package/dist/federation/inbox.js.map +1 -1
  322. package/dist/federation/index.d.ts +22 -10
  323. package/dist/federation/index.d.ts.map +1 -1
  324. package/dist/federation/index.js +13 -8
  325. package/dist/federation/index.js.map +1 -1
  326. package/dist/federation/keys.d.ts +98 -20
  327. package/dist/federation/keys.d.ts.map +1 -1
  328. package/dist/federation/keys.js +269 -39
  329. package/dist/federation/keys.js.map +1 -1
  330. package/dist/federation/mount.d.ts +46 -10
  331. package/dist/federation/mount.d.ts.map +1 -1
  332. package/dist/federation/mount.js +300 -28
  333. package/dist/federation/mount.js.map +1 -1
  334. package/dist/federation/paths.d.ts +23 -35
  335. package/dist/federation/paths.d.ts.map +1 -1
  336. package/dist/federation/paths.js +26 -39
  337. package/dist/federation/paths.js.map +1 -1
  338. package/dist/federation/records.d.ts +223 -0
  339. package/dist/federation/records.d.ts.map +1 -0
  340. package/dist/federation/records.js +506 -0
  341. package/dist/federation/records.js.map +1 -0
  342. package/dist/federation/relays.d.ts +114 -0
  343. package/dist/federation/relays.d.ts.map +1 -0
  344. package/dist/federation/relays.js +290 -0
  345. package/dist/federation/relays.js.map +1 -0
  346. package/dist/federation/replies.d.ts +80 -0
  347. package/dist/federation/replies.d.ts.map +1 -0
  348. package/dist/federation/replies.js +166 -0
  349. package/dist/federation/replies.js.map +1 -0
  350. package/dist/federation/wordpress.d.ts +131 -0
  351. package/dist/federation/wordpress.d.ts.map +1 -0
  352. package/dist/federation/wordpress.js +341 -0
  353. package/dist/federation/wordpress.js.map +1 -0
  354. package/dist/files/atomic.d.ts +103 -0
  355. package/dist/files/atomic.d.ts.map +1 -0
  356. package/dist/files/atomic.js +150 -0
  357. package/dist/files/atomic.js.map +1 -0
  358. package/dist/files/index.d.ts +3 -0
  359. package/dist/files/index.d.ts.map +1 -0
  360. package/dist/files/index.js +2 -0
  361. package/dist/files/index.js.map +1 -0
  362. package/dist/forms/protection.d.ts +85 -0
  363. package/dist/forms/protection.d.ts.map +1 -0
  364. package/dist/forms/protection.js +116 -0
  365. package/dist/forms/protection.js.map +1 -0
  366. package/dist/images/icons.d.ts +59 -0
  367. package/dist/images/icons.d.ts.map +1 -0
  368. package/dist/images/icons.js +131 -0
  369. package/dist/images/icons.js.map +1 -0
  370. package/dist/images/index.d.ts +7 -0
  371. package/dist/images/index.d.ts.map +1 -0
  372. package/dist/images/index.js +4 -0
  373. package/dist/images/index.js.map +1 -0
  374. package/dist/images/markup.d.ts +47 -0
  375. package/dist/images/markup.d.ts.map +1 -0
  376. package/dist/images/markup.js +175 -0
  377. package/dist/images/markup.js.map +1 -0
  378. package/dist/images/paths.d.ts +34 -0
  379. package/dist/images/paths.d.ts.map +1 -0
  380. package/dist/images/paths.js +41 -0
  381. package/dist/images/paths.js.map +1 -0
  382. package/dist/images/variants.d.ts +104 -0
  383. package/dist/images/variants.d.ts.map +1 -0
  384. package/dist/images/variants.js +320 -0
  385. package/dist/images/variants.js.map +1 -0
  386. package/dist/index.d.ts +123 -19
  387. package/dist/index.d.ts.map +1 -1
  388. package/dist/index.js +344 -25
  389. package/dist/index.js.map +1 -1
  390. package/dist/init.d.ts +18 -0
  391. package/dist/init.d.ts.map +1 -1
  392. package/dist/init.js +34 -3
  393. package/dist/init.js.map +1 -1
  394. package/dist/mail/brevo.d.ts +35 -0
  395. package/dist/mail/brevo.d.ts.map +1 -0
  396. package/dist/mail/brevo.js +85 -0
  397. package/dist/mail/brevo.js.map +1 -0
  398. package/dist/mail/credentials.d.ts +62 -0
  399. package/dist/mail/credentials.d.ts.map +1 -0
  400. package/dist/mail/credentials.js +86 -0
  401. package/dist/mail/credentials.js.map +1 -0
  402. package/dist/mail/index.d.ts +15 -0
  403. package/dist/mail/index.d.ts.map +1 -0
  404. package/dist/mail/index.js +8 -0
  405. package/dist/mail/index.js.map +1 -0
  406. package/dist/mail/memory.d.ts +35 -0
  407. package/dist/mail/memory.d.ts.map +1 -0
  408. package/dist/mail/memory.js +29 -0
  409. package/dist/mail/memory.js.map +1 -0
  410. package/dist/mail/provider.d.ts +80 -0
  411. package/dist/mail/provider.d.ts.map +1 -0
  412. package/dist/mail/provider.js +23 -0
  413. package/dist/mail/provider.js.map +1 -0
  414. package/dist/mail/service.d.ts +156 -0
  415. package/dist/mail/service.d.ts.map +1 -0
  416. package/dist/mail/service.js +265 -0
  417. package/dist/mail/service.js.map +1 -0
  418. package/dist/mail/smtp.d.ts +39 -0
  419. package/dist/mail/smtp.d.ts.map +1 -0
  420. package/dist/mail/smtp.js +58 -0
  421. package/dist/mail/smtp.js.map +1 -0
  422. package/dist/mail/templates.d.ts +91 -0
  423. package/dist/mail/templates.d.ts.map +1 -0
  424. package/dist/mail/templates.js +69 -0
  425. package/dist/mail/templates.js.map +1 -0
  426. package/dist/notifications/comments.d.ts +66 -0
  427. package/dist/notifications/comments.d.ts.map +1 -0
  428. package/dist/notifications/comments.js +151 -0
  429. package/dist/notifications/comments.js.map +1 -0
  430. package/dist/notifications/digest.d.ts +135 -0
  431. package/dist/notifications/digest.d.ts.map +1 -0
  432. package/dist/notifications/digest.js +287 -0
  433. package/dist/notifications/digest.js.map +1 -0
  434. package/dist/notifications/index.d.ts +13 -0
  435. package/dist/notifications/index.d.ts.map +1 -0
  436. package/dist/notifications/index.js +8 -0
  437. package/dist/notifications/index.js.map +1 -0
  438. package/dist/notifications/links.d.ts +60 -0
  439. package/dist/notifications/links.d.ts.map +1 -0
  440. package/dist/notifications/links.js +63 -0
  441. package/dist/notifications/links.js.map +1 -0
  442. package/dist/notifications/optouts.d.ts +48 -0
  443. package/dist/notifications/optouts.d.ts.map +1 -0
  444. package/dist/notifications/optouts.js +93 -0
  445. package/dist/notifications/optouts.js.map +1 -0
  446. package/dist/notifications/preferences.d.ts +158 -0
  447. package/dist/notifications/preferences.d.ts.map +1 -0
  448. package/dist/notifications/preferences.js +195 -0
  449. package/dist/notifications/preferences.js.map +1 -0
  450. package/dist/notifications/routes.d.ts +28 -0
  451. package/dist/notifications/routes.d.ts.map +1 -0
  452. package/dist/notifications/routes.js +184 -0
  453. package/dist/notifications/routes.js.map +1 -0
  454. package/dist/notifications/tokens.d.ts +60 -0
  455. package/dist/notifications/tokens.d.ts.map +1 -0
  456. package/dist/notifications/tokens.js +125 -0
  457. package/dist/notifications/tokens.js.map +1 -0
  458. package/dist/notify.d.ts +84 -0
  459. package/dist/notify.d.ts.map +1 -0
  460. package/dist/notify.js +149 -0
  461. package/dist/notify.js.map +1 -0
  462. package/dist/web/archive.d.ts +49 -0
  463. package/dist/web/archive.d.ts.map +1 -0
  464. package/dist/web/archive.js +59 -0
  465. package/dist/web/archive.js.map +1 -0
  466. package/dist/web/assets.d.ts +6 -5
  467. package/dist/web/assets.d.ts.map +1 -1
  468. package/dist/web/assets.js +5 -7
  469. package/dist/web/assets.js.map +1 -1
  470. package/dist/web/authors.d.ts +143 -0
  471. package/dist/web/authors.d.ts.map +1 -0
  472. package/dist/web/authors.js +178 -0
  473. package/dist/web/authors.js.map +1 -0
  474. package/dist/web/comments.d.ts +60 -0
  475. package/dist/web/comments.d.ts.map +1 -0
  476. package/dist/web/comments.js +207 -0
  477. package/dist/web/comments.js.map +1 -0
  478. package/dist/web/context.d.ts +162 -28
  479. package/dist/web/context.d.ts.map +1 -1
  480. package/dist/web/context.js +123 -26
  481. package/dist/web/context.js.map +1 -1
  482. package/dist/web/conversation.d.ts +209 -0
  483. package/dist/web/conversation.d.ts.map +1 -0
  484. package/dist/web/conversation.js +557 -0
  485. package/dist/web/conversation.js.map +1 -0
  486. package/dist/web/documents.d.ts +36 -6
  487. package/dist/web/documents.d.ts.map +1 -1
  488. package/dist/web/documents.js +52 -10
  489. package/dist/web/documents.js.map +1 -1
  490. package/dist/web/feed-atom.d.ts +22 -0
  491. package/dist/web/feed-atom.d.ts.map +1 -0
  492. package/dist/web/feed-atom.js +83 -0
  493. package/dist/web/feed-atom.js.map +1 -0
  494. package/dist/web/feed-item.d.ts +145 -0
  495. package/dist/web/feed-item.d.ts.map +1 -0
  496. package/dist/web/feed-item.js +120 -0
  497. package/dist/web/feed-item.js.map +1 -0
  498. package/dist/web/feed-json.d.ts +79 -0
  499. package/dist/web/feed-json.d.ts.map +1 -0
  500. package/dist/web/feed-json.js +53 -0
  501. package/dist/web/feed-json.js.map +1 -0
  502. package/dist/web/feed-rss.d.ts +26 -0
  503. package/dist/web/feed-rss.d.ts.map +1 -0
  504. package/dist/web/feed-rss.js +203 -0
  505. package/dist/web/feed-rss.js.map +1 -0
  506. package/dist/web/feed-source.d.ts +244 -0
  507. package/dist/web/feed-source.d.ts.map +1 -0
  508. package/dist/web/feed-source.js +201 -0
  509. package/dist/web/feed-source.js.map +1 -0
  510. package/dist/web/feed-xml.d.ts +63 -0
  511. package/dist/web/feed-xml.d.ts.map +1 -0
  512. package/dist/web/feed-xml.js +116 -0
  513. package/dist/web/feed-xml.js.map +1 -0
  514. package/dist/web/feeds.d.ts +31 -96
  515. package/dist/web/feeds.d.ts.map +1 -1
  516. package/dist/web/feeds.js +94 -198
  517. package/dist/web/feeds.js.map +1 -1
  518. package/dist/web/health.d.ts +31 -0
  519. package/dist/web/health.d.ts.map +1 -0
  520. package/dist/web/health.js +44 -0
  521. package/dist/web/health.js.map +1 -0
  522. package/dist/web/index.d.ts +30 -10
  523. package/dist/web/index.d.ts.map +1 -1
  524. package/dist/web/index.js +18 -7
  525. package/dist/web/index.js.map +1 -1
  526. package/dist/web/navigation.d.ts +195 -0
  527. package/dist/web/navigation.d.ts.map +1 -0
  528. package/dist/web/navigation.js +300 -0
  529. package/dist/web/navigation.js.map +1 -0
  530. package/dist/web/negotiate.d.ts +31 -0
  531. package/dist/web/negotiate.d.ts.map +1 -1
  532. package/dist/web/negotiate.js +31 -11
  533. package/dist/web/negotiate.js.map +1 -1
  534. package/dist/web/recent.d.ts +43 -0
  535. package/dist/web/recent.d.ts.map +1 -0
  536. package/dist/web/recent.js +37 -0
  537. package/dist/web/recent.js.map +1 -0
  538. package/dist/web/render.d.ts +203 -9
  539. package/dist/web/render.d.ts.map +1 -1
  540. package/dist/web/render.js +341 -17
  541. package/dist/web/render.js.map +1 -1
  542. package/dist/web/routes.d.ts +25 -8
  543. package/dist/web/routes.d.ts.map +1 -1
  544. package/dist/web/routes.js +854 -93
  545. package/dist/web/routes.js.map +1 -1
  546. package/dist/web/sanitize.d.ts +19 -0
  547. package/dist/web/sanitize.d.ts.map +1 -0
  548. package/dist/web/sanitize.js +272 -0
  549. package/dist/web/sanitize.js.map +1 -0
  550. package/dist/web/search.d.ts +79 -0
  551. package/dist/web/search.d.ts.map +1 -0
  552. package/dist/web/search.js +94 -0
  553. package/dist/web/search.js.map +1 -0
  554. package/dist/web/sitemap.d.ts +120 -0
  555. package/dist/web/sitemap.d.ts.map +1 -0
  556. package/dist/web/sitemap.js +199 -0
  557. package/dist/web/sitemap.js.map +1 -0
  558. package/dist/web/taxonomy.d.ts +152 -0
  559. package/dist/web/taxonomy.d.ts.map +1 -0
  560. package/dist/web/taxonomy.js +237 -0
  561. package/dist/web/taxonomy.js.map +1 -0
  562. package/dist/web/templates.d.ts +54 -16
  563. package/dist/web/templates.d.ts.map +1 -1
  564. package/dist/web/templates.js +109 -28
  565. package/dist/web/templates.js.map +1 -1
  566. package/dist/web/themes.d.ts +226 -0
  567. package/dist/web/themes.d.ts.map +1 -0
  568. package/dist/web/themes.js +314 -0
  569. package/dist/web/themes.js.map +1 -0
  570. package/dist/webmention/discovery.d.ts +51 -0
  571. package/dist/webmention/discovery.d.ts.map +1 -0
  572. package/dist/webmention/discovery.js +176 -0
  573. package/dist/webmention/discovery.js.map +1 -0
  574. package/dist/webmention/html.d.ts +71 -0
  575. package/dist/webmention/html.d.ts.map +1 -0
  576. package/dist/webmention/html.js +285 -0
  577. package/dist/webmention/html.js.map +1 -0
  578. package/dist/webmention/index.d.ts +12 -0
  579. package/dist/webmention/index.d.ts.map +1 -0
  580. package/dist/webmention/index.js +8 -0
  581. package/dist/webmention/index.js.map +1 -0
  582. package/dist/webmention/links.d.ts +18 -0
  583. package/dist/webmention/links.d.ts.map +1 -0
  584. package/dist/webmention/links.js +64 -0
  585. package/dist/webmention/links.js.map +1 -0
  586. package/dist/webmention/microformats.d.ts +93 -0
  587. package/dist/webmention/microformats.d.ts.map +1 -0
  588. package/dist/webmention/microformats.js +376 -0
  589. package/dist/webmention/microformats.js.map +1 -0
  590. package/dist/webmention/receive.d.ts +141 -0
  591. package/dist/webmention/receive.d.ts.map +1 -0
  592. package/dist/webmention/receive.js +264 -0
  593. package/dist/webmention/receive.js.map +1 -0
  594. package/dist/webmention/routes.d.ts +37 -0
  595. package/dist/webmention/routes.d.ts.map +1 -0
  596. package/dist/webmention/routes.js +75 -0
  597. package/dist/webmention/routes.js.map +1 -0
  598. package/dist/webmention/service.d.ts +94 -0
  599. package/dist/webmention/service.d.ts.map +1 -0
  600. package/dist/webmention/service.js +207 -0
  601. package/dist/webmention/service.js.map +1 -0
  602. package/package.json +11 -6
  603. package/templates/site/content/_data/site.json +8 -0
  604. package/templates/site/content/pages/about.md +7 -0
  605. package/templates/site/content/posts/2026-01-01-hello-world.md +5 -3
  606. package/templates/site/geekity.config.ts +11 -1
  607. package/templates/site/tsconfig.json +1 -1
  608. package/themes/default/README.md +1216 -50
  609. package/themes/default/layouts/404.njk +2 -3
  610. package/themes/default/layouts/author.njk +36 -0
  611. package/themes/default/layouts/base.njk +161 -31
  612. package/themes/default/layouts/category.njk +27 -0
  613. package/themes/default/layouts/front-page.njk +56 -0
  614. package/themes/default/layouts/home.njk +17 -1
  615. package/themes/default/layouts/page.njk +57 -5
  616. package/themes/default/layouts/post.njk +78 -19
  617. package/themes/default/layouts/search.njk +57 -0
  618. package/themes/default/layouts/tag.njk +3 -6
  619. package/themes/default/mail/comment-digest.html.njk +37 -0
  620. package/themes/default/mail/comment-digest.subject.njk +3 -0
  621. package/themes/default/mail/comment-digest.txt.njk +40 -0
  622. package/themes/default/mail/comment-pending.html.njk +27 -0
  623. package/themes/default/mail/comment-pending.subject.njk +2 -0
  624. package/themes/default/mail/comment-pending.txt.njk +24 -0
  625. package/themes/default/mail/comment-reply.html.njk +21 -0
  626. package/themes/default/mail/comment-reply.subject.njk +2 -0
  627. package/themes/default/mail/comment-reply.txt.njk +22 -0
  628. package/themes/default/mail/contact-message.html.njk +24 -0
  629. package/themes/default/mail/contact-message.subject.njk +5 -0
  630. package/themes/default/mail/contact-message.txt.njk +20 -0
  631. package/themes/default/mail/password-changed.html.njk +18 -0
  632. package/themes/default/mail/password-changed.subject.njk +2 -0
  633. package/themes/default/mail/password-changed.txt.njk +17 -0
  634. package/themes/default/mail/password-reset.html.njk +22 -0
  635. package/themes/default/mail/password-reset.subject.njk +2 -0
  636. package/themes/default/mail/password-reset.txt.njk +18 -0
  637. package/themes/default/mail/test.html.njk +14 -0
  638. package/themes/default/mail/test.subject.njk +2 -0
  639. package/themes/default/mail/test.txt.njk +12 -0
  640. package/themes/default/partials/archive.njk +27 -0
  641. package/themes/default/partials/bio.njk +71 -0
  642. package/themes/default/partials/comment-form.njk +137 -0
  643. package/themes/default/partials/contact-form.njk +88 -0
  644. package/themes/default/partials/conversation.njk +139 -0
  645. package/themes/default/partials/feeds.njk +26 -0
  646. package/themes/default/partials/jsonld.njk +120 -0
  647. package/themes/default/partials/menu.njk +32 -0
  648. package/themes/default/partials/pagination.njk +12 -6
  649. package/themes/default/partials/post-list.njk +51 -18
  650. package/themes/default/partials/search-form.njk +22 -0
  651. package/themes/default/partials/tags.njk +26 -5
  652. package/themes/default/static/highlight.js +4 -0
  653. package/themes/default/static/style.css +1142 -194
  654. package/themes/default/theme.json +9 -0
  655. package/admin/layouts/federation.njk +0 -145
  656. package/admin/layouts/login.njk +0 -23
  657. package/admin/layouts/settings.njk +0 -116
  658. package/admin/layouts/setup.njk +0 -27
  659. package/admin/layouts/users.njk +0 -91
  660. /package/admin/{layouts/_flash.njk → components/flash.njk} +0 -0
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Discussion: what the site takes back from the people reading it.
3
+ *
4
+ * WordPress's own name for the comment settings. Webmentions are here because
5
+ * one arriving is a comment by another road, and the spam checker is here
6
+ * because it is what decides whether either is shown.
7
+ */
8
+ import { readAkismetKey, removeAkismetKey, verifyAkismetKey, writeAkismetKey, } from '../comments/akismet.js';
9
+ import { flash } from './flash.js';
10
+ import { bodyField, settingsPagePath } from './settings-page.js';
11
+ import { effectiveBaseUrl, readSiteSettings, SETTINGS_PATH } from './settings.js';
12
+ import { ADMIN_TEMPLATES } from './templates.js';
13
+ /**
14
+ * Where the Akismet key's form and its Remove button post.
15
+ *
16
+ * Its own endpoint, for the reason the avatar has one: the key is a credential
17
+ * that lives in `data/akismet.json` rather than a setting that lives in
18
+ * `content/_data/site.json` (TASK-52), so it is not a field of the Discussion
19
+ * form, and a key Akismet will not take must not lose an edit to the closing
20
+ * window beside it.
21
+ */
22
+ export const AKISMET_PATH = `${SETTINGS_PATH}/akismet`;
23
+ /** The fields those two forms submit. */
24
+ export const AKISMET_FIELDS = { key: 'akismet_key', action: 'action' };
25
+ /** The {@link AKISMET_FIELDS.action} that forgets the key again. */
26
+ export const AKISMET_REMOVE = 'remove';
27
+ /** The Discussion settings page. */
28
+ export const DISCUSSION_SETTINGS = {
29
+ child: 'discussion',
30
+ label: 'Discussion',
31
+ path: settingsPagePath('discussion'),
32
+ template: ADMIN_TEMPLATES.settingsDiscussion,
33
+ fields: ['comments', 'commentsCloseAfterDays', 'webmentionsSend', 'webmentionsReceive'],
34
+ panels: (c) => akismetPanel(c.var.config.dataDir),
35
+ endpoints: mountAkismet,
36
+ };
37
+ /**
38
+ * The Akismet key: one form saves it, a second forgets it.
39
+ *
40
+ * The key is checked with Akismet's own `verify-key` before it is stored, so a
41
+ * site is told about a typo now rather than by a queue that quietly stops being
42
+ * filtered. What comes back is stored beside the key, because it is what the
43
+ * screen reports and re-asking on every render would be a network call to draw
44
+ * a page.
45
+ *
46
+ * A key Akismet refuses is stored all the same, marked as refused. It does no
47
+ * harm — `comment-check` with a key Akismet does not know answers `invalid`,
48
+ * which this treats as no opinion, so comments queue exactly as they did — and
49
+ * storing it is what lets the screen say "Akismet does not recognise this key"
50
+ * instead of throwing away what somebody pasted.
51
+ */
52
+ function mountAkismet(app, _options) {
53
+ const here = DISCUSSION_SETTINGS.path;
54
+ app.post(AKISMET_PATH, async (c) => {
55
+ const body = await c.req.parseBody();
56
+ const { config } = c.var;
57
+ if (bodyField(body[AKISMET_FIELDS.action]) === AKISMET_REMOVE) {
58
+ await removeAkismetKey(config.dataDir);
59
+ flash(c, 'notice', 'The Akismet key is gone. Nothing is sent to Akismet any more.');
60
+ return c.redirect(here, 303);
61
+ }
62
+ const key = bodyField(body[AKISMET_FIELDS.key]).trim();
63
+ if (key === '') {
64
+ flash(c, 'error', 'An Akismet key cannot be empty. Use Remove key to turn Akismet off.');
65
+ return c.redirect(here, 303);
66
+ }
67
+ const blog = effectiveBaseUrl(config, readSiteSettings(config.contentDir));
68
+ const status = await verifyAkismetKey({ key, blog });
69
+ await writeAkismetKey(config.dataDir, {
70
+ key,
71
+ status,
72
+ checkedAt: config.now().toISOString(),
73
+ });
74
+ flash(c, status === 'valid' ? 'notice' : 'error', status === 'valid'
75
+ ? 'Akismet is connected. Comments and webmentions are checked from now on.'
76
+ : status === 'invalid'
77
+ ? 'The key is stored, but Akismet does not recognise it, so nothing it says will be believed.'
78
+ : 'The key is stored, but Akismet could not be reached to check it. Save it again to try.');
79
+ return c.redirect(here, 303);
80
+ });
81
+ }
82
+ /**
83
+ * What the page says about Akismet: connected, refused, unchecked, or off.
84
+ *
85
+ * The key itself never leaves this function. A settings screen that printed it
86
+ * back would put a credential in every browser cache and every screenshot; the
87
+ * last four characters are enough for somebody to recognise which key is in
88
+ * there without being handed it.
89
+ */
90
+ export function akismetPanel(dataDir) {
91
+ const stored = readAkismetKey(dataDir);
92
+ if (stored === undefined) {
93
+ return {
94
+ akismetUrl: AKISMET_PATH,
95
+ akismetFields: AKISMET_FIELDS,
96
+ akismetRemove: AKISMET_REMOVE,
97
+ akismetPresent: false,
98
+ akismetState: 'none',
99
+ akismetHint: 'Not connected: no key, so no comment is sent to Akismet.',
100
+ };
101
+ }
102
+ return {
103
+ akismetUrl: AKISMET_PATH,
104
+ akismetFields: AKISMET_FIELDS,
105
+ akismetRemove: AKISMET_REMOVE,
106
+ akismetPresent: true,
107
+ akismetState: stored.status,
108
+ akismetKeyHint: `…${stored.key.slice(-4)}`,
109
+ akismetCheckedAt: stored.checkedAt,
110
+ akismetHint: stored.status === 'valid'
111
+ ? 'Connected. Every comment and every incoming webmention is checked.'
112
+ : stored.status === 'invalid'
113
+ ? 'Akismet does not recognise this key, so nothing it says is believed and every comment queues as it would without one.'
114
+ : 'Akismet could not be reached the last time this key was checked. Save it again to try.',
115
+ };
116
+ }
117
+ //# sourceMappingURL=settings-discussion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-discussion.js","sourceRoot":"","sources":["../../src/admin/settings-discussion.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Email: how the site sends mail, and where a message written to it goes.
3
+ *
4
+ * The settings are here and the credentials are not: an API key and an SMTP
5
+ * password live in `data/mail.json` at mode 0600, never in the public
6
+ * `site.json`, and they are their own pair of forms so a credential typed wrong
7
+ * cannot lose an edit to the From line beside it.
8
+ */
9
+ import type { SettingsPage } from './settings-page.ts';
10
+ import type { SiteSettings } from './settings.ts';
11
+ /**
12
+ * Where the mail credential's form and its Remove button post.
13
+ *
14
+ * Its own endpoint for the reason the Akismet key has one: an API key and an
15
+ * SMTP password are credentials, they live in `data/mail.json` rather than in
16
+ * `content/_data/site.json`, and a credential typed wrong must not lose an edit
17
+ * to the From line. Which provider is in use and who mail is from are settings
18
+ * and stay on the Email form.
19
+ */
20
+ export declare const MAIL_PATH = "/admin/settings/mail";
21
+ /** The fields the credential form and its Remove button submit. */
22
+ export declare const MAIL_FIELDS: {
23
+ readonly brevoApiKey: 'brevo_api_key';
24
+ readonly smtpHost: 'smtp_host';
25
+ readonly smtpPort: 'smtp_port';
26
+ readonly smtpSecure: 'smtp_secure';
27
+ readonly smtpUser: 'smtp_user';
28
+ readonly smtpPassword: 'smtp_password';
29
+ readonly action: 'action';
30
+ };
31
+ /** The {@link MAIL_FIELDS.action} that forgets every mail credential. */
32
+ export declare const MAIL_REMOVE = "remove";
33
+ /** Where the Send test email button posts. */
34
+ export declare const MAIL_TEST_PATH = "/admin/settings/mail/test";
35
+ /** The field that form submits: where to send the test message. */
36
+ export declare const MAIL_TEST_FIELDS: {
37
+ readonly to: 'to';
38
+ };
39
+ /** The message the Send test email button sends, as the theme names it. */
40
+ export declare const MAIL_TEST_TEMPLATE = "test";
41
+ /** The Email settings page. */
42
+ export declare const EMAIL_SETTINGS: SettingsPage;
43
+ /**
44
+ * What the page says about email: which provider is chosen, whether the
45
+ * credential it needs is there, and enough of it to recognise which one.
46
+ *
47
+ * Nothing here ever prints a key or a password. A settings screen that echoed
48
+ * one would put a credential in every browser cache, every screenshot and every
49
+ * `view-source`; the last four characters of an API key and the host and user
50
+ * of an SMTP connection are enough for somebody to tell what is stored without
51
+ * being handed the means to use it.
52
+ */
53
+ export declare function mailPanel(dataDir: string, settings: SiteSettings): Record<string, unknown>;
54
+ //# sourceMappingURL=settings-email.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-email.d.ts","sourceRoot":"","sources":["../../src/admin/settings-email.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAcH,OAAO,KAAK,EAAwB,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGlD;;;;;;;;GAQG;AACH,eAAO,MAAM,SAAS,yBAA0B,CAAC;AAEjD,mEAAmE;AACnE,eAAO,MAAM,WAAW;aACtB,WAAW,EAAE,eAAe;aAC5B,QAAQ,EAAE,WAAW;aACrB,QAAQ,EAAE,WAAW;aACrB,UAAU,EAAE,aAAa;aACzB,QAAQ,EAAE,WAAW;aACrB,YAAY,EAAE,eAAe;aAC7B,MAAM,EAAE,QAAQ;CACR,CAAC;AAEX,yEAAyE;AACzE,eAAO,MAAM,WAAW,WAAW,CAAC;AAEpC,8CAA8C;AAC9C,eAAO,MAAM,cAAc,8BAA+B,CAAC;AAE3D,mEAAmE;AACnE,eAAO,MAAM,gBAAgB;aAAK,EAAE,EAAE,IAAI;CAAW,CAAC;AAEtD,2EAA2E;AAC3E,eAAO,MAAM,kBAAkB,SAAS,CAAC;AAEzC,+BAA+B;AAC/B,eAAO,MAAM,cAAc,EAAE,YAU5B,CAAC;AA+GF;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA2C1F"}
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Email: how the site sends mail, and where a message written to it goes.
3
+ *
4
+ * The settings are here and the credentials are not: an API key and an SMTP
5
+ * password live in `data/mail.json` at mode 0600, never in the public
6
+ * `site.json`, and they are their own pair of forms so a credential typed wrong
7
+ * cannot lose an edit to the From line beside it.
8
+ */
9
+ import { readMailCredentials, removeMailCredentials, writeMailCredentials, } from '../mail/credentials.js';
10
+ import { MAIL_PROVIDERS } from '../mail/provider.js';
11
+ import { flash } from './flash.js';
12
+ import { bodyField, settingsPagePath } from './settings-page.js';
13
+ import { EMAIL_PATTERN, readSiteSettings, SETTINGS_PATH } from './settings.js';
14
+ import { ADMIN_TEMPLATES } from './templates.js';
15
+ /**
16
+ * Where the mail credential's form and its Remove button post.
17
+ *
18
+ * Its own endpoint for the reason the Akismet key has one: an API key and an
19
+ * SMTP password are credentials, they live in `data/mail.json` rather than in
20
+ * `content/_data/site.json`, and a credential typed wrong must not lose an edit
21
+ * to the From line. Which provider is in use and who mail is from are settings
22
+ * and stay on the Email form.
23
+ */
24
+ export const MAIL_PATH = `${SETTINGS_PATH}/mail`;
25
+ /** The fields the credential form and its Remove button submit. */
26
+ export const MAIL_FIELDS = {
27
+ brevoApiKey: 'brevo_api_key',
28
+ smtpHost: 'smtp_host',
29
+ smtpPort: 'smtp_port',
30
+ smtpSecure: 'smtp_secure',
31
+ smtpUser: 'smtp_user',
32
+ smtpPassword: 'smtp_password',
33
+ action: 'action',
34
+ };
35
+ /** The {@link MAIL_FIELDS.action} that forgets every mail credential. */
36
+ export const MAIL_REMOVE = 'remove';
37
+ /** Where the Send test email button posts. */
38
+ export const MAIL_TEST_PATH = `${SETTINGS_PATH}/mail/test`;
39
+ /** The field that form submits: where to send the test message. */
40
+ export const MAIL_TEST_FIELDS = { to: 'to' };
41
+ /** The message the Send test email button sends, as the theme names it. */
42
+ export const MAIL_TEST_TEMPLATE = 'test';
43
+ /** The Email settings page. */
44
+ export const EMAIL_SETTINGS = {
45
+ child: 'email',
46
+ label: 'Email',
47
+ path: settingsPagePath('email'),
48
+ template: ADMIN_TEMPLATES.settingsEmail,
49
+ fields: ['mailProvider', 'mailFromName', 'mailFromAddress', 'mailReplyTo', 'contactEmail'],
50
+ panels: (c, settings) => mailPanel(c.var.config.dataDir, settings),
51
+ endpoints: mountMail,
52
+ };
53
+ /** The mail credential's endpoints: save it, forget it, and prove it works. */
54
+ function mountMail(app, _options) {
55
+ const here = EMAIL_SETTINGS.path;
56
+ /**
57
+ * The mail credential: one form saves it, a second forgets it.
58
+ *
59
+ * It keeps both providers' credentials at once, so a site trying SMTP after
60
+ * Brevo can switch the provider back without pasting the key in again.
61
+ *
62
+ * A blank secret keeps the stored one. The form cannot render a password back
63
+ * into a page, so a blank field has to mean "unchanged" or nobody could ever
64
+ * edit the SMTP port without retyping the password.
65
+ */
66
+ app.post(MAIL_PATH, async (c) => {
67
+ const body = await c.req.parseBody();
68
+ const { config } = c.var;
69
+ const stored = readMailCredentials(config.dataDir);
70
+ if (bodyField(body[MAIL_FIELDS.action]) === MAIL_REMOVE) {
71
+ await removeMailCredentials(config.dataDir);
72
+ flash(c, 'notice', 'The mail credentials are gone. No email is sent any more.');
73
+ return c.redirect(here, 303);
74
+ }
75
+ const apiKey = bodyField(body[MAIL_FIELDS.brevoApiKey]).trim();
76
+ const host = bodyField(body[MAIL_FIELDS.smtpHost]).trim();
77
+ const port = Number(bodyField(body[MAIL_FIELDS.smtpPort]).trim());
78
+ const password = bodyField(body[MAIL_FIELDS.smtpPassword]);
79
+ if (host !== '' && (!Number.isInteger(port) || port < 1 || port > 65535)) {
80
+ flash(c, 'error', 'An SMTP port is a whole number between 1 and 65535. Nothing was saved.');
81
+ return c.redirect(here, 303);
82
+ }
83
+ const credentials = {
84
+ ...(apiKey === ''
85
+ ? stored.brevo === undefined
86
+ ? {}
87
+ : { brevo: stored.brevo }
88
+ : { brevo: { apiKey } }),
89
+ ...(host === ''
90
+ ? stored.smtp === undefined
91
+ ? {}
92
+ : { smtp: stored.smtp }
93
+ : {
94
+ smtp: {
95
+ host,
96
+ port,
97
+ secure: bodyField(body[MAIL_FIELDS.smtpSecure]) !== '',
98
+ user: bodyField(body[MAIL_FIELDS.smtpUser]).trim(),
99
+ // A blank password keeps the stored one, so the port and the user
100
+ // can be edited without retyping a secret the form was never
101
+ // allowed to show.
102
+ password: password === '' ? (stored.smtp?.password ?? '') : password,
103
+ },
104
+ }),
105
+ };
106
+ await writeMailCredentials(config.dataDir, credentials);
107
+ const settings = readSiteSettings(config.contentDir);
108
+ flash(c, 'notice', settings.mailProvider === 'none'
109
+ ? 'Saved. Choose a provider above and save the settings to start sending.'
110
+ : 'Saved. Send a test message to prove it reaches you.');
111
+ return c.redirect(here, 303);
112
+ });
113
+ /**
114
+ * Send test email: the one button that proves the whole chain.
115
+ *
116
+ * It goes through the same mail service every feature will, so what it proves
117
+ * is not "these credentials parse" but "a message from this site arrives" —
118
+ * the template, the From line, the provider and the retry included. Whatever
119
+ * the provider said comes back on the flash, its own words and all, because a
120
+ * refusal names the field to fix and a summary of one never does.
121
+ */
122
+ app.post(MAIL_TEST_PATH, async (c) => {
123
+ const body = await c.req.parseBody();
124
+ const to = bodyField(body[MAIL_TEST_FIELDS.to]).trim();
125
+ if (!EMAIL_PATTERN.test(to)) {
126
+ flash(c, 'error', 'Type the address to send the test message to.');
127
+ return c.redirect(here, 303);
128
+ }
129
+ const result = await c.var.mail.send({ to, template: MAIL_TEST_TEMPLATE });
130
+ flash(c, result.ok && !result.skipped ? 'notice' : 'error', result.skipped
131
+ ? 'No mail is configured, so nothing was sent. Choose a provider and save a credential first.'
132
+ : result.ok
133
+ ? `A test message was sent to ${to} via ${result.provider}${result.messageId === undefined ? '' : ` (${result.messageId})`}. If it does not arrive, look in the spam folder and at the provider's own log.`
134
+ : `${result.provider} would not send to ${to} after ${String(result.attempts)} ${result.attempts === 1 ? 'attempt' : 'attempts'}: ${result.error ?? 'no reason given'}`);
135
+ return c.redirect(here, 303);
136
+ });
137
+ }
138
+ /**
139
+ * What the page says about email: which provider is chosen, whether the
140
+ * credential it needs is there, and enough of it to recognise which one.
141
+ *
142
+ * Nothing here ever prints a key or a password. A settings screen that echoed
143
+ * one would put a credential in every browser cache, every screenshot and every
144
+ * `view-source`; the last four characters of an API key and the host and user
145
+ * of an SMTP connection are enough for somebody to tell what is stored without
146
+ * being handed the means to use it.
147
+ */
148
+ export function mailPanel(dataDir, settings) {
149
+ const stored = readMailCredentials(dataDir);
150
+ const present = settings.mailProvider === 'brevo' ? stored.brevo !== undefined : stored.smtp !== undefined;
151
+ return {
152
+ mailUrl: MAIL_PATH,
153
+ mailFields: MAIL_FIELDS,
154
+ mailRemove: MAIL_REMOVE,
155
+ mailTestUrl: MAIL_TEST_PATH,
156
+ mailTestFields: MAIL_TEST_FIELDS,
157
+ mailProviders: MAIL_PROVIDERS,
158
+ mailProvider: settings.mailProvider,
159
+ // Whether the chosen provider has what it needs. A key stored for the
160
+ // provider that is not chosen is not "configured": nothing would use it.
161
+ mailConfigured: settings.mailProvider !== 'none' && present,
162
+ mailBrevoPresent: stored.brevo !== undefined,
163
+ mailSmtpPresent: stored.smtp !== undefined,
164
+ ...(stored.brevo === undefined
165
+ ? {}
166
+ : { mailBrevoKeyHint: `…${stored.brevo.apiKey.slice(-4)}` }),
167
+ ...(stored.smtp === undefined
168
+ ? {}
169
+ : {
170
+ mailSmtp: {
171
+ host: stored.smtp.host,
172
+ port: stored.smtp.port,
173
+ secure: stored.smtp.secure,
174
+ user: stored.smtp.user,
175
+ // Not the password. Whether there is one at all is all the screen
176
+ // needs to say.
177
+ hasPassword: stored.smtp.password !== '',
178
+ },
179
+ }),
180
+ mailHint: settings.mailProvider === 'none'
181
+ ? 'This site sends no email. Password resets, moderation notices and contact messages are still recorded; they are simply not sent.'
182
+ : present
183
+ ? 'Mail is configured. Send a test message to prove it reaches you.'
184
+ : settings.mailProvider === 'brevo'
185
+ ? 'Brevo is chosen but there is no API key, so nothing is sent.'
186
+ : 'SMTP is chosen but there is no server, so nothing is sent.',
187
+ };
188
+ }
189
+ //# sourceMappingURL=settings-email.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-email.js","sourceRoot":"","sources":["../../src/admin/settings-email.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEjE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE/E,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,aAAa,OAAO,CAAC;AAEjD,mEAAmE;AACnE,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,WAAW,EAAE,eAAe;IAC5B,QAAQ,EAAE,WAAW;IACrB,QAAQ,EAAE,WAAW;IACrB,UAAU,EAAE,aAAa;IACzB,QAAQ,EAAE,WAAW;IACrB,YAAY,EAAE,eAAe;IAC7B,MAAM,EAAE,QAAQ;CACR,CAAC;AAEX,yEAAyE;AACzE,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC;AAEpC,8CAA8C;AAC9C,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,aAAa,YAAY,CAAC;AAE3D,mEAAmE;AACnE,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,EAAE,EAAE,IAAI,EAAW,CAAC;AAEtD,2EAA2E;AAC3E,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAEzC,+BAA+B;AAC/B,MAAM,CAAC,MAAM,cAAc,GAAiB;IAC1C,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,gBAAgB,CAAC,OAAO,CAAC;IAC/B,QAAQ,EAAE,eAAe,CAAC,aAAa;IACvC,MAAM,EAAE,CAAC,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,CAAC;IAE1F,MAAM,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC;IAElE,SAAS,EAAE,SAAS;CACrB,CAAC;AAEF,+EAA+E;AAC/E,SAAS,SAAS,CAAC,GAAqB,EAAE,QAA8B;IACtE,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC;IAEjC;;;;;;;;;OASG;IACH,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC9B,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;QACrC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC;QACzB,MAAM,MAAM,GAAG,mBAAmB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAEnD,IAAI,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,WAAW,EAAE,CAAC;YACxD,MAAM,qBAAqB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC5C,KAAK,CAAC,CAAC,EAAE,QAAQ,EAAE,2DAA2D,CAAC,CAAC;YAChF,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC/B,CAAC;QAED,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC/D,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1D,MAAM,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAClE,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC;QAE3D,IAAI,IAAI,KAAK,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;YACzE,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,wEAAwE,CAAC,CAAC;YAC5F,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC/B,CAAC;QAED,MAAM,WAAW,GAAoB;YACnC,GAAG,CAAC,MAAM,KAAK,EAAE;gBACf,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS;oBAC1B,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE;gBAC3B,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC;YAC1B,GAAG,CAAC,IAAI,KAAK,EAAE;gBACb,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS;oBACzB,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE;gBACzB,CAAC,CAAC;oBACE,IAAI,EAAE;wBACJ,IAAI;wBACJ,IAAI;wBACJ,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE;wBACtD,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE;wBAClD,kEAAkE;wBAClE,6DAA6D;wBAC7D,mBAAmB;wBACnB,QAAQ,EAAE,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ;qBACrE;iBACF,CAAC;SACP,CAAC;QAEF,MAAM,oBAAoB,CAAC,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QAExD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACrD,KAAK,CACH,CAAC,EACD,QAAQ,EACR,QAAQ,CAAC,YAAY,KAAK,MAAM;YAC9B,CAAC,CAAC,wEAAwE;YAC1E,CAAC,CAAC,qDAAqD,CAC1D,CAAC;QACF,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH;;;;;;;;OAQG;IACH,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACnC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;QACrC,MAAM,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAEvD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YAC5B,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,+CAA+C,CAAC,CAAC;YACnE,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC/B,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,kBAAkB,EAAE,CAAC,CAAC;QAE3E,KAAK,CACH,CAAC,EACD,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EACjD,MAAM,CAAC,OAAO;YACZ,CAAC,CAAC,4FAA4F;YAC9F,CAAC,CAAC,MAAM,CAAC,EAAE;gBACT,CAAC,CAAC,8BAA8B,EAAE,QAAQ,MAAM,CAAC,QAAQ,GACrD,MAAM,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,SAAS,GAC7D,iFAAiF;gBACnF,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,sBAAsB,EAAE,UAAU,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,IACzE,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UACtC,KAAK,MAAM,CAAC,KAAK,IAAI,iBAAiB,EAAE,CAC/C,CAAC;QACF,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,QAAsB;IAC/D,MAAM,MAAM,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,OAAO,GACX,QAAQ,CAAC,YAAY,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC;IAE7F,OAAO;QACL,OAAO,EAAE,SAAS;QAClB,UAAU,EAAE,WAAW;QACvB,UAAU,EAAE,WAAW;QACvB,WAAW,EAAE,cAAc;QAC3B,cAAc,EAAE,gBAAgB;QAChC,aAAa,EAAE,cAAc;QAC7B,YAAY,EAAE,QAAQ,CAAC,YAAY;QACnC,sEAAsE;QACtE,yEAAyE;QACzE,cAAc,EAAE,QAAQ,CAAC,YAAY,KAAK,MAAM,IAAI,OAAO;QAC3D,gBAAgB,EAAE,MAAM,CAAC,KAAK,KAAK,SAAS;QAC5C,eAAe,EAAE,MAAM,CAAC,IAAI,KAAK,SAAS;QAC1C,GAAG,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS;YAC5B,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAC9D,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS;YAC3B,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC;gBACE,QAAQ,EAAE;oBACR,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI;oBACtB,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI;oBACtB,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM;oBAC1B,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI;oBACtB,kEAAkE;oBAClE,gBAAgB;oBAChB,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,KAAK,EAAE;iBACzC;aACF,CAAC;QACN,QAAQ,EACN,QAAQ,CAAC,YAAY,KAAK,MAAM;YAC9B,CAAC,CAAC,kIAAkI;YACpI,CAAC,CAAC,OAAO;gBACP,CAAC,CAAC,kEAAkE;gBACpE,CAAC,CAAC,QAAQ,CAAC,YAAY,KAAK,OAAO;oBACjC,CAAC,CAAC,8DAA8D;oBAChE,CAAC,CAAC,4DAA4D;KACvE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Federation: which relays the site subscribes to.
3
+ *
4
+ * There is nothing else on this page any more. decision-14 replaced the site
5
+ * actor with one actor per user, so the handle, the type and the picture a
6
+ * site used to federate under are a user's profile, edited on the users
7
+ * screen; what is left here is the one setting that is an instruction as well
8
+ * as a value — a line added is a `Follow` to send and a line removed is an
9
+ * `Undo` — so a save of this page reconciles them.
10
+ *
11
+ * It is a settings page filed under Federation rather than under Settings
12
+ * (TASK-109). The admin used to have two menu entries called Federation,
13
+ * neither saying the other existed, and a person looking for the relays had no
14
+ * reason to prefer one over the other. Now the section holds everything about
15
+ * federation: Followers is what it is opened to look at, and this is what it
16
+ * is opened to change. Nothing else moves with the label — the fields, the
17
+ * save, the panels and the refusals are the settings-page machinery, exactly
18
+ * as they were when the URL was `/admin/settings/federation`.
19
+ */
20
+ import type { WordPressRequests } from '../federation/wordpress.ts';
21
+ import type { User } from './accounts.ts';
22
+ import type { SettingsPage } from './settings-page.ts';
23
+ /** The Federation settings page: Federation > Settings. */
24
+ export declare const FEDERATION_SETTINGS: SettingsPage;
25
+ /** One compatibility path, as the panel beside the switch shows it. */
26
+ export interface WordPressRouteRow {
27
+ /** The path itself, which is what a peer still holds. */
28
+ readonly path: string;
29
+ /** Whose it is, or the empty string for the instance-wide inbox. */
30
+ readonly username: string;
31
+ /** When it was last asked for, or `null` for never. */
32
+ readonly lastRequestedAt: string | null;
33
+ }
34
+ /**
35
+ * Every path the compatibility switch answers, and when each was last asked
36
+ * for.
37
+ *
38
+ * The whole point of the panel: the switch can come off once no follower's
39
+ * server is delivering to the old URLs any more, and that is a question only
40
+ * the record of what was asked for can answer. So a route nobody has ever
41
+ * asked for is listed too, saying never — an empty table would read as "no
42
+ * such path" rather than as "nobody is using it".
43
+ *
44
+ * A user with no WordPress number is not here at all: the plugin never
45
+ * published a path for them, so there is nothing for a peer to be holding.
46
+ */
47
+ export declare function wordPressRoutes(users: readonly User[], requests: WordPressRequests): WordPressRouteRow[];
48
+ //# sourceMappingURL=settings-federation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-federation.d.ts","sourceRoot":"","sources":["../../src/admin/settings-federation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,OAAO,KAAK,EAAE,iBAAiB,EAAkB,MAAM,4BAA4B,CAAC;AAEpF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAG1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvD,2DAA2D;AAC3D,eAAO,MAAM,mBAAmB,EAAE,YA8BjC,CAAC;AAwCF,uEAAuE;AACvE,MAAM,WAAW,iBAAiB;IAChC,yDAAyD;IACzD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,uDAAuD;IACvD,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CACzC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,IAAI,EAAE,EACtB,QAAQ,EAAE,iBAAiB,GAC1B,iBAAiB,EAAE,CA6BrB"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Federation: which relays the site subscribes to.
3
+ *
4
+ * There is nothing else on this page any more. decision-14 replaced the site
5
+ * actor with one actor per user, so the handle, the type and the picture a
6
+ * site used to federate under are a user's profile, edited on the users
7
+ * screen; what is left here is the one setting that is an instruction as well
8
+ * as a value — a line added is a `Follow` to send and a line removed is an
9
+ * `Undo` — so a save of this page reconciles them.
10
+ *
11
+ * It is a settings page filed under Federation rather than under Settings
12
+ * (TASK-109). The admin used to have two menu entries called Federation,
13
+ * neither saying the other existed, and a person looking for the relays had no
14
+ * reason to prefer one over the other. Now the section holds everything about
15
+ * federation: Followers is what it is opened to look at, and this is what it
16
+ * is opened to change. Nothing else moves with the label — the fields, the
17
+ * save, the panels and the refusals are the settings-page machinery, exactly
18
+ * as they were when the URL was `/admin/settings/federation`.
19
+ */
20
+ import { readWordPressRequests, WORDPRESS_ACTIVITYPUB_BASE, WORDPRESS_SHARED_INBOX_PATH, } from '../federation/wordpress.js';
21
+ import { listUsers } from './accounts.js';
22
+ import { FEDERATION_SETTINGS_PATH } from './federation.js';
23
+ import { settingsPagePath } from './settings-page.js';
24
+ import { ADMIN_TEMPLATES } from './templates.js';
25
+ /** The Federation settings page: Federation > Settings. */
26
+ export const FEDERATION_SETTINGS = {
27
+ section: 'federation',
28
+ child: 'settings',
29
+ // Settings under Federation, and headed Federation: the menu says which
30
+ // section's settings these are, and the page and its flash say it too.
31
+ label: 'Settings',
32
+ heading: 'Federation',
33
+ path: FEDERATION_SETTINGS_PATH,
34
+ template: ADMIN_TEMPLATES.federationSettings,
35
+ fields: ['relays', 'wordpressActivityPub'],
36
+ panels: (c) => ({
37
+ wordpressRoutes: wordPressRoutes(listUsers(c.var.config.dataDir), readWordPressRequests(c.var.config.dataDir)),
38
+ }),
39
+ saved: (c) => {
40
+ // The reconciliation reads the settings that were just written, so it has
41
+ // to come after the save rather than be derived from the form.
42
+ return toldRelays(c.var.relays.sync());
43
+ },
44
+ endpoints: (app) => {
45
+ // Where this page was until TASK-109. A bookmark points at it, and so do
46
+ // the older editions of the README, so it moves somebody along rather than
47
+ // telling them the screen they used is gone.
48
+ app.get(settingsPagePath('federation'), (c) => c.redirect(FEDERATION_SETTINGS_PATH, 301));
49
+ },
50
+ };
51
+ /**
52
+ * The sentence a flash adds about the relays a save subscribed to or left.
53
+ *
54
+ * A relay does not answer at once — FEP-ae0c allows a human to approve the
55
+ * subscription days later — so the message says a follow was sent rather than
56
+ * that the site is now on the relay, and points at the screen that will say.
57
+ */
58
+ function toldRelays(report) {
59
+ const parts = [];
60
+ if (report.followed.length > 0) {
61
+ parts.push(report.followed.length === 1
62
+ ? 'A follow has been sent to one new relay'
63
+ : `Follows have been sent to ${String(report.followed.length)} new relays`);
64
+ }
65
+ if (report.unfollowed.length > 0) {
66
+ parts.push(report.unfollowed.length === 1
67
+ ? 'one relay has been unfollowed'
68
+ : `${String(report.unfollowed.length)} relays have been unfollowed`);
69
+ }
70
+ if (parts.length === 0)
71
+ return '';
72
+ const sentence = parts.join(', and ');
73
+ return ` ${sentence.charAt(0).toUpperCase()}${sentence.slice(1)}; the Followers screen says where each stands.`;
74
+ }
75
+ /** The order the paths are listed in, which is the order the plugin's actor names them. */
76
+ const WORDPRESS_ROUTE_ORDER = [
77
+ 'actor',
78
+ 'inbox',
79
+ 'outbox',
80
+ 'followers',
81
+ 'following',
82
+ ];
83
+ /**
84
+ * Every path the compatibility switch answers, and when each was last asked
85
+ * for.
86
+ *
87
+ * The whole point of the panel: the switch can come off once no follower's
88
+ * server is delivering to the old URLs any more, and that is a question only
89
+ * the record of what was asked for can answer. So a route nobody has ever
90
+ * asked for is listed too, saying never — an empty table would read as "no
91
+ * such path" rather than as "nobody is using it".
92
+ *
93
+ * A user with no WordPress number is not here at all: the plugin never
94
+ * published a path for them, so there is nothing for a peer to be holding.
95
+ */
96
+ export function wordPressRoutes(users, requests) {
97
+ const rows = [];
98
+ for (const user of users) {
99
+ if (user.wordpressActorId === undefined)
100
+ continue;
101
+ const asked = requests.users[user.username] ?? {};
102
+ const actor = `${WORDPRESS_ACTIVITYPUB_BASE}/actors/${String(user.wordpressActorId)}`;
103
+ for (const route of WORDPRESS_ROUTE_ORDER) {
104
+ rows.push({
105
+ path: route === 'actor' ? actor : `${actor}/${route}`,
106
+ username: user.username,
107
+ lastRequestedAt: asked[route] ?? null,
108
+ });
109
+ }
110
+ }
111
+ // The shared inbox last, and only when somebody could be delivered through
112
+ // it: it belongs to the site rather than to a person, and a site with nobody
113
+ // to deliver to has no use for it.
114
+ if (rows.length > 0) {
115
+ rows.push({
116
+ path: WORDPRESS_SHARED_INBOX_PATH,
117
+ username: '',
118
+ lastRequestedAt: requests.sharedInbox ?? null,
119
+ });
120
+ }
121
+ return rows;
122
+ }
123
+ //# sourceMappingURL=settings-federation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-federation.js","sourceRoot":"","sources":["../../src/admin/settings-federation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * General: what the site is called, where it lives, and what it looks like.
3
+ *
4
+ * WordPress's own first settings page, and the one the Settings heading lands
5
+ * on. There is no avatar here any more: decision-14 made every user an actor
6
+ * with a picture of their own, so the picture a site shows the fediverse is a
7
+ * user's, edited on the users screen beside the rest of their profile.
8
+ */
9
+ import type { SettingsPage } from './settings-page.ts';
10
+ /** The General settings page. */
11
+ export declare const GENERAL_SETTINGS: SettingsPage;
12
+ //# sourceMappingURL=settings-general.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-general.d.ts","sourceRoot":"","sources":["../../src/admin/settings-general.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKvD,iCAAiC;AACjC,eAAO,MAAM,gBAAgB,EAAE,YAwB9B,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * General: what the site is called, where it lives, and what it looks like.
3
+ *
4
+ * WordPress's own first settings page, and the one the Settings heading lands
5
+ * on. There is no avatar here any more: decision-14 made every user an actor
6
+ * with a picture of their own, so the picture a site shows the fediverse is a
7
+ * user's, edited on the users screen beside the rest of their profile.
8
+ */
9
+ import { bodyField, settingsPagePath } from './settings-page.js';
10
+ import { effectiveBaseUrl, SETTINGS_FIELDS } from './settings.js';
11
+ import { ADMIN_TEMPLATES } from './templates.js';
12
+ /** The General settings page. */
13
+ export const GENERAL_SETTINGS = {
14
+ child: 'general',
15
+ label: 'General',
16
+ path: settingsPagePath('general'),
17
+ template: ADMIN_TEMPLATES.settingsGeneral,
18
+ fields: ['title', 'tagline', 'author', 'baseUrl', 'timezone', 'language'],
19
+ // The base URL field shows the one in effect rather than the one the file
20
+ // happens to hold: a site.json with no `url` at all would otherwise render an
21
+ // empty field that the validator refuses the moment anything is saved.
22
+ shown: (config, settings) => ({ ...settings, baseUrl: effectiveBaseUrl(config, settings) }),
23
+ panels: (c, settings) => baseUrlPanel(c.var.config, settings),
24
+ // A field the form rendered read-only is not submitted, so an overridden base
25
+ // URL keeps the value it had rather than being cleared by a save.
26
+ reads: ({ c, body, current }) => ({
27
+ baseUrl: c.var.config.baseUrlSource === 'default'
28
+ ? bodyField(body[SETTINGS_FIELDS.baseUrl])
29
+ : current.baseUrl === ''
30
+ ? c.var.config.baseUrl
31
+ : current.baseUrl,
32
+ }),
33
+ };
34
+ /** What the page says about the base URL: the one in effect, and why it is. */
35
+ function baseUrlPanel(config, settings) {
36
+ const overridden = config.baseUrlSource !== 'default';
37
+ return {
38
+ baseUrlInEffect: effectiveBaseUrl(config, settings),
39
+ baseUrlOverridden: overridden,
40
+ baseUrlSource: config.baseUrlSource,
41
+ baseUrlNote: overridden
42
+ ? config.baseUrlSource === 'environment'
43
+ ? 'GEEKITY_BASE_URL is set, so it is the base URL in effect and this field is not editable here.'
44
+ : 'The config file sets baseUrl, so it is the base URL in effect and this field is not editable here.'
45
+ : 'Absolute URLs, the feeds and the session cookie pick this up when the site next starts.',
46
+ };
47
+ }
48
+ //# sourceMappingURL=settings-general.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-general.js","sourceRoot":"","sources":["../../src/admin/settings-general.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEjE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAElE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,iCAAiC;AACjC,MAAM,CAAC,MAAM,gBAAgB,GAAiB;IAC5C,KAAK,EAAE,SAAS;IAChB,KAAK,EAAE,SAAS;IAChB,IAAI,EAAE,gBAAgB,CAAC,SAAS,CAAC;IACjC,QAAQ,EAAE,eAAe,CAAC,eAAe;IACzC,MAAM,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,CAAC;IAEzE,0EAA0E;IAC1E,8EAA8E;IAC9E,uEAAuE;IACvE,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,OAAO,EAAE,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;IAE3F,MAAM,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC;IAE7D,8EAA8E;IAC9E,kEAAkE;IAClE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;QAChC,OAAO,EACL,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,KAAK,SAAS;YACtC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YAC1C,CAAC,CAAC,OAAO,CAAC,OAAO,KAAK,EAAE;gBACtB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO;gBACtB,CAAC,CAAC,OAAO,CAAC,OAAO;KACxB,CAAC;CACH,CAAC;AAEF,+EAA+E;AAC/E,SAAS,YAAY,CACnB,MAAyD,EACzD,QAAsB;IAEtB,MAAM,UAAU,GAAG,MAAM,CAAC,aAAa,KAAK,SAAS,CAAC;IAEtD,OAAO;QACL,eAAe,EAAE,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC;QACnD,iBAAiB,EAAE,UAAU;QAC7B,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,WAAW,EAAE,UAAU;YACrB,CAAC,CAAC,MAAM,CAAC,aAAa,KAAK,aAAa;gBACtC,CAAC,CAAC,+FAA+F;gBACjG,CAAC,CAAC,oGAAoG;YACxG,CAAC,CAAC,yFAAyF;KAC9F,CAAC;AACJ,CAAC"}