@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,237 @@
1
+ /**
2
+ * Where the taxonomy archives live, and how their URLs are spelled.
3
+ *
4
+ * The bases are a setting rather than a constant: a site moving off WordPress
5
+ * keeps `/tag/` and `/category/`, and a site that spells them otherwise says
6
+ * so on the settings screen. Everything that builds or parses one of those
7
+ * URLs — the public routes, the canonical redirects, the feeds, the theme, the
8
+ * ActivityStreams hashtags — goes through this module, so they cannot
9
+ * disagree about where an archive is.
10
+ */
11
+ /** Where a paginated listing's later pages live, under any listing root. */
12
+ export const PAGE_SEGMENT = 'page';
13
+ /** Both taxonomies, in the order a screen or a loop should take them. */
14
+ export const TAXONOMIES = ['tag', 'category'];
15
+ /**
16
+ * The bases a site has before anybody says otherwise: WordPress's own, so a
17
+ * site imported from it keeps every archive URL it had published.
18
+ */
19
+ export const DEFAULT_TAXONOMY_BASES = {
20
+ tag: 'tag',
21
+ category: 'category',
22
+ };
23
+ /** The word each taxonomy is called on a screen. */
24
+ export const TAXONOMY_LABELS = {
25
+ tag: 'tag',
26
+ category: 'category',
27
+ };
28
+ /**
29
+ * What a base may be made of: one path segment, starting with a letter or a
30
+ * digit, of at most 64 characters.
31
+ *
32
+ * Deliberately narrower than what a URL would carry. A base is the first
33
+ * segment of every archive URL the site publishes and the thing the router
34
+ * matches on, so it holds nothing that would need percent-encoding, nothing
35
+ * that could be read as a file extension, and no slash that would make it two
36
+ * segments.
37
+ */
38
+ export const TAXONOMY_BASE_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;
39
+ /**
40
+ * Top-level paths the site already answers on, which a base may not take over.
41
+ *
42
+ * `feed` was here before anything served it: TASK-37 put the feeds at `/feed/`,
43
+ * and a site that had taken the word would find its archives shadowed by an
44
+ * upgrade. `comments` is the site-wide comments feed's root, for the same
45
+ * reason. `taxonomy.test.ts` pins this list against the prefixes those routes
46
+ * are actually registered under, so it cannot fall behind them.
47
+ *
48
+ * `sitemap.xml` and `robots.txt` are here because they are paths the site
49
+ * answers on, which is what the list is: {@link TAXONOMY_BASE_PATTERN} would
50
+ * refuse either of them anyway for the dot, so the entries are belt and
51
+ * braces rather than the only thing standing in the way.
52
+ *
53
+ * `author` and `inbox` are reserved harder than the rest (decision-14). Every
54
+ * user is an actor at `/author/{username}/` and the shared inbox is `/inbox/`,
55
+ * and an actor id is a name a follower's server has filed the account under:
56
+ * a base that took one of those words would not shadow an archive, it would
57
+ * unmake an account. `web/authors.ts` spells them as `AUTHOR_BASE` and
58
+ * `INBOX_BASE`, and `taxonomy.test.ts` holds this list against those two
59
+ * constants, so the reservation and the URLs cannot drift apart; they are
60
+ * literals here only because that module reads {@link PAGE_SEGMENT} from this
61
+ * one, and a cycle between two files of constants is not worth the tidiness.
62
+ */
63
+ export const RESERVED_TOP_LEVEL_PATHS = [
64
+ PAGE_SEGMENT,
65
+ 'feed',
66
+ 'comments',
67
+ 'admin',
68
+ 'theme',
69
+ 'uploads',
70
+ 'nodeinfo',
71
+ 'author',
72
+ 'inbox',
73
+ 'sitemap.xml',
74
+ 'robots.txt',
75
+ 'search',
76
+ ];
77
+ /**
78
+ * The URL of a page of either taxonomy's archive, by zero-based index.
79
+ *
80
+ * This is the one place a taxonomy archive URL is spelled, so the routes, the
81
+ * pager, the canonical redirect, the theme links and the ActivityStreams
82
+ * hashtags cannot disagree about where an archive lives.
83
+ */
84
+ export function termHref(term, index, bases) {
85
+ const root = `/${bases[term.taxonomy]}/${encodeURIComponent(term.term)}/`;
86
+ return index === 0 ? root : `${root}${PAGE_SEGMENT}/${String(index + 1)}/`;
87
+ }
88
+ /** The URL of a page of a tag archive, by zero-based index. */
89
+ export function tagHref(tag, index, bases) {
90
+ return termHref({ taxonomy: 'tag', term: tag }, index, bases);
91
+ }
92
+ /** The URL of a page of a category archive, by zero-based index. */
93
+ export function categoryHref(category, index, bases) {
94
+ return termHref({ taxonomy: 'category', term: category }, index, bases);
95
+ }
96
+ /** The taxonomy a first URL segment names, or `undefined` when it names none. */
97
+ export function taxonomyForSegment(segment, bases) {
98
+ if (segment === undefined)
99
+ return undefined;
100
+ for (const taxonomy of TAXONOMIES) {
101
+ if (bases[taxonomy] === segment)
102
+ return taxonomy;
103
+ }
104
+ return undefined;
105
+ }
106
+ /**
107
+ * What is wrong with a pair of bases, one message per taxonomy.
108
+ *
109
+ * The pair is checked together rather than one at a time because two of the
110
+ * rules are about the pair: they may not be the same word, and neither may be
111
+ * a path the site already answers on.
112
+ */
113
+ export function taxonomyBaseProblems(bases) {
114
+ const problems = {};
115
+ for (const taxonomy of TAXONOMIES) {
116
+ const value = bases[taxonomy].trim();
117
+ const label = TAXONOMY_LABELS[taxonomy];
118
+ if (value === '') {
119
+ problems[taxonomy] = `The ${label} base cannot be empty.`;
120
+ }
121
+ else if (!TAXONOMY_BASE_PATTERN.test(value)) {
122
+ problems[taxonomy] =
123
+ `A ${label} base is one path segment: up to 64 letters, digits, dashes or ` +
124
+ 'underscores, starting with a letter or a digit, and no slash.';
125
+ }
126
+ else if (RESERVED_TOP_LEVEL_PATHS.includes(value.toLowerCase())) {
127
+ problems[taxonomy] =
128
+ `“${value}” is already a path this site answers on. Reserved: ` +
129
+ `${RESERVED_TOP_LEVEL_PATHS.join(', ')}.`;
130
+ }
131
+ }
132
+ if (problems.tag === undefined &&
133
+ problems.category === undefined &&
134
+ bases.tag.trim() === bases.category.trim()) {
135
+ const message = 'The tag base and the category base have to be different words.';
136
+ problems.tag = message;
137
+ problems.category = message;
138
+ }
139
+ return problems;
140
+ }
141
+ /**
142
+ * A pair of bases as they should be stored: trimmed, and each replaced by its
143
+ * default when it is not usable. Only for reading a value back out of storage
144
+ * or a data file, where a bad value should not take the site down; a value on
145
+ * its way in goes through {@link taxonomyBaseProblems} and is refused.
146
+ */
147
+ export function taxonomyBasesOrDefault(bases) {
148
+ const candidate = { ...DEFAULT_TAXONOMY_BASES };
149
+ for (const taxonomy of TAXONOMIES) {
150
+ const value = bases[taxonomy];
151
+ if (typeof value !== 'string')
152
+ continue;
153
+ const trimmed = value.trim();
154
+ if (TAXONOMY_BASE_PATTERN.test(trimmed) && !RESERVED_TOP_LEVEL_PATHS.includes(trimmed)) {
155
+ candidate[taxonomy] = trimmed;
156
+ }
157
+ }
158
+ // Two taxonomies at the same base would make one of the archives
159
+ // unreachable, so a pair that collides falls back to the defaults rather
160
+ // than serving half of what was asked for.
161
+ return candidate.tag === candidate.category ? DEFAULT_TAXONOMY_BASES : candidate;
162
+ }
163
+ /**
164
+ * The recorded renames after one more, with chains collapsed.
165
+ *
166
+ * Three rules, all of them about not making a browser walk a history it does
167
+ * not care about. Anything that pointed at `from` is repointed at `to`, so
168
+ * `a → b` followed by `b → c` is stored as `a → c` and answered in one hop. An
169
+ * older record of `from` moving somewhere else is replaced, because it is no
170
+ * longer true. And any record of `to` having moved away is dropped, because
171
+ * the term is back and an archive that answers always beats a record of where
172
+ * it used to be.
173
+ */
174
+ export function recordTermRename(existing, change) {
175
+ const recorded = [];
176
+ for (const entry of existing) {
177
+ if (entry.taxonomy !== change.taxonomy) {
178
+ recorded.push(entry);
179
+ continue;
180
+ }
181
+ if (entry.from === change.from || entry.from === change.to)
182
+ continue;
183
+ recorded.push(entry.to === change.from ? { ...entry, to: change.to } : entry);
184
+ }
185
+ recorded.push(change);
186
+ return recorded.filter((entry) => entry.from !== entry.to);
187
+ }
188
+ /**
189
+ * The recorded renames after a term is deleted.
190
+ *
191
+ * Every record pointing at it goes: the archive it named is about to 404, and
192
+ * a redirect to a 404 costs a round trip and tells the reader nothing. So does
193
+ * any record of that term having moved, which the delete has just settled.
194
+ */
195
+ export function forgetTerm(existing, taxonomy, term) {
196
+ return existing.filter((entry) => entry.taxonomy !== taxonomy || (entry.from !== term && entry.to !== term));
197
+ }
198
+ /**
199
+ * Where a term went, or `undefined` when nothing says it went anywhere.
200
+ *
201
+ * One hop, deliberately: the list is written with its chains already collapsed
202
+ * ({@link recordTermRename}), and following it further would let a hand-edited
203
+ * `site.json` send a reader round a loop.
204
+ */
205
+ export function redirectedTerm(redirects, term) {
206
+ const found = redirects.find((entry) => entry.taxonomy === term.taxonomy && entry.from === term.term);
207
+ return found?.to;
208
+ }
209
+ /**
210
+ * A value out of `site.json` or a stored setting as the renames it names.
211
+ *
212
+ * Tolerant, like everything that reads that file: an entry that is not a
213
+ * `{ taxonomy, from, to }` of three non-empty strings is dropped rather than
214
+ * failing the read, and so is one that redirects a term to itself.
215
+ */
216
+ export function taxonomyRedirectsOf(value) {
217
+ if (!Array.isArray(value))
218
+ return [];
219
+ const redirects = [];
220
+ for (const entry of value) {
221
+ if (typeof entry !== 'object' || entry === null)
222
+ continue;
223
+ const record = entry;
224
+ const taxonomy = record['taxonomy'];
225
+ const from = record['from'];
226
+ const to = record['to'];
227
+ if (!TAXONOMIES.includes(taxonomy))
228
+ continue;
229
+ if (typeof from !== 'string' || typeof to !== 'string')
230
+ continue;
231
+ if (from.trim() === '' || to.trim() === '' || from === to)
232
+ continue;
233
+ redirects.push({ taxonomy: taxonomy, from, to });
234
+ }
235
+ return redirects;
236
+ }
237
+ //# sourceMappingURL=taxonomy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"taxonomy.js","sourceRoot":"","sources":["../../src/web/taxonomy.ts"],"names":[],"mappings":"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"}
@@ -1,14 +1,16 @@
1
1
  import { Environment } from 'nunjucks';
