@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,295 @@
1
+ /**
2
+ * The media screen: what is under `content/uploads/`, what links to it, and
3
+ * the two things that can be done to it — add one, and take one away.
4
+ *
5
+ * The listing is a walk of the directory rather than a query, because the
6
+ * directory is the truth (decision-1, decision-9). Nothing records that a file
7
+ * exists; a file dropped in by hand over ssh, by a git pull, or by an Eleventy
8
+ * build is on the screen the next time it is asked for, and a file taken away
9
+ * the same way is off it. The only thing the index is asked is which documents
10
+ * mention a URL, which is a question a directory cannot answer.
11
+ */
12
+ import { readdir, stat, unlink } from 'node:fs/promises';
13
+ import path from 'node:path';
14
+ import { UPLOAD_MEDIA_TYPES } from '../content/media.js';
15
+ import { isTrashedPath } from '../content/store.js';
16
+ import { removeImageVariants } from '../images/variants.js';
17
+ import { UPLOAD_ASSET_PREFIX, UPLOAD_DIRECTORY } from '../web/assets.js';
18
+ import { editorPath, PAGE_KIND, POST_KIND } from './documents.js';
19
+ import { flash } from './flash.js';
20
+ import { ADMIN_PREFIX } from './session.js';
21
+ import { ADMIN_TEMPLATES } from './templates.js';
22
+ import { refusedUpload, storeUpload, uploadMarkdown } from './uploads.js';
23
+ /** Where the media screen lives. */
24
+ export const MEDIA_PATH = `${ADMIN_PREFIX}/media`;
25
+ /** The navigation section the screen marks as current. */
26
+ export const MEDIA_SECTION = 'media';
27
+ /** Where the screen's upload form posts. */
28
+ export const MEDIA_UPLOAD_PATH = `${MEDIA_PATH}/upload`;
29
+ /** Where a row's Delete button posts. */
30
+ export const MEDIA_DELETE_PATH = `${MEDIA_PATH}/delete`;
31
+ /** How many files one page of the library shows. */
32
+ export const MEDIA_PER_PAGE = 24;
33
+ /** The fields the forms on the media screen submit. */
34
+ export const MEDIA_FIELDS = {
35
+ /** The file being added, on the upload form. */
36
+ file: 'file',
37
+ /** The upload being deleted, as a path under `content/uploads/`. */
38
+ path: 'path',
39
+ /** Set once the admin has been shown what still references the file. */
40
+ confirm: 'confirm',
41
+ };
42
+ /**
43
+ * Every file under `content/uploads/`, newest first.
44
+ *
45
+ * Recursive, because uploads land under `{yyyy}/{mm}/`, and a site that has
46
+ * been copying files in by hand may have any shape at all under there. The
47
+ * order is by modification time rather than by the dated path: the path is
48
+ * only a hint about when a file arrived, and a file dropped in by hand may
49
+ * have no dated path to read.
50
+ *
51
+ * A directory that does not exist yet is an empty library rather than an
52
+ * error — a site that has never uploaded anything has no `uploads/`.
53
+ */
54
+ export async function listUploads(contentDir) {
55
+ const root = path.join(contentDir, UPLOAD_DIRECTORY);
56
+ let entries;
57
+ try {
58
+ entries = await readdir(root, { recursive: true, withFileTypes: true });
59
+ }
60
+ catch (error) {
61
+ if (error.code === 'ENOENT')
62
+ return [];
63
+ throw error;
64
+ }
65
+ const found = [];
66
+ for (const entry of entries) {
67
+ if (!entry.isFile())
68
+ continue;
69
+ // Hidden files are the operating system's business, not the site's:
70
+ // .DS_Store is not something anybody uploaded or wants to link to.
71
+ if (entry.name.startsWith('.'))
72
+ continue;
73
+ const file = path.join(entry.parentPath, entry.name);
74
+ const relative = path.relative(root, file).split(path.sep).join('/');
75
+ let stats;
76
+ try {
77
+ stats = await stat(file);
78
+ }
79
+ catch {
80
+ // It went away between the walk and the stat. Nothing to show.
81
+ continue;
82
+ }
83
+ found.push(describeUpload(relative, stats.size, stats.mtime));
84
+ }
85
+ // Newest first, and by path when two files share a timestamp, so a page of
86
+ // files copied in together has a stable order rather than the readdir one.
87
+ found.sort((left, right) => left.modified === right.modified
88
+ ? right.path.localeCompare(left.path)
89
+ : right.modified.localeCompare(left.modified));
90
+ return found;
91
+ }
92
+ /** One upload as the screen shows it, from what a directory walk knows. */
93
+ export function describeUpload(relative, bytes, modified) {
94
+ const name = relative.slice(relative.lastIndexOf('/') + 1);
95
+ const extension = path.extname(name).toLowerCase();
96
+ const image = UPLOAD_MEDIA_TYPES.get(extension)?.image ?? false;
97
+ const url = `${UPLOAD_ASSET_PREFIX}${relative}`;
98
+ return {
99
+ path: relative,
100
+ url,
101
+ name,
102
+ extension,
103
+ bytes,
104
+ modified: modified.toISOString(),
105
+ image,
106
+ // The same Markdown the editor's upload control pastes, from the same
107
+ // function, so a file linked from the media screen and the same file
108
+ // linked from the editor are written identically.
109
+ markdown: uploadMarkdown({ url, label: name.slice(0, name.length - extension.length), image }),
110
+ };
111
+ }
112
+ /**
113
+ * Every document whose body mentions an upload's URL, trash included.
114
+ *
115
+ * The trash counts. A trashed post can be restored tomorrow, and restoring one
116
+ * whose picture was deleted in the meantime is a broken post nobody was warned
117
+ * about — so a file the trash still points at asks for confirmation exactly as
118
+ * a published one does.
119
+ *
120
+ * This is the one thing on the screen that comes out of the index rather than
121
+ * off the disk. The index is a cache of the files (decision-1), so it may be a
122
+ * moment behind a hand edit; that is acceptable here because the answer is a
123
+ * warning rather than a decision, and the confirmation step is what makes an
124
+ * out-of-date answer harmless in both directions.
125
+ */
126
+ export function referencesTo(store, url) {
127
+ // Two queries rather than one because `listAll` shows the live tree or the
128
+ // trash and never both, which is the same reason the taxonomy screens ask
129
+ // twice.
130
+ return [...store.listAll({ trashed: false }), ...store.listAll({ trashed: true })]
131
+ .filter((document) => mentionsUpload(document.body, url))
132
+ .map((document) => ({
133
+ path: document.path,
134
+ title: document.title === '' ? document.path : document.title,
135
+ editUrl: editorPath(document.type === 'page' ? PAGE_KIND : POST_KIND, document.slug),
136
+ trashed: isTrashedPath(document.path),
137
+ }));
138
+ }
139
+ /**
140
+ * Whether a body points at an upload URL.
141
+ *
142
+ * A substring search with one guard on the end of it: `/uploads/a.png` must not
143
+ * count as a mention of `/uploads/a.pn`, and `/uploads/logo.png` must not count
144
+ * as a mention of `/uploads/logo`. Anything that could still be part of the
145
+ * same filename disqualifies the match; a quote, a bracket, a space or the end
146
+ * of the body ends it.
147
+ *
148
+ * Deliberately blind to whether the mention is Markdown, HTML or prose. All
149
+ * three break when the file goes, and a warning that only understood
150
+ * `![](…)` would be a warning that missed most of them.
151
+ */
152
+ export function mentionsUpload(body, url) {
153
+ for (let at = body.indexOf(url); at !== -1; at = body.indexOf(url, at + 1)) {
154
+ const next = body[at + url.length];
155
+ if (next === undefined || !FILENAME_CHARACTER.test(next))
156
+ return true;
157
+ }
158
+ return false;
159
+ }
160
+ /** Characters that could still be part of the filename a match landed in. */
161
+ const FILENAME_CHARACTER = /[A-Za-z0-9._~-]/;
162
+ /**
163
+ * Delete one upload, and whatever was derived from it.
164
+ *
165
+ * Returns `false` when there was no such file, which is what a second click on
166
+ * a Delete button on a stale page is, rather than throwing: the end state the
167
+ * admin asked for is the end state they have.
168
+ */
169
+ export async function deleteUpload(options) {
170
+ const file = resolveUpload(options.contentDir, options.path);
171
+ if (file === undefined)
172
+ return false;
173
+ try {
174
+ await unlink(file);
175
+ }
176
+ catch (error) {
177
+ if (error.code !== 'ENOENT')
178
+ throw error;
179
+ return false;
180
+ }
181
+ // After the original, so a hook that throws leaves a file with stale
182
+ // variants rather than variants with no file: the first is repairable by
183
+ // regenerating, the second is orphaned bytes.
184
+ await options.removeDerived?.(options.path);
185
+ return true;
186
+ }
187
+ /**
188
+ * A submitted path as an absolute file under `content/uploads/`, or
189
+ * `undefined` when it is not one.
190
+ *
191
+ * The path arrives in a form, so it is an attacker's string as much as an
192
+ * admin's. Containment is checked after resolution rather than by inspecting
193
+ * the string, so `..`, an encoded one, or an absolute path cannot slip past —
194
+ * the same rule {@link findAsset} applies to a request for a file.
195
+ */
196
+ export function resolveUpload(contentDir, relative) {
197
+ if (relative === '' || relative.includes('\0'))
198
+ return undefined;
199
+ const root = path.resolve(contentDir, UPLOAD_DIRECTORY);
200
+ const file = path.resolve(root, relative);
201
+ if (!file.startsWith(root + path.sep))
202
+ return undefined;
203
+ return file;
204
+ }
205
+ /**
206
+ * Register the media screen: the library, the upload form and the delete.
207
+ *
208
+ * Uploading here is {@link storeUpload}, exactly as the editor's control and
209
+ * the avatar are, so what a site accepts is one answer given in one place
210
+ * rather than three screens that might disagree.
211
+ */
212
+ export function mountMediaScreen(app, options) {
213
+ const { render, removeDerived } = options;
214
+ app.get(MEDIA_PATH, async (c) => render(c, ADMIN_TEMPLATES.media, await screen(c)));
215
+ app.post(MEDIA_UPLOAD_PATH, async (c) => {
216
+ const body = await c.req.parseBody();
217
+ const outcome = await storeUpload(body[MEDIA_FIELDS.file], c.var.config);
218
+ if (refusedUpload(outcome)) {
219
+ flash(c, 'error', `${outcome.error} Nothing was added.`);
220
+ return c.redirect(MEDIA_PATH, 303);
221
+ }
222
+ flash(c, 'notice', `Uploaded ${outcome.url}.`);
223
+ return c.redirect(MEDIA_PATH, 303);
224
+ });
225
+ app.post(MEDIA_DELETE_PATH, async (c) => {
226
+ const body = await c.req.parseBody();
227
+ const relative = field(body[MEDIA_FIELDS.path]);
228
+ const file = relative === '' ? undefined : resolveUpload(c.var.config.contentDir, relative);
229
+ if (file === undefined) {
230
+ flash(c, 'error', 'That is not a file in this site’s uploads.');
231
+ return c.redirect(MEDIA_PATH, 303);
232
+ }
233
+ const url = `${UPLOAD_ASSET_PREFIX}${relative}`;
234
+ const references = referencesTo(c.var.store, url);
235
+ // A file something still points at is offered rather than deleted: the
236
+ // bytes do not come back, and the documents naming them are the whole
237
+ // reason to think twice.
238
+ if (references.length > 0 && field(body[MEDIA_FIELDS.confirm]) === '') {
239
+ return render(c, ADMIN_TEMPLATES.media, await screen(c, { confirm: { path: relative, url, references } }));
240
+ }
241
+ const deleted = await deleteUpload({
242
+ contentDir: c.var.config.contentDir,
243
+ path: relative,
244
+ // The site's own image variants unless the caller named something else,
245
+ // so nothing has to be wired at the mount site for the ordinary case
246
+ // and a test can still watch the hook being called.
247
+ removeDerived: removeDerived ?? ((uploadPath) => removeImageVariants(c.var.config, uploadPath)),
248
+ });
249
+ flash(c, deleted ? 'notice' : 'error', deleted ? `Deleted ${url}.` : `There is no longer a file at ${url}.`);
250
+ return c.redirect(MEDIA_PATH, 303);
251
+ });
252
+ /** Everything the media template renders. */
253
+ async function screen(c, extra = {}) {
254
+ const files = await listUploads(c.var.config.contentDir);
255
+ const page = pageNumber(c.req.query('page'));
256
+ const start = (page - 1) * MEDIA_PER_PAGE;
257
+ return {
258
+ section: MEDIA_SECTION,
259
+ child: 'library',
260
+ heading: 'Media',
261
+ listUrl: MEDIA_PATH,
262
+ uploadUrl: MEDIA_UPLOAD_PATH,
263
+ deleteUrl: MEDIA_DELETE_PATH,
264
+ fields: MEDIA_FIELDS,
265
+ accepts: c.var.config.uploadTypes.join(','),
266
+ maxBytes: c.var.config.uploadMaxBytes,
267
+ total: files.length,
268
+ page,
269
+ pages: Math.max(1, Math.ceil(files.length / MEDIA_PER_PAGE)),
270
+ previousUrl: page > 1 ? mediaPageUrl(page - 1) : undefined,
271
+ nextUrl: start + MEDIA_PER_PAGE < files.length ? mediaPageUrl(page + 1) : undefined,
272
+ // Reference counts are one index scan per file on the page rather than
273
+ // per file in the library, which is what paging is for.
274
+ files: files.slice(start, start + MEDIA_PER_PAGE).map((file) => ({
275
+ ...file,
276
+ references: referencesTo(c.var.store, file.url),
277
+ })),
278
+ ...extra,
279
+ };
280
+ }
281
+ }
282
+ /** The URL of one page of the library. Page one is the screen's own URL. */
283
+ export function mediaPageUrl(page) {
284
+ return page > 1 ? `${MEDIA_PATH}?page=${String(page)}` : MEDIA_PATH;
285
+ }
286
+ /** A `page` query as a page number. Anything that is not one is page one. */
287
+ function pageNumber(value) {
288
+ const parsed = Number(value ?? '1');
289
+ return Number.isFinite(parsed) && parsed >= 1 ? Math.floor(parsed) : 1;
290
+ }
291
+ /** A form field as a string. A file upload, or a missing field, is the empty one. */
292
+ function field(value) {
293
+ return typeof value === 'string' ? value.trim() : '';
294
+ }
295
+ //# sourceMappingURL=media.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media.js","sourceRoot":"","sources":["../../src/admin/media.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * The admin's left-hand menu: which sections there are, what is under each of
3
+ * them, and which one a screen is standing in.
4
+ *
5
+ * The shape is WordPress classic. A section is a heading with one or more
6
+ * children; clicking the heading opens the section and lands on its first
7
+ * child; the open section shows its children and the one you are on is marked.
8
+ * Every section has at least one child even when it has exactly one screen,
9
+ * because that is what makes the rule uniform — a second child can appear
10
+ * later without the menu changing shape, and no screen has to know whether it
11
+ * is the only one of its kind.
12
+ *
13
+ * The registry below is the whole menu. A screen names its section and its
14
+ * child, {@link adminMenu} turns that pair into the rendered list, and a pair
15
+ * the registry does not hold is refused rather than quietly rendered as a
16
+ * menu with nothing marked.
17
+ */
18
+ /** One screen under a section, as the menu lists it. */
19
+ export interface AdminMenuChild {
20
+ /** The name a screen passes as `child` to mark itself current. */
21
+ child: string;
22
+ /** What the link says. */
23
+ label: string;
24
+ /** Where it goes. */
25
+ url: string;
26
+ }
27
+ /** One top-level entry in the admin's left-hand navigation. */
28
+ export interface AdminSection {
29
+ /** The name a screen passes as `section` to open it. */
30
+ section: string;
31
+ /** What the heading says. */
32
+ label: string;
33
+ /** Where the heading goes: its first child, always. */
34
+ url: string;
35
+ /** The screens under it, in the order they are shown. Never empty. */
36
+ children: readonly AdminMenuChild[];
37
+ }
38
+ /** A section as a screen renders it: the same entry, plus where you are. */
39
+ export interface AdminMenuSection extends AdminSection {
40
+ /** Whether this is the section being looked at, so its children show. */
41
+ open: boolean;
42
+ /** Its children, each saying whether it is the screen being looked at. */
43
+ children: readonly AdminMenuCurrentChild[];
44
+ }
45
+ /** A child as a screen renders it. */
46
+ export interface AdminMenuCurrentChild extends AdminMenuChild {
47
+ /** Whether this is the screen being looked at, for `aria-current`. */
48
+ current: boolean;
49
+ }
50
+ /** Where a screen says it is standing. */
51
+ export interface AdminScreenLocation {
52
+ /** The section it is under. */
53
+ section?: string | undefined;
54
+ /** The child of that section it is. */
55
+ child?: string | undefined;
56
+ }
57
+ /** A screen naming a section or a child the registry does not hold. */
58
+ export declare class UnknownAdminScreenError extends Error {
59
+ constructor(message: string);
60
+ }
61
+ /**
62
+ * The sections of the admin, in the order doc-5 lists them.
63
+ *
64
+ * Adding a screen to the menu is one entry in one of these `children` lists
65
+ * and the same `child` name on whatever the screen passes to `render`.
66
+ */
67
+ export declare const ADMIN_SECTIONS: readonly AdminSection[];
68
+ /**
69
+ * The whole menu, with the section a screen named open and the child it named
70
+ * marked current.
71
+ *
72
+ * A screen outside the shell — the login form, the two halves of forgetting a
73
+ * password — names neither, and gets a menu with nothing open, which is what
74
+ * the templates that never render it expect. Anything else has to name both:
75
+ * a section with no child is a screen that only knows half of where it is, and
76
+ * would render a menu that expands around nothing.
77
+ */
78
+ export declare function adminMenu(location?: AdminScreenLocation): AdminMenuSection[];
79
+ //# sourceMappingURL=menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../../src/admin/menu.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAaH,wDAAwD;AACxD,MAAM,WAAW,cAAc;IAC7B,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,+DAA+D;AAC/D,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,GAAG,EAAE,MAAM,CAAC;IACZ,sEAAsE;IACtE,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;CACrC;AAED,4EAA4E;AAC5E,MAAM,WAAW,gBAAiB,SAAQ,YAAY;IACpD,yEAAyE;IACzE,IAAI,EAAE,OAAO,CAAC;IACd,0EAA0E;IAC1E,QAAQ,EAAE,SAAS,qBAAqB,EAAE,CAAC;CAC5C;AAED,sCAAsC;AACtC,MAAM,WAAW,qBAAsB,SAAQ,cAAc;IAC3D,sEAAsE;IACtE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,0CAA0C;AAC1C,MAAM,WAAW,mBAAmB;IAClC,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED,uEAAuE;AACvE,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,YAAY,OAAO,EAAE,MAAM,EAG1B;CACF;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,YAAY,EAsCjD,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,QAAQ,GAAE,mBAAwB,GAAG,gBAAgB,EAAE,CA4BhF"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * The admin's left-hand menu: which sections there are, what is under each of
3
+ * them, and which one a screen is standing in.
4
+ *
5
+ * The shape is WordPress classic. A section is a heading with one or more
6
+ * children; clicking the heading opens the section and lands on its first
7
+ * child; the open section shows its children and the one you are on is marked.
8
+ * Every section has at least one child even when it has exactly one screen,
9
+ * because that is what makes the rule uniform — a second child can appear
10
+ * later without the menu changing shape, and no screen has to know whether it
11
+ * is the only one of its kind.
12
+ *
13
+ * The registry below is the whole menu. A screen names its section and its
14
+ * child, {@link adminMenu} turns that pair into the rendered list, and a pair
15
+ * the registry does not hold is refused rather than quietly rendered as a
16
+ * menu with nothing marked.
17
+ */
18
+ import { THEMES_PATH } from './appearance.js';
19
+ import { COMMENTS_PATH } from './comments.js';
20
+ import { newEditorPath, PAGE_KIND, POST_KIND } from './documents.js';
21
+ import { FEDERATION_PATH } from './federation.js';
22
+ import { MEDIA_PATH } from './media.js';
23
+ import { MESSAGES_PATH } from './messages.js';
24
+ import { settingsPagePath } from './settings-page.js';
25
+ import { ADMIN_PREFIX } from './session.js';
26
+ import { CATEGORY_KIND, TAG_KIND } from './taxonomy.js';
27
+ import { ADD_USER_PATH, USERS_PATH } from './users.js';
28
+ /** A screen naming a section or a child the registry does not hold. */
29
+ export class UnknownAdminScreenError extends Error {
30
+ constructor(message) {
31
+ super(message);
32
+ this.name = 'UnknownAdminScreenError';
33
+ }
34
+ }
35
+ /**
36
+ * The sections of the admin, in the order doc-5 lists them.
37
+ *
38
+ * Adding a screen to the menu is one entry in one of these `children` lists
39
+ * and the same `child` name on whatever the screen passes to `render`.
40
+ */
41
+ export const ADMIN_SECTIONS = [
42
+ section('dashboard', 'Dashboard', [{ child: 'home', label: 'Home', url: ADMIN_PREFIX }]),
43
+ section('posts', 'Posts', [
44
+ { child: 'all', label: 'All posts', url: POST_KIND.basePath },
45
+ { child: 'new', label: 'Add new', url: newEditorPath(POST_KIND) },
46
+ // The terms live here rather than at the top level because that is what
47
+ // they are about: a tag with no post on it is nothing.
48
+ { child: 'categories', label: 'Categories', url: CATEGORY_KIND.basePath },
49
+ { child: 'tags', label: 'Tags', url: TAG_KIND.basePath },
50
+ ]),
51
+ section('pages', 'Pages', [
52
+ { child: 'all', label: 'All pages', url: PAGE_KIND.basePath },
53
+ { child: 'new', label: 'Add new', url: newEditorPath(PAGE_KIND) },
54
+ ]),
55
+ section('media', 'Media', [{ child: 'library', label: 'Library', url: MEDIA_PATH }]),
56
+ section('comments', 'Comments', [{ child: 'all', label: 'All comments', url: COMMENTS_PATH }]),
57
+ section('messages', 'Messages', [{ child: 'all', label: 'All messages', url: MESSAGES_PATH }]),
58
+ // In WordPress's place, between what the site holds and who may change it.
59
+ // One child, because the rule is uniform: a second kind of theme, or a menu
60
+ // editor, slots in beside Themes without the menu changing shape.
61
+ section('appearance', 'Appearance', [{ child: 'themes', label: 'Themes', url: THEMES_PATH }]),
62
+ section('users', 'Users', [
63
+ { child: 'all', label: 'All users', url: USERS_PATH },
64
+ { child: 'new', label: 'Add new', url: ADD_USER_PATH },
65
+ ]),
66
+ // WordPress's own pages, in its own order. General is first because the
67
+ // heading lands on the first child and General is `/admin/settings` itself.
68
+ section('settings', 'Settings', [
69
+ { child: 'general', label: 'General', url: settingsPagePath('general') },
70
+ { child: 'reading', label: 'Reading', url: settingsPagePath('reading') },
71
+ { child: 'permalinks', label: 'Permalinks', url: settingsPagePath('permalinks') },
72
+ { child: 'discussion', label: 'Discussion', url: settingsPagePath('discussion') },
73
+ { child: 'email', label: 'Email', url: settingsPagePath('email') },
74
+ { child: 'federation', label: 'Federation', url: settingsPagePath('federation') },
75
+ ]),
76
+ section('federation', 'Federation', [
77
+ { child: 'followers', label: 'Followers', url: FEDERATION_PATH },
78
+ ]),
79
+ ];
80
+ /**
81
+ * The whole menu, with the section a screen named open and the child it named
82
+ * marked current.
83
+ *
84
+ * A screen outside the shell — the login form, the two halves of forgetting a
85
+ * password — names neither, and gets a menu with nothing open, which is what
86
+ * the templates that never render it expect. Anything else has to name both:
87
+ * a section with no child is a screen that only knows half of where it is, and
88
+ * would render a menu that expands around nothing.
89
+ */
90
+ export function adminMenu(location = {}) {
91
+ const { section: name, child } = location;
92
+ if (name !== undefined) {
93
+ const found = ADMIN_SECTIONS.find((entry) => entry.section === name);
94
+ if (found === undefined) {
95
+ throw new UnknownAdminScreenError(`The admin menu has no section called ${quoted(name)}.`);
96
+ }
97
+ if (child === undefined) {
98
+ throw new UnknownAdminScreenError(`A screen under ${quoted(name)} named no child. Every admin screen is a child of its section.`);
99
+ }
100
+ if (!found.children.some((entry) => entry.child === child)) {
101
+ throw new UnknownAdminScreenError(`The admin menu's ${quoted(name)} section has no child called ${quoted(child)}.`);
102
+ }
103
+ }
104
+ return ADMIN_SECTIONS.map((entry) => ({
105
+ ...entry,
106
+ open: entry.section === name,
107
+ children: entry.children.map((item) => ({
108
+ ...item,
109
+ current: entry.section === name && item.child === child,
110
+ })),
111
+ }));
112
+ }
113
+ /** One section, landing on the first of its children. */
114
+ function section(name, label, children) {
115
+ const [first] = children;
116
+ // Not reachable from the registry above, which names children for every
117
+ // section; it is here so the type of `url` is a string rather than a maybe.
118
+ if (first === undefined)
119
+ throw new Error(`The ${label} admin section has no children.`);
120
+ return { section: name, label, url: first.url, children };
121
+ }
122
+ /** A name as it reads in a message. */
123
+ function quoted(value) {
124
+ return JSON.stringify(value);
125
+ }
126
+ //# sourceMappingURL=menu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu.js","sourceRoot":"","sources":["../../src/admin/menu.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ import type { Hono } from 'hono';
2
+ import type { ContactStatus } from '../contact/records.ts';
3
+ import type { GeekityEnv } from '../env.ts';
4
+ import type { AdminRender } from './documents.ts';
5
+ /**
6
+ * The inbox: what the contact form left behind (TASK-56).
7
+ *
8
+ * A message is a file under `data/contact/` and nothing else — there is no
9
+ * index, because this screen reads every file to sort them anyway and a second
10
+ * copy of the truth would only be a second thing to keep true. So the two
11
+ * actions here are a rewrite and an unlink, and the screen is a view of the
12
+ * directory as it is at that moment (decision-9).
13
+ *
14
+ * Two lists rather than one. A checker's `spam` is an opinion about a message
15
+ * somebody may really have sent, so it is kept rather than thrown away — but a
16
+ * run of it must not bury the messages a person actually has to answer.
17
+ */
18
+ /** Where the Messages screen lives. */
19
+ export declare const MESSAGES_PATH = "/admin/messages";
20
+ /** The navigation section it marks as current. */
21
+ export declare const MESSAGES_SECTION = "messages";
22
+ /** Where the Mark read and Mark unread buttons post. */
23
+ export declare const MESSAGES_READ_PATH = "/admin/messages/read";
24
+ /** Where the Delete button posts. */
25
+ export declare const MESSAGES_DELETE_PATH = "/admin/messages/delete";
26
+ /** The fields the forms on this screen submit. */
27
+ export declare const MESSAGE_FIELDS: {
28
+ /** Which message a button is about. */
29
+ readonly id: 'id';
30
+ /** Whether Mark read means read or unread. Empty is unread. */
31
+ readonly read: 'read';
32
+ /** Which list to go back to afterwards. */
33
+ readonly status: 'status';
34
+ };
35
+ /** How many messages one page of a list shows. */
36
+ export declare const MESSAGES_PER_PAGE = 25;
37
+ /** The two lists, in the order the screen offers them. */
38
+ export declare const MESSAGE_TABS: readonly {
39
+ status: ContactStatus;
40
+ label: string;
41
+ }[];
42
+ /** One message as the screen shows it. */
43
+ export interface MessageRow {
44
+ /** Its id, which the buttons carry. */
45
+ id: string;
46
+ /** Where it stands. */
47
+ status: ContactStatus;
48
+ /** Whether somebody has read it. */
49
+ read: boolean;
50
+ /** The name they gave. */
51
+ author: string;
52
+ /** Their address, which is what a reply goes to. */
53
+ email: string;
54
+ /** What it is about, or the empty string. */
55
+ subject: string;
56
+ /** What it says, as plain text. */
57
+ message: string;
58
+ /** When it arrived, in the site's own time zone. */
59
+ received: string;
60
+ /** A short form of the address hash, for spotting one machine's run of them. */
61
+ address: string | null;
62
+ /** The page the form was on. */
63
+ page: string;
64
+ /** Where that page can be read, or `null` when it has no permalink. */
65
+ pageUrl: string | null;
66
+ /** A `mailto:` that answers this message with its subject already filled in. */
67
+ replyUrl: string;
68
+ }
69
+ /** What {@link mountMessagesScreen} needs from the admin around it. */
70
+ export interface MountMessagesScreenOptions {
71
+ /** The admin's renderer, which injects the chrome, the CSRF token and the flash. */
72
+ render: AdminRender;
73
+ }
74
+ /** Register the Messages screen. */
75
+ export declare function mountMessagesScreen(app: Hono<GeekityEnv>, options: MountMessagesScreenOptions): void;
76
+ /** How many messages are waiting to be read, which is the number on the dashboard. */
77
+ export declare function unreadMessages(dataDir: string): number;
78
+ /** Where one list of the inbox lives. */
79
+ export declare function listUrl(status: ContactStatus, page?: number): string;
80
+ //# sourceMappingURL=messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/admin/messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AASjC,OAAO,KAAK,EAAkB,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAOlD;;;;;;;;;;;;GAYG;AAEH,uCAAuC;AACvC,eAAO,MAAM,aAAa,oBAA6B,CAAC;AAExD,kDAAkD;AAClD,eAAO,MAAM,gBAAgB,aAAa,CAAC;AAE3C,wDAAwD;AACxD,eAAO,MAAM,kBAAkB,yBAA0B,CAAC;AAE1D,qCAAqC;AACrC,eAAO,MAAM,oBAAoB,2BAA4B,CAAC;AAE9D,kDAAkD;AAClD,eAAO,MAAM,cAAc;IACzB,uCAAuC;aACvC,EAAE,EAAE,IAAI;IACR,+DAA+D;aAC/D,IAAI,EAAE,MAAM;IACZ,2CAA2C;aAC3C,MAAM,EAAE,QAAQ;CACR,CAAC;AAEX,kDAAkD;AAClD,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,0DAA0D;AAC1D,eAAO,MAAM,YAAY,EAAE,SAAS;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAG3E,CAAC;AAEF,0CAA0C;AAC1C,MAAM,WAAW,UAAU;IACzB,uCAAuC;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,uBAAuB;IACvB,MAAM,EAAE,aAAa,CAAC;IACtB,oCAAoC;IACpC,IAAI,EAAE,OAAO,CAAC;IACd,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,gFAAgF;IAChF,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,uEAAuE;AACvE,MAAM,WAAW,0BAA0B;IACzC,oFAAoF;IACpF,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,oCAAoC;AACpC,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,EACrB,OAAO,EAAE,0BAA0B,GAClC,IAAI,CAuFN;AAED,sFAAsF;AACtF,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,yCAAyC;AACzC,wBAAgB,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,SAAI,GAAG,MAAM,CAG/D"}