@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.
- package/README.md +2091 -214
- package/admin/components/fields.njk +165 -0
- package/admin/layouts/base.njk +1 -1
- package/admin/layouts/settings-page.njk +26 -0
- package/admin/layouts/shell.njk +17 -3
- package/admin/pages/account/forgot.njk +47 -0
- package/admin/pages/account/login.njk +26 -0
- package/admin/pages/account/reset.njk +38 -0
- package/admin/pages/account/setup.njk +28 -0
- package/admin/pages/appearance/themes.njk +69 -0
- package/admin/pages/comments/all.njk +133 -0
- package/admin/{layouts/dashboard.njk → pages/dashboard/home.njk} +8 -15
- package/admin/{layouts/document-conflict.njk → pages/documents/conflict.njk} +1 -0
- package/admin/pages/documents/editor.njk +196 -0
- package/admin/{layouts/document-list.njk → pages/documents/list.njk} +19 -2
- package/admin/pages/documents/taxonomy.njk +95 -0
- package/admin/pages/federation/followers.njk +238 -0
- package/admin/pages/media/library.njk +160 -0
- package/admin/pages/messages/all.njk +110 -0
- package/admin/{layouts → pages}/placeholder.njk +5 -1
- package/admin/pages/settings/discussion.njk +99 -0
- package/admin/pages/settings/email.njk +203 -0
- package/admin/pages/settings/federation.njk +75 -0
- package/admin/pages/settings/general.njk +29 -0
- package/admin/pages/settings/permalinks.njk +50 -0
- package/admin/pages/settings/reading.njk +72 -0
- package/admin/pages/users/edit.njk +239 -0
- package/admin/pages/users/list.njk +48 -0
- package/admin/pages/users/new.njk +41 -0
- package/admin/static/admin.css +498 -3
- package/admin/static/copy.js +52 -0
- package/admin/static/editor.js +16 -16
- package/admin/static/slug.js +61 -0
- package/dist/admin/accounts.d.ts +413 -0
- package/dist/admin/accounts.d.ts.map +1 -0
- package/dist/admin/accounts.js +680 -0
- package/dist/admin/accounts.js.map +1 -0
- package/dist/admin/appearance.d.ts +80 -0
- package/dist/admin/appearance.d.ts.map +1 -0
- package/dist/admin/appearance.js +136 -0
- package/dist/admin/appearance.js.map +1 -0
- package/dist/admin/comments.d.ts +90 -0
- package/dist/admin/comments.d.ts.map +1 -0
- package/dist/admin/comments.js +244 -0
- package/dist/admin/comments.js.map +1 -0
- package/dist/admin/credentials.d.ts +26 -2
- package/dist/admin/credentials.d.ts.map +1 -1
- package/dist/admin/credentials.js +35 -2
- package/dist/admin/credentials.js.map +1 -1
- package/dist/admin/documents.d.ts +127 -10
- package/dist/admin/documents.d.ts.map +1 -1
- package/dist/admin/documents.js +360 -41
- package/dist/admin/documents.js.map +1 -1
- package/dist/admin/federation.d.ts +151 -50
- package/dist/admin/federation.d.ts.map +1 -1
- package/dist/admin/federation.js +225 -93
- package/dist/admin/federation.js.map +1 -1
- package/dist/admin/formatting.d.ts +20 -0
- package/dist/admin/formatting.d.ts.map +1 -0
- package/dist/admin/formatting.js +72 -0
- package/dist/admin/formatting.js.map +1 -0
- package/dist/admin/headers.d.ts +65 -0
- package/dist/admin/headers.d.ts.map +1 -0
- package/dist/admin/headers.js +104 -0
- package/dist/admin/headers.js.map +1 -0
- package/dist/admin/index.d.ts +38 -12
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +25 -7
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/media.d.ts +168 -0
- package/dist/admin/media.d.ts.map +1 -0
- package/dist/admin/media.js +295 -0
- package/dist/admin/media.js.map +1 -0
- package/dist/admin/menu.d.ts +79 -0
- package/dist/admin/menu.d.ts.map +1 -0
- package/dist/admin/menu.js +126 -0
- package/dist/admin/menu.js.map +1 -0
- package/dist/admin/messages.d.ts +80 -0
- package/dist/admin/messages.d.ts.map +1 -0
- package/dist/admin/messages.js +152 -0
- package/dist/admin/messages.js.map +1 -0
- package/dist/admin/preview.d.ts.map +1 -1
- package/dist/admin/preview.js +31 -7
- package/dist/admin/preview.js.map +1 -1
- package/dist/admin/recovery.d.ts +92 -0
- package/dist/admin/recovery.d.ts.map +1 -0
- package/dist/admin/recovery.js +229 -0
- package/dist/admin/recovery.js.map +1 -0
- package/dist/admin/routes.d.ts +0 -20
- package/dist/admin/routes.d.ts.map +1 -1
- package/dist/admin/routes.js +155 -105
- package/dist/admin/routes.js.map +1 -1
- package/dist/admin/settings-discussion.d.ts +37 -0
- package/dist/admin/settings-discussion.d.ts.map +1 -0
- package/dist/admin/settings-discussion.js +117 -0
- package/dist/admin/settings-discussion.js.map +1 -0
- package/dist/admin/settings-email.d.ts +54 -0
- package/dist/admin/settings-email.d.ts.map +1 -0
- package/dist/admin/settings-email.js +189 -0
- package/dist/admin/settings-email.js.map +1 -0
- package/dist/admin/settings-federation.d.ts +39 -0
- package/dist/admin/settings-federation.d.ts.map +1 -0
- package/dist/admin/settings-federation.js +103 -0
- package/dist/admin/settings-federation.js.map +1 -0
- package/dist/admin/settings-general.d.ts +12 -0
- package/dist/admin/settings-general.d.ts.map +1 -0
- package/dist/admin/settings-general.js +48 -0
- package/dist/admin/settings-general.js.map +1 -0
- package/dist/admin/settings-page.d.ts +102 -0
- package/dist/admin/settings-page.d.ts.map +1 -0
- package/dist/admin/settings-page.js +126 -0
- package/dist/admin/settings-page.js.map +1 -0
- package/dist/admin/settings-pages.d.ts +19 -0
- package/dist/admin/settings-pages.d.ts.map +1 -0
- package/dist/admin/settings-pages.js +33 -0
- package/dist/admin/settings-pages.js.map +1 -0
- package/dist/admin/settings-permalinks.d.ts +16 -0
- package/dist/admin/settings-permalinks.d.ts.map +1 -0
- package/dist/admin/settings-permalinks.js +32 -0
- package/dist/admin/settings-permalinks.js.map +1 -0
- package/dist/admin/settings-reading.d.ts +33 -0
- package/dist/admin/settings-reading.d.ts.map +1 -0
- package/dist/admin/settings-reading.js +48 -0
- package/dist/admin/settings-reading.js.map +1 -0
- package/dist/admin/settings.d.ts +325 -96
- package/dist/admin/settings.d.ts.map +1 -1
- package/dist/admin/settings.js +650 -308
- package/dist/admin/settings.js.map +1 -1
- package/dist/admin/store.d.ts +606 -152
- package/dist/admin/store.d.ts.map +1 -1
- package/dist/admin/store.js +863 -268
- package/dist/admin/store.js.map +1 -1
- package/dist/admin/taxonomy.d.ts +114 -0
- package/dist/admin/taxonomy.d.ts.map +1 -0
- package/dist/admin/taxonomy.js +289 -0
- package/dist/admin/taxonomy.js.map +1 -0
- package/dist/admin/templates.d.ts +44 -14
- package/dist/admin/templates.d.ts.map +1 -1
- package/dist/admin/templates.js +44 -14
- package/dist/admin/templates.js.map +1 -1
- package/dist/admin/throttle.d.ts +84 -0
- package/dist/admin/throttle.d.ts.map +1 -0
- package/dist/admin/throttle.js +143 -0
- package/dist/admin/throttle.js.map +1 -0
- package/dist/admin/uploads.d.ts +28 -2
- package/dist/admin/uploads.d.ts.map +1 -1
- package/dist/admin/uploads.js +43 -4
- package/dist/admin/uploads.js.map +1 -1
- package/dist/admin/users.d.ts +100 -13
- package/dist/admin/users.d.ts.map +1 -1
- package/dist/admin/users.js +412 -39
- package/dist/admin/users.js.map +1 -1
- package/dist/cache.d.ts +141 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +207 -0
- package/dist/cache.js.map +1 -0
- package/dist/cli.d.ts +14 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +424 -21
- package/dist/cli.js.map +1 -1
- package/dist/comments/akismet.d.ts +130 -0
- package/dist/comments/akismet.d.ts.map +1 -0
- package/dist/comments/akismet.js +274 -0
- package/dist/comments/akismet.js.map +1 -0
- package/dist/comments/conversation.d.ts +29 -0
- package/dist/comments/conversation.d.ts.map +1 -0
- package/dist/comments/conversation.js +60 -0
- package/dist/comments/conversation.js.map +1 -0
- package/dist/comments/form.d.ts +75 -0
- package/dist/comments/form.d.ts.map +1 -0
- package/dist/comments/form.js +64 -0
- package/dist/comments/form.js.map +1 -0
- package/dist/comments/index.d.ts +15 -0
- package/dist/comments/index.d.ts.map +1 -0
- package/dist/comments/index.js +9 -0
- package/dist/comments/index.js.map +1 -0
- package/dist/comments/markdown.d.ts +8 -0
- package/dist/comments/markdown.d.ts.map +1 -0
- package/dist/comments/markdown.js +85 -0
- package/dist/comments/markdown.js.map +1 -0
- package/dist/comments/moderate.d.ts +71 -0
- package/dist/comments/moderate.d.ts.map +1 -0
- package/dist/comments/moderate.js +88 -0
- package/dist/comments/moderate.js.map +1 -0
- package/dist/comments/policy.d.ts +57 -0
- package/dist/comments/policy.d.ts.map +1 -0
- package/dist/comments/policy.js +80 -0
- package/dist/comments/policy.js.map +1 -0
- package/dist/comments/records.d.ts +266 -0
- package/dist/comments/records.d.ts.map +1 -0
- package/dist/comments/records.js +487 -0
- package/dist/comments/records.js.map +1 -0
- package/dist/comments/routes.d.ts +58 -0
- package/dist/comments/routes.d.ts.map +1 -0
- package/dist/comments/routes.js +177 -0
- package/dist/comments/routes.js.map +1 -0
- package/dist/comments/submission.d.ts +263 -0
- package/dist/comments/submission.d.ts.map +1 -0
- package/dist/comments/submission.js +241 -0
- package/dist/comments/submission.js.map +1 -0
- package/dist/config.d.ts +190 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +118 -6
- package/dist/config.js.map +1 -1
- package/dist/contact/delivery.d.ts +60 -0
- package/dist/contact/delivery.d.ts.map +1 -0
- package/dist/contact/delivery.js +87 -0
- package/dist/contact/delivery.js.map +1 -0
- package/dist/contact/form.d.ts +130 -0
- package/dist/contact/form.d.ts.map +1 -0
- package/dist/contact/form.js +163 -0
- package/dist/contact/form.js.map +1 -0
- package/dist/contact/index.d.ts +17 -0
- package/dist/contact/index.d.ts.map +1 -0
- package/dist/contact/index.js +13 -0
- package/dist/contact/index.js.map +1 -0
- package/dist/contact/records.d.ts +124 -0
- package/dist/contact/records.d.ts.map +1 -0
- package/dist/contact/records.js +218 -0
- package/dist/contact/records.js.map +1 -0
- package/dist/contact/routes.d.ts +17 -0
- package/dist/contact/routes.d.ts.map +1 -0
- package/dist/contact/routes.js +127 -0
- package/dist/contact/routes.js.map +1 -0
- package/dist/contact/submission.d.ts +103 -0
- package/dist/contact/submission.d.ts.map +1 -0
- package/dist/contact/submission.js +166 -0
- package/dist/contact/submission.js.map +1 -0
- package/dist/content/document.d.ts +7 -2
- package/dist/content/document.d.ts.map +1 -1
- package/dist/content/document.js +1 -0
- package/dist/content/document.js.map +1 -1
- package/dist/content/index.d.ts +7 -2
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +4 -1
- package/dist/content/index.js.map +1 -1
- package/dist/content/markdown.d.ts.map +1 -1
- package/dist/content/markdown.js +24 -2
- package/dist/content/markdown.js.map +1 -1
- package/dist/content/parser.d.ts.map +1 -1
- package/dist/content/parser.js +11 -4
- package/dist/content/parser.js.map +1 -1
- package/dist/content/save.d.ts +5 -0
- package/dist/content/save.d.ts.map +1 -1
- package/dist/content/save.js +44 -1
- package/dist/content/save.js.map +1 -1
- package/dist/content/schedule.d.ts +125 -0
- package/dist/content/schedule.d.ts.map +1 -0
- package/dist/content/schedule.js +207 -0
- package/dist/content/schedule.js.map +1 -0
- package/dist/content/search.d.ts +64 -0
- package/dist/content/search.d.ts.map +1 -0
- package/dist/content/search.js +136 -0
- package/dist/content/search.js.map +1 -0
- package/dist/content/store.d.ts +202 -7
- package/dist/content/store.d.ts.map +1 -1
- package/dist/content/store.js +374 -67
- package/dist/content/store.js.map +1 -1
- package/dist/content/sync.d.ts +7 -1
- package/dist/content/sync.d.ts.map +1 -1
- package/dist/content/sync.js +18 -10
- package/dist/content/sync.js.map +1 -1
- package/dist/content/time.d.ts +56 -0
- package/dist/content/time.d.ts.map +1 -0
- package/dist/content/time.js +141 -0
- package/dist/content/time.js.map +1 -0
- package/dist/content/writer.d.ts.map +1 -1
- package/dist/content/writer.js +3 -0
- package/dist/content/writer.js.map +1 -1
- package/dist/env.d.ts +58 -4
- package/dist/env.d.ts.map +1 -1
- package/dist/federation/actor.d.ts +95 -41
- package/dist/federation/actor.d.ts.map +1 -1
- package/dist/federation/actor.js +180 -53
- package/dist/federation/actor.js.map +1 -1
- package/dist/federation/article.d.ts +44 -17
- package/dist/federation/article.d.ts.map +1 -1
- package/dist/federation/article.js +98 -46
- package/dist/federation/article.js.map +1 -1
- package/dist/federation/delivery.d.ts +63 -15
- package/dist/federation/delivery.d.ts.map +1 -1
- package/dist/federation/delivery.js +154 -80
- package/dist/federation/delivery.js.map +1 -1
- package/dist/federation/federation.d.ts +22 -17
- package/dist/federation/federation.d.ts.map +1 -1
- package/dist/federation/federation.js +98 -77
- package/dist/federation/federation.js.map +1 -1
- package/dist/federation/followers.d.ts +3 -2
- package/dist/federation/followers.d.ts.map +1 -1
- package/dist/federation/followers.js +6 -5
- package/dist/federation/followers.js.map +1 -1
- package/dist/federation/import-wordpress.d.ts +128 -0
- package/dist/federation/import-wordpress.d.ts.map +1 -0
- package/dist/federation/import-wordpress.js +426 -0
- package/dist/federation/import-wordpress.js.map +1 -0
- package/dist/federation/inbox.d.ts +36 -13
- package/dist/federation/inbox.d.ts.map +1 -1
- package/dist/federation/inbox.js +120 -49
- package/dist/federation/inbox.js.map +1 -1
- package/dist/federation/index.d.ts +22 -10
- package/dist/federation/index.d.ts.map +1 -1
- package/dist/federation/index.js +13 -8
- package/dist/federation/index.js.map +1 -1
- package/dist/federation/keys.d.ts +98 -20
- package/dist/federation/keys.d.ts.map +1 -1
- package/dist/federation/keys.js +269 -39
- package/dist/federation/keys.js.map +1 -1
- package/dist/federation/mount.d.ts +42 -10
- package/dist/federation/mount.d.ts.map +1 -1
- package/dist/federation/mount.js +266 -26
- package/dist/federation/mount.js.map +1 -1
- package/dist/federation/paths.d.ts +23 -35
- package/dist/federation/paths.d.ts.map +1 -1
- package/dist/federation/paths.js +26 -39
- package/dist/federation/paths.js.map +1 -1
- package/dist/federation/records.d.ts +223 -0
- package/dist/federation/records.d.ts.map +1 -0
- package/dist/federation/records.js +506 -0
- package/dist/federation/records.js.map +1 -0
- package/dist/federation/relays.d.ts +114 -0
- package/dist/federation/relays.d.ts.map +1 -0
- package/dist/federation/relays.js +290 -0
- package/dist/federation/relays.js.map +1 -0
- package/dist/federation/replies.d.ts +80 -0
- package/dist/federation/replies.d.ts.map +1 -0
- package/dist/federation/replies.js +166 -0
- package/dist/federation/replies.js.map +1 -0
- package/dist/federation/wordpress.d.ts +131 -0
- package/dist/federation/wordpress.d.ts.map +1 -0
- package/dist/federation/wordpress.js +341 -0
- package/dist/federation/wordpress.js.map +1 -0
- package/dist/files/atomic.d.ts +103 -0
- package/dist/files/atomic.d.ts.map +1 -0
- package/dist/files/atomic.js +150 -0
- package/dist/files/atomic.js.map +1 -0
- package/dist/files/index.d.ts +3 -0
- package/dist/files/index.d.ts.map +1 -0
- package/dist/files/index.js +2 -0
- package/dist/files/index.js.map +1 -0
- package/dist/forms/protection.d.ts +85 -0
- package/dist/forms/protection.d.ts.map +1 -0
- package/dist/forms/protection.js +116 -0
- package/dist/forms/protection.js.map +1 -0
- package/dist/images/icons.d.ts +59 -0
- package/dist/images/icons.d.ts.map +1 -0
- package/dist/images/icons.js +131 -0
- package/dist/images/icons.js.map +1 -0
- package/dist/images/index.d.ts +7 -0
- package/dist/images/index.d.ts.map +1 -0
- package/dist/images/index.js +4 -0
- package/dist/images/index.js.map +1 -0
- package/dist/images/markup.d.ts +47 -0
- package/dist/images/markup.d.ts.map +1 -0
- package/dist/images/markup.js +175 -0
- package/dist/images/markup.js.map +1 -0
- package/dist/images/paths.d.ts +34 -0
- package/dist/images/paths.d.ts.map +1 -0
- package/dist/images/paths.js +41 -0
- package/dist/images/paths.js.map +1 -0
- package/dist/images/variants.d.ts +104 -0
- package/dist/images/variants.d.ts.map +1 -0
- package/dist/images/variants.js +320 -0
- package/dist/images/variants.js.map +1 -0
- package/dist/index.d.ts +123 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +327 -25
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +18 -0
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +34 -3
- package/dist/init.js.map +1 -1
- package/dist/mail/brevo.d.ts +35 -0
- package/dist/mail/brevo.d.ts.map +1 -0
- package/dist/mail/brevo.js +85 -0
- package/dist/mail/brevo.js.map +1 -0
- package/dist/mail/credentials.d.ts +62 -0
- package/dist/mail/credentials.d.ts.map +1 -0
- package/dist/mail/credentials.js +86 -0
- package/dist/mail/credentials.js.map +1 -0
- package/dist/mail/index.d.ts +15 -0
- package/dist/mail/index.d.ts.map +1 -0
- package/dist/mail/index.js +8 -0
- package/dist/mail/index.js.map +1 -0
- package/dist/mail/memory.d.ts +35 -0
- package/dist/mail/memory.d.ts.map +1 -0
- package/dist/mail/memory.js +29 -0
- package/dist/mail/memory.js.map +1 -0
- package/dist/mail/provider.d.ts +80 -0
- package/dist/mail/provider.d.ts.map +1 -0
- package/dist/mail/provider.js +23 -0
- package/dist/mail/provider.js.map +1 -0
- package/dist/mail/service.d.ts +156 -0
- package/dist/mail/service.d.ts.map +1 -0
- package/dist/mail/service.js +265 -0
- package/dist/mail/service.js.map +1 -0
- package/dist/mail/smtp.d.ts +39 -0
- package/dist/mail/smtp.d.ts.map +1 -0
- package/dist/mail/smtp.js +58 -0
- package/dist/mail/smtp.js.map +1 -0
- package/dist/mail/templates.d.ts +91 -0
- package/dist/mail/templates.d.ts.map +1 -0
- package/dist/mail/templates.js +69 -0
- package/dist/mail/templates.js.map +1 -0
- package/dist/notifications/comments.d.ts +66 -0
- package/dist/notifications/comments.d.ts.map +1 -0
- package/dist/notifications/comments.js +151 -0
- package/dist/notifications/comments.js.map +1 -0
- package/dist/notifications/digest.d.ts +135 -0
- package/dist/notifications/digest.d.ts.map +1 -0
- package/dist/notifications/digest.js +287 -0
- package/dist/notifications/digest.js.map +1 -0
- package/dist/notifications/index.d.ts +13 -0
- package/dist/notifications/index.d.ts.map +1 -0
- package/dist/notifications/index.js +8 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/notifications/links.d.ts +60 -0
- package/dist/notifications/links.d.ts.map +1 -0
- package/dist/notifications/links.js +63 -0
- package/dist/notifications/links.js.map +1 -0
- package/dist/notifications/optouts.d.ts +48 -0
- package/dist/notifications/optouts.d.ts.map +1 -0
- package/dist/notifications/optouts.js +93 -0
- package/dist/notifications/optouts.js.map +1 -0
- package/dist/notifications/preferences.d.ts +158 -0
- package/dist/notifications/preferences.d.ts.map +1 -0
- package/dist/notifications/preferences.js +195 -0
- package/dist/notifications/preferences.js.map +1 -0
- package/dist/notifications/routes.d.ts +28 -0
- package/dist/notifications/routes.d.ts.map +1 -0
- package/dist/notifications/routes.js +184 -0
- package/dist/notifications/routes.js.map +1 -0
- package/dist/notifications/tokens.d.ts +60 -0
- package/dist/notifications/tokens.d.ts.map +1 -0
- package/dist/notifications/tokens.js +125 -0
- package/dist/notifications/tokens.js.map +1 -0
- package/dist/notify.d.ts +84 -0
- package/dist/notify.d.ts.map +1 -0
- package/dist/notify.js +149 -0
- package/dist/notify.js.map +1 -0
- package/dist/web/archive.d.ts +49 -0
- package/dist/web/archive.d.ts.map +1 -0
- package/dist/web/archive.js +59 -0
- package/dist/web/archive.js.map +1 -0
- package/dist/web/assets.d.ts +6 -5
- package/dist/web/assets.d.ts.map +1 -1
- package/dist/web/assets.js +5 -7
- package/dist/web/assets.js.map +1 -1
- package/dist/web/authors.d.ts +143 -0
- package/dist/web/authors.d.ts.map +1 -0
- package/dist/web/authors.js +178 -0
- package/dist/web/authors.js.map +1 -0
- package/dist/web/comments.d.ts +60 -0
- package/dist/web/comments.d.ts.map +1 -0
- package/dist/web/comments.js +207 -0
- package/dist/web/comments.js.map +1 -0
- package/dist/web/context.d.ts +162 -28
- package/dist/web/context.d.ts.map +1 -1
- package/dist/web/context.js +123 -26
- package/dist/web/context.js.map +1 -1
- package/dist/web/conversation.d.ts +209 -0
- package/dist/web/conversation.d.ts.map +1 -0
- package/dist/web/conversation.js +557 -0
- package/dist/web/conversation.js.map +1 -0
- package/dist/web/documents.d.ts +36 -6
- package/dist/web/documents.d.ts.map +1 -1
- package/dist/web/documents.js +52 -10
- package/dist/web/documents.js.map +1 -1
- package/dist/web/feed-atom.d.ts +22 -0
- package/dist/web/feed-atom.d.ts.map +1 -0
- package/dist/web/feed-atom.js +83 -0
- package/dist/web/feed-atom.js.map +1 -0
- package/dist/web/feed-item.d.ts +145 -0
- package/dist/web/feed-item.d.ts.map +1 -0
- package/dist/web/feed-item.js +120 -0
- package/dist/web/feed-item.js.map +1 -0
- package/dist/web/feed-json.d.ts +79 -0
- package/dist/web/feed-json.d.ts.map +1 -0
- package/dist/web/feed-json.js +53 -0
- package/dist/web/feed-json.js.map +1 -0
- package/dist/web/feed-rss.d.ts +26 -0
- package/dist/web/feed-rss.d.ts.map +1 -0
- package/dist/web/feed-rss.js +203 -0
- package/dist/web/feed-rss.js.map +1 -0
- package/dist/web/feed-source.d.ts +244 -0
- package/dist/web/feed-source.d.ts.map +1 -0
- package/dist/web/feed-source.js +201 -0
- package/dist/web/feed-source.js.map +1 -0
- package/dist/web/feed-xml.d.ts +63 -0
- package/dist/web/feed-xml.d.ts.map +1 -0
- package/dist/web/feed-xml.js +116 -0
- package/dist/web/feed-xml.js.map +1 -0
- package/dist/web/feeds.d.ts +31 -96
- package/dist/web/feeds.d.ts.map +1 -1
- package/dist/web/feeds.js +94 -198
- package/dist/web/feeds.js.map +1 -1
- package/dist/web/health.d.ts +31 -0
- package/dist/web/health.d.ts.map +1 -0
- package/dist/web/health.js +44 -0
- package/dist/web/health.js.map +1 -0
- package/dist/web/index.d.ts +30 -10
- package/dist/web/index.d.ts.map +1 -1
- package/dist/web/index.js +18 -7
- package/dist/web/index.js.map +1 -1
- package/dist/web/navigation.d.ts +73 -0
- package/dist/web/navigation.d.ts.map +1 -0
- package/dist/web/navigation.js +110 -0
- package/dist/web/navigation.js.map +1 -0
- package/dist/web/negotiate.d.ts +9 -0
- package/dist/web/negotiate.d.ts.map +1 -1
- package/dist/web/negotiate.js +6 -1
- package/dist/web/negotiate.js.map +1 -1
- package/dist/web/recent.d.ts +43 -0
- package/dist/web/recent.d.ts.map +1 -0
- package/dist/web/recent.js +37 -0
- package/dist/web/recent.js.map +1 -0
- package/dist/web/render.d.ts +197 -9
- package/dist/web/render.d.ts.map +1 -1
- package/dist/web/render.js +334 -17
- package/dist/web/render.js.map +1 -1
- package/dist/web/routes.d.ts +25 -8
- package/dist/web/routes.d.ts.map +1 -1
- package/dist/web/routes.js +845 -93
- package/dist/web/routes.js.map +1 -1
- package/dist/web/sanitize.d.ts +19 -0
- package/dist/web/sanitize.d.ts.map +1 -0
- package/dist/web/sanitize.js +272 -0
- package/dist/web/sanitize.js.map +1 -0
- package/dist/web/search.d.ts +79 -0
- package/dist/web/search.d.ts.map +1 -0
- package/dist/web/search.js +94 -0
- package/dist/web/search.js.map +1 -0
- package/dist/web/sitemap.d.ts +120 -0
- package/dist/web/sitemap.d.ts.map +1 -0
- package/dist/web/sitemap.js +199 -0
- package/dist/web/sitemap.js.map +1 -0
- package/dist/web/taxonomy.d.ts +152 -0
- package/dist/web/taxonomy.d.ts.map +1 -0
- package/dist/web/taxonomy.js +237 -0
- package/dist/web/taxonomy.js.map +1 -0
- package/dist/web/templates.d.ts +54 -16
- package/dist/web/templates.d.ts.map +1 -1
- package/dist/web/templates.js +109 -28
- package/dist/web/templates.js.map +1 -1
- package/dist/web/themes.d.ts +205 -0
- package/dist/web/themes.d.ts.map +1 -0
- package/dist/web/themes.js +277 -0
- package/dist/web/themes.js.map +1 -0
- package/dist/webmention/discovery.d.ts +51 -0
- package/dist/webmention/discovery.d.ts.map +1 -0
- package/dist/webmention/discovery.js +176 -0
- package/dist/webmention/discovery.js.map +1 -0
- package/dist/webmention/html.d.ts +71 -0
- package/dist/webmention/html.d.ts.map +1 -0
- package/dist/webmention/html.js +285 -0
- package/dist/webmention/html.js.map +1 -0
- package/dist/webmention/index.d.ts +12 -0
- package/dist/webmention/index.d.ts.map +1 -0
- package/dist/webmention/index.js +8 -0
- package/dist/webmention/index.js.map +1 -0
- package/dist/webmention/links.d.ts +18 -0
- package/dist/webmention/links.d.ts.map +1 -0
- package/dist/webmention/links.js +64 -0
- package/dist/webmention/links.js.map +1 -0
- package/dist/webmention/microformats.d.ts +93 -0
- package/dist/webmention/microformats.d.ts.map +1 -0
- package/dist/webmention/microformats.js +376 -0
- package/dist/webmention/microformats.js.map +1 -0
- package/dist/webmention/receive.d.ts +141 -0
- package/dist/webmention/receive.d.ts.map +1 -0
- package/dist/webmention/receive.js +264 -0
- package/dist/webmention/receive.js.map +1 -0
- package/dist/webmention/routes.d.ts +37 -0
- package/dist/webmention/routes.d.ts.map +1 -0
- package/dist/webmention/routes.js +75 -0
- package/dist/webmention/routes.js.map +1 -0
- package/dist/webmention/service.d.ts +94 -0
- package/dist/webmention/service.d.ts.map +1 -0
- package/dist/webmention/service.js +207 -0
- package/dist/webmention/service.js.map +1 -0
- package/package.json +11 -6
- package/templates/site/content/_data/site.json +1 -0
- package/templates/site/content/posts/2026-01-01-hello-world.md +5 -3
- package/templates/site/geekity.config.ts +11 -1
- package/templates/site/tsconfig.json +1 -1
- package/themes/default/README.md +1096 -50
- package/themes/default/layouts/404.njk +2 -3
- package/themes/default/layouts/author.njk +37 -0
- package/themes/default/layouts/base.njk +172 -31
- package/themes/default/layouts/category.njk +27 -0
- package/themes/default/layouts/front-page.njk +57 -0
- package/themes/default/layouts/home.njk +17 -1
- package/themes/default/layouts/page.njk +57 -5
- package/themes/default/layouts/post.njk +78 -19
- package/themes/default/layouts/search.njk +57 -0
- package/themes/default/layouts/tag.njk +3 -6
- package/themes/default/mail/comment-digest.html.njk +37 -0
- package/themes/default/mail/comment-digest.subject.njk +3 -0
- package/themes/default/mail/comment-digest.txt.njk +40 -0
- package/themes/default/mail/comment-pending.html.njk +27 -0
- package/themes/default/mail/comment-pending.subject.njk +2 -0
- package/themes/default/mail/comment-pending.txt.njk +24 -0
- package/themes/default/mail/comment-reply.html.njk +21 -0
- package/themes/default/mail/comment-reply.subject.njk +2 -0
- package/themes/default/mail/comment-reply.txt.njk +22 -0
- package/themes/default/mail/contact-message.html.njk +24 -0
- package/themes/default/mail/contact-message.subject.njk +5 -0
- package/themes/default/mail/contact-message.txt.njk +20 -0
- package/themes/default/mail/password-changed.html.njk +18 -0
- package/themes/default/mail/password-changed.subject.njk +2 -0
- package/themes/default/mail/password-changed.txt.njk +17 -0
- package/themes/default/mail/password-reset.html.njk +22 -0
- package/themes/default/mail/password-reset.subject.njk +2 -0
- package/themes/default/mail/password-reset.txt.njk +18 -0
- package/themes/default/mail/test.html.njk +14 -0
- package/themes/default/mail/test.subject.njk +2 -0
- package/themes/default/mail/test.txt.njk +12 -0
- package/themes/default/partials/archive.njk +27 -0
- package/themes/default/partials/bio.njk +77 -0
- package/themes/default/partials/comment-form.njk +109 -0
- package/themes/default/partials/contact-form.njk +88 -0
- package/themes/default/partials/conversation.njk +139 -0
- package/themes/default/partials/feeds.njk +26 -0
- package/themes/default/partials/jsonld.njk +120 -0
- package/themes/default/partials/pagination.njk +12 -6
- package/themes/default/partials/post-list.njk +51 -18
- package/themes/default/partials/search-form.njk +17 -0
- package/themes/default/partials/tags.njk +26 -5
- package/themes/default/static/highlight.js +4 -0
- package/themes/default/static/style.css +1119 -194
- package/themes/default/theme.json +5 -0
- package/admin/layouts/document-editor.njk +0 -167
- package/admin/layouts/federation.njk +0 -145
- package/admin/layouts/login.njk +0 -23
- package/admin/layouts/settings.njk +0 -116
- package/admin/layouts/setup.njk +0 -27
- package/admin/layouts/users.njk +0 -91
- /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":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AA8CvD,uEAAuE;AACvE,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAChD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAA4B;IACrD,OAAO,CAAC,WAAW,EAAE,WAAW,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC,CAAC;IACxF,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE;QACxB,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,SAAS,CAAC,QAAQ,EAAE;QAC7D,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,CAAC,SAAS,CAAC,EAAE;QACjE,wEAAwE;QACxE,uDAAuD;QACvD,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,aAAa,CAAC,QAAQ,EAAE;QACzE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,CAAC,QAAQ,EAAE;KACzD,CAAC;IACF,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE;QACxB,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,SAAS,CAAC,QAAQ,EAAE;QAC7D,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,CAAC,SAAS,CAAC,EAAE;KAClE,CAAC;IACF,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;IACpF,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC;IAC9F,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,CAAC;IAC9F,2EAA2E;IAC3E,4EAA4E;IAC5E,kEAAkE;IAClE,OAAO,CAAC,YAAY,EAAE,YAAY,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC,CAAC;IAC7F,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE;QACxB,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,UAAU,EAAE;QACrD,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE;KACvD,CAAC;IACF,wEAAwE;IACxE,4EAA4E;IAC5E,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE;QAC9B,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,gBAAgB,CAAC,SAAS,CAAC,EAAE;QACxE,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,gBAAgB,CAAC,SAAS,CAAC,EAAE;QACxE,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,gBAAgB,CAAC,YAAY,CAAC,EAAE;QACjF,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,gBAAgB,CAAC,YAAY,CAAC,EAAE;QACjF,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,gBAAgB,CAAC,OAAO,CAAC,EAAE;QAClE,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,gBAAgB,CAAC,YAAY,CAAC,EAAE;KAClF,CAAC;IACF,OAAO,CAAC,YAAY,EAAE,YAAY,EAAE;QAClC,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,EAAE,eAAe,EAAE;KACjE,CAAC;CACH,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,UAAU,SAAS,CAAC,QAAQ,GAAwB,EAAE;IAC1D,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC;IAE1C,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC;QACrE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,IAAI,uBAAuB,CAAC,wCAAwC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7F,CAAC;QACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,IAAI,uBAAuB,CAC/B,kBAAkB,MAAM,CAAC,IAAI,CAAC,gEAAgE,CAC/F,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,uBAAuB,CAC/B,oBAAoB,MAAM,CAAC,IAAI,CAAC,gCAAgC,MAAM,CAAC,KAAK,CAAC,GAAG,CACjF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,cAAc,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACpC,GAAG,KAAK;QACR,IAAI,EAAE,KAAK,CAAC,OAAO,KAAK,IAAI;QAC5B,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACtC,GAAG,IAAI;YACP,OAAO,EAAE,KAAK,CAAC,OAAO,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK;SACxD,CAAC,CAAC;KACJ,CAAC,CAAC,CAAC;AACN,CAAC;AAED,yDAAyD;AACzD,SAAS,OAAO,CAAC,IAAY,EAAE,KAAa,EAAE,QAA0B;IACtE,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC;IACzB,wEAAwE;IACxE,4EAA4E;IAC5E,IAAI,KAAK,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,OAAO,KAAK,iCAAiC,CAAC,CAAC;IACxF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC;AAC5D,CAAC;AAED,uCAAuC;AACvC,SAAS,MAAM,CAAC,KAAa;IAC3B,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -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"}
|