2
- /**
3
- * The theme that ships inside the package, resolved from this module rather
4
- * than from the working directory, so it is found whether the CMS is running
5
- * from `src/` under tsx or from `dist/` as an installed dependency.
6
- */
7
- export declare const PACKAGED_THEME_DIR: string;
8
2
  /** Where a {@link createTemplateEnvironment} looks, and how it caches. */
9
3
  export interface CreateTemplateEnvironmentOptions {
10
- /** The site's own theme directory. Searched first. It need not exist. */
11
- themeDir: string;
4
+ /**
5
+ * The theme directories to read, in the order {@link themeSearchPath} gives
6
+ * them. Defaults to the packaged theme alone, which is what a site that has
7
+ * chosen no theme of its own renders through. None of them need exist.
8
+ *
9
+ * Where they came from is the caller's business, and changing them later is
10
+ * {@link useThemeDirs}: this is the environment's starting point, not a
11
+ * promise that it will read the same directories forever.
12
+ */
13
+ themeDirs?: readonly string[] | undefined;
12
14
  /** Public origin, for the `url` and `absoluteUrl` filters. */
13
15
  baseUrl: string;
14
16
  /**
@@ -17,18 +19,54 @@ export interface CreateTemplateEnvironmentOptions {
17
19
  * without a restart.
18
20
  */
19
21
  noCache?: boolean | undefined;
22
+ /**
23
+ * Whether `{{ }}` escapes for HTML. On everywhere a page is rendered, and
24
+ * off for the plain text half of an email (TASK-55): a text body and a
25
+ * subject line are not HTML, so escaping there turns an ampersand in a URL
26
+ * into `&` and an apostrophe in a name into `'`.
27
+ */
28
+ autoescape?: boolean | undefined;
20
29
  }
