@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,127 @@
|
|
|
1
|
+
import { clientAddress, createLoginThrottle } from '../admin/throttle.js';
|
|
2
|
+
import { isPublicDocument } from '../web/documents.js';
|
|
3
|
+
import { sendContactMessage } from './delivery.js';
|
|
4
|
+
import { CONTACT_ANCHOR, CONTACT_FIELDS, CONTACT_NOTICE_PARAM, CONTACT_POST_PATH, contactOpen, contactValuesOf, refilledContactForm, } from './form.js';
|
|
5
|
+
import { CONTACT_RATE_LIMIT, CONTACT_RATE_WINDOW_SECONDS, submitContactMessage, } from './submission.js';
|
|
6
|
+
/**
|
|
7
|
+
* The one public endpoint the contact form adds: where the form on a page
|
|
8
|
+
* posts to.
|
|
9
|
+
*
|
|
10
|
+
* A single path rather than one per page because the page is a field of the
|
|
11
|
+
* form. That keeps it out of the way of every permalink a site might mint — a
|
|
12
|
+
* path under `/_geekity/` is the CMS's own, like the comment endpoint beside
|
|
13
|
+
* it — and means the route table does not grow with the site.
|
|
14
|
+
*
|
|
15
|
+
* Everything it answers is either a redirect or the page rendered again with
|
|
16
|
+
* the form still filled in. There is no JSON, no fragment and no script.
|
|
17
|
+
*/
|
|
18
|
+
/** Register the contact endpoint. Mounted by the public site. */
|
|
19
|
+
export function mountContact(app) {
|
|
20
|
+
// One limiter for the whole mount, built on the first submission because the
|
|
21
|
+
// clock is on the context. It holds nothing but recent submissions, so it
|
|
22
|
+
// belongs to the process rather than the database: a restart clears it,
|
|
23
|
+
// which is the right trade for state an anonymous caller can create.
|
|
24
|
+
let limiter;
|
|
25
|
+
function throttle(config) {
|
|
26
|
+
limiter ??= createLoginThrottle({
|
|
27
|
+
attempts: CONTACT_RATE_LIMIT,
|
|
28
|
+
lockoutSeconds: CONTACT_RATE_WINDOW_SECONDS,
|
|
29
|
+
now: config.now,
|
|
30
|
+
});
|
|
31
|
+
return limiter;
|
|
32
|
+
}
|
|
33
|
+
app.post(CONTACT_POST_PATH, async (c) => {
|
|
34
|
+
const { store, config } = c.var;
|
|
35
|
+
const body = await c.req.parseBody();
|
|
36
|
+
const form = formOf(body);
|
|
37
|
+
const document = store.getBySlug(form.page);
|
|
38
|
+
if (document === undefined || !isPublicDocument(document, store.now())) {
|
|
39
|
+
return c.text('There is no such page to write to.', 404);
|
|
40
|
+
}
|
|
41
|
+
if (!contactOpen(document)) {
|
|
42
|
+
// 403 rather than 404: the page is there, and a reader can see for
|
|
43
|
+
// themselves that it is. It simply does not take messages.
|
|
44
|
+
return c.text('That page is not taking messages.', 403);
|
|
45
|
+
}
|
|
46
|
+
const now = config.now();
|
|
47
|
+
const outcome = await submitContactMessage({
|
|
48
|
+
dataDir: config.dataDir,
|
|
49
|
+
document,
|
|
50
|
+
form,
|
|
51
|
+
baseUrl: config.baseUrl,
|
|
52
|
+
// The same checker comments go through, told this is a contact form.
|
|
53
|
+
checker: config.commentChecker,
|
|
54
|
+
address: clientAddress(c, config),
|
|
55
|
+
userAgent: c.req.header('user-agent'),
|
|
56
|
+
referrer: c.req.header('referer'),
|
|
57
|
+
throttle: throttle(config),
|
|
58
|
+
now,
|
|
59
|
+
});
|
|
60
|
+
if (outcome.kind === 'stored') {
|
|
61
|
+
// The message is on disk already, so the sender is thanked now and the
|
|
62
|
+
// mail goes out behind them. A provider that is down costs a
|
|
63
|
+
// notification rather than the message.
|
|
64
|
+
sendContactMessage({
|
|
65
|
+
mail: c.var.mail,
|
|
66
|
+
contentDir: config.contentDir,
|
|
67
|
+
dataDir: config.dataDir,
|
|
68
|
+
baseUrl: config.baseUrl,
|
|
69
|
+
message: outcome.message,
|
|
70
|
+
});
|
|
71
|
+
return c.redirect(sentUrl(document), 303);
|
|
72
|
+
}
|
|
73
|
+
const refusal = outcome.refusal;
|
|
74
|
+
if (refusal.kind === 'discarded') {
|
|
75
|
+
// Nothing is said about why. A robot that filled the honeypot, or that a
|
|
76
|
+
// checker recognised, learns exactly as much from this as from a
|
|
77
|
+
// message that went — which is the point of both defences.
|
|
78
|
+
return c.redirect(sentUrl(document), 303);
|
|
79
|
+
}
|
|
80
|
+
if (refusal.kind === 'rate-limited') {
|
|
81
|
+
c.header('Retry-After', String(refusal.retryAfter));
|
|
82
|
+
return page(c, document, 429, {
|
|
83
|
+
...refilledContactForm(document, contactValuesOf(form), {}, now),
|
|
84
|
+
error: 'That is a lot of messages in a short time. Try again in a few minutes.',
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
const message = refusal.kind === 'too-quick'
|
|
88
|
+
? 'That was sent faster than anybody types. Try again.'
|
|
89
|
+
: refusal.kind === 'stale'
|
|
90
|
+
? 'That form had been open a long time. Here it is again — the words are still there.'
|
|
91
|
+
: undefined;
|
|
92
|
+
return page(c, document, 400, {
|
|
93
|
+
...refilledContactForm(document, contactValuesOf(form), problemsOf(refusal), now),
|
|
94
|
+
...(message === undefined ? {} : { error: message }),
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/** Where a sender is redirected once the message is stored. */
|
|
99
|
+
function sentUrl(document) {
|
|
100
|
+
return `${document.permalink}?${CONTACT_NOTICE_PARAM}=sent#${CONTACT_ANCHOR}`;
|
|
101
|
+
}
|
|
102
|
+
/** The page itself, rendered again with this form on it. */
|
|
103
|
+
function page(c, document, status, form) {
|
|
104
|
+
c.status(status);
|
|
105
|
+
return c.html(c.var.renderer.renderDocument(document, { contactForm: form }));
|
|
106
|
+
}
|
|
107
|
+
/** The per-field messages a refusal carries, if it carries any. */
|
|
108
|
+
function problemsOf(refusal) {
|
|
109
|
+
return refusal.kind === 'invalid' ? (refusal.problems ?? {}) : {};
|
|
110
|
+
}
|
|
111
|
+
/** A submitted body as the form it is, every field a string. */
|
|
112
|
+
function formOf(body) {
|
|
113
|
+
return {
|
|
114
|
+
page: text(body[CONTACT_FIELDS.page]),
|
|
115
|
+
name: text(body[CONTACT_FIELDS.name]),
|
|
116
|
+
email: text(body[CONTACT_FIELDS.email]),
|
|
117
|
+
subject: text(body[CONTACT_FIELDS.subject]),
|
|
118
|
+
message: text(body[CONTACT_FIELDS.message]),
|
|
119
|
+
trap: text(body[CONTACT_FIELDS.trap]),
|
|
120
|
+
loaded: text(body[CONTACT_FIELDS.loaded]),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/** A form field as a string. A file upload, or a missing field, is the empty one. */
|
|
124
|
+
function text(value) {
|
|
125
|
+
return typeof value === 'string' ? value : '';
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/contact/routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { CommentChecker } from '../comments/submission.ts';
|
|
2
|
+
import type { Document } from '../content/document.ts';
|
|
3
|
+
import type { ContactForm, ContactProblems } from './form.ts';
|
|
4
|
+
import type { ContactMessage } from './records.ts';
|
|
5
|
+
/**
|
|
6
|
+
* What happens between somebody pressing Send and a message existing.
|
|
7
|
+
*
|
|
8
|
+
* The same four defences a comment goes through, in the same order and out of
|
|
9
|
+
* the same modules, because a contact form is the same problem as a comment
|
|
10
|
+
* form wearing different fields:
|
|
11
|
+
*
|
|
12
|
+
* 1. **The honeypot**, first, because it costs one comparison and because a
|
|
13
|
+
* submission that tripped it should not reach anything that could tell it
|
|
14
|
+
* so.
|
|
15
|
+
* 2. **The age of the form** — too new to have been typed, or too old to be
|
|
16
|
+
* the form it claims to be.
|
|
17
|
+
* 3. **The per-address rate limit**, the same limiter the login form and the
|
|
18
|
+
* comment form use, so one machine cannot send a hundred messages while
|
|
19
|
+
* nobody is looking.
|
|
20
|
+
* 4. **{@link CommentChecker}**, the one seam a third-party service plugs
|
|
21
|
+
* into, told this is a `contact-form` rather than a comment.
|
|
22
|
+
*
|
|
23
|
+
* Then the file, and only then the mail. The order is the point: a message is
|
|
24
|
+
* on disk before anything is asked to deliver it, so a provider that is down
|
|
25
|
+
* costs a notification rather than the message.
|
|
26
|
+
*/
|
|
27
|
+
/** How many messages one address may send before it has to wait. */
|
|
28
|
+
export declare const CONTACT_RATE_LIMIT = 5;
|
|
29
|
+
/** How long that window is, and how long the first wait after it lasts. */
|
|
30
|
+
export declare const CONTACT_RATE_WINDOW_SECONDS = 600;
|
|
31
|
+
/** The part of the login throttle a contact form needs. */
|
|
32
|
+
export interface ContactThrottle {
|
|
33
|
+
/** Seconds before this address may send again, or `undefined`. */
|
|
34
|
+
retryAfter(keys: readonly string[]): number | undefined;
|
|
35
|
+
/** Count one submission against it. */
|
|
36
|
+
fail(keys: readonly string[]): void;
|
|
37
|
+
}
|
|
38
|
+
/** The keys a submission is rate limited against. */
|
|
39
|
+
export declare function contactKeys(address: string | undefined): string[];
|
|
40
|
+
/** Why a submission did not become a message. */
|
|
41
|
+
export type ContactRefusal =
|
|
42
|
+
/** The form said something a person can put right. */
|
|
43
|
+
{
|
|
44
|
+
kind: 'invalid';
|
|
45
|
+
problems: ContactProblems;
|
|
46
|
+
}
|
|
47
|
+
/** The form was submitted faster than a person types. */
|
|
48
|
+
| {
|
|
49
|
+
kind: 'too-quick';
|
|
50
|
+
}
|
|
51
|
+
/** The form was rendered too long ago to still be one. */
|
|
52
|
+
| {
|
|
53
|
+
kind: 'stale';
|
|
54
|
+
}
|
|
55
|
+
/** This address has sent enough for now. `retryAfter` is in seconds. */
|
|
56
|
+
| {
|
|
57
|
+
kind: 'rate-limited';
|
|
58
|
+
retryAfter: number;
|
|
59
|
+
}
|
|
60
|
+
/** The honeypot was filled in, or a checker said to throw it away. */
|
|
61
|
+
| {
|
|
62
|
+
kind: 'discarded';
|
|
63
|
+
};
|
|
64
|
+
/** What became of a submission. */
|
|
65
|
+
export type ContactOutcome = {
|
|
66
|
+
kind: 'stored';
|
|
67
|
+
message: ContactMessage;
|
|
68
|
+
} | {
|
|
69
|
+
kind: 'refused';
|
|
70
|
+
refusal: ContactRefusal;
|
|
71
|
+
};
|
|
72
|
+
/** What {@link submitContactMessage} needs around it. */
|
|
73
|
+
export interface SubmitContactMessageOptions {
|
|
74
|
+
/** Where `data/contact/` is, and where the address salt lives. */
|
|
75
|
+
dataDir: string;
|
|
76
|
+
/** The page the form was on. */
|
|
77
|
+
document: Document;
|
|
78
|
+
/** What was submitted. */
|
|
79
|
+
form: ContactForm;
|
|
80
|
+
/** The site's public origin, for the checker. */
|
|
81
|
+
baseUrl: string;
|
|
82
|
+
/** The checker, when the site has one. */
|
|
83
|
+
checker?: CommentChecker | undefined;
|
|
84
|
+
/** Where the request came from, as far as the site can tell. */
|
|
85
|
+
address?: string | undefined;
|
|
86
|
+
/** The `User-Agent` header, for the checker. */
|
|
87
|
+
userAgent?: string | undefined;
|
|
88
|
+
/** The `Referer` header, for the checker. */
|
|
89
|
+
referrer?: string | undefined;
|
|
90
|
+
/** The rate limiter, kept by the mount so it outlives one request. */
|
|
91
|
+
throttle: ContactThrottle;
|
|
92
|
+
/** The clock. */
|
|
93
|
+
now?: Date | undefined;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Take a submitted form and, if it survives everything, store the message.
|
|
97
|
+
*
|
|
98
|
+
* The caller has already decided that the page offers a form at all: whether
|
|
99
|
+
* one should exist is `contactOpen`'s question, and asking it here as well
|
|
100
|
+
* would let the two answers differ.
|
|
101
|
+
*/
|
|
102
|
+
export declare function submitContactMessage(options: SubmitContactMessageOptions): Promise<ContactOutcome>;
|
|
103
|
+
//# sourceMappingURL=submission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"submission.d.ts","sourceRoot":"","sources":["../../src/contact/submission.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,2BAA2B,CAAC;AAChF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGvD,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAE9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,oEAAoE;AACpE,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC,2EAA2E;AAC3E,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAE/C,2DAA2D;AAC3D,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,UAAU,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAAC;IACxD,uCAAuC;IACvC,IAAI,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;CACrC;AAED,qDAAqD;AACrD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAEjE;AAED,iDAAiD;AACjD,MAAM,MAAM,cAAc;AACxB,sDAAsD;AACpD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,eAAe,CAAA;CAAE;AAChD,yDAAyD;GACvD;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE;AACvB,0DAA0D;GACxD;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE;AACnB,wEAAwE;GACtE;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE;AAC9C,sEAAsE;GACpE;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC;AAE1B,mCAAmC;AACnC,MAAM,MAAM,cAAc,GACxB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAAE,CAAC;AAE7F,yDAAyD;AACzD,MAAM,WAAW,2BAA2B;IAC1C,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,QAAQ,EAAE,QAAQ,CAAC;IACnB,0BAA0B;IAC1B,IAAI,EAAE,WAAW,CAAC;IAClB,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACrC,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,sEAAsE;IACtE,QAAQ,EAAE,eAAe,CAAC;IAC1B,iBAAiB;IACjB,GAAG,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,cAAc,CAAC,CAkDzB"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { formTimingRefusal, hashClientAddress, trapped } from '../forms/protection.js';
|
|
2
|
+
import { contactProblems } from './form.js';
|
|
3
|
+
import { addContactMessage } from './records.js';
|
|
4
|
+
/**
|
|
5
|
+
* What happens between somebody pressing Send and a message existing.
|
|
6
|
+
*
|
|
7
|
+
* The same four defences a comment goes through, in the same order and out of
|
|
8
|
+
* the same modules, because a contact form is the same problem as a comment
|
|
9
|
+
* form wearing different fields:
|
|
10
|
+
*
|
|
11
|
+
* 1. **The honeypot**, first, because it costs one comparison and because a
|
|
12
|
+
* submission that tripped it should not reach anything that could tell it
|
|
13
|
+
* so.
|
|
14
|
+
* 2. **The age of the form** — too new to have been typed, or too old to be
|
|
15
|
+
* the form it claims to be.
|
|
16
|
+
* 3. **The per-address rate limit**, the same limiter the login form and the
|
|
17
|
+
* comment form use, so one machine cannot send a hundred messages while
|
|
18
|
+
* nobody is looking.
|
|
19
|
+
* 4. **{@link CommentChecker}**, the one seam a third-party service plugs
|
|
20
|
+
* into, told this is a `contact-form` rather than a comment.
|
|
21
|
+
*
|
|
22
|
+
* Then the file, and only then the mail. The order is the point: a message is
|
|
23
|
+
* on disk before anything is asked to deliver it, so a provider that is down
|
|
24
|
+
* costs a notification rather than the message.
|
|
25
|
+
*/
|
|
26
|
+
/** How many messages one address may send before it has to wait. */
|
|
27
|
+
export const CONTACT_RATE_LIMIT = 5;
|
|
28
|
+
/** How long that window is, and how long the first wait after it lasts. */
|
|
29
|
+
export const CONTACT_RATE_WINDOW_SECONDS = 600;
|
|
30
|
+
/** The keys a submission is rate limited against. */
|
|
31
|
+
export function contactKeys(address) {
|
|
32
|
+
return address === undefined ? [] : [`contact:${address}`];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Take a submitted form and, if it survives everything, store the message.
|
|
36
|
+
*
|
|
37
|
+
* The caller has already decided that the page offers a form at all: whether
|
|
38
|
+
* one should exist is `contactOpen`'s question, and asking it here as well
|
|
39
|
+
* would let the two answers differ.
|
|
40
|
+
*/
|
|
41
|
+
export async function submitContactMessage(options) {
|
|
42
|
+
const { form, throttle } = options;
|
|
43
|
+
const now = options.now ?? new Date();
|
|
44
|
+
// The honeypot first, because a submission that tripped it should not reach
|
|
45
|
+
// anything that could tell it why.
|
|
46
|
+
if (trapped(form.trap))
|
|
47
|
+
return refused({ kind: 'discarded' });
|
|
48
|
+
const problems = contactProblems(form);
|
|
49
|
+
if (Object.keys(problems).length > 0)
|
|
50
|
+
return refused({ kind: 'invalid', problems });
|
|
51
|
+
const timing = formTimingRefusal(form.loaded, now);
|
|
52
|
+
if (timing !== undefined)
|
|
53
|
+
return refused({ kind: timing });
|
|
54
|
+
const keys = contactKeys(options.address);
|
|
55
|
+
const wait = throttle.retryAfter(keys);
|
|
56
|
+
if (wait !== undefined)
|
|
57
|
+
return refused({ kind: 'rate-limited', retryAfter: wait });
|
|
58
|
+
const proposed = {
|
|
59
|
+
received: now.toISOString(),
|
|
60
|
+
status: 'received',
|
|
61
|
+
page: {
|
|
62
|
+
slug: options.document.slug,
|
|
63
|
+
permalink: options.document.permalink,
|
|
64
|
+
title: options.document.title,
|
|
65
|
+
},
|
|
66
|
+
from: { name: form.name.trim(), email: form.email.trim() },
|
|
67
|
+
subject: form.subject.trim(),
|
|
68
|
+
message: form.message.trim(),
|
|
69
|
+
addressHash: hashClientAddress(options.dataDir, options.address),
|
|
70
|
+
};
|
|
71
|
+
const verdict = await ask(options, proposed, now);
|
|
72
|
+
if (verdict === 'discard') {
|
|
73
|
+
// Counted against the address even so: a machine sending rubbish should
|
|
74
|
+
// not get unlimited free attempts because the rubbish was recognised.
|
|
75
|
+
throttle.fail(keys);
|
|
76
|
+
return refused({ kind: 'discarded' });
|
|
77
|
+
}
|
|
78
|
+
// A message a checker called spam is stored all the same, on a list of its
|
|
79
|
+
// own. A false positive on a contact form is somebody's message vanishing,
|
|
80
|
+
// which is a worse failure than a spam list to glance at.
|
|
81
|
+
const message = await addContactMessage(options.dataDir, {
|
|
82
|
+
...proposed,
|
|
83
|
+
status: verdict === 'spam' ? 'spam' : 'received',
|
|
84
|
+
});
|
|
85
|
+
throttle.fail(keys);
|
|
86
|
+
return { kind: 'stored', message };
|
|
87
|
+
}
|
|
88
|
+
/** Ask the checker, if there is one, and treat a broken one as no opinion. */
|
|
89
|
+
async function ask(options, proposed, now) {
|
|
90
|
+
const checker = options.checker;
|
|
91
|
+
if (checker === undefined)
|
|
92
|
+
return 'unknown';
|
|
93
|
+
try {
|
|
94
|
+
return await checker.check({
|
|
95
|
+
// The seam takes a comment, and a contact message is not one — so it is
|
|
96
|
+
// described as the comment it most nearly is, and `type` says what it
|
|
97
|
+
// actually is. Akismet sends that as `comment_type: contact-form`, which
|
|
98
|
+
// is a value it documents; a site's own checker can read it or ignore it.
|
|
99
|
+
type: 'contact-form',
|
|
100
|
+
comment: asComment(proposed, now),
|
|
101
|
+
post: {
|
|
102
|
+
slug: options.document.slug,
|
|
103
|
+
title: options.document.title,
|
|
104
|
+
url: absolute(options.document.permalink, options.baseUrl),
|
|
105
|
+
},
|
|
106
|
+
address: options.address,
|
|
107
|
+
userAgent: options.userAgent,
|
|
108
|
+
referrer: options.referrer,
|
|
109
|
+
baseUrl: options.baseUrl,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
// A checker that is down must not stop a site taking messages; the message
|
|
114
|
+
// is stored exactly as it would have been before anybody had a checker.
|
|
115
|
+
console.warn(`The comment checker refused to answer about a message: ${messageOf(error)}`);
|
|
116
|
+
return 'unknown';
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* A proposed message in the shape the checker seam speaks.
|
|
121
|
+
*
|
|
122
|
+
* The subject is put in front of the message rather than dropped, because it
|
|
123
|
+
* is text a person wrote and a spam service should see it; the address is
|
|
124
|
+
* `null` here because the record keeps a salted hash and the seam is handed
|
|
125
|
+
* the real one separately.
|
|
126
|
+
*/
|
|
127
|
+
function asComment(proposed, now) {
|
|
128
|
+
const content = proposed.subject === '' ? proposed.message : `${proposed.subject}\n\n${proposed.message}`;
|
|
129
|
+
return {
|
|
130
|
+
slug: proposed.page.slug,
|
|
131
|
+
permalink: proposed.page.permalink,
|
|
132
|
+
source: 'comment',
|
|
133
|
+
kind: 'reply',
|
|
134
|
+
status: 'pending',
|
|
135
|
+
author: {
|
|
136
|
+
name: proposed.from.name,
|
|
137
|
+
url: null,
|
|
138
|
+
email: proposed.from.email,
|
|
139
|
+
avatar: null,
|
|
140
|
+
},
|
|
141
|
+
// Plain text, and plain text is its own HTML for a checker's purposes:
|
|
142
|
+
// nothing here is ever rendered onto a page.
|
|
143
|
+
content: { markdown: content, html: content },
|
|
144
|
+
submitted: now.toISOString(),
|
|
145
|
+
addressHash: proposed.addressHash,
|
|
146
|
+
inReplyTo: null,
|
|
147
|
+
url: null,
|
|
148
|
+
notify: false,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/** A site-root path as an absolute URL. */
|
|
152
|
+
function absolute(pathname, baseUrl) {
|
|
153
|
+
try {
|
|
154
|
+
return new URL(pathname, baseUrl).href;
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
return pathname;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function refused(refusal) {
|
|
161
|
+
return { kind: 'refused', refusal };
|
|
162
|
+
}
|
|
163
|
+
function messageOf(error) {
|
|
164
|
+
return error instanceof Error ? error.message : String(error);
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=submission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"submission.js","sourceRoot":"","sources":["../../src/contact/submission.ts"],"names":[],"mappings":"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"}
|
|
@@ -38,6 +38,11 @@ export interface Document {
|
|
|
38
38
|
updated?: string | undefined;
|
|
39
39
|
/** Taxonomy. The `post` tag comes from `posts.json`, not from the file. */
|
|
40
40
|
tags: string[];
|
|
41
|
+
/**
|
|
42
|
+
* The second taxonomy: what the document is filed under, as WordPress files
|
|
43
|
+
* a post under a category. Eleventy reads it as an ordinary data key.
|
|
44
|
+
*/
|
|
45
|
+
categories: string[];
|
|
41
46
|
/** `true` hides the document from the public site and the feeds. */
|
|
42
47
|
draft: boolean;
|
|
43
48
|
/** Meta description and excerpt fallback. */
|
|
@@ -60,7 +65,7 @@ export interface Document {
|
|
|
60
65
|
hash: string;
|
|
61
66
|
}
|
|
62
67
|
/** The part of a {@link Document} that a file is written from. */
|
|
63
|
-
export type DocumentContent = Pick<Document, 'title' | 'date' | 'updated' | 'permalink' | 'tags' | 'draft' | 'description' | 'author' | 'activitypub' | 'extra' | 'body'>;
|
|
68
|
+
export type DocumentContent = Pick<Document, 'title' | 'date' | 'updated' | 'permalink' | 'tags' | 'categories' | 'draft' | 'description' | 'author' | 'activitypub' | 'extra' | 'body'>;
|
|
64
69
|
/** Front-matter keys the CMS models. Everything else lands in `extra`. */
|
|
65
|
-
export declare const KNOWN_FRONT_MATTER_KEYS: readonly ['title', 'date', 'updated', 'permalink', 'tags', 'draft', 'description', 'author', 'activitypub'];
|
|
70
|
+
export declare const KNOWN_FRONT_MATTER_KEYS: readonly ['title', 'date', 'updated', 'permalink', 'tags', 'categories', 'draft', 'description', 'author', 'activitypub'];
|
|
66
71
|
//# sourceMappingURL=document.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../src/content/document.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC;AAE3C;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,qCAAqC;IACrC,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,QAAQ;IACvB,yDAAyD;IACzD,IAAI,EAAE,YAAY,CAAC;IACnB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,oEAAoE;IACpE,KAAK,EAAE,OAAO,CAAC;IACf,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,yEAAyE;IACzE,WAAW,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;IAC9C,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;CACd;AAED,kEAAkE;AAClE,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,QAAQ,EACN,OAAO,GACP,MAAM,GACN,SAAS,GACT,WAAW,GACX,MAAM,GACN,OAAO,GACP,aAAa,GACb,QAAQ,GACR,aAAa,GACb,OAAO,GACP,MAAM,CACT,CAAC;AAEF,0EAA0E;AAC1E,eAAO,MAAM,uBAAuB,YAClC,OAAO,EACP,MAAM,EACN,SAAS,EACT,WAAW,EACX,MAAM,EACN,OAAO,EACP,aAAa,EACb,QAAQ,EACR,aAAa,CACL,CAAC"}
|
|
1
|
+
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../src/content/document.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC;AAE3C;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,qCAAqC;IACrC,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,QAAQ;IACvB,yDAAyD;IACzD,IAAI,EAAE,YAAY,CAAC;IACnB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;OAGG;IACH,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,oEAAoE;IACpE,KAAK,EAAE,OAAO,CAAC;IACf,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,yEAAyE;IACzE,WAAW,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;IAC9C,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;CACd;AAED,kEAAkE;AAClE,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,QAAQ,EACN,OAAO,GACP,MAAM,GACN,SAAS,GACT,WAAW,GACX,MAAM,GACN,YAAY,GACZ,OAAO,GACP,aAAa,GACb,QAAQ,GACR,aAAa,GACb,OAAO,GACP,MAAM,CACT,CAAC;AAEF,0EAA0E;AAC1E,eAAO,MAAM,uBAAuB,YAClC,OAAO,EACP,MAAM,EACN,SAAS,EACT,WAAW,EACX,MAAM,EACN,YAAY,EACZ,OAAO,EACP,aAAa,EACb,QAAQ,EACR,aAAa,CACL,CAAC"}
|
package/dist/content/document.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document.js","sourceRoot":"","sources":["../../src/content/document.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"document.js","sourceRoot":"","sources":["../../src/content/document.ts"],"names":[],"mappings":"AAsFA,0EAA0E;AAC1E,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,OAAO;IACP,MAAM;IACN,SAAS;IACT,WAAW;IACX,MAAM;IACN,YAAY;IACZ,OAAO;IACP,aAAa;IACb,QAAQ;IACR,aAAa;CACL,CAAC"}
|
package/dist/content/index.d.ts
CHANGED
|
@@ -7,11 +7,16 @@ export { hashDocument, parseDocument, typeForPath } from './parser.ts';
|
|
|
7
7
|
export type { ParseDocumentOptions } from './parser.ts';
|
|
8
8
|
export { contentFilePath, freeSlug, saveDocument } from './save.ts';
|
|
9
9
|
export type { ContentFilePathInput, FreeSlugOptions, SaveDocumentOptions } from './save.ts';
|
|
10
|
+
export { htmlToText, MAXIMUM_QUERY_TERMS, searchExpression, searchText, SNIPPET_CLOSE, SNIPPET_OPEN, } from './search.ts';
|
|
11
|
+
export type { SearchText } from './search.ts';
|
|
10
12
|
export { defaultPermalink, slugify } from './slug.ts';
|
|
11
13
|
export type { DefaultPermalinkInput } from './slug.ts';
|
|
12
14
|
export { documentContent, documentFrontMatter, normalizeBody, serializeDocument, } from './writer.ts';
|
|
13
|
-
export {
|
|
14
|
-
export type {
|
|
15
|
+
export { createScheduler, isScheduled, MAXIMUM_DELAY_MS, SCHEDULE_ORIGIN, scheduledFor, systemTimers, } from './schedule.ts';
|
|
16
|
+
export type { CreateSchedulerOptions, ScheduleLogger, Scheduler, ScheduleTimers, ScheduleWatermark, } from './schedule.ts';
|
|
17
|
+
export { DATABASE_FILE, dateSortKey, DuplicatePermalinkError, isTrashedPath, openContentStore, systemClock, TRASH_DIRECTORY, } from './store.ts';
|
|
18
|
+
export type { CategoryCount, Clock, ContentCounts, ContentStore, ListAllOptions, ListByTagOptions, ListOptions, OpenContentStoreOptions, SearchHit, TagCount, } from './store.ts';
|
|
19
|
+
export { calendarDayIn, DEFAULT_TIMEZONE, toUtcInstant, wallClockIn, zoneLabel } from './time.ts';
|
|
15
20
|
export { createContentSync, DEFAULT_DEBOUNCE_MS } from './sync.ts';
|
|
16
21
|
export type { ChangeOrigin, ContentEventListener, ContentEventMap, ContentEvents, ContentSync, CreateContentSyncOptions, DocumentChange, DocumentChangeType, SyncLogger, SyncResult, } from './sync.ts';
|
|
17
22
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/content/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,YAAY,EAAE,mBAAmB,EAAE,QAAQ,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClG,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACvE,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACpE,YAAY,EAAE,oBAAoB,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAC5F,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,aAAa,EACb,WAAW,EACX,uBAAuB,EACvB,aAAa,EACb,gBAAgB,EAChB,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,aAAa,EACb,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,uBAAuB,EACvB,QAAQ,GACT,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AACnE,YAAY,EACV,YAAY,EACZ,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,WAAW,EACX,wBAAwB,EACxB,cAAc,EACd,kBAAkB,EAClB,UAAU,EACV,UAAU,GACX,MAAM,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/content/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,YAAY,EAAE,mBAAmB,EAAE,QAAQ,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClG,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACvE,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACpE,YAAY,EAAE,oBAAoB,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAC5F,OAAO,EACL,UAAU,EACV,mBAAmB,EACnB,gBAAgB,EAChB,UAAU,EACV,aAAa,EACb,YAAY,GACb,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,sBAAsB,EACtB,cAAc,EACd,SAAS,EACT,cAAc,EACd,iBAAiB,GAClB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,aAAa,EACb,WAAW,EACX,uBAAuB,EACvB,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,aAAa,EACb,KAAK,EACL,aAAa,EACb,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,uBAAuB,EACvB,SAAS,EACT,QAAQ,GACT,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAClG,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AACnE,YAAY,EACV,YAAY,EACZ,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,WAAW,EACX,wBAAwB,EACxB,cAAc,EACd,kBAAkB,EAClB,UAAU,EACV,UAAU,GACX,MAAM,WAAW,CAAC"}
|
package/dist/content/index.js
CHANGED
|
@@ -3,8 +3,11 @@ export { renderMarkdown } from './markdown.js';
|
|
|
3
3
|
export { KNOWN_UPLOAD_TYPES, matchesSignature, normalizeUploadType, UPLOAD_MEDIA_TYPES, } from './media.js';
|
|
4
4
|
export { hashDocument, parseDocument, typeForPath } from './parser.js';
|
|
5
5
|
export { contentFilePath, freeSlug, saveDocument } from './save.js';
|
|
6
|
+
export { htmlToText, MAXIMUM_QUERY_TERMS, searchExpression, searchText, SNIPPET_CLOSE, SNIPPET_OPEN, } from './search.js';
|
|
6
7
|
export { defaultPermalink, slugify } from './slug.js';
|
|
7
8
|
export { documentContent, documentFrontMatter, normalizeBody, serializeDocument, } from './writer.js';
|
|
8
|
-
export {
|
|
9
|
+
export { createScheduler, isScheduled, MAXIMUM_DELAY_MS, SCHEDULE_ORIGIN, scheduledFor, systemTimers, } from './schedule.js';
|
|
10
|
+
export { DATABASE_FILE, dateSortKey, DuplicatePermalinkError, isTrashedPath, openContentStore, systemClock, TRASH_DIRECTORY, } from './store.js';
|
|
11
|
+
export { calendarDayIn, DEFAULT_TIMEZONE, toUtcInstant, wallClockIn, zoneLabel } from './time.js';
|
|
9
12
|
export { createContentSync, DEFAULT_DEBOUNCE_MS } from './sync.js';
|
|
10
13
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/content/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAExD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEvE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEpE,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEtD,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,aAAa,EACb,WAAW,EACX,uBAAuB,EACvB,aAAa,EACb,gBAAgB,EAChB,eAAe,GAChB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/content/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAExD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEvE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEpE,OAAO,EACL,UAAU,EACV,mBAAmB,EACnB,gBAAgB,EAChB,UAAU,EACV,aAAa,EACb,YAAY,GACb,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEtD,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,eAAe,EACf,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,YAAY,GACb,MAAM,eAAe,CAAC;AAQvB,OAAO,EACL,aAAa,EACb,WAAW,EACX,uBAAuB,EACvB,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,eAAe,GAChB,MAAM,YAAY,CAAC;AAapB,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAClG,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/content/markdown.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/content/markdown.ts"],"names":[],"mappings":"AAiBA,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD"}
|
package/dist/content/markdown.js
CHANGED
|
@@ -4,15 +4,37 @@ import { slugify } from './slug.js';
|
|
|
4
4
|
/**
|
|
5
5
|
* The renderer: markdown-it with Eleventy's default option (`html: true`),
|
|
6
6
|
* plus footnotes and heading anchors. Code blocks get a language class and no
|
|
7
|
-
* highlighting
|
|
7
|
+
* highlighting and a `tabindex` on the `<pre>`, so a theme can pick its own
|
|
8
|
+
* highlighter on the client and a wide block scrolls by keyboard.
|
|
8
9
|
*/
|
|
9
10
|
const markdown = new MarkdownIt({ html: true })
|
|
10
11
|
.use(footnote)
|
|
11
|
-
.use(headingAnchors)
|
|
12
|
+
.use(headingAnchors)
|
|
13
|
+
.use(focusableCodeBlocks);
|
|
12
14
|
/** Render a Markdown body to the HTML the site and the feeds serve. */
|
|
13
15
|
export function renderMarkdown(body) {
|
|
14
16
|
return markdown.render(body);
|
|
15
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Put `tabindex="0"` on every `<pre>`, so a block of code wider than the
|
|
20
|
+
* measure can be scrolled from the keyboard.
|
|
21
|
+
*
|
|
22
|
+
* A `<pre>` scrolls sideways rather than wrapping, and a scroll container that
|
|
23
|
+
* nothing can focus is unreachable without a pointer — WCAG 2.2's keyboard
|
|
24
|
+
* criterion, and the reason the Eleventy site this design comes from passed
|
|
25
|
+
* `preAttributes: { tabindex: 0 }` to its highlighter. There is no highlighter
|
|
26
|
+
* here (a theme highlights on the client), so the renderer does it.
|
|
27
|
+
*
|
|
28
|
+
* Both block rules are wrapped: `fence` for a ``` block and `code_block` for an
|
|
29
|
+
* indented one.
|
|
30
|
+
*/
|
|
31
|
+
function focusableCodeBlocks(md) {
|
|
32
|
+
for (const rule of ['fence', 'code_block']) {
|
|
33
|
+
const original = md.renderer.rules[rule]?.bind(md.renderer.rules);
|
|
34
|
+
const render = original ?? md.renderer.renderToken.bind(md.renderer);
|
|
35
|
+
md.renderer.rules[rule] = (tokens, index, options, env, self) => render(tokens, index, options, env, self).replace('<pre>', '<pre tabindex="0">');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
16
38
|
/**
|
|
17
39
|
* Give every heading an `id` so a URL can point at it. Ids come from the same
|
|
18
40
|
* slugifier as permalinks, and repeat headings get a numeric suffix so the ids
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/content/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,aAAa,CAAC;AAErC,OAAO,QAAQ,MAAM,sBAAsB,CAAC;AAE5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/content/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,aAAa,CAAC;AAErC,OAAO,QAAQ,MAAM,sBAAsB,CAAC;AAE5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,QAAQ,GAAuB,IAAI,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;KAChE,GAAG,CAAC,QAAQ,CAAC;KACb,GAAG,CAAC,cAAc,CAAC;KACnB,GAAG,CAAC,mBAAmB,CAAC,CAAC;AAE5B,uEAAuE;AACvE,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAS,mBAAmB,CAAC,EAAsB;IACjD,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,YAAY,CAAU,EAAE,CAAC;QACpD,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,QAAQ,IAAI,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;QAErE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,CAC9D,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;IACrF,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CAAC,EAAsB;IAC5C,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,yBAAyB,EAAE,CAAC,KAAK,EAAE,EAAE;QACtD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;QACvC,IAAI,KAAK,GAAG,CAAC,CAAC;QAEd,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;YACvD,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc;gBAAE,SAAS;YAC5C,KAAK,IAAI,CAAC,CAAC;YAEX,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;YAC1C,MAAM,IAAI,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;YACxD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,WAAW,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAE/E,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;YACzB,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;QACzE,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/content/parser.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAuB,QAAQ,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAOlG,wEAAwE;AACxE,MAAM,WAAW,oBAAoB;IACnC,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,IAAI,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;CACjC;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,QAAQ,
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/content/parser.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAuB,QAAQ,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAOlG,wEAAwE;AACxE,MAAM,WAAW,oBAAoB;IACnC,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,IAAI,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;CACjC;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,QAAQ,CAiDrF;AAED,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAE7D;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAQtD"}
|
package/dist/content/parser.js
CHANGED
|
@@ -35,7 +35,8 @@ export function parseDocument(source, options) {
|
|
|
35
35
|
const content = {
|
|
36
36
|
title,
|
|
37
37
|
permalink,
|
|
38
|
-
tags:
|
|
38
|
+
tags: asTerms(data['tags']),
|
|
39
|
+
categories: asTerms(data['categories']),
|
|
39
40
|
draft: data['draft'] === true,
|
|
40
41
|
extra: extraOf(data),
|
|
41
42
|
body,
|
|
@@ -139,15 +140,21 @@ function asDate(value, key, path) {
|
|
|
139
140
|
}
|
|
140
141
|
return text;
|
|
141
142
|
}
|
|
142
|
-
/**
|
|
143
|
-
|
|
143
|
+
/**
|
|
144
|
+
* One taxonomy's terms: `tags` or `categories`.
|
|
145
|
+
*
|
|
146
|
+
* Eleventy accepts one tag as a bare string, so both keys do; the CMS always
|
|
147
|
+
* keeps a list, and both taxonomies are read the same way so a category
|
|
148
|
+
* behaves exactly as a tag does.
|
|
149
|
+
*/
|
|
150
|
+
function asTerms(value) {
|
|
144
151
|
if (value === undefined || value === null)
|
|
145
152
|
return [];
|
|
146
153
|
if (typeof value === 'string')
|
|
147
154
|
return value === '' ? [] : [value];
|
|
148
155
|
if (!Array.isArray(value))
|
|
149
156
|
return [];
|
|
150
|
-
return value.filter((
|
|
157
|
+
return value.filter((term) => typeof term === 'string' && term !== '');
|
|
151
158
|
}
|
|
152
159
|
function asActivityPub(value, path) {
|
|
153
160
|
if (value === undefined || value === null)
|