@geekity/cms 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2217 -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/{layouts/document-editor.njk → pages/documents/editor.njk} +75 -59
- 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/federation/settings.njk +77 -0
- package/admin/pages/media/library.njk +160 -0
- package/admin/pages/messages/all.njk +110 -0
- package/admin/pages/navigation/menus.njk +129 -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/general.njk +29 -0
- package/admin/pages/settings/permalinks.njk +50 -0
- package/admin/pages/settings/reading.njk +64 -0
- package/admin/pages/tools/content-index.njk +89 -0
- package/admin/pages/users/edit.njk +239 -0
- package/admin/pages/users/list.njk +51 -0
- package/admin/pages/users/new.njk +41 -0
- package/admin/static/admin.css +558 -3
- package/admin/static/copy.js +52 -0
- package/admin/static/editor.js +16 -16
- package/admin/static/slug.js +61 -0
- package/dist/access-log.d.ts +44 -0
- package/dist/access-log.d.ts.map +1 -0
- package/dist/access-log.js +71 -0
- package/dist/access-log.js.map +1 -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 +117 -10
- package/dist/admin/documents.d.ts.map +1 -1
- package/dist/admin/documents.js +328 -41
- package/dist/admin/documents.js.map +1 -1
- package/dist/admin/federation.d.ts +161 -50
- package/dist/admin/federation.d.ts.map +1 -1
- package/dist/admin/federation.js +235 -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 +143 -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/navigation.d.ts +155 -0
- package/dist/admin/navigation.d.ts.map +1 -0
- package/dist/admin/navigation.js +292 -0
- package/dist/admin/navigation.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 +164 -105
- package/dist/admin/routes.js.map +1 -1
- package/dist/admin/session.d.ts +17 -3
- package/dist/admin/session.d.ts.map +1 -1
- package/dist/admin/session.js +19 -5
- package/dist/admin/session.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 +48 -0
- package/dist/admin/settings-federation.d.ts.map +1 -0
- package/dist/admin/settings-federation.js +123 -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 +119 -0
- package/dist/admin/settings-page.d.ts.map +1 -0
- package/dist/admin/settings-page.js +132 -0
- package/dist/admin/settings-page.js.map +1 -0
- package/dist/admin/settings-pages.d.ts +30 -0
- package/dist/admin/settings-pages.d.ts.map +1 -0
- package/dist/admin/settings-pages.js +43 -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 +34 -0
- package/dist/admin/settings-reading.d.ts.map +1 -0
- package/dist/admin/settings-reading.js +49 -0
- package/dist/admin/settings-reading.js.map +1 -0
- package/dist/admin/settings.d.ts +339 -96
- package/dist/admin/settings.d.ts.map +1 -1
- package/dist/admin/settings.js +600 -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 +46 -14
- package/dist/admin/templates.d.ts.map +1 -1
- package/dist/admin/templates.js +46 -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/tools.d.ts +111 -0
- package/dist/admin/tools.d.ts.map +1 -0
- package/dist/admin/tools.js +182 -0
- package/dist/admin/tools.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 +429 -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 +123 -0
- package/dist/comments/form.d.ts.map +1 -0
- package/dist/comments/form.js +79 -0
- package/dist/comments/form.js.map +1 -0
- package/dist/comments/index.d.ts +16 -0
- package/dist/comments/index.d.ts.map +1 -0
- package/dist/comments/index.js +10 -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 +60 -0
- package/dist/comments/routes.d.ts.map +1 -0
- package/dist/comments/routes.js +212 -0
- package/dist/comments/routes.js.map +1 -0
- package/dist/comments/submission.d.ts +297 -0
- package/dist/comments/submission.d.ts.map +1 -0
- package/dist/comments/submission.js +280 -0
- package/dist/comments/submission.js.map +1 -0
- package/dist/comments/viewer.d.ts +21 -0
- package/dist/comments/viewer.d.ts.map +1 -0
- package/dist/comments/viewer.js +45 -0
- package/dist/comments/viewer.js.map +1 -0
- package/dist/config.d.ts +225 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +121 -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 +220 -7
- package/dist/content/store.d.ts.map +1 -1
- package/dist/content/store.js +392 -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 +70 -5
- 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 +46 -10
- package/dist/federation/mount.d.ts.map +1 -1
- package/dist/federation/mount.js +300 -28
- 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 +344 -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 +195 -0
- package/dist/web/navigation.d.ts.map +1 -0
- package/dist/web/navigation.js +300 -0
- package/dist/web/navigation.js.map +1 -0
- package/dist/web/negotiate.d.ts +31 -0
- package/dist/web/negotiate.d.ts.map +1 -1
- package/dist/web/negotiate.js +31 -11
- 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 +203 -9
- package/dist/web/render.d.ts.map +1 -1
- package/dist/web/render.js +341 -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 +854 -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 +226 -0
- package/dist/web/themes.d.ts.map +1 -0
- package/dist/web/themes.js +314 -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 +8 -0
- package/templates/site/content/pages/about.md +7 -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 +1216 -50
- package/themes/default/layouts/404.njk +2 -3
- package/themes/default/layouts/author.njk +36 -0
- package/themes/default/layouts/base.njk +161 -31
- package/themes/default/layouts/category.njk +27 -0
- package/themes/default/layouts/front-page.njk +56 -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 +71 -0
- package/themes/default/partials/comment-form.njk +137 -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/menu.njk +32 -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 +22 -0
- package/themes/default/partials/tags.njk +26 -5
- package/themes/default/static/highlight.js +4 -0
- package/themes/default/static/style.css +1142 -194
- package/themes/default/theme.json +9 -0
- 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
package/dist/web/documents.js
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
|
+
import { isScheduled } from '../content/schedule.js';
|
|
1
2
|
import { isTrashedPath } from '../content/store.js';
|
|
2
|
-
import {
|
|
3
|
+
import { absoluteUrl } from './negotiate.js';
|
|
3
4
|
/**
|
|
4
5
|
* Whether the public site may show a document.
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
-
* `_trash
|
|
8
|
-
* served, listed, or fed.
|
|
7
|
+
* Three things hide one: `draft: true` in the front matter, living under
|
|
8
|
+
* `_trash/`, and a date that has not arrived yet. All three stay indexed so
|
|
9
|
+
* the admin can find them; none is ever served, listed, or fed.
|
|
10
|
+
*
|
|
11
|
+
* This is the predicate the index answers in SQL, so anything that has to
|
|
12
|
+
* decide about a single document in hand — a permalink, a View link, the
|
|
13
|
+
* sitemap — asks it here rather than deriving the rule again. The clock
|
|
14
|
+
* defaults to the system one; a caller with a store should pass
|
|
15
|
+
* {@link ContentStore.now} so the answer matches the listings it came from.
|
|
9
16
|
*/
|
|
10
|
-
export function isPublicDocument(document) {
|
|
11
|
-
return !document.draft && !isTrashedPath(document.path);
|
|
17
|
+
export function isPublicDocument(document, now = new Date()) {
|
|
18
|
+
return !document.draft && !isTrashedPath(document.path) && !isScheduled(document, now);
|
|
12
19
|
}
|
|
13
20
|
/**
|
|
14
21
|
* The document a public URL resolves to, or `undefined`.
|
|
@@ -19,21 +26,56 @@ export function isPublicDocument(document) {
|
|
|
19
26
|
*/
|
|
20
27
|
export function publicDocumentAt(store, permalink) {
|
|
21
28
|
const document = store.getByPermalink(permalink);
|
|
22
|
-
if (document === undefined || !isPublicDocument(document))
|
|
29
|
+
if (document === undefined || !isPublicDocument(document, store.now()))
|
|
23
30
|
return undefined;
|
|
24
31
|
return document;
|
|
25
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* A post's ActivityStreams object id: its permalink, absolute on the site's
|
|
35
|
+
* base URL, or the id its file already names.
|
|
36
|
+
*
|
|
37
|
+
* decision-13. A permalink is by name permanent, and the fediverse id is the
|
|
38
|
+
* same promise made to a different audience, so one URL answers both: a
|
|
39
|
+
* browser gets the page and a peer gets the `Article`, by content negotiation.
|
|
40
|
+
* There is no second URL to mint and none to keep in step.
|
|
41
|
+
*
|
|
42
|
+
* A stored `activitypub.id` wins, for the life of the post. That is not a
|
|
43
|
+
* cache: it is what lets a post migrated from WordPress keep the
|
|
44
|
+
* `https://example.com/?p=813` id its followers, its replies and its RSS
|
|
45
|
+
* subscribers already hold (decision-14), so the CMS serves the object there
|
|
46
|
+
* too and names it in every `Update` and `Delete`. A hand-written
|
|
47
|
+
* `activitypub.id` that is not a URL is not an id, and the permalink is used
|
|
48
|
+
* instead.
|
|
49
|
+
*
|
|
50
|
+
* Unlike {@link activityStreamsId} this answers for any post, published or
|
|
51
|
+
* not: a draft that was announced before it was withdrawn still has the name
|
|
52
|
+
* its followers filed it under, and a `Delete` has to say it.
|
|
53
|
+
*/
|
|
54
|
+
export function postObjectId(document, baseUrl) {
|
|
55
|
+
const stored = document.activitypub?.id;
|
|
56
|
+
if (stored !== undefined && stored !== '') {
|
|
57
|
+
try {
|
|
58
|
+
return new URL(stored).href;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
// Not a URL, so not an id. Fall through to the permalink.
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return absoluteUrl(document.permalink, baseUrl);
|
|
65
|
+
}
|
|
26
66
|
/**
|
|
27
67
|
* The ActivityStreams id of a document, or `undefined` when it has none.
|
|
28
68
|
*
|
|
29
69
|
* Only a published post federates (doc-4), so only a published post has an id
|
|
30
70
|
* to advertise. This is what the theme's `<link rel="alternate">` points at,
|
|
31
|
-
*
|
|
32
|
-
*
|
|
71
|
+
* what every feed keys the post by (decision-12) and what the permalink
|
|
72
|
+
* answers an ActivityStreams request with: the page, the feed item and the
|
|
73
|
+
* object all agree about the post's name in the fediverse, because after
|
|
74
|
+
* decision-13 they are the same URL.
|
|
33
75
|
*/
|
|
34
76
|
export function activityStreamsId(document, baseUrl) {
|
|
35
77
|
if (document.type !== 'post' || !isPublicDocument(document))
|
|
36
78
|
return undefined;
|
|
37
|
-
return postObjectId(document
|
|
79
|
+
return postObjectId(document, baseUrl);
|
|
38
80
|
}
|
|
39
81
|
//# sourceMappingURL=documents.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documents.js","sourceRoot":"","sources":["../../src/web/documents.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"documents.js","sourceRoot":"","sources":["../../src/web/documents.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAkB,EAAE,GAAG,GAAS,IAAI,IAAI,EAAE;IACzE,OAAO,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;AACzF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAmB,EAAE,SAAiB;IACrE,MAAM,QAAQ,GAAG,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IACjD,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC;QAAE,OAAO,SAAS,CAAC;IACzF,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,YAAY,CAAC,QAAkB,EAAE,OAAe;IAC9D,MAAM,MAAM,GAAG,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;IACxC,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;QAC1C,IAAI,CAAC;YACH,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,0DAA0D;QAC5D,CAAC;IACH,CAAC;IACD,OAAO,WAAW,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAkB,EAAE,OAAe;IACnE,IAAI,QAAQ,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAC;IAC9E,OAAO,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { FeedItem } from './feed-item.ts';
|
|
2
|
+
import type { FeedSource } from './feed-source.ts';
|
|
3
|
+
/**
|
|
4
|
+
* Atom 1.0: the feed and its entries, rendered from {@link FeedItem}s.
|
|
5
|
+
*
|
|
6
|
+
* An entry names the post by its object id and lists every term it carries,
|
|
7
|
+
* which is what RSS and JSON Feed do with the same item: decision-12 leaves
|
|
8
|
+
* the three formats nothing to disagree about.
|
|
9
|
+
*/
|
|
10
|
+
/** One feed as an Atom 1.0 document. */
|
|
11
|
+
export declare function atomFeed(source: FeedSource): string;
|
|
12
|
+
/**
|
|
13
|
+
* One item as an Atom entry.
|
|
14
|
+
*
|
|
15
|
+
* `<id>` is the object id and the `rel="alternate"` link is the permalink,
|
|
16
|
+
* which are the same URL for every post born on this CMS and differ only for
|
|
17
|
+
* one carrying a stored id. A summary is written whenever there is one, which
|
|
18
|
+
* after decision-12 is every post with a body: Atom's `<summary>` is optional,
|
|
19
|
+
* and an empty one says less than none.
|
|
20
|
+
*/
|
|
21
|
+
export declare function atomEntry(item: FeedItem): string[];
|
|
22
|
+
//# sourceMappingURL=feed-atom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feed-atom.d.ts","sourceRoot":"","sources":["../../src/web/feed-atom.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAS/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAInD;;;;;;GAMG;AAEH,wCAAwC;AACxC,wBAAgB,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CA8BnD;AAeD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE,CAoBlD"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { feedItems } from './feed-item.js';
|
|
2
|
+
import { contentTypeOf, EMPTY_FEED_UPDATED, FEED_GENERATOR, FEED_GENERATOR_URI, feedLanguage, notifyServerOf, } from './feed-source.js';
|
|
3
|
+
import { author, element, escapeXml, link, optionalElement, SOURCE_NAMESPACE } from './feed-xml.js';
|
|
4
|
+
import { absoluteUrl, latestModified } from './negotiate.js';
|
|
5
|
+
/**
|
|
6
|
+
* Atom 1.0: the feed and its entries, rendered from {@link FeedItem}s.
|
|
7
|
+
*
|
|
8
|
+
* An entry names the post by its object id and lists every term it carries,
|
|
9
|
+
* which is what RSS and JSON Feed do with the same item: decision-12 leaves
|
|
10
|
+
* the three formats nothing to disagree about.
|
|
11
|
+
*/
|
|
12
|
+
/** One feed as an Atom 1.0 document. */
|
|
13
|
+
export function atomFeed(source) {
|
|
14
|
+
const { site, documents, baseUrl } = source;
|
|
15
|
+
const updated = latestModified(documents) ?? EMPTY_FEED_UPDATED;
|
|
16
|
+
const lines = [
|
|
17
|
+
'<?xml version="1.0" encoding="utf-8"?>',
|
|
18
|
+
`<feed xmlns="http://www.w3.org/2005/Atom"`,
|
|
19
|
+
` xmlns:source="${SOURCE_NAMESPACE}"`,
|
|
20
|
+
` xml:lang="${escapeXml(feedLanguage(site))}">`,
|
|
21
|
+
element('id', absoluteUrl(source.href, baseUrl)),
|
|
22
|
+
element('title', source.title),
|
|
23
|
+
...optionalElement('subtitle', site.tagline),
|
|
24
|
+
element('updated', updated.toISOString()),
|
|
25
|
+
link({
|
|
26
|
+
rel: 'self',
|
|
27
|
+
type: contentTypeOf('atom'),
|
|
28
|
+
href: absoluteUrl(source.feedHref, baseUrl),
|
|
29
|
+
}),
|
|
30
|
+
link({ rel: 'alternate', type: 'text/html', href: absoluteUrl(source.href, baseUrl) }),
|
|
31
|
+
...atomCloud(site),
|
|
32
|
+
` <generator uri="${escapeXml(FEED_GENERATOR_URI)}">${escapeXml(FEED_GENERATOR)}</generator>`,
|
|
33
|
+
...author(site.author, 1),
|
|
34
|
+
];
|
|
35
|
+
for (const item of feedItems(documents, source)) {
|
|
36
|
+
lines.push(...atomEntry(item));
|
|
37
|
+
}
|
|
38
|
+
lines.push('</feed>', '');
|
|
39
|
+
return lines.join('\n');
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The notify server as an Atom feed can say it: the `rel="hub"` link WebSub
|
|
43
|
+
* defines, and `<source:cloud>`, which is namespaced and so belongs here as
|
|
44
|
+
* much as in RSS. The legacy `<cloud>` is not: it is an RSS 2.0 element with
|
|
45
|
+
* no namespace, and Atom has nowhere to put it.
|
|
46
|
+
*/
|
|
47
|
+
function atomCloud(site) {
|
|
48
|
+
const notify = notifyServerOf(site);
|
|
49
|
+
if (notify === undefined)
|
|
50
|
+
return [];
|
|
51
|
+
return [element('source:cloud', notify.pleaseNotify), link({ rel: 'hub', href: notify.hub })];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* One item as an Atom entry.
|
|
55
|
+
*
|
|
56
|
+
* `<id>` is the object id and the `rel="alternate"` link is the permalink,
|
|
57
|
+
* which are the same URL for every post born on this CMS and differ only for
|
|
58
|
+
* one carrying a stored id. A summary is written whenever there is one, which
|
|
59
|
+
* after decision-12 is every post with a body: Atom's `<summary>` is optional,
|
|
60
|
+
* and an empty one says less than none.
|
|
61
|
+
*/
|
|
62
|
+
export function atomEntry(item) {
|
|
63
|
+
return [
|
|
64
|
+
' <entry>',
|
|
65
|
+
element('id', item.id, 2),
|
|
66
|
+
element('title', item.title, 2),
|
|
67
|
+
element('updated', (item.updated ?? EMPTY_FEED_UPDATED).toISOString(), 2),
|
|
68
|
+
...(item.published === undefined
|
|
69
|
+
? []
|
|
70
|
+
: [element('published', item.published.toISOString(), 2)]),
|
|
71
|
+
link({ rel: 'alternate', type: 'text/html', href: item.link }, 2),
|
|
72
|
+
...author(item.author, 2),
|
|
73
|
+
...item.terms.map((term) => ` <category term="${escapeXml(term)}"/>`),
|
|
74
|
+
...(item.summary === ''
|
|
75
|
+
? []
|
|
76
|
+
: [` <summary type="text">${escapeXml(item.summary)}</summary>`]),
|
|
77
|
+
// `type="html"` means the markup is escaped rather than inlined, so a
|
|
78
|
+
// reader that does not parse XHTML still gets the whole post.
|
|
79
|
+
` <content type="html">${escapeXml(item.html)}</content>`,
|
|
80
|
+
' </entry>',
|
|
81
|
+
];
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=feed-atom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feed-atom.js","sourceRoot":"","sources":["../../src/web/feed-atom.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import type { Document } from '../content/document.ts';
|
|
2
|
+
import type { SiteData } from './context.ts';
|
|
3
|
+
/**
|
|
4
|
+
* One post as a feed shows it, in one shape whatever format the feed is.
|
|
5
|
+
*
|
|
6
|
+
* This is the model the three serialisers render. It exists because they used
|
|
7
|
+
* to read the {@link Document} themselves, three times, and disagreed about
|
|
8
|
+
* what they found: RSS keyed an item by the post's ActivityStreams object id
|
|
9
|
+
* where Atom and JSON Feed used the permalink, RSS listed both taxonomies
|
|
10
|
+
* where the others listed tags only, and RSS fell back to an excerpt where the
|
|
11
|
+
* others printed nothing. One derivation, done once per post and site, means
|
|
12
|
+
* there is one answer to each of those questions and one place to change it.
|
|
13
|
+
*
|
|
14
|
+
* decision-12 is what each of those answers is, and the shape here is what
|
|
15
|
+
* makes it unavoidable: there is one {@link FeedItem.id}, one
|
|
16
|
+
* {@link FeedItem.terms} list and one {@link FeedItem.summary}, so a format
|
|
17
|
+
* cannot print a second-best version of any of them. The one pair left,
|
|
18
|
+
* {@link FeedItem.id} beside {@link FeedItem.link}, is two real things: what
|
|
19
|
+
* the post is called and where it is read, which differ only for a post
|
|
20
|
+
* carrying a stored id.
|
|
21
|
+
*/
|
|
22
|
+
export interface FeedItem {
|
|
23
|
+
/**
|
|
24
|
+
* The post's name: its ActivityStreams object id, which after decision-13 is
|
|
25
|
+
* the permalink, or the stored id a migrated post carries. decision-12 makes
|
|
26
|
+
* this every feed's key for the post, so all three formats print it: RSS as
|
|
27
|
+
* `guid`, Atom as `<id>` and JSON Feed as `id`.
|
|
28
|
+
*/
|
|
29
|
+
id: string;
|
|
30
|
+
/**
|
|
31
|
+
* Where the post is read: its permalink, absolute on the site's base URL.
|
|
32
|
+
* The same in every format — RSS's `link`, Atom's `rel="alternate"` and JSON
|
|
33
|
+
* Feed's `url` — and equal to {@link FeedItem.id} unless the post carries a
|
|
34
|
+
* stored one.
|
|
35
|
+
*/
|
|
36
|
+
link: string;
|
|
37
|
+
/** Display title. */
|
|
38
|
+
title: string;
|
|
39
|
+
/** When it was published, if it carries a date that parses. */
|
|
40
|
+
published?: Date | undefined;
|
|
41
|
+
/** When it last changed: its `updated`, else its date. */
|
|
42
|
+
updated?: Date | undefined;
|
|
43
|
+
/** The post's own author, when it names one. Atom and JSON Feed print this. */
|
|
44
|
+
author?: string | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Who a feed credits: the post's own author, else the site's. RSS's
|
|
47
|
+
* `dc:creator` prints it, because an RSS item has nowhere else to say it.
|
|
48
|
+
*/
|
|
49
|
+
creator?: string | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* What the post is filed under and tagged with, categories first and each in
|
|
52
|
+
* file order, as one list.
|
|
53
|
+
*
|
|
54
|
+
* One list rather than two because no feed format distinguishes them: RSS has
|
|
55
|
+
* a single `<category>`, Atom a single `<category term>` and JSON Feed a
|
|
56
|
+
* single `tags`, which is exactly how WordPress publishes both taxonomies
|
|
57
|
+
* too. decision-12 says every format lists every term, and a model that
|
|
58
|
+
* cannot say which vocabulary a term came from is a model no format can
|
|
59
|
+
* quietly list half of.
|
|
60
|
+
*/
|
|
61
|
+
terms: readonly string[];
|
|
62
|
+
/**
|
|
63
|
+
* What every format prints as the summary: the description the author wrote,
|
|
64
|
+
* else an excerpt of the rendered body. Never the whole post — the content is
|
|
65
|
+
* where that goes — and empty only for a post with nothing to summarise,
|
|
66
|
+
* which is the one case a format leaves the element out.
|
|
67
|
+
*/
|
|
68
|
+
summary: string;
|
|
69
|
+
/** The rendered body. */
|
|
70
|
+
html: string;
|
|
71
|
+
/** The Markdown the body was written from, for `source:markdown`. */
|
|
72
|
+
markdown: string;
|
|
73
|
+
/**
|
|
74
|
+
* Where this item's comments are, and how many there are, or `undefined`
|
|
75
|
+
* when the feed did not resolve the counts. A feed whose builder did not
|
|
76
|
+
* would otherwise publish "0 comments" about a post with plenty.
|
|
77
|
+
*/
|
|
78
|
+
comments?: FeedItemComments | undefined;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Which revision of the item's serialisation a feed's validator is keyed by.
|
|
82
|
+
*
|
|
83
|
+
* A feed's ETag is a hash of the documents and the site's metadata, because
|
|
84
|
+
* those are what usually move it. The rules for turning a document into an item
|
|
85
|
+
* are not in that hash, so a release that changes them — this one, which
|
|
86
|
+
* changes every RSS `guid`, both the other formats' ids, the terms they list
|
|
87
|
+
* and their summaries — would leave the validator where it was, and a reader
|
|
88
|
+
* polling with `If-None-Match` would be handed a 304 that hides the new bytes.
|
|
89
|
+
*
|
|
90
|
+
* Bumping this moves every post feed's ETag exactly once, at the upgrade, and
|
|
91
|
+
* never again until the next such change. The comments feeds do not carry it:
|
|
92
|
+
* a comment is not a {@link FeedItem} and its bytes are untouched.
|
|
93
|
+
*/
|
|
94
|
+
export declare const FEED_ITEM_REVISION = 2;
|
|
95
|
+
/** Where one item's comments are, counted. */
|
|
96
|
+
export interface FeedItemComments {
|
|
97
|
+
/** The page a person reads them on. */
|
|
98
|
+
page: string;
|
|
99
|
+
/** The feed a reader polls for them. */
|
|
100
|
+
feed: string;
|
|
101
|
+
/** How many there are. */
|
|
102
|
+
count: number;
|
|
103
|
+
}
|
|
104
|
+
/** What an item needs to know about the feed it is part of. */
|
|
105
|
+
export interface FeedItemContext {
|
|
106
|
+
/** Site-wide data, for the author a post does not name. */
|
|
107
|
+
site: SiteData;
|
|
108
|
+
/** The site's public origin, for absolute ids and links. */
|
|
109
|
+
baseUrl: string;
|
|
110
|
+
/** How many replies each document has, by permalink. See {@link FeedItem.comments}. */
|
|
111
|
+
commentCounts?: ReadonlyMap<string, number> | undefined;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* One document as the item every format renders.
|
|
115
|
+
*
|
|
116
|
+
* The only reading of a {@link Document} a feed does: after this, a serialiser
|
|
117
|
+
* sees an item and nothing else, so two formats cannot quietly disagree about
|
|
118
|
+
* what a post's summary or its name is.
|
|
119
|
+
*/
|
|
120
|
+
export declare function feedItem(document: Document, context: FeedItemContext): FeedItem;
|
|
121
|
+
/** One item per document, in the order the feed was given them. */
|
|
122
|
+
export declare function feedItems(documents: readonly Document[], context: FeedItemContext): readonly FeedItem[];
|
|
123
|
+
/**
|
|
124
|
+
* How many words of the rendered text an excerpt keeps when a post carries no
|
|
125
|
+
* `description`. WordPress's own excerpt length, so a migrated site's feed
|
|
126
|
+
* reads the same.
|
|
127
|
+
*/
|
|
128
|
+
export declare const EXCERPT_WORDS = 55;
|
|
129
|
+
/**
|
|
130
|
+
* The plain-text summary a feed carries for a post.
|
|
131
|
+
*
|
|
132
|
+
* The `description` front matter when the post has one — it is what the author
|
|
133
|
+
* wrote for exactly this — and otherwise the first paragraph of the rendered
|
|
134
|
+
* body, stripped to text and cut where WordPress cuts an excerpt. Never the
|
|
135
|
+
* whole post: the content element is where the whole post goes, and a reader
|
|
136
|
+
* that shows both should have something to choose between.
|
|
137
|
+
*/
|
|
138
|
+
export declare function feedExcerpt(document: Document): string;
|
|
139
|
+
/**
|
|
140
|
+
* The first paragraph of some HTML as plain text, cut where WordPress cuts an
|
|
141
|
+
* excerpt. What a post falls back to when it carries no `description`, and
|
|
142
|
+
* what a comment — which never carries one — always uses.
|
|
143
|
+
*/
|
|
144
|
+
export declare function excerptFromHtml(html: string): string;
|
|
145
|
+
//# sourceMappingURL=feed-item.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feed-item.d.ts","sourceRoot":"","sources":["../../src/web/feed-item.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAK7C;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,QAAQ;IACvB;;;;;OAKG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,SAAS,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;IAC7B,0DAA0D;IAC1D,OAAO,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;IAC3B,+EAA+E;IAC/E,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B;;;;;;;;;;OAUG;IACH,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;CACzC;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC,8CAA8C;AAC9C,MAAM,WAAW,gBAAgB;IAC/B,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,+DAA+D;AAC/D,MAAM,WAAW,eAAe;IAC9B,2DAA2D;IAC3D,IAAI,EAAE,QAAQ,CAAC;IACf,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,uFAAuF;IACvF,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;CACzD;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,eAAe,GAAG,QAAQ,CAsC/E;AAED,mEAAmE;AACnE,wBAAgB,SAAS,CACvB,SAAS,EAAE,SAAS,QAAQ,EAAE,EAC9B,OAAO,EAAE,eAAe,GACvB,SAAS,QAAQ,EAAE,CAErB;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,KAAK,CAAC;AAEhC;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAGtD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAapD"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { activityStreamsId } from './documents.js';
|
|
2
|
+
import { feedPathUnder } from './feed-source.js';
|
|
3
|
+
import { absoluteUrl, lastModifiedOf } from './negotiate.js';
|
|
4
|
+
/**
|
|
5
|
+
* Which revision of the item's serialisation a feed's validator is keyed by.
|
|
6
|
+
*
|
|
7
|
+
* A feed's ETag is a hash of the documents and the site's metadata, because
|
|
8
|
+
* those are what usually move it. The rules for turning a document into an item
|
|
9
|
+
* are not in that hash, so a release that changes them — this one, which
|
|
10
|
+
* changes every RSS `guid`, both the other formats' ids, the terms they list
|
|
11
|
+
* and their summaries — would leave the validator where it was, and a reader
|
|
12
|
+
* polling with `If-None-Match` would be handed a 304 that hides the new bytes.
|
|
13
|
+
*
|
|
14
|
+
* Bumping this moves every post feed's ETag exactly once, at the upgrade, and
|
|
15
|
+
* never again until the next such change. The comments feeds do not carry it:
|
|
16
|
+
* a comment is not a {@link FeedItem} and its bytes are untouched.
|
|
17
|
+
*/
|
|
18
|
+
export const FEED_ITEM_REVISION = 2;
|
|
19
|
+
/**
|
|
20
|
+
* One document as the item every format renders.
|
|
21
|
+
*
|
|
22
|
+
* The only reading of a {@link Document} a feed does: after this, a serialiser
|
|
23
|
+
* sees an item and nothing else, so two formats cannot quietly disagree about
|
|
24
|
+
* what a post's summary or its name is.
|
|
25
|
+
*/
|
|
26
|
+
export function feedItem(document, context) {
|
|
27
|
+
const { baseUrl } = context;
|
|
28
|
+
const link = absoluteUrl(document.permalink, baseUrl);
|
|
29
|
+
const published = document.date === undefined ? undefined : new Date(document.date);
|
|
30
|
+
const item = {
|
|
31
|
+
// A page or a draft has no ActivityStreams id to advertise, and falls back
|
|
32
|
+
// to its address. A feed only ever carries published posts, so in practice
|
|
33
|
+
// this is the object id; the fallback is what keeps the shape total.
|
|
34
|
+
id: activityStreamsId(document, baseUrl) ?? link,
|
|
35
|
+
link,
|
|
36
|
+
title: document.title,
|
|
37
|
+
terms: [...document.categories, ...document.tags],
|
|
38
|
+
summary: feedExcerpt(document),
|
|
39
|
+
html: document.html,
|
|
40
|
+
markdown: document.body,
|
|
41
|
+
};
|
|
42
|
+
if (published !== undefined && !Number.isNaN(published.getTime()))
|
|
43
|
+
item.published = published;
|
|
44
|
+
const updated = lastModifiedOf(document);
|
|
45
|
+
if (updated !== undefined)
|
|
46
|
+
item.updated = updated;
|
|
47
|
+
if (document.author !== undefined)
|
|
48
|
+
item.author = document.author;
|
|
49
|
+
const creator = document.author ?? context.site.author;
|
|
50
|
+
if (creator !== undefined && creator !== '')
|
|
51
|
+
item.creator = creator;
|
|
52
|
+
const counts = context.commentCounts;
|
|
53
|
+
if (counts !== undefined) {
|
|
54
|
+
item.comments = {
|
|
55
|
+
page: `${link}#comments`,
|
|
56
|
+
feed: absoluteUrl(feedPathUnder(document.permalink, 'rss'), baseUrl),
|
|
57
|
+
count: counts.get(document.permalink) ?? 0,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return item;
|
|
61
|
+
}
|
|
62
|
+
/** One item per document, in the order the feed was given them. */
|
|
63
|
+
export function feedItems(documents, context) {
|
|
64
|
+
return documents.map((document) => feedItem(document, context));
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* How many words of the rendered text an excerpt keeps when a post carries no
|
|
68
|
+
* `description`. WordPress's own excerpt length, so a migrated site's feed
|
|
69
|
+
* reads the same.
|
|
70
|
+
*/
|
|
71
|
+
export const EXCERPT_WORDS = 55;
|
|
72
|
+
/**
|
|
73
|
+
* The plain-text summary a feed carries for a post.
|
|
74
|
+
*
|
|
75
|
+
* The `description` front matter when the post has one — it is what the author
|
|
76
|
+
* wrote for exactly this — and otherwise the first paragraph of the rendered
|
|
77
|
+
* body, stripped to text and cut where WordPress cuts an excerpt. Never the
|
|
78
|
+
* whole post: the content element is where the whole post goes, and a reader
|
|
79
|
+
* that shows both should have something to choose between.
|
|
80
|
+
*/
|
|
81
|
+
export function feedExcerpt(document) {
|
|
82
|
+
if (document.description !== undefined)
|
|
83
|
+
return document.description;
|
|
84
|
+
return excerptFromHtml(document.html);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The first paragraph of some HTML as plain text, cut where WordPress cuts an
|
|
88
|
+
* excerpt. What a post falls back to when it carries no `description`, and
|
|
89
|
+
* what a comment — which never carries one — always uses.
|
|
90
|
+
*/
|
|
91
|
+
export function excerptFromHtml(html) {
|
|
92
|
+
// Tags are dropped rather than replaced by a space: the markup inside a
|
|
93
|
+
// paragraph is inline, and "now</span>," is one word followed by a comma.
|
|
94
|
+
// What separates the words is the whitespace the renderer already put
|
|
95
|
+
// between its block tags, which the collapse below turns into single spaces.
|
|
96
|
+
const paragraph = /<p[^>]*>([\s\S]*?)<\/p>/i.exec(html)?.[1] ?? html;
|
|
97
|
+
const text = decodeHtmlText(paragraph.replace(/<[^>]*>/g, ''))
|
|
98
|
+
.replace(/\s+/g, ' ')
|
|
99
|
+
.trim();
|
|
100
|
+
if (text === '')
|
|
101
|
+
return '';
|
|
102
|
+
const words = text.split(' ');
|
|
103
|
+
return words.length <= EXCERPT_WORDS ? text : `${words.slice(0, EXCERPT_WORDS).join(' ')} …`;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* The five named entities the Markdown renderer emits, resolved.
|
|
107
|
+
*
|
|
108
|
+
* An excerpt is text rather than markup, so `&` in the rendered HTML has
|
|
109
|
+
* to become `&` here before the XML escaping puts it back: leaving it would
|
|
110
|
+
* publish a summary reading "Fish &amp; chips".
|
|
111
|
+
*/
|
|
112
|
+
function decodeHtmlText(value) {
|
|
113
|
+
return value
|
|
114
|
+
.replace(/</g, '<')
|
|
115
|
+
.replace(/>/g, '>')
|
|
116
|
+
.replace(/"/g, '"')
|
|
117
|
+
.replace(/&#(?:39|x27);/g, "'")
|
|
118
|
+
.replace(/&/g, '&');
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=feed-item.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feed-item.js","sourceRoot":"","sources":["../../src/web/feed-item.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { FeedItem } from './feed-item.ts';
|
|
2
|
+
import type { FeedSource } from './feed-source.ts';
|
|
3
|
+
/**
|
|
4
|
+
* JSON Feed 1.1: the document, its items, and the vocabulary they are spelled
|
|
5
|
+
* in.
|
|
6
|
+
*
|
|
7
|
+
* An item is keyed by the post's object id and lists every term it carries,
|
|
8
|
+
* which is what the two XML formats do with the same item: decision-12 leaves
|
|
9
|
+
* the three formats nothing to disagree about.
|
|
10
|
+
*/
|
|
11
|
+
/** The `version` every JSON Feed this CMS writes declares. */
|
|
12
|
+
export declare const JSON_FEED_VERSION = "https://jsonfeed.org/version/1.1";
|
|
13
|
+
/** What JSON Feed 1.1 calls the protocol the notify server's hub speaks. */
|
|
14
|
+
export declare const JSON_FEED_HUB_TYPE = "WebSub";
|
|
15
|
+
/** A JSON Feed 1.1 document. */
|
|
16
|
+
export interface JsonFeed {
|
|
17
|
+
/** {@link JSON_FEED_VERSION}. */
|
|
18
|
+
version: string;
|
|
19
|
+
/** The feed's name. */
|
|
20
|
+
title: string;
|
|
21
|
+
/** The HTML page this feed syndicates. */
|
|
22
|
+
home_page_url: string;
|
|
23
|
+
/** Where this feed itself lives. */
|
|
24
|
+
feed_url: string;
|
|
25
|
+
/** The site's tagline, when it has one. */
|
|
26
|
+
description?: string;
|
|
27
|
+
/** Site-level authors, when the site names one. */
|
|
28
|
+
authors?: JsonFeedAuthor[];
|
|
29
|
+
/**
|
|
30
|
+
* Where a subscriber can be told the feed changed rather than polling it.
|
|
31
|
+
* One entry, the site's notify server, when it names one.
|
|
32
|
+
*/
|
|
33
|
+
hubs?: JsonFeedHub[];
|
|
34
|
+
/** The entries, newest first. */
|
|
35
|
+
items: JsonFeedItem[];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* A real-time endpoint, as JSON Feed 1.1 models one. `type` names the protocol
|
|
39
|
+
* rather than a media type, and `WebSub` is the one this CMS's server speaks.
|
|
40
|
+
*/
|
|
41
|
+
export interface JsonFeedHub {
|
|
42
|
+
/** The protocol: `WebSub`. */
|
|
43
|
+
type: string;
|
|
44
|
+
/** The hub's URL. */
|
|
45
|
+
url: string;
|
|
46
|
+
}
|
|
47
|
+
/** An author, as JSON Feed 1.1 models one. */
|
|
48
|
+
export interface JsonFeedAuthor {
|
|
49
|
+
name: string;
|
|
50
|
+
}
|
|
51
|
+
/** One entry of a {@link JsonFeed}. */
|
|
52
|
+
export interface JsonFeedItem {
|
|
53
|
+
/**
|
|
54
|
+
* Permanent identifier: the post's ActivityStreams object id, which is its
|
|
55
|
+
* permalink unless the post carries a stored one.
|
|
56
|
+
*/
|
|
57
|
+
id: string;
|
|
58
|
+
/** Where the entry can be read: the permalink. */
|
|
59
|
+
url: string;
|
|
60
|
+
/** Display title. */
|
|
61
|
+
title: string;
|
|
62
|
+
/** The rendered body. */
|
|
63
|
+
content_html: string;
|
|
64
|
+
/** The post's summary, unless there is nothing to summarise. */
|
|
65
|
+
summary?: string;
|
|
66
|
+
/** Publish date, RFC 3339. */
|
|
67
|
+
date_published?: string;
|
|
68
|
+
/** Last modification date, RFC 3339. */
|
|
69
|
+
date_modified?: string;
|
|
70
|
+
/** The post's terms — its categories and then its tags, in file order. */
|
|
71
|
+
tags?: string[];
|
|
72
|
+
/** The post's own author, when it names one. */
|
|
73
|
+
authors?: JsonFeedAuthor[];
|
|
74
|
+
}
|
|
75
|
+
/** One feed as a JSON Feed 1.1 document. */
|
|
76
|
+
export declare function jsonFeed(source: FeedSource): JsonFeed;
|
|
77
|
+
/** One item as a JSON Feed item. */
|
|
78
|
+
export declare function jsonFeedItem(item: FeedItem): JsonFeedItem;
|
|
79
|
+
//# sourceMappingURL=feed-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feed-json.d.ts","sourceRoot":"","sources":["../../src/web/feed-json.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD;;;;;;;GAOG;AAEH,8DAA8D;AAC9D,eAAO,MAAM,iBAAiB,qCAAqC,CAAC;AAEpE,4EAA4E;AAC5E,eAAO,MAAM,kBAAkB,WAAW,CAAC;AAE3C,gCAAgC;AAChC,MAAM,WAAW,QAAQ;IACvB,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,aAAa,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;IAC3B;;;OAGG;IACH,IAAI,CAAC,EAAE,WAAW,EAAE,CAAC;IACrB,iCAAiC;IACjC,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,8CAA8C;AAC9C,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,uCAAuC;AACvC,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,EAAE,EAAE,MAAM,CAAC;IACX,kDAAkD;IAClD,GAAG,EAAE,MAAM,CAAC;IACZ,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,yBAAyB;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wCAAwC;IACxC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,gDAAgD;IAChD,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;CAC5B;AAED,4CAA4C;AAC5C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,QAAQ,CAcrD;AAED,oCAAoC;AACpC,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,YAAY,CAiBzD"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { feedItems } from './feed-item.js';
|
|
2
|
+
import { notifyServerOf } from './feed-source.js';
|
|
3
|
+
import { absoluteUrl } from './negotiate.js';
|
|
4
|
+
/**
|
|
5
|
+
* JSON Feed 1.1: the document, its items, and the vocabulary they are spelled
|
|
6
|
+
* in.
|
|
7
|
+
*
|
|
8
|
+
* An item is keyed by the post's object id and lists every term it carries,
|
|
9
|
+
* which is what the two XML formats do with the same item: decision-12 leaves
|
|
10
|
+
* the three formats nothing to disagree about.
|
|
11
|
+
*/
|
|
12
|
+
/** The `version` every JSON Feed this CMS writes declares. */
|
|
13
|
+
export const JSON_FEED_VERSION = 'https://jsonfeed.org/version/1.1';
|
|
14
|
+
/** What JSON Feed 1.1 calls the protocol the notify server's hub speaks. */
|
|
15
|
+
export const JSON_FEED_HUB_TYPE = 'WebSub';
|
|
16
|
+
/** One feed as a JSON Feed 1.1 document. */
|
|
17
|
+
export function jsonFeed(source) {
|
|
18
|
+
const { site, baseUrl } = source;
|
|
19
|
+
const notify = notifyServerOf(site);
|
|
20
|
+
return {
|
|
21
|
+
version: JSON_FEED_VERSION,
|
|
22
|
+
title: source.title,
|
|
23
|
+
home_page_url: absoluteUrl(source.href, baseUrl),
|
|
24
|
+
feed_url: absoluteUrl(source.feedHref, baseUrl),
|
|
25
|
+
...(site.tagline === undefined ? {} : { description: site.tagline }),
|
|
26
|
+
...(site.author === undefined ? {} : { authors: [{ name: site.author }] }),
|
|
27
|
+
...(notify === undefined ? {} : { hubs: [{ type: JSON_FEED_HUB_TYPE, url: notify.hub }] }),
|
|
28
|
+
items: feedItems(source.documents, source).map(jsonFeedItem),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/** One item as a JSON Feed item. */
|
|
32
|
+
export function jsonFeedItem(item) {
|
|
33
|
+
const entry = {
|
|
34
|
+
id: item.id,
|
|
35
|
+
url: item.link,
|
|
36
|
+
title: item.title,
|
|
37
|
+
content_html: item.html,
|
|
38
|
+
};
|
|
39
|
+
// A key with nothing behind it is left out rather than sent empty: a JSON
|
|
40
|
+
// Feed reader treats absent and empty differently.
|
|
41
|
+
if (item.summary !== '')
|
|
42
|
+
entry.summary = item.summary;
|
|
43
|
+
if (item.published !== undefined)
|
|
44
|
+
entry.date_published = item.published.toISOString();
|
|
45
|
+
if (item.updated !== undefined)
|
|
46
|
+
entry.date_modified = item.updated.toISOString();
|
|
47
|
+
if (item.terms.length > 0)
|
|
48
|
+
entry.tags = [...item.terms];
|
|
49
|
+
if (item.author !== undefined)
|
|
50
|
+
entry.authors = [{ name: item.author }];
|
|
51
|
+
return entry;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=feed-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feed-json.js","sourceRoot":"","sources":["../../src/web/feed-json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C;;;;;;;GAOG;AAEH,8DAA8D;AAC9D,MAAM,CAAC,MAAM,iBAAiB,GAAG,kCAAkC,CAAC;AAEpE,4EAA4E;AAC5E,MAAM,CAAC,MAAM,kBAAkB,GAAG,QAAQ,CAAC;AAkE3C,4CAA4C;AAC5C,MAAM,UAAU,QAAQ,CAAC,MAAkB;IACzC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;IACjC,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IAEpC,OAAO;QACL,OAAO,EAAE,iBAAiB;QAC1B,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC;QAChD,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC;QAC/C,GAAG,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;QACpE,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;QAC1E,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;QAC1F,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC;KAC7D,CAAC;AACJ,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,YAAY,CAAC,IAAc;IACzC,MAAM,KAAK,GAAiB;QAC1B,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,GAAG,EAAE,IAAI,CAAC,IAAI;QACd,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,YAAY,EAAE,IAAI,CAAC,IAAI;KACxB,CAAC;IAEF,0EAA0E;IAC1E,mDAAmD;IACnD,IAAI,IAAI,CAAC,OAAO,KAAK,EAAE;QAAE,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IACtD,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS;QAAE,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;IACtF,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;QAAE,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;IACjF,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IACxD,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;QAAE,KAAK,CAAC,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAEvE,OAAO,KAAK,CAAC;AACf,CAAC"}
|