21
30
  /**
22
- * A Nunjucks environment whose loader searches the site theme first and the
23
- * packaged default theme second, one file at a time.
31
+ * A Nunjucks environment whose loader searches the theme directories in the
32
+ * order {@link themeSearchPath} gives them, one file at a time.
24
33
  *
25
- * That is the whole override mechanism: a site that ships only
26
- * `theme/layouts/post.njk` replaces the post layout and keeps receiving
27
- * updates to every other template.
34
+ * That is the whole override mechanism: a theme that ships only
35
+ * `layouts/post.njk` replaces the post layout and keeps receiving updates to
36
+ * every other template.
28
37
  */
29
38
  export declare function createTemplateEnvironment(options: CreateTemplateEnvironmentOptions): Environment;
39
+ /**
40
+ * Point an environment at these theme directories for the renders that follow.
41
+ *
42
+ * This is what makes a change of theme take effect without a restart. An
43
+ * environment is built once per process and holds the filters a site added to
44
+ * it, so switching theme by building a second one would either lose those
45
+ * filters or hand two objects to something that was promised one. Nunjucks
46
+ * reads `searchPaths` afresh on every miss, so moving the path and dropping
47
+ * the compiled templates is the whole of it.
48
+ *
49
+ * Directories that have not changed cost nothing: the compiled templates are
50
+ * only thrown away when the answer is actually different, so the ordinary
51
+ * request — every request on a site that never changes theme — pays one array
52
+ * comparison.
53
+ */
54
+ export declare function useThemeDirs(environment: Environment, dirs: readonly string[]): void;
30
55
  /** How `date` renders a value. */
