@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 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/notifications/tokens.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,uDAAuD;AACvD,eAAO,MAAM,wBAAwB,wBAAwB,CAAC;AAE9D,mEAAmE;AACnE,MAAM,WAAW,iBAAiB;IAChC,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,0EAA0E;AAC1E,MAAM,WAAW,oBAAqB,SAAQ,iBAAiB;IAC7D,yCAAyC;IACzC,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,0EAA0E;AAC1E,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,oBAAoB,EAC3B,GAAG,GAAE,IAAiB,GACrB,MAAM,CAOR;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,GAAG,GAAE,IAAiB,GACrB,iBAAiB,GAAG,SAAS,CAwB/B;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAc1F"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { createHmac, randomBytes, timingSafeEqual } from 'node:crypto';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { readFileIfPresentSync, writeFileAtomicallySync } from '../files/atomic.js';
|
|
4
|
+
/**
|
|
5
|
+
* The thing that makes a link in an email work without a login.
|
|
6
|
+
*
|
|
7
|
+
* A notification is only worth sending if acting on it is one click. That
|
|
8
|
+
* means the link itself has to carry the authority, and the two ways of doing
|
|
9
|
+
* that are a random string written down somewhere and a signed claim that
|
|
10
|
+
* needs nothing written down. This is the second, for one reason: a link lives
|
|
11
|
+
* in an inbox for a week, and `data/geekity.db` is a cache that a site may
|
|
12
|
+
* legitimately delete, rebuild or restore from a backup at any moment
|
|
13
|
+
* (decision-9). A stack of rows would take every link in flight with it.
|
|
14
|
+
*
|
|
15
|
+
* So the token says what it is for — approve *this* comment, unsubscribe
|
|
16
|
+
* *this* address — and carries an HMAC over exactly that, taken with a secret
|
|
17
|
+
* in `data/notification-secret`. Nothing but the secret is needed to check
|
|
18
|
+
* one, the claim cannot be edited without breaking the signature, and a token
|
|
19
|
+
* signed by one site means nothing to another.
|
|
20
|
+
*
|
|
21
|
+
* What is *not* in the token is the right to be used twice. That is a row in
|
|
22
|
+
* the cache (`spent_tokens`), and it is deliberately the half that a lost
|
|
23
|
+
* database forgets: forgetting that a link was spent re-enables an action that
|
|
24
|
+
* has already happened and is idempotent — approving an approved comment, or
|
|
25
|
+
* deleting one that is gone — whereas forgetting the secret would break every
|
|
26
|
+
* link a site had sent.
|
|
27
|
+
*/
|
|
28
|
+
/** Where the signing secret lives, under `dataDir`. */
|
|
29
|
+
export const NOTIFICATION_SECRET_FILE = 'notification-secret';
|
|
30
|
+
/** Mint a signed link token. It is the whole of what the link carries. */
|
|
31
|
+
export function signNotificationToken(dataDir, claim, now = new Date()) {
|
|
32
|
+
const expiresAt = Math.floor(now.getTime() / 1000) + claim.lifetimeSeconds;
|
|
33
|
+
const payload = Buffer.from(JSON.stringify({ a: claim.action, s: claim.subject, x: expiresAt })).toString('base64url');
|
|
34
|
+
return `${payload}.${sign(dataDir, payload)}`;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* What a token entitles its holder to, or `undefined` when it entitles them to
|
|
38
|
+
* nothing: not a token at all, edited, signed by somebody else, or expired.
|
|
39
|
+
*
|
|
40
|
+
* The signature is checked before the payload is believed, so nothing here
|
|
41
|
+
* ever acts on bytes a stranger chose.
|
|
42
|
+
*/
|
|
43
|
+
export function readNotificationToken(dataDir, token, now = new Date()) {
|
|
44
|
+
const [payload, signature] = token.split('.');
|
|
45
|
+
if (payload === undefined || signature === undefined || payload === '')
|
|
46
|
+
return undefined;
|
|
47
|
+
if (!matches(sign(dataDir, payload), signature))
|
|
48
|
+
return undefined;
|
|
49
|
+
let parsed;
|
|
50
|
+
try {
|
|
51
|
+
parsed = JSON.parse(Buffer.from(payload, 'base64url').toString('utf8'));
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))
|
|
57
|
+
return undefined;
|
|
58
|
+
const claim = parsed;
|
|
59
|
+
const action = claim['a'];
|
|
60
|
+
const subject = claim['s'];
|
|
61
|
+
const expiresAt = claim['x'];
|
|
62
|
+
if (typeof action !== 'string' || action === '')
|
|
63
|
+
return undefined;
|
|
64
|
+
if (typeof subject !== 'string' || subject === '')
|
|
65
|
+
return undefined;
|
|
66
|
+
if (typeof expiresAt !== 'number' || !Number.isFinite(expiresAt))
|
|
67
|
+
return undefined;
|
|
68
|
+
if (expiresAt * 1000 <= now.getTime())
|
|
69
|
+
return undefined;
|
|
70
|
+
return { action, subject };
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* When a token stops working, as an ISO 8601 instant, or `undefined` when it
|
|
74
|
+
* never worked.
|
|
75
|
+
*
|
|
76
|
+
* What the spent-token row is pruned by: a ledger of links that can never be
|
|
77
|
+
* used again is a ledger that can be thrown away.
|
|
78
|
+
*/
|
|
79
|
+
export function notificationTokenExpiry(dataDir, token) {
|
|
80
|
+
const [payload, signature] = token.split('.');
|
|
81
|
+
if (payload === undefined || signature === undefined)
|
|
82
|
+
return undefined;
|
|
83
|
+
if (!matches(sign(dataDir, payload), signature))
|
|
84
|
+
return undefined;
|
|
85
|
+
try {
|
|
86
|
+
const parsed = JSON.parse(Buffer.from(payload, 'base64url').toString('utf8'));
|
|
87
|
+
if (typeof parsed !== 'object' || parsed === null)
|
|
88
|
+
return undefined;
|
|
89
|
+
const seconds = parsed['x'];
|
|
90
|
+
if (typeof seconds !== 'number' || !Number.isFinite(seconds))
|
|
91
|
+
return undefined;
|
|
92
|
+
return new Date(seconds * 1000).toISOString();
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/** The HMAC over one payload, base64url so the whole token is URL safe. */
|
|
99
|
+
function sign(dataDir, payload) {
|
|
100
|
+
return createHmac('sha256', notificationSecret(dataDir)).update(payload).digest('base64url');
|
|
101
|
+
}
|
|
102
|
+
/** Whether two signatures are the same, without saying how far they agreed. */
|
|
103
|
+
function matches(expected, given) {
|
|
104
|
+
const left = Buffer.from(expected);
|
|
105
|
+
const right = Buffer.from(given);
|
|
106
|
+
return left.length === right.length && timingSafeEqual(left, right);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The site's signing secret, minted on first use.
|
|
110
|
+
*
|
|
111
|
+
* Beside `comment-salt` in `data/`, at the same permissions and for the same
|
|
112
|
+
* reason: `content/` is published with the site and goes into git, and a
|
|
113
|
+
* secret there would be a secret in a public repository. Losing it invalidates
|
|
114
|
+
* every link a site has sent and costs nothing else.
|
|
115
|
+
*/
|
|
116
|
+
function notificationSecret(dataDir) {
|
|
117
|
+
const file = path.join(dataDir, NOTIFICATION_SECRET_FILE);
|
|
118
|
+
const held = readFileIfPresentSync(file)?.trim();
|
|
119
|
+
if (held !== undefined && held !== '')
|
|
120
|
+
return held;
|
|
121
|
+
const minted = randomBytes(32).toString('hex');
|
|
122
|
+
writeFileAtomicallySync(file, `${minted}\n`, { mode: 0o600 });
|
|
123
|
+
return minted;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/notifications/tokens.ts"],"names":[],"mappings":"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"}
|
package/dist/notify.d.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { ResolvedConfig } from './config.ts';
|
|
2
|
+
import type { DocumentChange } from './content/sync.ts';
|
|
3
|
+
/**
|
|
4
|
+
* How long one ping is given before it is abandoned.
|
|
5
|
+
*
|
|
6
|
+
* A notify server refetches the feed before it fans anything out, so a slow
|
|
7
|
+
* answer is normal and a hung one must not hold the queue behind it.
|
|
8
|
+
*/
|
|
9
|
+
export declare const NOTIFY_TIMEOUT_MS = 10000;
|
|
10
|
+
/** What one ping came to. */
|
|
11
|
+
export interface NotifyPing {
|
|
12
|
+
/** The feed the server was told about. */
|
|
13
|
+
readonly url: string;
|
|
14
|
+
/** Whether the server accepted it. */
|
|
15
|
+
readonly ok: boolean;
|
|
16
|
+
/** Why it did not, when it did not. */
|
|
17
|
+
readonly error?: string;
|
|
18
|
+
}
|
|
19
|
+
/** What a round of pings came to, one entry per feed. */
|
|
20
|
+
export interface NotifyReport {
|
|
21
|
+
/** Where the pings went, or `undefined` when the site names no server. */
|
|
22
|
+
readonly server?: string;
|
|
23
|
+
/** One entry per distinct feed, in the order they were sent. */
|
|
24
|
+
readonly pings: readonly NotifyPing[];
|
|
25
|
+
}
|
|
26
|
+
/** Where a notifier reports what it could not do. `console` will do. */
|
|
27
|
+
export interface NotifyLogger {
|
|
28
|
+
warn(message: string): void;
|
|
29
|
+
}
|
|
30
|
+
/** What {@link createFeedNotifier} needs. */
|
|
31
|
+
export interface CreateFeedNotifierOptions {
|
|
32
|
+
/**
|
|
33
|
+
* Config after defaults and environment overrides: the base URL, the clock a
|
|
34
|
+
* scheduled post is held against, and the content directory the settings —
|
|
35
|
+
* the notify server and the two archive bases — are read from.
|
|
36
|
+
*/
|
|
37
|
+
config: Pick<ResolvedConfig, 'baseUrl' | 'contentDir' | 'now'>;
|
|
38
|
+
/** Where failures are reported. Defaults to `console`. */
|
|
39
|
+
logger?: NotifyLogger | undefined;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Tells the site's notify server which feeds have changed.
|
|
43
|
+
*
|
|
44
|
+
* The server notifies nobody until it hears from the publisher, so a feed that
|
|
45
|
+
* advertises a cloud and never pings it is a feed whose subscribers still
|
|
46
|
+
* poll. This is the other half of the advertisement.
|
|
47
|
+
*
|
|
48
|
+
* Pings run one after another on a queue of their own and never throw: a
|
|
49
|
+
* publish is not held up by a notification about it, and a server that is down
|
|
50
|
+
* costs a line in the log rather than a save.
|
|
51
|
+
*/
|
|
52
|
+
export interface FeedNotifier {
|
|
53
|
+
/**
|
|
54
|
+
* Tell the server about these feeds, in order and without repeating one.
|
|
55
|
+
* Absolute URLs, because it is going to fetch them.
|
|
56
|
+
*/
|
|
57
|
+
notify(urls: readonly string[]): Promise<NotifyReport>;
|
|
58
|
+
/**
|
|
59
|
+
* Consider one index change and ping whatever feeds it moved.
|
|
60
|
+
*
|
|
61
|
+
* It returns as soon as the pings are queued rather than when they are
|
|
62
|
+
* answered — the save is already done, and a notification about it is not
|
|
63
|
+
* something the editor's redirect should wait for. Use
|
|
64
|
+
* {@link FeedNotifier.settled} to wait for them.
|
|
65
|
+
*/
|
|
66
|
+
handle(change: DocumentChange): void;
|
|
67
|
+
/**
|
|
68
|
+
* Which feeds a change moved: the site's three, and the three of every term
|
|
69
|
+
* the post carried before or after it. Absolute, deduplicated, and empty
|
|
70
|
+
* when the change moved no feed at all.
|
|
71
|
+
*/
|
|
72
|
+
feedsFor(change: DocumentChange): string[];
|
|
73
|
+
/** Resolve once every queued ping has finished, however it finished. */
|
|
74
|
+
settled(): Promise<void>;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Build the feed notifier for one site.
|
|
78
|
+
*
|
|
79
|
+
* The settings are read per ping rather than at boot, so moving the server on
|
|
80
|
+
* the settings screen takes effect on the next publish rather than on the next
|
|
81
|
+
* restart — the same way the feeds pick up the new address.
|
|
82
|
+
*/
|
|
83
|
+
export declare function createFeedNotifier(options: CreateFeedNotifierOptions): FeedNotifier;
|
|
84
|
+
//# sourceMappingURL=notify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../src/notify.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AASxD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,QAAS,CAAC;AAExC,6BAA6B;AAC7B,MAAM,WAAW,UAAU;IACzB,0CAA0C;IAC1C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,uCAAuC;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,yDAAyD;AACzD,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;CACvC;AAED,wEAAwE;AACxE,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,6CAA6C;AAC7C,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,GAAG,YAAY,GAAG,KAAK,CAAC,CAAC;IAC/D,0DAA0D;IAC1D,MAAM,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;CACnC;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACvD;;;;;;;OAOG;IACH,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,EAAE,CAAC;IAC3C,wEAAwE;IACxE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,YAAY,CAkGnF"}
|
package/dist/notify.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { readSiteSettings, taxonomyBasesFromSettings } from './admin/settings.js';
|
|
2
|
+
import { isFederatedDocument } from './federation/article.js';
|
|
3
|
+
import { FEED_FORMATS, notifyEndpoints } from './web/feeds.js';
|
|
4
|
+
import { absoluteUrl } from './web/negotiate.js';
|
|
5
|
+
import { feedHref } from './web/routes.js';
|
|
6
|
+
import { TAXONOMIES } from './web/taxonomy.js';
|
|
7
|
+
/**
|
|
8
|
+
* How long one ping is given before it is abandoned.
|
|
9
|
+
*
|
|
10
|
+
* A notify server refetches the feed before it fans anything out, so a slow
|
|
11
|
+
* answer is normal and a hung one must not hold the queue behind it.
|
|
12
|
+
*/
|
|
13
|
+
export const NOTIFY_TIMEOUT_MS = 10_000;
|
|
14
|
+
/**
|
|
15
|
+
* Build the feed notifier for one site.
|
|
16
|
+
*
|
|
17
|
+
* The settings are read per ping rather than at boot, so moving the server on
|
|
18
|
+
* the settings screen takes effect on the next publish rather than on the next
|
|
19
|
+
* restart — the same way the feeds pick up the new address.
|
|
20
|
+
*/
|
|
21
|
+
export function createFeedNotifier(options) {
|
|
22
|
+
const { config } = options;
|
|
23
|
+
const logger = options.logger ?? console;
|
|
24
|
+
// Pings are chained rather than sent at once, and the chain never rejects:
|
|
25
|
+
// one server that hangs delays the next ping and nothing else.
|
|
26
|
+
let chain = Promise.resolve();
|
|
27
|
+
function enqueue(task) {
|
|
28
|
+
const result = chain.then(task);
|
|
29
|
+
chain = result.then(ignore, ignore);
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
/** The server the settings name, or `undefined` when they name none. */
|
|
33
|
+
function server() {
|
|
34
|
+
return notifyEndpoints(readSiteSettings(config.contentDir).notifyServer);
|
|
35
|
+
}
|
|
36
|
+
/** Tell one server about one feed, answering with what happened. */
|
|
37
|
+
async function ping(endpoint, url) {
|
|
38
|
+
try {
|
|
39
|
+
const response = await fetch(endpoint.ping, {
|
|
40
|
+
method: 'POST',
|
|
41
|
+
headers: {
|
|
42
|
+
'content-type': 'application/x-www-form-urlencoded',
|
|
43
|
+
accept: 'application/json',
|
|
44
|
+
},
|
|
45
|
+
body: new URLSearchParams({ url }).toString(),
|
|
46
|
+
signal: AbortSignal.timeout(NOTIFY_TIMEOUT_MS),
|
|
47
|
+
});
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
return { url, ok: false, error: `${endpoint.ping} answered ${String(response.status)}` };
|
|
50
|
+
}
|
|
51
|
+
return { url, ok: true };
|
|
52
|
+
}
|
|
53
|
+
catch (thrown) {
|
|
54
|
+
return { url, ok: false, error: messageOf(thrown) };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
async notify(urls) {
|
|
59
|
+
const endpoint = server();
|
|
60
|
+
const wanted = [...new Set(urls)];
|
|
61
|
+
if (endpoint === undefined || wanted.length === 0)
|
|
62
|
+
return { pings: [] };
|
|
63
|
+
return await enqueue(async () => {
|
|
64
|
+
const sent = [];
|
|
65
|
+
for (const url of wanted) {
|
|
66
|
+
const result = await ping(endpoint, url);
|
|
67
|
+
if (!result.ok) {
|
|
68
|
+
logger.warn(`Could not ping ${endpoint.ping} about ${url}: ${result.error ?? ''}`);
|
|
69
|
+
}
|
|
70
|
+
sent.push(result);
|
|
71
|
+
}
|
|
72
|
+
return { server: endpoint.base, pings: sent };
|
|
73
|
+
});
|
|
74
|
+
},
|
|
75
|
+
feedsFor(change) {
|
|
76
|
+
// A full scan is a rebuild of the index, not news about the site: the
|
|
77
|
+
// boot scan reports a cold index as a directory full of creations, and
|
|
78
|
+
// pinging for each would announce the whole archive every time somebody
|
|
79
|
+
// deleted the database.
|
|
80
|
+
if (change.origin === 'scan')
|
|
81
|
+
return [];
|
|
82
|
+
const now = config.now();
|
|
83
|
+
const before = inFeeds(change.previous, now);
|
|
84
|
+
const after = inFeeds(change.next, now);
|
|
85
|
+
if (before === undefined && after === undefined)
|
|
86
|
+
return [];
|
|
87
|
+
const bases = taxonomyBasesFromSettings(readSiteSettings(config.contentDir));
|
|
88
|
+
const urls = new Set();
|
|
89
|
+
for (const format of FEED_FORMATS) {
|
|
90
|
+
urls.add(absoluteUrl(feedHref(undefined, format, bases), config.baseUrl));
|
|
91
|
+
}
|
|
92
|
+
// Both versions, because a post that left a tag changed that tag's feed
|
|
93
|
+
// exactly as much as the one it joined.
|
|
94
|
+
for (const term of termsOf(before, after)) {
|
|
95
|
+
for (const format of FEED_FORMATS) {
|
|
96
|
+
urls.add(absoluteUrl(feedHref(term, format, bases), config.baseUrl));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return [...urls];
|
|
100
|
+
},
|
|
101
|
+
handle(change) {
|
|
102
|
+
const urls = this.feedsFor(change);
|
|
103
|
+
if (urls.length > 0)
|
|
104
|
+
void this.notify(urls);
|
|
105
|
+
},
|
|
106
|
+
async settled() {
|
|
107
|
+
await chain;
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* The document if it appears in a feed, and `undefined` otherwise.
|
|
113
|
+
*
|
|
114
|
+
* The same predicate delivery uses, because it is the same question: a
|
|
115
|
+
* published post is what goes to the followers and what goes in the feeds, and
|
|
116
|
+
* a draft or a page is in neither.
|
|
117
|
+
*/
|
|
118
|
+
function inFeeds(document, now) {
|
|
119
|
+
if (document === undefined)
|
|
120
|
+
return undefined;
|
|
121
|
+
return isFederatedDocument(document, now) ? document : undefined;
|
|
122
|
+
}
|
|
123
|
+
/** Every taxonomy term either version of a post carried, without repeats. */
|
|
124
|
+
function termsOf(before, after) {
|
|
125
|
+
const terms = [];
|
|
126
|
+
const seen = new Set();
|
|
127
|
+
for (const document of [before, after]) {
|
|
128
|
+
if (document === undefined)
|
|
129
|
+
continue;
|
|
130
|
+
for (const taxonomy of TAXONOMIES) {
|
|
131
|
+
for (const term of taxonomy === 'tag' ? document.tags : document.categories) {
|
|
132
|
+
const key = `${taxonomy}:${term}`;
|
|
133
|
+
if (seen.has(key))
|
|
134
|
+
continue;
|
|
135
|
+
seen.add(key);
|
|
136
|
+
terms.push({ taxonomy, term });
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return terms;
|
|
141
|
+
}
|
|
142
|
+
/** What a thrown value has to say for itself. */
|
|
143
|
+
function messageOf(thrown) {
|
|
144
|
+
return thrown instanceof Error ? thrown.message : String(thrown);
|
|
145
|
+
}
|
|
146
|
+
function ignore() {
|
|
147
|
+
// A failed ping is already logged; the chain carries on regardless.
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=notify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../src/notify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Document } from '../content/document.ts';
|
|
2
|
+
/**
|
|
3
|
+
* The archive page: every post the site has published, grouped by the month it
|
|
4
|
+
* was published in, as the source design's essays page lists them
|
|
5
|
+
* (decision-16).
|
|
6
|
+
|
|
7
|
+
* A page opts in with `archive: true` in its front matter — one key, ignored
|
|
8
|
+
* by Eleventy, the same shape as the `contact: true` beside it — and the
|
|
9
|
+
* layout prints `partials/archive.njk` under the page's words.
|
|
10
|
+
*
|
|
11
|
+
* The grouping is here rather than in the template because a month is a
|
|
12
|
+
* calendar question: a date in a file is a UTC instant and the site's timezone
|
|
13
|
+
* is the lens it is read through (decision-11), so what month a post belongs
|
|
14
|
+
* to is the same decision as what day the entry under it says, and Nunjucks is
|
|
15
|
+
* the wrong place to make it twice.
|
|
16
|
+
*/
|
|
17
|
+
/** The front matter key a page opts in with. */
|
|
18
|
+
export declare const ARCHIVE_FRONT_MATTER_KEY = "archive";
|
|
19
|
+
/** Whether this document lists the archive under its words. */
|
|
20
|
+
export declare function archiveOpen(document: Document): boolean;
|
|
21
|
+
/** One post of an archive page, which is a link and the date beside it. */
|
|
22
|
+
export interface ArchiveEntry {
|
|
23
|
+
/** The post's title, which is what the link says. */
|
|
24
|
+
title: string;
|
|
25
|
+
/** Its URL path. */
|
|
26
|
+
url: string;
|
|
27
|
+
/** When it was published, for a theme that dates the line. */
|
|
28
|
+
date: Date;
|
|
29
|
+
}
|
|
30
|
+
/** One month of an archive page: the heading, and what was published under it. */
|
|
31
|
+
export interface ArchiveMonth {
|
|
32
|
+
/** The month as a reader sees it, "September 2026". */
|
|
33
|
+
month: string;
|
|
34
|
+
/** The posts published in it, newest first. */
|
|
35
|
+
posts: ArchiveEntry[];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Published posts as the months an archive page heads, newest month first.
|
|
39
|
+
*
|
|
40
|
+
* The posts arrive in the order every listing is in — newest first — and are
|
|
41
|
+
* kept in it, so the months come out newest first without a second sort and
|
|
42
|
+
* each month reads down from its last post to its first.
|
|
43
|
+
*
|
|
44
|
+
* A post with no date is left out rather than collected under a heading of its
|
|
45
|
+
* own: an archive is a calendar, and a post that is on no day of it is not a
|
|
46
|
+
* month a reader could be shown.
|
|
47
|
+
*/
|
|
48
|
+
export declare function archiveMonths(posts: readonly Document[], timezone?: string): ArchiveMonth[];
|
|
49
|
+
//# sourceMappingURL=archive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../src/web/archive.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGvD;;;;;;;;;;;;;;GAcG;AAEH,gDAAgD;AAChD,eAAO,MAAM,wBAAwB,YAAY,CAAC;AAElD,+DAA+D;AAC/D,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAEvD;AAED,2EAA2E;AAC3E,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,oBAAoB;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,8DAA8D;IAC9D,IAAI,EAAE,IAAI,CAAC;CACZ;AAED,kFAAkF;AAClF,MAAM,WAAW,YAAY;IAC3B,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,SAAS,QAAQ,EAAE,EAC1B,QAAQ,GAAE,MAAyB,GAClC,YAAY,EAAE,CAyBhB"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { calendarDayIn, DEFAULT_TIMEZONE } from '../content/time.js';
|
|
2
|
+
import { formatDate } from './templates.js';
|
|
3
|
+
/**
|
|
4
|
+
* The archive page: every post the site has published, grouped by the month it
|
|
5
|
+
* was published in, as the source design's essays page lists them
|
|
6
|
+
* (decision-16).
|
|
7
|
+
|
|
8
|
+
* A page opts in with `archive: true` in its front matter — one key, ignored
|
|
9
|
+
* by Eleventy, the same shape as the `contact: true` beside it — and the
|
|
10
|
+
* layout prints `partials/archive.njk` under the page's words.
|
|
11
|
+
*
|
|
12
|
+
* The grouping is here rather than in the template because a month is a
|
|
13
|
+
* calendar question: a date in a file is a UTC instant and the site's timezone
|
|
14
|
+
* is the lens it is read through (decision-11), so what month a post belongs
|
|
15
|
+
* to is the same decision as what day the entry under it says, and Nunjucks is
|
|
16
|
+
* the wrong place to make it twice.
|
|
17
|
+
*/
|
|
18
|
+
/** The front matter key a page opts in with. */
|
|
19
|
+
export const ARCHIVE_FRONT_MATTER_KEY = 'archive';
|
|
20
|
+
/** Whether this document lists the archive under its words. */
|
|
21
|
+
export function archiveOpen(document) {
|
|
22
|
+
return document.extra[ARCHIVE_FRONT_MATTER_KEY] === true;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Published posts as the months an archive page heads, newest month first.
|
|
26
|
+
*
|
|
27
|
+
* The posts arrive in the order every listing is in — newest first — and are
|
|
28
|
+
* kept in it, so the months come out newest first without a second sort and
|
|
29
|
+
* each month reads down from its last post to its first.
|
|
30
|
+
*
|
|
31
|
+
* A post with no date is left out rather than collected under a heading of its
|
|
32
|
+
* own: an archive is a calendar, and a post that is on no day of it is not a
|
|
33
|
+
* month a reader could be shown.
|
|
34
|
+
*/
|
|
35
|
+
export function archiveMonths(posts, timezone = DEFAULT_TIMEZONE) {
|
|
36
|
+
const months = [];
|
|
37
|
+
let current;
|
|
38
|
+
for (const document of posts) {
|
|
39
|
+
if (document.date === undefined)
|
|
40
|
+
continue;
|
|
41
|
+
const date = new Date(document.date);
|
|
42
|
+
if (Number.isNaN(date.getTime()))
|
|
43
|
+
continue;
|
|
44
|
+
// The calendar day in the site's zone, of which the first seven characters
|
|
45
|
+
// are the month it is in: one lens for the grouping and for the heading,
|
|
46
|
+
// so a post can never be filed under one month and dated in another.
|
|
47
|
+
const day = calendarDayIn(date, timezone);
|
|
48
|
+
if (day === undefined)
|
|
49
|
+
continue;
|
|
50
|
+
const key = day.slice(0, 7);
|
|
51
|
+
if (key !== current) {
|
|
52
|
+
current = key;
|
|
53
|
+
months.push({ month: formatDate(date, 'month', timezone), posts: [] });
|
|
54
|
+
}
|
|
55
|
+
months.at(-1)?.posts.push({ title: document.title, url: document.permalink, date });
|
|
56
|
+
}
|
|
57
|
+
return months;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=archive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/web/archive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAErE,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C;;;;;;;;;;;;;;GAcG;AAEH,gDAAgD;AAChD,MAAM,CAAC,MAAM,wBAAwB,GAAG,SAAS,CAAC;AAElD,+DAA+D;AAC/D,MAAM,UAAU,WAAW,CAAC,QAAkB;IAC5C,OAAO,QAAQ,CAAC,KAAK,CAAC,wBAAwB,CAAC,KAAK,IAAI,CAAC;AAC3D,CAAC;AAoBD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,aAAa,CAC3B,KAA0B,EAC1B,QAAQ,GAAW,gBAAgB;IAEnC,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,IAAI,OAA2B,CAAC;IAEhC,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS;YAAE,SAAS;QAC1C,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAAE,SAAS;QAE3C,2EAA2E;QAC3E,yEAAyE;QACzE,qEAAqE;QACrE,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC1C,IAAI,GAAG,KAAK,SAAS;YAAE,SAAS;QAEhC,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5B,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YACpB,OAAO,GAAG,GAAG,CAAC;YACd,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QACzE,CAAC;QAED,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtF,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/web/assets.d.ts
CHANGED
|
@@ -41,12 +41,13 @@ export type ThemeAsset = StaticAsset;
|
|
|
41
41
|
*/
|
|
42
42
|
export declare function findAsset(relative: string, roots: string[]): StaticAsset | undefined;
|
|
43
43
|
/**
|
|
44
|
-
* Find one asset
|
|
45
|
-
* templates resolve in.
|
|
44
|
+
* Find one asset under the `static/` directory of each theme on a search path,
|
|
45
|
+
* the same order templates resolve in.
|
|
46
|
+
*
|
|
47
|
+
* The path comes from `themeSearchPath`, so an asset and a layout are always
|
|
48
|
+
* read from the same themes.
|
|
46
49
|
*/
|
|
47
|
-
export declare function findThemeAsset(relative: string, themeDirs: string[]): ThemeAsset | undefined;
|
|
48
|
-
/** The theme directories to search, in order: the site's, then the package's. */
|
|
49
|
-
export declare function themeSearchPath(siteThemeDir: string): string[];
|
|
50
|
+
export declare function findThemeAsset(relative: string, themeDirs: readonly string[]): ThemeAsset | undefined;
|
|
50
51
|
/** How long a browser may keep an asset, when the caller does not say. */
|
|
51
52
|
export interface AssetResponseOptions {
|
|
52
53
|
/** Seconds. Defaults to {@link THEME_ASSET_MAX_AGE}. */
|
package/dist/web/assets.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/web/assets.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/web/assets.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAIrC,yDAAyD;AACzD,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAE5C;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,cAAc,CAAC;AAE/C,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,YAAY,CAAC;AAE1C,qFAAqF;AACrF,eAAO,MAAM,oBAAoB,QAAQ,CAAC;AAE1C,yDAAyD;AACzD,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAExF;AAED,sEAAsE;AACtE,eAAO,MAAM,gBAAgB,WAAW,CAAC;AAEzC,2DAA2D;AAC3D,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAExC,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC1B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,KAAK,EAAE,KAAK,CAAC;IACb,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,0EAA0E;AAC1E,MAAM,MAAM,UAAU,GAAG,WAAW,CAAC;AAErC;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,WAAW,GAAG,SAAS,CA6BpF;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,SAAS,MAAM,EAAE,GAC3B,UAAU,GAAG,SAAS,CAKxB;AAED,0EAA0E;AAC1E,MAAM,WAAW,oBAAoB;IACnC,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,kDAAkD;AAClD,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,GAAE,oBAAyB,GAAG,QAAQ,CAG9F;AAED,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,GAAE,oBAAyB,GAAG,QAAQ,CAKjG;AAED,2DAA2D;AAC3D,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,QAAQ,CAE9D;AAED,8DAA8D;AAC9D,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,UAAU,GAAG,QAAQ,CAEjE;AAED,6DAA6D;AAC7D,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAOlF"}
|
package/dist/web/assets.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { createReadStream, statSync } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { Readable } from 'node:stream';
|
|
4
|
-
import { PACKAGED_THEME_DIR } from './templates.js';
|
|
5
4
|
/** URL prefix the theme's own files are served under. */
|
|
6
5
|
export const THEME_ASSET_PREFIX = '/theme/';
|
|
7
6
|
/**
|
|
@@ -61,16 +60,15 @@ export function findAsset(relative, roots) {
|
|
|
61
60
|
return undefined;
|
|
62
61
|
}
|
|
63
62
|
/**
|
|
64
|
-
* Find one asset
|
|
65
|
-
* templates resolve in.
|
|
63
|
+
* Find one asset under the `static/` directory of each theme on a search path,
|
|
64
|
+
* the same order templates resolve in.
|
|
65
|
+
*
|
|
66
|
+
* The path comes from `themeSearchPath`, so an asset and a layout are always
|
|
67
|
+
* read from the same themes.
|
|
66
68
|
*/
|
|
67
69
|
export function findThemeAsset(relative, themeDirs) {
|
|
68
70
|
return findAsset(relative, themeDirs.map((themeDir) => path.join(themeDir, THEME_STATIC_DIR)));
|
|
69
71
|
}
|
|
70
|
-
/** The theme directories to search, in order: the site's, then the package's. */
|
|
71
|
-
export function themeSearchPath(siteThemeDir) {
|
|
72
|
-
return [siteThemeDir, PACKAGED_THEME_DIR];
|
|
73
|
-
}
|
|
74
72
|
/** The response body and headers for an asset. */
|
|
75
73
|
export function assetResponse(asset, options = {}) {
|
|
76
74
|
const body = Readable.toWeb(createReadStream(asset.file));
|
package/dist/web/assets.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assets.js","sourceRoot":"","sources":["../../src/web/assets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAErD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,
|
|
1
|
+
{"version":3,"file":"assets.js","sourceRoot":"","sources":["../../src/web/assets.ts"],"names":[],"mappings":"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"}
|