31
- export type DateFormat = 'readable' | 'iso' | 'html' | 'year';
32
- /** `date` filter. An unparseable value renders as the empty string. */
33
- export declare function formatDate(value: unknown, format: string): string;
56
+ export type DateFormat = 'readable' | 'iso' | 'html' | 'year' | 'month';
57
+ /**
58
+ * `date` filter. An unparseable value renders as the empty string.
59
+ *
60
+ * `iso` is the instant, always in UTC, because that is what a `<time
61
+ * datetime>` and a feed want and it must not move when a setting does. The
62
+ * other four are the calendar the reader in `timezone` is on, which is what
63
+ * makes a post published at half past midnight in Berlin say 1 October rather
64
+ * than the 30 September UTC was still on.
65
+ *
66
+ * `month` is the month that calendar day falls in, "September 2026", which is
67
+ * what heads a group of an archive page (TASK-85). It is a format rather than
68
+ * something the archive works out for itself so that the month names are in
69
+ * one table and a theme can head a group of its own the same way.
70
+ */
71
+ export declare function formatDate(value: unknown, format: string, timezone?: string): string;
34
72
  //# sourceMappingURL=templates.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/web/templates.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAoB,MAAM,UAAU,CAAC;AAEzD;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAEhC,CAAC;AAEF,0EAA0E;AAC1E,MAAM,WAAW,gCAAgC;IAC/C,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,gCAAgC,GAAG,WAAW,CAahG;AAED,kCAAkC;AAClC,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AA0D9D,uEAAuE;AACvE,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAmBjE"}
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/web/templates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAoB,MAAM,UAAU,CAAC;AAKzD,0EAA0E;AAC1E,MAAM,WAAW,gCAAgC;IAC/C;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAC1C,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAClC;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,gCAAgC,GAAG,WAAW,CAahG;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAiBpF;AAED,kCAAkC;AAClC,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAsExE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,GAAE,MAAyB,GAClC,MAAM,CAqBR"}
@@ -1,44 +1,76 @@
1
- import { fileURLToPath } from 'node:url';
2
1
  import { Environment, FileSystemLoader } from 'nunjucks';
2
+ import { calendarDayIn, DEFAULT_TIMEZONE } from '../content/time.js';
3
+ import { themeSearchPath } from './themes.js';
3
4
  /**
4
- * The theme that ships inside the package, resolved from this module rather
5
- * than from the working directory, so it is found whether the CMS is running
6
- * from `src/` under tsx or from `dist/` as an installed dependency.
7
- */
8
- export const PACKAGED_THEME_DIR = fileURLToPath(new URL('../../themes/default/', import.meta.url));
9
- /**
10
- * A Nunjucks environment whose loader searches the site theme first and the
11
- * packaged default theme second, one file at a time.
5
+ * A Nunjucks environment whose loader searches the theme directories in the
6
+ * order {@link themeSearchPath} gives them, one file at a time.
12
7
  *
13
- * That is the whole override mechanism: a site that ships only
14
- * `theme/layouts/post.njk` replaces the post layout and keeps receiving
15
- * updates to every other template.
8
+ * That is the whole override mechanism: a theme that ships only
9
+ * `layouts/post.njk` replaces the post layout and keeps receiving updates to
10
+ * every other template.
16
11
  */
17
12
  export function createTemplateEnvironment(options) {
18
- const loader = new FileSystemLoader([options.themeDir, PACKAGED_THEME_DIR], {
13
+ const loader = new FileSystemLoader([...(options.themeDirs ?? themeSearchPath())], {
19
14
  noCache: options.noCache === true,
20
15
  });
21
16
  const environment = new Environment(loader, {
22
- autoescape: true,
17
+ autoescape: options.autoescape ?? true,
23
18
  throwOnUndefined: false,
24
19
  trimBlocks: true,
25
20
  lstripBlocks: true,
26
21
  });
27
22
  return addFilters(environment, options.baseUrl);
28
23
  }
24
+ /**
25
+ * Point an environment at these theme directories for the renders that follow.
26
+ *
27
+ * This is what makes a change of theme take effect without a restart. An
28
+ * environment is built once per process and holds the filters a site added to
29
+ * it, so switching theme by building a second one would either lose those
30
+ * filters or hand two objects to something that was promised one. Nunjucks
31
+ * reads `searchPaths` afresh on every miss, so moving the path and dropping
32
+ * the compiled templates is the whole of it.
33
+ *
34
+ * Directories that have not changed cost nothing: the compiled templates are
35
+ * only thrown away when the answer is actually different, so the ordinary
36
+ * request — every request on a site that never changes theme — pays one array
37
+ * comparison.
38
+ */
39
+ export function useThemeDirs(environment, dirs) {
40
+ // Through a cast because neither the loader's search paths nor the cache it
41
+ // keeps them for are in the published types, though both are documented API
42
+ // and both have been there since Nunjucks 2.
43
+ const internals = environment;
44
+ for (const loader of internals.loaders) {
45
+ const paths = loader.searchPaths;
46
+ if (paths === undefined)
47
+ continue;
48
+ if (paths.length === dirs.length && paths.every((dir, index) => dir === dirs[index]))
49
+ continue;
50
+ loader.searchPaths = [...dirs];
51
+ internals.invalidateCache();
52
+ }
53
+ }
29
54
  /**
30
55
  * The filter set, which is part of the semver contract because site templates
31
56
  * are written against it.
32
57
  *
33
- * Dates are formatted in UTC. A date in the front matter keeps its offset in
34
- * the file and in the JSON representation; what a theme prints is the same
35
- * instant expressed as UTC, which is what an Eleventy site using Luxon with
36
- * `zone: 'utc'` prints too.
58
+ * Per decision-11 a date in a file is a UTC instant and the site's `timezone`
59
+ * setting is the lens it is read through, so `readable`, `html`, `year` and
60
+ * `month` are rendered in the site's zone and `iso` stays the instant. The
61
+ * zone comes from
62
+ * the `site` global of the render in hand — Nunjucks calls a filter with the
63
+ * template context as `this`, so nothing has to be threaded through every
64
+ * template — which is what lets the setting change what every page shows
65
+ * without a file changing. An Eleventy build of the same content applies the
66
+ * same lens with Luxon and `zone` read from `site.json`.
37
67
  */
38
68
  function addFilters(environment, baseUrl) {
39
69
  const base = new URL(baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`);
40
70
  const basePath = base.pathname === '/' ? '' : base.pathname.replace(/\/$/, '');
41
- environment.addFilter('date', (value, format = 'readable') => formatDate(value, typeof format === 'string' ? format : 'readable'));
71
+ environment.addFilter('date', function (value, format = 'readable', timezone) {
72
+ return formatDate(value, typeof format === 'string' ? format : 'readable', typeof timezone === 'string' && timezone !== '' ? timezone : siteTimezone(this));
73
+ });
42
74
  // Eleventy's `url` filter: make a site-root path absolute against the base
43
75
  // path, so a site served from a subdirectory links correctly.
44
76
  const withBasePath = (value) => {
@@ -74,29 +106,78 @@ const MONTHS = [
74
106
  'November',
75
107
  'December',
76
108
  ];
77
- /** `date` filter. An unparseable value renders as the empty string. */
78
- export function formatDate(value, format) {
109
+ /**
110
+ * `date` filter. An unparseable value renders as the empty string.
111
+ *
112
+ * `iso` is the instant, always in UTC, because that is what a `<time
113
+ * datetime>` and a feed want and it must not move when a setting does. The
114
+ * other four are the calendar the reader in `timezone` is on, which is what
115
+ * makes a post published at half past midnight in Berlin say 1 October rather
116
+ * than the 30 September UTC was still on.
117
+ *
118
+ * `month` is the month that calendar day falls in, "September 2026", which is
119
+ * what heads a group of an archive page (TASK-85). It is a format rather than
120
+ * something the archive works out for itself so that the month names are in
121
+ * one table and a theme can head a group of its own the same way.
122
+ */
123
+ export function formatDate(value, format, timezone = DEFAULT_TIMEZONE) {
79
124
  const date = toDate(value);
80
125
  if (date === undefined)
81
126
  return '';
82
- const year = String(date.getUTCFullYear());
83
- const month = String(date.getUTCMonth() + 1).padStart(2, '0');
84
- const day = String(date.getUTCDate()).padStart(2, '0');
127
+ if (format === 'iso')
128
+ return date.toISOString();
129
+ const day = calendarDayIn(date, timezone);
130
+ if (day === undefined)
131
+ return '';
132
+ const [year = '', month = '', dayOfMonth = ''] = day.split('-');
85
133
  switch (format) {
86
- case 'iso':
87
- return date.toISOString();
88
134
  case 'html':
89
- return `${year}-${month}-${day}`;
135
+ return day;
90
136
  case 'year':
91
137
  return year;
138
+ case 'month':
139
+ return `${MONTHS[Number(month) - 1] ?? ''} ${year}`;
92
140
  case 'readable':
93
141
  default:
94
- return `${String(date.getUTCDate())} ${MONTHS[date.getUTCMonth()] ?? ''} ${year}`;
142
+ return `${String(Number(dayOfMonth))} ${MONTHS[Number(month) - 1] ?? ''} ${year}`;
95
143
  }
96
144
  }
145
+ /**
146
+ * The zone the render in hand is in: the `timezone` of its `site` global.
147
+ *
148
+ * Nunjucks calls a filter with the template context as `this`, so the filter
149
+ * can read a per-render value without the environment holding any state of its
150
+ * own — which matters, because one environment serves every request and a zone
151
+ * stored on it would be a race between two of them.
152
+ */
153
+ function siteTimezone(context) {
154
+ if (typeof context !== 'object' || context === null)
155
+ return DEFAULT_TIMEZONE;
156
+ const lookup = context.lookup;
157
+ if (typeof lookup !== 'function')
158
+ return DEFAULT_TIMEZONE;
159
+ const site = lookup.call(context, 'site');
160
+ if (typeof site !== 'object' || site === null)
161
+ return DEFAULT_TIMEZONE;
162
+ const timezone = site['timezone'];
163
+ return typeof timezone === 'string' && timezone !== '' ? timezone : DEFAULT_TIMEZONE;
164
+ }
165
+ /**
166
+ * A value as an instant, or `undefined` when it is not one.
167
+ *
168
+ * `'now'` is the one word the filter reads rather than parses, for the thing a
169
+ * page has that no file carries: the year in the footer's copyright line. It is
170
+ * read at render time rather than at boot so a site left running over New Year
171
+ * says the new one, and it goes through the same zone lens as every other date,
172
+ * so a site in Auckland turns the year over when Auckland does. Eleventy themes
173
+ * spell it the same way, and `docs/eleventy.config.example.js` answers to it
174
+ * too, so one footer renders identically in both builds.
175
+ */
97
176
  function toDate(value) {
98
177
  if (value instanceof Date)
99
178
  return Number.isNaN(value.getTime()) ? undefined : value;
179
+ if (value === 'now')
180
+ return new Date();
100
181
  if (typeof value === 'string' || typeof value === 'number') {
101
182
  const parsed = new Date(value);
102
183
  return Number.isNaN(parsed.getTime()) ? undefined : parsed;
@@ -1 +1 @@
1
- {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/web/templates.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/web/templates.ts"],"names":[],"mappings":"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"}