emdash 0.36.0 → 0.38.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/dist/{activation-K0kGBWuJ.mjs → activation-DyNTe_Tl.mjs} +3 -3
- package/dist/{activation-K0kGBWuJ.mjs.map → activation-DyNTe_Tl.mjs.map} +1 -1
- package/dist/{adapters-CzL3H752.d.mts → adapters-DCEgOBXi.d.mts} +4 -2
- package/dist/{adapters-CzL3H752.d.mts.map → adapters-DCEgOBXi.d.mts.map} +1 -1
- package/dist/{allowed-origins-maylGaHv.mjs → allowed-origins-GFUVavRj.mjs} +2 -2
- package/dist/{allowed-origins-maylGaHv.mjs.map → allowed-origins-GFUVavRj.mjs.map} +1 -1
- package/dist/api/route-utils.d.mts +3 -3
- package/dist/api/route-utils.mjs +25 -24
- package/dist/api/route-utils.mjs.map +1 -1
- package/dist/api/schemas/index.d.mts +2 -2
- package/dist/api/schemas/index.mjs +5 -5
- package/dist/api-BvxJmnFY.mjs +10094 -0
- package/dist/api-BvxJmnFY.mjs.map +1 -0
- package/dist/{api-tokens-9YrrCoE6.mjs → api-tokens-xpGqMHrC.mjs} +2 -2
- package/dist/{api-tokens-9YrrCoE6.mjs.map → api-tokens-xpGqMHrC.mjs.map} +1 -1
- package/dist/{apply-B_VMpJ2P.mjs → apply-DLmM3R7f.mjs} +26 -22
- package/dist/apply-DLmM3R7f.mjs.map +1 -0
- package/dist/artifact-fetch-P2JXVwOq.mjs +972 -0
- package/dist/artifact-fetch-P2JXVwOq.mjs.map +1 -0
- package/dist/astro/image-endpoint.mjs +2 -2
- package/dist/astro/image-endpoint.mjs.map +1 -1
- package/dist/astro/index.d.mts +12 -12
- package/dist/astro/index.d.mts.map +1 -1
- package/dist/astro/index.mjs +138 -39
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +10 -10
- package/dist/astro/middleware/auth.mjs +6 -6
- package/dist/astro/middleware/media-usage-write-fence.mjs +3 -3
- package/dist/astro/middleware/redirect.mjs +7 -5
- package/dist/astro/middleware/redirect.mjs.map +1 -1
- package/dist/astro/middleware/request-context.mjs +3 -3
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.d.mts +10 -10
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +223 -232
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +6 -6
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +6 -6
- package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +3 -3
- package/dist/astro/routes/api/admin/api-tokens/index.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/api-tokens/index.mjs +5 -5
- package/dist/astro/routes/api/admin/api-tokens/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +4 -4
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +9 -9
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +9 -9
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +9 -9
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +17 -17
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +17 -17
- package/dist/astro/routes/api/admin/bylines/index.mjs +17 -17
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +13 -13
- package/dist/astro/routes/api/admin/comments/_id_.mjs +5 -5
- package/dist/astro/routes/api/admin/comments/bulk.mjs +10 -10
- package/dist/astro/routes/api/admin/comments/counts.mjs +5 -5
- package/dist/astro/routes/api/admin/comments/index.mjs +10 -10
- package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +4 -4
- package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
- package/dist/astro/routes/api/admin/media-usage/activation.mjs +13 -13
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +15 -15
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +15 -15
- package/dist/astro/routes/api/admin/media-usage/progress.mjs +14 -14
- package/dist/astro/routes/api/admin/media-usage/repair.mjs +17 -17
- package/dist/astro/routes/api/admin/media-usage/work/index.mjs +15 -15
- package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +15 -15
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +4 -4
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +4 -4
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +59 -56
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +59 -56
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +57 -54
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +4 -4
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +57 -54
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +58 -55
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +58 -55
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/index.mjs +57 -54
- package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +2 -2
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +57 -54
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +58 -55
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +57 -54
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +58 -55
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +64 -57
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +18 -16
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/install.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +65 -58
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/verify.d.mts +8 -0
- package/dist/astro/routes/api/admin/plugins/registry/verify.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/plugins/registry/verify.mjs +96 -0
- package/dist/astro/routes/api/admin/plugins/registry/verify.mjs.map +1 -0
- package/dist/astro/routes/api/admin/plugins/updates.mjs +57 -54
- package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +57 -54
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +2 -2
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +57 -54
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/_id_/disable.mjs +1 -1
- package/dist/astro/routes/api/admin/users/_id_/enable.mjs +1 -1
- package/dist/astro/routes/api/admin/users/_id_/index.mjs +6 -6
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +3 -3
- package/dist/astro/routes/api/admin/users/index.mjs +6 -6
- package/dist/astro/routes/api/auth/dev-bypass.mjs +3 -3
- package/dist/astro/routes/api/auth/invite/accept.mjs +1 -1
- package/dist/astro/routes/api/auth/invite/complete.mjs +11 -11
- package/dist/astro/routes/api/auth/invite/index.mjs +8 -8
- package/dist/astro/routes/api/auth/invite/register-options.mjs +10 -10
- package/dist/astro/routes/api/auth/logout.mjs +2 -2
- package/dist/astro/routes/api/auth/magic-link/send.mjs +10 -10
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +2 -2
- package/dist/astro/routes/api/auth/me.mjs +7 -7
- package/dist/astro/routes/api/auth/mode.mjs +2 -2
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +6 -6
- package/dist/astro/routes/api/auth/passkey/index.mjs +1 -1
- package/dist/astro/routes/api/auth/passkey/options.mjs +12 -12
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +10 -10
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +11 -11
- package/dist/astro/routes/api/auth/passkey/verify.mjs +11 -11
- package/dist/astro/routes/api/auth/signup/complete.mjs +11 -11
- package/dist/astro/routes/api/auth/signup/request.mjs +10 -10
- package/dist/astro/routes/api/auth/signup/verify.mjs +1 -1
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +14 -14
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +13 -13
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +19 -5
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/lock.d.mts +10 -0
- package/dist/astro/routes/api/content/_collection_/_id_/lock.d.mts.map +1 -0
- package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs +66 -0
- package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs.map +1 -0
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +11 -11
- package/dist/astro/routes/api/content/_collection_/_id_/publish.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +18 -10
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +20 -18
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +20 -18
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +15 -8
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +16 -15
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +19 -5
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +23 -11
- package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/authors.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/index.mjs +14 -9
- package/dist/astro/routes/api/content/_collection_/index.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/trash.mjs +7 -7
- package/dist/astro/routes/api/dashboard.mjs +8 -8
- package/dist/astro/routes/api/dev/emails.mjs +2 -2
- package/dist/astro/routes/api/import/probe.d.mts +3 -3
- package/dist/astro/routes/api/import/probe.mjs +18 -18
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress/execute.mjs +15 -14
- package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -10
- package/dist/astro/routes/api/import/wordpress/media.mjs +11 -11
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +10 -10
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +13 -13
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +18 -18
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +11 -11
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +29 -28
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
- package/dist/astro/routes/api/manifest.mjs +4 -4
- package/dist/astro/routes/api/manifest.mjs.map +1 -1
- package/dist/astro/routes/api/mcp.mjs +213 -74
- package/dist/astro/routes/api/mcp.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_/confirm.mjs +11 -11
- package/dist/astro/routes/api/media/_id_/replace.d.mts +8 -0
- package/dist/astro/routes/api/media/_id_/replace.d.mts.map +1 -0
- package/dist/astro/routes/api/media/_id_/replace.mjs +91 -0
- package/dist/astro/routes/api/media/_id_/replace.mjs.map +1 -0
- package/dist/astro/routes/api/media/_id_/upload.mjs +6 -6
- package/dist/astro/routes/api/media/_id_/usage.mjs +19 -19
- package/dist/astro/routes/api/media/_id_.mjs +18 -18
- package/dist/astro/routes/api/media/file/_...key_.d.mts.map +1 -1
- package/dist/astro/routes/api/media/file/_...key_.mjs +3 -2
- package/dist/astro/routes/api/media/file/_...key_.mjs.map +1 -1
- package/dist/astro/routes/api/media/folders/_id_.mjs +8 -8
- package/dist/astro/routes/api/media/folders/index.mjs +8 -8
- package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +2 -2
- package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +2 -2
- package/dist/astro/routes/api/media/providers/index.mjs +2 -2
- package/dist/astro/routes/api/media/upload-url.mjs +16 -14
- package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
- package/dist/astro/routes/api/media.d.mts.map +1 -1
- package/dist/astro/routes/api/media.mjs +53 -30
- package/dist/astro/routes/api/media.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items/_id_.d.mts.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +20 -13
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items.d.mts.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items.mjs +15 -11
- package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/reorder.d.mts.map +1 -1
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +15 -11
- package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/translations.d.mts.map +1 -1
- package/dist/astro/routes/api/menus/_name_/translations.mjs +16 -12
- package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_.d.mts.map +1 -1
- package/dist/astro/routes/api/menus/_name_.mjs +21 -14
- package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/menus/index.d.mts.map +1 -1
- package/dist/astro/routes/api/menus/index.mjs +15 -11
- package/dist/astro/routes/api/menus/index.mjs.map +1 -1
- package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
- package/dist/astro/routes/api/oauth/device/authorize.mjs +5 -5
- package/dist/astro/routes/api/oauth/device/code.mjs +8 -8
- package/dist/astro/routes/api/oauth/device/token.mjs +7 -7
- package/dist/astro/routes/api/oauth/register.mjs +2 -2
- package/dist/astro/routes/api/oauth/token/refresh.mjs +5 -5
- package/dist/astro/routes/api/oauth/token/revoke.mjs +5 -5
- package/dist/astro/routes/api/oauth/token.mjs +5 -5
- package/dist/astro/routes/api/openapi.json.mjs +184 -52
- package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +4 -4
- package/dist/astro/routes/api/redirects/404s/index.mjs +12 -11
- package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/404s/summary.mjs +12 -11
- package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/_id_.mjs +13 -12
- package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/index.mjs +13 -12
- package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
- package/dist/astro/routes/api/relations/_id_/index.mjs +20 -18
- package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/relations/_id_/translations.mjs +15 -13
- package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/relations/index.mjs +20 -18
- package/dist/astro/routes/api/relations/index.mjs.map +1 -1
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +2 -2
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +57 -54
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +57 -54
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +57 -54
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +57 -54
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/index.mjs +57 -54
- package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/reorder.mjs +57 -54
- package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/index.mjs +13 -11
- package/dist/astro/routes/api/schema/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +57 -54
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/index.mjs +57 -54
- package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/enable.mjs +12 -11
- package/dist/astro/routes/api/search/enable.mjs.map +1 -1
- package/dist/astro/routes/api/search/index.mjs +11 -10
- package/dist/astro/routes/api/search/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/rebuild.mjs +12 -11
- package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
- package/dist/astro/routes/api/search/stats.mjs +7 -6
- package/dist/astro/routes/api/search/stats.mjs.map +1 -1
- package/dist/astro/routes/api/search/suggest.mjs +11 -10
- package/dist/astro/routes/api/search/suggest.mjs.map +1 -1
- package/dist/astro/routes/api/sections/_slug_.mjs +11 -10
- package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/sections/index.mjs +11 -10
- package/dist/astro/routes/api/sections/index.mjs.map +1 -1
- package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +7 -6
- package/dist/astro/routes/api/settings/backups/archives/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/settings/backups/archives/index.mjs +6 -5
- package/dist/astro/routes/api/settings/backups/archives/index.mjs.map +1 -1
- package/dist/astro/routes/api/settings/backups/export.mjs +7 -6
- package/dist/astro/routes/api/settings/backups/export.mjs.map +1 -1
- package/dist/astro/routes/api/settings/backups/index.mjs +8 -7
- package/dist/astro/routes/api/settings/backups/index.mjs.map +1 -1
- package/dist/astro/routes/api/settings/email.mjs +5 -5
- package/dist/astro/routes/api/settings/email.mjs.map +1 -1
- package/dist/astro/routes/api/settings.d.mts.map +1 -1
- package/dist/astro/routes/api/settings.mjs +21 -17
- package/dist/astro/routes/api/settings.mjs.map +1 -1
- package/dist/astro/routes/api/setup/admin-verify.mjs +12 -12
- package/dist/astro/routes/api/setup/admin.mjs +11 -11
- package/dist/astro/routes/api/setup/dev-bypass.mjs +35 -33
- package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
- package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
- package/dist/astro/routes/api/setup/index.mjs +35 -33
- package/dist/astro/routes/api/setup/index.mjs.map +1 -1
- package/dist/astro/routes/api/setup/status.mjs +3 -3
- package/dist/astro/routes/api/snapshot.mjs +8 -7
- package/dist/astro/routes/api/snapshot.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/reorder.d.mts.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +22 -17
- package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.d.mts.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +23 -18
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.d.mts.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +27 -19
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.d.mts.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +22 -17
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +16 -15
- package/dist/astro/routes/api/taxonomies/_name_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_.d.mts.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_.mjs +28 -20
- package/dist/astro/routes/api/taxonomies/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/index.d.mts.map +1 -1
- package/dist/astro/routes/api/taxonomies/index.mjs +22 -17
- package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
- package/dist/astro/routes/api/themes/preview.mjs +5 -5
- package/dist/astro/routes/api/typegen.mjs +4 -4
- package/dist/astro/routes/api/well-known/auth.mjs +2 -2
- package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
- package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
- package/dist/astro/routes/api/widget-areas/_name_/reorder.d.mts.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +10 -8
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.d.mts.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +18 -14
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets.d.mts.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +16 -13
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_.d.mts.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_.mjs +9 -7
- package/dist/astro/routes/api/widget-areas/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/index.d.mts.map +1 -1
- package/dist/astro/routes/api/widget-areas/index.mjs +16 -13
- package/dist/astro/routes/api/widget-areas/index.mjs.map +1 -1
- package/dist/astro/routes/api/widget-components.mjs +2 -2
- package/dist/astro/routes/robots.txt.mjs +8 -8
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +13 -12
- package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
- package/dist/astro/routes/sitemap.xml.mjs +9 -9
- package/dist/astro/types.d.mts +50 -20
- package/dist/astro/types.d.mts.map +1 -1
- package/dist/auth/providers/github.d.mts +1 -1
- package/dist/auth/providers/google.d.mts +1 -1
- package/dist/{authorize-ByYs-Uxs.mjs → authorize-C2QHlWSS.mjs} +2 -2
- package/dist/{authorize-ByYs-Uxs.mjs.map → authorize-C2QHlWSS.mjs.map} +1 -1
- package/dist/{backup-ChyHfIoX.mjs → backup-oS8ft5Cm.mjs} +5 -5
- package/dist/{backup-ChyHfIoX.mjs.map → backup-oS8ft5Cm.mjs.map} +1 -1
- package/dist/{bundle-DZFhFurR.mjs → bundle-CL0JjIPx.mjs} +4 -4
- package/dist/{bundle-DZFhFurR.mjs.map → bundle-CL0JjIPx.mjs.map} +1 -1
- package/dist/{byline-Cpnwrje1.mjs → byline-Vdi85CsZ.mjs} +27 -14
- package/dist/byline-Vdi85CsZ.mjs.map +1 -0
- package/dist/{byline-fields-CAyA_Umd.mjs → byline-fields-DPVRFMz2.mjs} +2 -2
- package/dist/{byline-fields-CAyA_Umd.mjs.map → byline-fields-DPVRFMz2.mjs.map} +1 -1
- package/dist/{byline-registry-Bpu9-MVs.mjs → byline-registry-BxDGIO0I.mjs} +2 -2
- package/dist/{byline-registry-Bpu9-MVs.mjs.map → byline-registry-BxDGIO0I.mjs.map} +1 -1
- package/dist/{bylines-BSo9B9RX.mjs → bylines-BX8QhcTk.mjs} +7 -7
- package/dist/{bylines-BSo9B9RX.mjs.map → bylines-BX8QhcTk.mjs.map} +1 -1
- package/dist/{bylines-CHjvehVX.mjs → bylines-w-E1IEQd.mjs} +3 -3
- package/dist/{bylines-CHjvehVX.mjs.map → bylines-w-E1IEQd.mjs.map} +1 -1
- package/dist/{cache-5VirJ2Cn.mjs → cache--7HKu5Xm.mjs} +4 -4
- package/dist/{cache-5VirJ2Cn.mjs.map → cache--7HKu5Xm.mjs.map} +1 -1
- package/dist/{capture-triggers-CNW1q3HK.mjs → capture-triggers-CeAsC76Z.mjs} +2 -2
- package/dist/{capture-triggers-CNW1q3HK.mjs.map → capture-triggers-CeAsC76Z.mjs.map} +1 -1
- package/dist/{challenge-store-D5pSY2S1.mjs → challenge-store-BIOak-tp.mjs} +5 -3
- package/dist/challenge-store-BIOak-tp.mjs.map +1 -0
- package/dist/chrome-tags-DzDQBCjX.mjs +24 -0
- package/dist/chrome-tags-DzDQBCjX.mjs.map +1 -0
- package/dist/{chunks-bNiX6_DR.mjs → chunks-VG_tyqnP.mjs} +2 -2
- package/dist/{chunks-bNiX6_DR.mjs.map → chunks-VG_tyqnP.mjs.map} +1 -1
- package/dist/cli/index.mjs +68 -40
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/cf-access.d.mts +1 -1
- package/dist/client/index.d.mts +17 -7
- package/dist/client/index.d.mts.map +1 -1
- package/dist/client/index.mjs +17 -12
- package/dist/client/index.mjs.map +1 -1
- package/dist/{collection-deletion-m_oi2c0N.mjs → collection-deletion-BCwaWTDw.mjs} +4 -4
- package/dist/{collection-deletion-m_oi2c0N.mjs.map → collection-deletion-BCwaWTDw.mjs.map} +1 -1
- package/dist/collection-slugs-cache-7lTmNzeA.mjs +85 -0
- package/dist/collection-slugs-cache-7lTmNzeA.mjs.map +1 -0
- package/dist/{comment-reaction-CRuItEjt.mjs → comment-reaction-CDyvPQRj.mjs} +2 -2
- package/dist/{comment-reaction-CRuItEjt.mjs.map → comment-reaction-CDyvPQRj.mjs.map} +1 -1
- package/dist/{comment-DhvLEdhQ.mjs → comment-vxOzWbZN.mjs} +2 -2
- package/dist/{comment-DhvLEdhQ.mjs.map → comment-vxOzWbZN.mjs.map} +1 -1
- package/dist/{comments-CLj4bi8I.mjs → comments-VzmVLyaC.mjs} +2 -2
- package/dist/{comments-CLj4bi8I.mjs.map → comments-VzmVLyaC.mjs.map} +1 -1
- package/dist/{components-v4U4DT2y.mjs → components-CL6Wkdk-.mjs} +1 -1
- package/dist/{components-v4U4DT2y.mjs.map → components-CL6Wkdk-.mjs.map} +1 -1
- package/dist/config--eWjQJE5.mjs +217 -0
- package/dist/config--eWjQJE5.mjs.map +1 -0
- package/dist/{index-DWbJrsAg.d.mts → config-CGAhyOjP.d.mts} +276 -76
- package/dist/config-CGAhyOjP.d.mts.map +1 -0
- package/dist/{config-DrfghTPe.d.mts → config-ChFzshGd.d.mts} +1 -1
- package/dist/{config-DrfghTPe.d.mts.map → config-ChFzshGd.d.mts.map} +1 -1
- package/dist/{content-CP-SeXNa.mjs → content-CNfMWuhY.mjs} +202 -46
- package/dist/content-CNfMWuhY.mjs.map +1 -0
- package/dist/{content-list-query-BhejKVqb.d.mts → content-list-query-B8d4UQp9.d.mts} +1 -1
- package/dist/{content-list-query-BhejKVqb.d.mts.map → content-list-query-B8d4UQp9.d.mts.map} +1 -1
- package/dist/{content-refresh-DLOfIhYc.mjs → content-refresh-GTMyi2Xy.mjs} +53 -26
- package/dist/content-refresh-GTMyi2Xy.mjs.map +1 -0
- package/dist/{content-repair-BCxzy0r4.mjs → content-repair-CIMt5C0U.mjs} +4 -4
- package/dist/{content-repair-BCxzy0r4.mjs.map → content-repair-CIMt5C0U.mjs.map} +1 -1
- package/dist/{context-BR5hRWiK.mjs → context-C9PB8vGd.mjs} +308 -33
- package/dist/context-C9PB8vGd.mjs.map +1 -0
- package/dist/{cron-CWfWrWKG.mjs → cron-DHAy9oyq.mjs} +1 -1
- package/dist/{cron-CWfWrWKG.mjs.map → cron-DHAy9oyq.mjs.map} +1 -1
- package/dist/{dashboard-CkIV2rnQ.mjs → dashboard-BNSvAN8A.mjs} +5 -5
- package/dist/{dashboard-CkIV2rnQ.mjs.map → dashboard-BNSvAN8A.mjs.map} +1 -1
- package/dist/db/index.d.mts +3 -3
- package/dist/db/index.mjs +2 -2
- package/dist/db/index.mjs.map +1 -1
- package/dist/db/libsql-migrations.d.mts +1 -1
- package/dist/db/libsql-migrations.mjs +5 -5
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/postgres-migrations.d.mts +1 -1
- package/dist/db/postgres-migrations.mjs +5 -5
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/postgres.d.mts.map +1 -1
- package/dist/db/postgres.mjs +19 -3
- package/dist/db/postgres.mjs.map +1 -1
- package/dist/db/sqlite-migrations.d.mts +1 -1
- package/dist/db/sqlite-migrations.mjs +5 -5
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/db/sqlite.mjs +1 -1
- package/dist/{default-YMEfcQUx.mjs → default-ByZ0JqZo.mjs} +1 -1
- package/dist/{default-YMEfcQUx.mjs.map → default-ByZ0JqZo.mjs.map} +1 -1
- package/dist/{deferred-tasks-DfqxH5Xf.d.mts → deferred-tasks-Cu4NSJpa.d.mts} +1 -1
- package/dist/{deferred-tasks-DfqxH5Xf.d.mts.map → deferred-tasks-Cu4NSJpa.d.mts.map} +1 -1
- package/dist/dev-typegen-DHT7lcMU.mjs +29 -0
- package/dist/dev-typegen-DHT7lcMU.mjs.map +1 -0
- package/dist/{device-flow-CojjSBwb.mjs → device-flow-Cf6bhCCT.mjs} +4 -4
- package/dist/{device-flow-CojjSBwb.mjs.map → device-flow-Cf6bhCCT.mjs.map} +1 -1
- package/dist/{dialect-helpers-BSbfaO3F.mjs → dialect-helpers-BcQvkHgn.mjs} +83 -2
- package/dist/dialect-helpers-BcQvkHgn.mjs.map +1 -0
- package/dist/{direct-executor-BWeWiRYB.mjs → direct-executor-yAyUGSqB.mjs} +3 -3
- package/dist/{direct-executor-BWeWiRYB.mjs.map → direct-executor-yAyUGSqB.mjs.map} +1 -1
- package/dist/{dist-89xCrGqi.mjs → dist-BAsh8dbf.mjs} +1 -1
- package/dist/{dist-89xCrGqi.mjs.map → dist-BAsh8dbf.mjs.map} +1 -1
- package/dist/{email-console-CEJgR_LB.mjs → email-console-DNup1Fku.mjs} +1 -1
- package/dist/{email-console-CEJgR_LB.mjs.map → email-console-DNup1Fku.mjs.map} +1 -1
- package/dist/{enrich-BX0IDp4z.mjs → enrich-t2Xvjdqa.mjs} +3 -3
- package/dist/{enrich-BX0IDp4z.mjs.map → enrich-t2Xvjdqa.mjs.map} +1 -1
- package/dist/entry-lock-BEr8gDkG.mjs +163 -0
- package/dist/entry-lock-BEr8gDkG.mjs.map +1 -0
- package/dist/{relations-C7B46bcU.d.mts → entry-lock-CGAtrwAR.d.mts} +265 -76
- package/dist/entry-lock-CGAtrwAR.d.mts.map +1 -0
- package/dist/{redirects-CRIM55KH.mjs → entry-lock-DIYHAaSw.mjs} +112 -34
- package/dist/entry-lock-DIYHAaSw.mjs.map +1 -0
- package/dist/entry-locks-BEcX7ET0.mjs +167 -0
- package/dist/entry-locks-BEcX7ET0.mjs.map +1 -0
- package/dist/{error-D9w94fjV.mjs → error-BDcFyoRt.mjs} +2 -2
- package/dist/{error-D9w94fjV.mjs.map → error-BDcFyoRt.mjs.map} +1 -1
- package/dist/{errors-n2j49uNf.mjs → errors-DvMdNrgf.mjs} +10 -1
- package/dist/errors-DvMdNrgf.mjs.map +1 -0
- package/dist/{escape-DN4Qmjsl.mjs → escape-B3asJC6W.mjs} +1 -1
- package/dist/{escape-DN4Qmjsl.mjs.map → escape-B3asJC6W.mjs.map} +1 -1
- package/dist/{field-defs-cache-Bh4q6oar.mjs → field-defs-cache-Cf5FHK0M.mjs} +5 -5
- package/dist/{field-defs-cache-Bh4q6oar.mjs.map → field-defs-cache-Cf5FHK0M.mjs.map} +1 -1
- package/dist/{fts-manager-BhOdW0bi.mjs → fts-manager-iddym8cd.mjs} +4 -4
- package/dist/{fts-manager-BhOdW0bi.mjs.map → fts-manager-iddym8cd.mjs.map} +1 -1
- package/dist/{hash-CTcngWvj.mjs → hash-BRweX6jz.mjs} +1 -1
- package/dist/{hash-CTcngWvj.mjs.map → hash-BRweX6jz.mjs.map} +1 -1
- package/dist/hook-result-BrshYHLx.d.mts +31 -0
- package/dist/hook-result-BrshYHLx.d.mts.map +1 -0
- package/dist/{hreflang-7pTHsLZJ.d.mts → hreflang-CQpu5bMy.d.mts} +2 -2
- package/dist/{hreflang-7pTHsLZJ.d.mts.map → hreflang-CQpu5bMy.d.mts.map} +1 -1
- package/dist/{hreflang-Huc6O5wa.mjs → hreflang-DshnweTC.mjs} +9 -8
- package/dist/{hreflang-Huc6O5wa.mjs.map → hreflang-DshnweTC.mjs.map} +1 -1
- package/dist/{identity-DXmb4aVp.mjs → identity-CjGKDq8J.mjs} +3 -3
- package/dist/{identity-DXmb4aVp.mjs.map → identity-CjGKDq8J.mjs.map} +1 -1
- package/dist/{import-C4_O3KXU.mjs → import-D96g2otw.mjs} +6 -6
- package/dist/{import-C4_O3KXU.mjs.map → import-D96g2otw.mjs.map} +1 -1
- package/dist/{index-6bRee8zb.d.mts → index-1ECYpfiF.d.mts} +3 -3
- package/dist/{index-6bRee8zb.d.mts.map → index-1ECYpfiF.d.mts.map} +1 -1
- package/dist/index.d.mts +22 -21
- package/dist/index.mjs +84 -81
- package/dist/{init-lock-DJkX6Hto.mjs → init-lock-CFNBe_iH.mjs} +1 -1
- package/dist/{init-lock-DJkX6Hto.mjs.map → init-lock-CFNBe_iH.mjs.map} +1 -1
- package/dist/{load-Bo7fZAbg.mjs → load-DPtY9cZo.mjs} +2 -2
- package/dist/{load-Bo7fZAbg.mjs.map → load-DPtY9cZo.mjs.map} +1 -1
- package/dist/{loader-ZsjE4paL.mjs → loader-WJi6GFRn.mjs} +90 -17
- package/dist/loader-WJi6GFRn.mjs.map +1 -0
- package/dist/{manifest-builder-QXuqvVMP.mjs → manifest-builder-BfNlGQIA.mjs} +2 -2
- package/dist/{manifest-builder-QXuqvVMP.mjs.map → manifest-builder-BfNlGQIA.mjs.map} +1 -1
- package/dist/{manifest-schema-CUYPfCEH.mjs → manifest-schema-CILooI5J.mjs} +5 -5
- package/dist/manifest-schema-CILooI5J.mjs.map +1 -0
- package/dist/media/image-endpoint.d.mts +4 -2
- package/dist/media/image-endpoint.d.mts.map +1 -1
- package/dist/media/image-endpoint.mjs +6 -4
- package/dist/media/image-endpoint.mjs.map +1 -1
- package/dist/media/index.d.mts +1 -1
- package/dist/media/index.mjs +3 -3
- package/dist/media/local-runtime.d.mts +12 -12
- package/dist/media/local-runtime.mjs +7 -7
- package/dist/{media-D6SeAfBl.mjs → media-BBm8Wg3f.mjs} +30 -2
- package/dist/media-BBm8Wg3f.mjs.map +1 -0
- package/dist/{media-BjwNuLEu.mjs → media-C1EIZKh1.mjs} +35 -5
- package/dist/media-C1EIZKh1.mjs.map +1 -0
- package/dist/{media-allowlist-D35v7bmL.mjs → media-allowlist-elXJgb_K.mjs} +2 -2
- package/dist/{media-allowlist-D35v7bmL.mjs.map → media-allowlist-elXJgb_K.mjs.map} +1 -1
- package/dist/{media-folders-D-0CmRZj.mjs → media-folders-DASfX_DH.mjs} +1 -1
- package/dist/{media-folders-D-0CmRZj.mjs.map → media-folders-DASfX_DH.mjs.map} +1 -1
- package/dist/{media-upload-C7bLXGcI.mjs → media-upload-C7_AQJ5v.mjs} +9 -9
- package/dist/{media-upload-C7bLXGcI.mjs.map → media-upload-C7_AQJ5v.mjs.map} +1 -1
- package/dist/{media-url-DH7giMx_.mjs → media-url-8dVl1loq.mjs} +19 -2
- package/dist/media-url-8dVl1loq.mjs.map +1 -0
- package/dist/{media-usage-BTRJvS6V.mjs → media-usage-C1EswMTq.mjs} +10 -10
- package/dist/{media-usage-BTRJvS6V.mjs.map → media-usage-C1EswMTq.mjs.map} +1 -1
- package/dist/{media-usage-activation-Dx0kPV6b.mjs → media-usage-activation-CrHNltlL.mjs} +3 -3
- package/dist/{media-usage-activation-Dx0kPV6b.mjs.map → media-usage-activation-CrHNltlL.mjs.map} +1 -1
- package/dist/{media-usage-work-C-fhM30c.mjs → media-usage-work-C5B1zT1c.mjs} +2 -2
- package/dist/{media-usage-work-C-fhM30c.mjs.map → media-usage-work-C5B1zT1c.mjs.map} +1 -1
- package/dist/{media-usage-work-DWb2XPMI.mjs → media-usage-work-IkQx_Yz6.mjs} +4 -4
- package/dist/{media-usage-work-DWb2XPMI.mjs.map → media-usage-work-IkQx_Yz6.mjs.map} +1 -1
- package/dist/{media-usage-write-fence-BwoJVRDC.mjs → media-usage-write-fence-B9anjOSg.mjs} +3 -3
- package/dist/{media-usage-write-fence-BwoJVRDC.mjs.map → media-usage-write-fence-B9anjOSg.mjs.map} +1 -1
- package/dist/{menus-CNg0QlDt.mjs → menus-D8mC4eaN.mjs} +406 -175
- package/dist/menus-D8mC4eaN.mjs.map +1 -0
- package/dist/{menus-CD7EFLwz.mjs → menus-UdwjHZJC.mjs} +12 -4
- package/dist/{menus-CD7EFLwz.mjs.map → menus-UdwjHZJC.mjs.map} +1 -1
- package/dist/migrations/index.d.mts +1 -1
- package/dist/migrations/index.mjs +4 -4
- package/dist/{mime-CUIG6x84.mjs → mime-DYpsOAny.mjs} +1 -1
- package/dist/{mime-CUIG6x84.mjs.map → mime-DYpsOAny.mjs.map} +1 -1
- package/dist/{mode-DaUM_MB2.mjs → mode-Dm4BHhRH.mjs} +1 -1
- package/dist/{mode-DaUM_MB2.mjs.map → mode-Dm4BHhRH.mjs.map} +1 -1
- package/dist/{node-sqlite-compat-Udb4Y-rs.mjs → node-sqlite-compat-2sezm-Zd.mjs} +1 -1
- package/dist/{node-sqlite-compat-Udb4Y-rs.mjs.map → node-sqlite-compat-2sezm-Zd.mjs.map} +1 -1
- package/dist/{normalize-CSxdKBVa.mjs → normalize-4nkKGsuW.mjs} +15 -5
- package/dist/normalize-4nkKGsuW.mjs.map +1 -0
- package/dist/{oauth-authorization-Dpsb-fMJ.mjs → oauth-authorization-BxE_lURD.mjs} +4 -4
- package/dist/{oauth-authorization-Dpsb-fMJ.mjs.map → oauth-authorization-BxE_lURD.mjs.map} +1 -1
- package/dist/{oauth-clients-Bxnoe_67.mjs → oauth-clients-DJIdOdq0.mjs} +1 -1
- package/dist/{oauth-clients-Bxnoe_67.mjs.map → oauth-clients-DJIdOdq0.mjs.map} +1 -1
- package/dist/{oauth-state-store-0C4s0K6w.mjs → oauth-state-store-CsdxP57n.mjs} +1 -1
- package/dist/{oauth-state-store-0C4s0K6w.mjs.map → oauth-state-store-CsdxP57n.mjs.map} +1 -1
- package/dist/{oauth-user-lookup-wlGYSeqX.mjs → oauth-user-lookup-HzzW-dkF.mjs} +1 -1
- package/dist/{oauth-user-lookup-wlGYSeqX.mjs.map → oauth-user-lookup-HzzW-dkF.mjs.map} +1 -1
- package/dist/object-cache/memory.d.mts +1 -1
- package/dist/{object-cache-71tPfV4A.mjs → object-cache-DVKnyOfy.mjs} +19 -3
- package/dist/object-cache-DVKnyOfy.mjs.map +1 -0
- package/dist/{options-BHPeIbBd.mjs → options-D1FBiAv1.mjs} +60 -5
- package/dist/options-D1FBiAv1.mjs.map +1 -0
- package/dist/{options-BhZIeFY1.d.mts → options-D8Y0VHc7.d.mts} +30 -11
- package/dist/options-D8Y0VHc7.d.mts.map +1 -0
- package/dist/page/index.d.mts +2 -2
- package/dist/page/index.d.mts.map +1 -1
- package/dist/page/index.mjs +12 -0
- package/dist/page/index.mjs.map +1 -1
- package/dist/{parse-BRJg1kz8.mjs → parse-WRg5C3NX.mjs} +2 -2
- package/dist/{parse-BRJg1kz8.mjs.map → parse-WRg5C3NX.mjs.map} +1 -1
- package/dist/{passkey-config-B3P0nHRR.mjs → passkey-config-qIdO-wF6.mjs} +1 -1
- package/dist/{passkey-config-B3P0nHRR.mjs.map → passkey-config-qIdO-wF6.mjs.map} +1 -1
- package/dist/{patterns-D9iDO3j8.mjs → patterns-DC8CLptu.mjs} +1 -1
- package/dist/{patterns-D9iDO3j8.mjs.map → patterns-DC8CLptu.mjs.map} +1 -1
- package/dist/{placeholder-BR4ZhVJl.d.mts → placeholder-COrvARyD.d.mts} +1 -1
- package/dist/{placeholder-BR4ZhVJl.d.mts.map → placeholder-COrvARyD.d.mts.map} +1 -1
- package/dist/plugin-types.d.mts +8 -3
- package/dist/plugin-types.d.mts.map +1 -1
- package/dist/plugin-utils.d.mts +10 -10
- package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
- package/dist/plugins/adapt-sandbox-entry.mjs +2 -2
- package/dist/{policy-BVRganJQ.mjs → policy-XCfb-IE9.mjs} +2 -2
- package/dist/{policy-BVRganJQ.mjs.map → policy-XCfb-IE9.mjs.map} +1 -1
- package/dist/{portable-text-C8Tvp4_g.mjs → portable-text-BS3d5n-0.mjs} +1 -1
- package/dist/{portable-text-C8Tvp4_g.mjs.map → portable-text-BS3d5n-0.mjs.map} +1 -1
- package/dist/{preview-dn2dUyM0.mjs → preview-BxwsGgGp.mjs} +2 -2
- package/dist/{preview-dn2dUyM0.mjs.map → preview-BxwsGgGp.mjs.map} +1 -1
- package/dist/{protocol-CuBEsqgE.d.mts → protocol-CLn58-nw.d.mts} +2 -2
- package/dist/{protocol-CuBEsqgE.d.mts.map → protocol-CLn58-nw.d.mts.map} +1 -1
- package/dist/{public-url-DRz_AinV.mjs → public-url-FWWAvnre.mjs} +1 -1
- package/dist/{public-url-DRz_AinV.mjs.map → public-url-FWWAvnre.mjs.map} +1 -1
- package/dist/{query-D18vTdha.mjs → query-DygOte9M.mjs} +26 -17
- package/dist/query-DygOte9M.mjs.map +1 -0
- package/dist/{query-tZDEdtCN.mjs → query-gtXT03Wc.mjs} +5 -5
- package/dist/{query-tZDEdtCN.mjs.map → query-gtXT03Wc.mjs.map} +1 -1
- package/dist/{rate-limit-on7KPo-v.mjs → rate-limit-CQUPm0dh.mjs} +2 -2
- package/dist/{rate-limit-on7KPo-v.mjs.map → rate-limit-CQUPm0dh.mjs.map} +1 -1
- package/dist/{redirect-DrbEmU9a.mjs → redirect-D1cWafi6.mjs} +1 -1
- package/dist/{redirect-DrbEmU9a.mjs.map → redirect-D1cWafi6.mjs.map} +1 -1
- package/dist/{redirect-CZkbozu9.mjs → redirect-DId44BS1.mjs} +19 -6
- package/dist/redirect-DId44BS1.mjs.map +1 -0
- package/dist/{redirects-BahWiu8Z.mjs → redirects-DN-ZE33W.mjs} +5 -5
- package/dist/{redirects-BahWiu8Z.mjs.map → redirects-DN-ZE33W.mjs.map} +1 -1
- package/dist/{registry-Cx-jEJOS.mjs → registry-DTqaqxed.mjs} +46 -12
- package/dist/registry-DTqaqxed.mjs.map +1 -0
- package/dist/{relation-A6wLF_DS.mjs → relation-DxgCHOBw.mjs} +2 -2
- package/dist/{relation-A6wLF_DS.mjs.map → relation-DxgCHOBw.mjs.map} +1 -1
- package/dist/{relations-Cj5hZ6Zg.mjs → relations-KKDSLUwS.mjs} +4 -4
- package/dist/{relations-Cj5hZ6Zg.mjs.map → relations-KKDSLUwS.mjs.map} +1 -1
- package/dist/{relations-BTPM2saV.mjs → relations-rOmbndUJ.mjs} +8 -8
- package/dist/relations-rOmbndUJ.mjs.map +1 -0
- package/dist/{request-cache-DH9zdCOD.mjs → request-cache-DAZZmesc.mjs} +1 -1
- package/dist/{request-cache-DH9zdCOD.mjs.map → request-cache-DAZZmesc.mjs.map} +1 -1
- package/dist/request-context.d.mts +1 -1
- package/dist/{request-meta-DRp5ENd_.mjs → request-meta-BgjUQLQ-.mjs} +2 -2
- package/dist/{request-meta-DRp5ENd_.mjs.map → request-meta-BgjUQLQ-.mjs.map} +1 -1
- package/dist/{resolve-DxUpTMmE.mjs → resolve-Cy0aWSRj.mjs} +37 -4
- package/dist/resolve-Cy0aWSRj.mjs.map +1 -0
- package/dist/{runner-zgqA_CqP.d.mts → runner-CfwysRM0.d.mts} +3 -2
- package/dist/runner-CfwysRM0.d.mts.map +1 -0
- package/dist/{runner-77GOZCnH.mjs → runner-nEzvnogG.mjs} +476 -295
- package/dist/runner-nEzvnogG.mjs.map +1 -0
- package/dist/runtime.d.mts +11 -11
- package/dist/runtime.mjs +3 -2
- package/dist/runtime.mjs.map +1 -1
- package/dist/{schema-BY-oVntF.mjs → schema-CRu38Pr5.mjs} +3 -3
- package/dist/{schema-BY-oVntF.mjs.map → schema-CRu38Pr5.mjs.map} +1 -1
- package/dist/{schema-Cw9kVK0I.mjs → schema-DifxndJx.mjs} +5 -5
- package/dist/{schema-Cw9kVK0I.mjs.map → schema-DifxndJx.mjs.map} +1 -1
- package/dist/{scopes-vMR1uIbt.mjs → scopes-D5A1OZbq.mjs} +3 -3
- package/dist/{scopes-vMR1uIbt.mjs.map → scopes-D5A1OZbq.mjs.map} +1 -1
- package/dist/{search-CfT3KxO5.mjs → search-DEPFSBFq.mjs} +4 -4
- package/dist/{search-CfT3KxO5.mjs.map → search-DEPFSBFq.mjs.map} +1 -1
- package/dist/{secrets-BH2Qow1-.mjs → secrets-CdfzLdoO.mjs} +3 -3
- package/dist/{secrets-BH2Qow1-.mjs.map → secrets-CdfzLdoO.mjs.map} +1 -1
- package/dist/{sections-DTfjyf1z.mjs → sections-3X52kmIR.mjs} +2 -2
- package/dist/{sections-DTfjyf1z.mjs.map → sections-3X52kmIR.mjs.map} +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +28 -26
- package/dist/seo/index.d.mts +3 -3
- package/dist/seo/index.d.mts.map +1 -1
- package/dist/seo/index.mjs +20 -21
- package/dist/seo/index.mjs.map +1 -1
- package/dist/{seo-Cm-dtvgk.mjs → seo-Bw68KxRc.mjs} +3 -3
- package/dist/{seo-Cm-dtvgk.mjs.map → seo-Bw68KxRc.mjs.map} +1 -1
- package/dist/{seo-BSiTIXzd.mjs → seo-C4AmbsMU.mjs} +3 -2
- package/dist/seo-C4AmbsMU.mjs.map +1 -0
- package/dist/{service-DYsDHEKe.mjs → service-J_-Vgo7R.mjs} +3 -3
- package/dist/{service-DYsDHEKe.mjs.map → service-J_-Vgo7R.mjs.map} +1 -1
- package/dist/{session-user-CNAfvsdw.mjs → session-user-CbnMMwk6.mjs} +1 -1
- package/dist/{session-user-CNAfvsdw.mjs.map → session-user-CbnMMwk6.mjs.map} +1 -1
- package/dist/{settings-DjtkUo__.mjs → settings-AnEFYICn.mjs} +3 -3
- package/dist/{settings-DjtkUo__.mjs.map → settings-AnEFYICn.mjs.map} +1 -1
- package/dist/{settings-BgN-0DT-.mjs → settings-DcMjREe5.mjs} +21 -8
- package/dist/settings-DcMjREe5.mjs.map +1 -0
- package/dist/{setup-complete-CcpXaPU7.mjs → setup-complete-BClXXTvr.mjs} +2 -2
- package/dist/{setup-complete-CcpXaPU7.mjs.map → setup-complete-BClXXTvr.mjs.map} +1 -1
- package/dist/{setup-nonce-Reyw30jg.mjs → setup-nonce-BheRa4RG.mjs} +1 -1
- package/dist/{setup-nonce-Reyw30jg.mjs.map → setup-nonce-BheRa4RG.mjs.map} +1 -1
- package/dist/{single-flight-cache-BPuGPdcN.mjs → single-flight-cache-jaswDzmQ.mjs} +2 -2
- package/dist/{single-flight-cache-BPuGPdcN.mjs.map → single-flight-cache-jaswDzmQ.mjs.map} +1 -1
- package/dist/{site-url-Cs_V9n3V.mjs → site-url-Bqf-ea3N.mjs} +3 -3
- package/dist/{site-url-Cs_V9n3V.mjs.map → site-url-Bqf-ea3N.mjs.map} +1 -1
- package/dist/{snapshot-DSB8P7Lm.mjs → snapshot-C4CtXntb.mjs} +51 -35
- package/dist/snapshot-C4CtXntb.mjs.map +1 -0
- package/dist/{ssrf-DqebVE34.mjs → ssrf-gl4gFNhw.mjs} +151 -93
- package/dist/ssrf-gl4gFNhw.mjs.map +1 -0
- package/dist/{state-BJfU9Uzw.mjs → state-1F6IOhdQ.mjs} +1 -1
- package/dist/{state-BJfU9Uzw.mjs.map → state-1F6IOhdQ.mjs.map} +1 -1
- package/dist/{status-DDu8HIQl.mjs → status-Cenfk_r5.mjs} +1 -1
- package/dist/{status-DDu8HIQl.mjs.map → status-Cenfk_r5.mjs.map} +1 -1
- package/dist/storage/local.d.mts +2 -1
- package/dist/storage/local.d.mts.map +1 -1
- package/dist/storage/local.mjs +1 -1
- package/dist/storage/local.mjs.map +1 -1
- package/dist/storage/s3.d.mts +2 -1
- package/dist/storage/s3.d.mts.map +1 -1
- package/dist/storage/s3.mjs +3 -2
- package/dist/storage/s3.mjs.map +1 -1
- package/dist/{target-D0o26Azo.mjs → target-CRzeTs8G.mjs} +1 -1
- package/dist/{target-D0o26Azo.mjs.map → target-CRzeTs8G.mjs.map} +1 -1
- package/dist/{taxonomies-CPGxo-bn.mjs → taxonomies-BOdxuZpV.mjs} +23 -13
- package/dist/taxonomies-BOdxuZpV.mjs.map +1 -0
- package/dist/{taxonomies-kmyudNGP.mjs → taxonomies-NcFDq5Gg.mjs} +58 -23
- package/dist/taxonomies-NcFDq5Gg.mjs.map +1 -0
- package/dist/{taxonomy-8X09dLN5.mjs → taxonomy-DP1vny4K.mjs} +12 -4
- package/dist/{taxonomy-8X09dLN5.mjs.map → taxonomy-DP1vny4K.mjs.map} +1 -1
- package/dist/{tokens-gTS-IVUp.mjs → tokens-CDk8ox9p.mjs} +1 -1
- package/dist/{tokens-gTS-IVUp.mjs.map → tokens-CDk8ox9p.mjs.map} +1 -1
- package/dist/{transport-_6R1ub7t.d.mts → transport-BVn4tVb9.d.mts} +1 -1
- package/dist/{transport-_6R1ub7t.d.mts.map → transport-BVn4tVb9.d.mts.map} +1 -1
- package/dist/{transport-fX59xaJz.mjs → transport-DP0JI-8i.mjs} +1 -1
- package/dist/{transport-fX59xaJz.mjs.map → transport-DP0JI-8i.mjs.map} +1 -1
- package/dist/{trusted-proxy-fe6nEgR4.mjs → trusted-proxy-BTM6UxqD.mjs} +1 -1
- package/dist/{trusted-proxy-fe6nEgR4.mjs.map → trusted-proxy-BTM6UxqD.mjs.map} +1 -1
- package/dist/{types-D_DWe7k9.d.mts → types-2n848aVW.d.mts} +3 -2
- package/dist/types-2n848aVW.d.mts.map +1 -0
- package/dist/types-A2cN6a4a.mjs +3 -0
- package/dist/{types-75KIqzL9.mjs → types-BMXnRIrX.mjs} +4 -2
- package/dist/types-BMXnRIrX.mjs.map +1 -0
- package/dist/{types-Vg6f5i3s.d.mts → types-BouXpOsa.d.mts} +121 -4
- package/dist/types-BouXpOsa.d.mts.map +1 -0
- package/dist/{types-BXUmsINL.mjs → types-ByG2coLw.mjs} +1 -1
- package/dist/{types-BXUmsINL.mjs.map → types-ByG2coLw.mjs.map} +1 -1
- package/dist/types-CQPWhPxE.mjs.map +1 -1
- package/dist/{types-Blb-MRC3.d.mts → types-DEfNJ__A.d.mts} +1 -1
- package/dist/{types-Blb-MRC3.d.mts.map → types-DEfNJ__A.d.mts.map} +1 -1
- package/dist/{types-Br-ERaxh.d.mts → types-DKcKSbtB.d.mts} +23 -7
- package/dist/types-DKcKSbtB.d.mts.map +1 -0
- package/dist/{types-BzBd3PeX.d.mts → types-DRYs7uTL.d.mts} +1 -1
- package/dist/{types-BzBd3PeX.d.mts.map → types-DRYs7uTL.d.mts.map} +1 -1
- package/dist/{types-CLqvnd05.d.mts → types-DaEg7KX2.d.mts} +1 -1
- package/dist/{types-CLqvnd05.d.mts.map → types-DaEg7KX2.d.mts.map} +1 -1
- package/dist/{types-DJQxln7q.d.mts → types-LU8utpP_.d.mts} +14 -10
- package/dist/types-LU8utpP_.d.mts.map +1 -0
- package/dist/{types-D5VVLr7J.d.mts → types-VpYfPUxN.d.mts} +1 -1
- package/dist/{types-D5VVLr7J.d.mts.map → types-VpYfPUxN.d.mts.map} +1 -1
- package/dist/{types-DM3vioBY.mjs → types-c9GP7Dj5.mjs} +1 -1
- package/dist/{types-DM3vioBY.mjs.map → types-c9GP7Dj5.mjs.map} +1 -1
- package/dist/{types-DHxzBjbD.d.mts → types-tJWDK__M.d.mts} +14 -1
- package/dist/types-tJWDK__M.d.mts.map +1 -0
- package/dist/{upload-attempts-CNyGSepg.mjs → upload-attempts-C6S2y-lp.mjs} +1 -1
- package/dist/{upload-attempts-CNyGSepg.mjs.map → upload-attempts-C6S2y-lp.mjs.map} +1 -1
- package/dist/{url-pattern-K-KdXcSe.mjs → url-pattern-UYtxVTuj.mjs} +1 -1
- package/dist/{url-pattern-K-KdXcSe.mjs.map → url-pattern-UYtxVTuj.mjs.map} +1 -1
- package/dist/{user-CtYY0tp2.mjs → user-DIsIXogT.mjs} +2 -2
- package/dist/{user-CtYY0tp2.mjs.map → user-DIsIXogT.mjs.map} +1 -1
- package/dist/{utils-HztC73hq.mjs → utils-BicP5Qbg.mjs} +2 -2
- package/dist/{utils-HztC73hq.mjs.map → utils-BicP5Qbg.mjs.map} +1 -1
- package/dist/{validate-Dd-IUjnZ.mjs → validate-D8VPn4Hv.mjs} +8 -3
- package/dist/validate-D8VPn4Hv.mjs.map +1 -0
- package/dist/{validate-DlqdOZXB.d.mts → validate-Df6Dvwbw.d.mts} +12 -7
- package/dist/validate-Df6Dvwbw.d.mts.map +1 -0
- package/dist/{validation-D83n7Npi.mjs → validation-CzMJn9Ku.mjs} +13 -11
- package/dist/{validation-D83n7Npi.mjs.map → validation-CzMJn9Ku.mjs.map} +1 -1
- package/dist/version-CK67_SXX.mjs +7 -0
- package/dist/{version-ri-sCyAp.mjs.map → version-CK67_SXX.mjs.map} +1 -1
- package/dist/{widgets-CpmZd9Q-.mjs → widgets-RFVAxQl3.mjs} +18 -5
- package/dist/widgets-RFVAxQl3.mjs.map +1 -0
- package/dist/{wxr-taxonomies-BFd0y72_.d.mts → wxr-taxonomies-BX4yQL9s.d.mts} +1 -1
- package/dist/{wxr-taxonomies-BFd0y72_.d.mts.map → wxr-taxonomies-BX4yQL9s.d.mts.map} +1 -1
- package/dist/{wxr-taxonomies-Df4vxWcU.mjs → wxr-taxonomies-Csdp7yde.mjs} +4 -4
- package/dist/{wxr-taxonomies-Df4vxWcU.mjs.map → wxr-taxonomies-Csdp7yde.mjs.map} +1 -1
- package/dist/{zod-generator-DylzusHh.mjs → zod-generator-CNRGdnBY.mjs} +11 -7
- package/dist/zod-generator-CNRGdnBY.mjs.map +1 -0
- package/package.json +16 -11
- package/src/api/errors.ts +9 -0
- package/src/api/handlers/content.ts +115 -90
- package/src/api/handlers/entry-lock.ts +206 -0
- package/src/api/handlers/index.ts +1 -0
- package/src/api/handlers/manifest.ts +162 -12
- package/src/api/handlers/marketplace.ts +28 -20
- package/src/api/handlers/media.ts +30 -0
- package/src/api/handlers/menus.ts +9 -0
- package/src/api/handlers/registry.ts +406 -297
- package/src/api/handlers/revision.ts +2 -1
- package/src/api/handlers/seo.ts +10 -1
- package/src/api/handlers/snapshot.ts +84 -72
- package/src/api/handlers/taxonomies.ts +25 -9
- package/src/api/openapi/document.ts +196 -11
- package/src/api/parse.ts +1 -1
- package/src/api/schemas/auth.ts +4 -4
- package/src/api/schemas/bylines.ts +3 -3
- package/src/api/schemas/comments.ts +1 -1
- package/src/api/schemas/common.ts +3 -2
- package/src/api/schemas/content.ts +86 -22
- package/src/api/schemas/entry-lock.ts +48 -0
- package/src/api/schemas/index.ts +1 -0
- package/src/api/schemas/media.ts +52 -0
- package/src/api/schemas/redirects.ts +6 -1
- package/src/api/schemas/schema.ts +14 -1
- package/src/api/schemas/setup.ts +1 -1
- package/src/api/schemas/taxonomies.ts +2 -2
- package/src/api/schemas/users.ts +1 -1
- package/src/api/types.ts +25 -10
- package/src/astro/dev-typegen.ts +35 -0
- package/src/astro/image-endpoint.ts +2 -2
- package/src/astro/integration/dev-typegen.ts +91 -0
- package/src/astro/integration/index.ts +18 -50
- package/src/astro/integration/routes.ts +10 -0
- package/src/astro/integration/runtime.ts +13 -5
- package/src/astro/integration/vite-config.ts +51 -2
- package/src/astro/middleware.ts +21 -0
- package/src/astro/routes/api/admin/api-tokens/index.ts +4 -1
- package/src/astro/routes/api/admin/oauth-clients/[id].ts +1 -1
- package/src/astro/routes/api/admin/oauth-clients/index.ts +1 -1
- package/src/astro/routes/api/admin/plugins/registry/[id]/update.ts +4 -0
- package/src/astro/routes/api/admin/plugins/registry/artifact.ts +3 -7
- package/src/astro/routes/api/admin/plugins/registry/install.ts +4 -0
- package/src/astro/routes/api/admin/plugins/registry/verify.ts +60 -0
- package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +18 -2
- package/src/astro/routes/api/content/[collection]/[id]/lock.ts +133 -0
- package/src/astro/routes/api/content/[collection]/[id]/publish.ts +12 -1
- package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +20 -0
- package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +16 -2
- package/src/astro/routes/api/content/[collection]/[id].ts +27 -2
- package/src/astro/routes/api/content/[collection]/index.ts +3 -0
- package/src/astro/routes/api/manifest.ts +1 -1
- package/src/astro/routes/api/media/[id]/replace.ts +114 -0
- package/src/astro/routes/api/media/file/[...key].ts +4 -1
- package/src/astro/routes/api/media/upload-url.ts +8 -4
- package/src/astro/routes/api/media.ts +54 -8
- package/src/astro/routes/api/menus/[name]/items/[id].ts +7 -2
- package/src/astro/routes/api/menus/[name]/items.ts +4 -1
- package/src/astro/routes/api/menus/[name]/reorder.ts +4 -1
- package/src/astro/routes/api/menus/[name]/translations.ts +4 -1
- package/src/astro/routes/api/menus/[name].ts +7 -2
- package/src/astro/routes/api/menus/index.ts +4 -1
- package/src/astro/routes/api/settings/email.ts +1 -1
- package/src/astro/routes/api/settings.ts +4 -1
- package/src/astro/routes/api/taxonomies/[name]/reorder.ts +4 -1
- package/src/astro/routes/api/taxonomies/[name]/terms/[slug]/translations.ts +4 -1
- package/src/astro/routes/api/taxonomies/[name]/terms/[slug].ts +7 -2
- package/src/astro/routes/api/taxonomies/[name]/terms/index.ts +4 -1
- package/src/astro/routes/api/taxonomies/[name].ts +7 -2
- package/src/astro/routes/api/taxonomies/index.ts +4 -1
- package/src/astro/routes/api/widget-areas/[name]/reorder.ts +3 -1
- package/src/astro/routes/api/widget-areas/[name]/widgets/[id].ts +5 -2
- package/src/astro/routes/api/widget-areas/[name]/widgets.ts +3 -1
- package/src/astro/routes/api/widget-areas/[name].ts +3 -1
- package/src/astro/routes/api/widget-areas/index.ts +3 -1
- package/src/astro/routes/sitemap-[collection].xml.ts +4 -0
- package/src/astro/types.ts +36 -8
- package/src/auth/challenge-store.ts +3 -1
- package/src/aws-sdk.d.ts +1 -0
- package/src/cache/chrome-tags.ts +24 -0
- package/src/cli/commands/content.ts +31 -5
- package/src/cli/commands/export-seed.ts +2 -0
- package/src/client/index.ts +34 -7
- package/src/components/EmDashBodyEnd.astro +4 -1
- package/src/components/EmDashBodyStart.astro +4 -1
- package/src/components/EmDashHead.astro +35 -16
- package/src/components/EmDashImage.astro +2 -1
- package/src/components/EmDashMedia.astro +2 -1
- package/src/components/Gallery.astro +18 -4
- package/src/components/InlineEditor.astro +3 -1
- package/src/components/InlinePortableTextEditor.tsx +112 -12
- package/src/components/PortableText.astro +4 -0
- package/src/components/Table.astro +147 -62
- package/src/components/widgets/Archives.astro +2 -37
- package/src/config/errors.ts +13 -0
- package/src/content/converters/index.ts +2 -0
- package/src/content/converters/mark-safety.ts +1 -0
- package/src/content/converters/portable-text-identity.ts +139 -0
- package/src/content/converters/portable-text-to-prosemirror.ts +226 -69
- package/src/content/converters/prosemirror-to-portable-text.ts +128 -28
- package/src/content/converters/types.ts +11 -0
- package/src/database/dialect-helpers.ts +125 -0
- package/src/database/migrations/017_authorization_codes.ts +14 -4
- package/src/database/migrations/074_content_deleted_scheduled_index.ts +55 -0
- package/src/database/migrations/075_entry_edit_locks.ts +44 -0
- package/src/database/migrations/076_collection_nav_group.ts +22 -0
- package/src/database/migrations/077_plugin_storage_revisions.ts +89 -0
- package/src/database/migrations/runner.ts +9 -1
- package/src/database/repositories/byline.ts +32 -16
- package/src/database/repositories/content.ts +284 -48
- package/src/database/repositories/entry-locks.ts +257 -0
- package/src/database/repositories/media-usage.ts +66 -37
- package/src/database/repositories/media.ts +60 -1
- package/src/database/repositories/options.ts +69 -5
- package/src/database/repositories/plugin-storage.ts +233 -9
- package/src/database/repositories/redirect.ts +17 -6
- package/src/database/repositories/taxonomy.ts +8 -0
- package/src/database/repositories/types.ts +11 -7
- package/src/database/types.ts +15 -1
- package/src/db/adapters.ts +8 -1
- package/src/db/postgres.ts +23 -0
- package/src/emdash-runtime.ts +196 -199
- package/src/fields/boolean.ts +1 -1
- package/src/fields/datetime.ts +1 -1
- package/src/fields/file.ts +1 -1
- package/src/fields/integer.ts +1 -1
- package/src/fields/json.ts +1 -1
- package/src/fields/multiselect.ts +1 -1
- package/src/fields/number.ts +1 -1
- package/src/fields/portable-text.ts +1 -1
- package/src/fields/richtext.ts +1 -1
- package/src/fields/select.ts +1 -1
- package/src/fields/slug.ts +1 -1
- package/src/fields/text.ts +1 -1
- package/src/fields/textarea.ts +1 -1
- package/src/fields/types.ts +2 -2
- package/src/i18n/resolve.ts +44 -4
- package/src/index.ts +39 -3
- package/src/loader.ts +96 -12
- package/src/mcp/server.ts +251 -29
- package/src/media/image-endpoint.ts +5 -2
- package/src/media/normalize.ts +15 -4
- package/src/media/responsive.ts +23 -0
- package/src/media/usage/cleanup.ts +9 -8
- package/src/media/usage/content-refresh.ts +2 -1
- package/src/menus/index.ts +33 -21
- package/src/object-cache/index.ts +44 -2
- package/src/page/seo-contributions.ts +78 -1
- package/src/page/seo-panel.ts +47 -0
- package/src/plugin-types.ts +27 -1
- package/src/plugins/conditional-storage.ts +30 -0
- package/src/plugins/context.ts +49 -17
- package/src/plugins/hooks.ts +10 -1
- package/src/plugins/index.ts +15 -0
- package/src/plugins/manager.ts +6 -2
- package/src/plugins/manifest-schema.ts +1 -1
- package/src/plugins/routes.ts +3 -1
- package/src/plugins/sandbox/hook-result.ts +52 -0
- package/src/plugins/sandbox/index.ts +10 -0
- package/src/plugins/sandbox/types.ts +16 -2
- package/src/plugins/storage-query.ts +45 -0
- package/src/plugins/storage-update.ts +96 -0
- package/src/plugins/types.ts +120 -0
- package/src/query.ts +29 -3
- package/src/registry/artifact-checksum.ts +15 -0
- package/src/registry/artifact-verification.ts +85 -0
- package/src/registry/authoritative-records.ts +180 -0
- package/src/registry/config.ts +130 -27
- package/src/registry/record-labels.ts +28 -0
- package/src/registry/types.ts +5 -6
- package/src/schema/collection-slugs-cache.ts +157 -0
- package/src/schema/registry.ts +45 -3
- package/src/schema/types.ts +25 -6
- package/src/schema/zod-generator.ts +16 -13
- package/src/security/ssrf.ts +172 -143
- package/src/seed/apply.ts +4 -0
- package/src/seed/types.ts +7 -2
- package/src/seed/validate.ts +18 -1
- package/src/seo/hreflang.ts +1 -0
- package/src/seo/index.ts +5 -10
- package/src/seo/media-url.ts +26 -0
- package/src/settings/index.ts +16 -0
- package/src/storage/local.ts +1 -0
- package/src/storage/s3.ts +2 -0
- package/src/storage/types.ts +2 -0
- package/src/taxonomies/index.ts +40 -20
- package/src/taxonomies/term-counts.ts +22 -5
- package/src/widgets/archives.ts +67 -0
- package/src/widgets/index.ts +16 -0
- package/dist/api-B0w3uBiG.mjs +0 -2269
- package/dist/api-B0w3uBiG.mjs.map +0 -1
- package/dist/apply-B_VMpJ2P.mjs.map +0 -1
- package/dist/byline-Cpnwrje1.mjs.map +0 -1
- package/dist/challenge-store-D5pSY2S1.mjs.map +0 -1
- package/dist/content-CP-SeXNa.mjs.map +0 -1
- package/dist/content-refresh-DLOfIhYc.mjs.map +0 -1
- package/dist/context-BR5hRWiK.mjs.map +0 -1
- package/dist/dialect-helpers-BSbfaO3F.mjs.map +0 -1
- package/dist/errors-n2j49uNf.mjs.map +0 -1
- package/dist/index-DWbJrsAg.d.mts.map +0 -1
- package/dist/loader-ZsjE4paL.mjs.map +0 -1
- package/dist/manifest-schema-CUYPfCEH.mjs.map +0 -1
- package/dist/media-BjwNuLEu.mjs.map +0 -1
- package/dist/media-D6SeAfBl.mjs.map +0 -1
- package/dist/media-url-DH7giMx_.mjs.map +0 -1
- package/dist/menus-CNg0QlDt.mjs.map +0 -1
- package/dist/normalize-CSxdKBVa.mjs.map +0 -1
- package/dist/object-cache-71tPfV4A.mjs.map +0 -1
- package/dist/options-BHPeIbBd.mjs.map +0 -1
- package/dist/options-BhZIeFY1.d.mts.map +0 -1
- package/dist/query-D18vTdha.mjs.map +0 -1
- package/dist/redirect-CZkbozu9.mjs.map +0 -1
- package/dist/redirects-CRIM55KH.mjs.map +0 -1
- package/dist/registry-BiO5WwPq.mjs +0 -2716
- package/dist/registry-BiO5WwPq.mjs.map +0 -1
- package/dist/registry-Cx-jEJOS.mjs.map +0 -1
- package/dist/relations-BTPM2saV.mjs.map +0 -1
- package/dist/relations-C7B46bcU.d.mts.map +0 -1
- package/dist/resolve-DxUpTMmE.mjs.map +0 -1
- package/dist/runner-77GOZCnH.mjs.map +0 -1
- package/dist/runner-zgqA_CqP.d.mts.map +0 -1
- package/dist/seo-BSiTIXzd.mjs.map +0 -1
- package/dist/settings-BgN-0DT-.mjs.map +0 -1
- package/dist/snapshot-DSB8P7Lm.mjs.map +0 -1
- package/dist/ssrf-DqebVE34.mjs.map +0 -1
- package/dist/taxonomies-CPGxo-bn.mjs.map +0 -1
- package/dist/taxonomies-kmyudNGP.mjs.map +0 -1
- package/dist/types-75KIqzL9.mjs.map +0 -1
- package/dist/types-Br-ERaxh.d.mts.map +0 -1
- package/dist/types-D6OcIp2P.mjs +0 -3
- package/dist/types-DHxzBjbD.d.mts.map +0 -1
- package/dist/types-DJQxln7q.d.mts.map +0 -1
- package/dist/types-D_DWe7k9.d.mts.map +0 -1
- package/dist/types-Vg6f5i3s.d.mts.map +0 -1
- package/dist/validate-Dd-IUjnZ.mjs.map +0 -1
- package/dist/validate-DlqdOZXB.d.mts.map +0 -1
- package/dist/version-ri-sCyAp.mjs +0 -7
- package/dist/widgets-CpmZd9Q-.mjs.map +0 -1
- package/dist/zod-generator-DylzusHh.mjs.map +0 -1
- /package/dist/{api-tokens-B5NHLNUN.mjs → api-tokens-B_lfpmH3.mjs} +0 -0
- /package/dist/{ssrf-BPKzkm6O.mjs → ssrf-TQhaljuI.mjs} +0 -0
package/dist/page/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/page/context.ts","../../src/page/metadata.ts","../../src/page/fragments.ts","../../src/page/jsonld.ts","../../src/page/seo-contributions.ts","../../src/page/index.ts"],"sourcesContent":["/**\n * Public page context builder\n *\n * Templates call this to describe the page being rendered.\n * The resulting context is passed to EmDashHead / EmDashBodyStart / EmDashBodyEnd.\n */\n\nimport type { BreadcrumbItem, PublicPageContext } from \"../plugins/types.js\";\n\n/** Fields shared by both input forms */\ninterface PageContextFields {\n\tkind: \"content\" | \"custom\";\n\tpageType?: string;\n\ttitle?: string | null;\n\tpageTitle?: string | null;\n\tdescription?: string | null;\n\tcanonical?: string | null;\n\timage?: string | null;\n\tcontent?: { collection: string; id: string; slug?: string | null };\n\t/** SEO overrides for OG/Twitter meta generation */\n\tseo?: {\n\t\togTitle?: string | null;\n\t\togDescription?: string | null;\n\t\togImage?: string | null;\n\t\trobots?: string | null;\n\t};\n\t/** Article metadata for Open Graph article: tags */\n\tarticleMeta?: {\n\t\tpublishedTime?: string | null;\n\t\tmodifiedTime?: string | null;\n\t\tauthor?: string | null;\n\t};\n\t/** Site name for structured data and og:site_name */\n\tsiteName?: string;\n\t/**\n\t * Breadcrumb trail for this page, root first. Pass an empty array\n\t * to explicitly opt out of breadcrumbs (e.g. homepage), or omit the\n\t * field to let consumers fall back to their own derivation.\n\t */\n\tbreadcrumbs?: BreadcrumbItem[];\n\t/** Public-facing site URL (origin) for structured data */\n\tsiteUrl?: string;\n}\n\n/** Input with Astro global -- used in .astro files */\ninterface AstroInput extends PageContextFields {\n\tAstro: { url: URL; currentLocale?: string };\n}\n\n/** Input with explicit URL -- used outside .astro files */\ninterface UrlInput extends PageContextFields {\n\turl: URL | string;\n\tlocale?: string;\n}\n\nexport type CreatePublicPageContextInput = AstroInput | UrlInput;\n\nfunction isAstroInput(input: CreatePublicPageContextInput): input is AstroInput {\n\treturn \"Astro\" in input;\n}\n\n/**\n * Build a PublicPageContext from template input.\n */\nexport function createPublicPageContext(input: CreatePublicPageContextInput): PublicPageContext {\n\tlet url: string;\n\tlet path: string;\n\tlet locale: string | null;\n\n\tif (isAstroInput(input)) {\n\t\turl = input.Astro.url.href;\n\t\tpath = input.Astro.url.pathname;\n\t\tlocale = input.Astro.currentLocale ?? null;\n\t} else {\n\t\tconst parsed = typeof input.url === \"string\" ? new URL(input.url) : input.url;\n\t\turl = parsed.href;\n\t\tpath = parsed.pathname;\n\t\tlocale = input.locale ?? null;\n\t}\n\n\treturn {\n\t\turl,\n\t\tpath,\n\t\tlocale,\n\t\tkind: input.kind,\n\t\tpageType: input.pageType ?? (input.kind === \"content\" ? \"article\" : \"website\"),\n\t\ttitle: input.title ?? null,\n\t\tpageTitle: input.pageTitle ?? null,\n\t\tdescription: input.description ?? null,\n\t\tcanonical: input.canonical ?? null,\n\t\timage: input.image ?? null,\n\t\tcontent: input.content\n\t\t\t? {\n\t\t\t\t\tcollection: input.content.collection,\n\t\t\t\t\tid: input.content.id,\n\t\t\t\t\tslug: input.content.slug ?? null,\n\t\t\t\t}\n\t\t\t: undefined,\n\t\tseo: input.seo,\n\t\tarticleMeta: input.articleMeta,\n\t\tsiteName: input.siteName,\n\t\tbreadcrumbs: input.breadcrumbs,\n\t\tsiteUrl: input.siteUrl,\n\t};\n}\n","/**\n * Page metadata collection and rendering\n *\n * Collects typed metadata contributions from plugins via the page:metadata hook,\n * validates them, and resolves them into a deduplicated structure ready to render.\n */\n\nimport type { PageMetadataContribution, PageMetadataLinkRel } from \"../plugins/types.js\";\n\n// ── Resolved output ─────────────────────────────────────────────\n\nexport interface ResolvedPageMetadata {\n\tmeta: Array<{ name: string; content: string }>;\n\tproperties: Array<{ property: string; content: string }>;\n\tlinks: Array<{\n\t\trel: PageMetadataLinkRel;\n\t\thref: string;\n\t\threflang?: string;\n\t}>;\n\tjsonld: Array<{ id?: string; json: string }>;\n}\n\ninterface RenderPageMetadataOptions {\n\tincludeJsonLd?: boolean;\n}\n\n// ── Validation ──────────────────────────────────────────────────\n\n/** Schemes safe for use in link href attributes */\nconst SAFE_HREF_RE = /^(https?|at):\\/\\//i;\nconst HTML_ESCAPE_MAP: Record<string, string> = {\n\t\"&\": \"&\",\n\t\"<\": \"<\",\n\t\">\": \">\",\n\t'\"': \""\",\n\t\"'\": \"'\",\n};\nconst HTML_ESCAPE_RE = /[&<>\"']/g;\n\n/** Escape a string for safe use in an HTML attribute value */\nexport function escapeHtmlAttr(value: string): string {\n\treturn value.replace(HTML_ESCAPE_RE, (ch) => HTML_ESCAPE_MAP[ch] ?? ch);\n}\n\n/** Validate that a URL uses a safe scheme (http, https, at) */\nfunction isSafeHref(url: string): boolean {\n\treturn SAFE_HREF_RE.test(url);\n}\n\n// ── JSON-LD serialization ───────────────────────────────────────\n\nconst JSONLD_LT_RE = /</g;\nconst JSONLD_GT_RE = />/g;\nconst JSONLD_U2028_RE = /\\u2028/g;\nconst JSONLD_U2029_RE = /\\u2029/g;\n\n/**\n * Safely serialize a value for embedding in a <script type=\"application/ld+json\"> tag.\n *\n * Plain JSON.stringify is not sufficient because:\n * - \"</script>\" in a nested string breaks out of the script tag\n * - \"<!--\" can open an HTML comment\n * - U+2028/U+2029 are line terminators in some JS engines\n */\nexport function safeJsonLdSerialize(value: unknown): string {\n\treturn JSON.stringify(value)\n\t\t.replace(JSONLD_LT_RE, \"\\\\u003c\")\n\t\t.replace(JSONLD_GT_RE, \"\\\\u003e\")\n\t\t.replace(JSONLD_U2028_RE, \"\\\\u2028\")\n\t\t.replace(JSONLD_U2029_RE, \"\\\\u2029\");\n}\n\nexport async function createSha256CspHash(value: string): Promise<string> {\n\tconst digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(value));\n\tconst bytes = new Uint8Array(digest);\n\tlet binary = \"\";\n\tfor (const byte of bytes) {\n\t\tbinary += String.fromCharCode(byte);\n\t}\n\treturn `sha256-${btoa(binary)}`;\n}\n\ninterface CspScriptHashSink {\n\tinsertScriptHash(hash: string): void;\n}\n\n/**\n * Register JSON-LD hashes with Astro's CSP runtime when CSP is enabled.\n *\n * The getter stays lazy because Astro warns when `Astro.csp` is accessed on a\n * project that has not enabled its built-in CSP support.\n */\nexport async function registerJsonLdCspHashes(\n\tenabled: boolean,\n\tgetCsp: () => CspScriptHashSink | undefined,\n\tscripts: ReadonlyArray<{ json: string }>,\n): Promise<void> {\n\tif (!enabled || scripts.length === 0) return;\n\n\tconst csp = getCsp();\n\tif (!csp) return;\n\n\tawait Promise.all(\n\t\tscripts.map(async ({ json }) => {\n\t\t\tcsp.insertScriptHash(await createSha256CspHash(json));\n\t\t}),\n\t);\n}\n\n// ── Merge / dedupe ──────────────────────────────────────────────\n\n/**\n * Resolve a flat list of contributions into deduplicated metadata.\n * First contribution wins for any given dedupe key.\n */\nexport function resolvePageMetadata(\n\tcontributions: PageMetadataContribution[],\n): ResolvedPageMetadata {\n\tconst result: ResolvedPageMetadata = {\n\t\tmeta: [],\n\t\tproperties: [],\n\t\tlinks: [],\n\t\tjsonld: [],\n\t};\n\n\tconst seenMeta = new Set<string>();\n\tconst seenProperties = new Set<string>();\n\tconst seenLinks = new Set<string>();\n\tconst seenJsonLd = new Set<string>();\n\n\tfor (const c of contributions) {\n\t\tswitch (c.kind) {\n\t\t\tcase \"meta\": {\n\t\t\t\tconst dedupeKey = c.key ?? c.name;\n\t\t\t\tif (seenMeta.has(dedupeKey)) continue;\n\t\t\t\tseenMeta.add(dedupeKey);\n\t\t\t\tresult.meta.push({ name: c.name, content: c.content });\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"property\": {\n\t\t\t\tconst dedupeKey = c.key ?? c.property;\n\t\t\t\tif (seenProperties.has(dedupeKey)) continue;\n\t\t\t\tseenProperties.add(dedupeKey);\n\t\t\t\tresult.properties.push({\n\t\t\t\t\tproperty: c.property,\n\t\t\t\t\tcontent: c.content,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"link\": {\n\t\t\t\tif (!isSafeHref(c.href)) {\n\t\t\t\t\tif (import.meta.env?.DEV) {\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`[page:metadata] Rejected link contribution with unsafe href scheme: ${c.href}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (c.rel === \"canonical\") {\n\t\t\t\t\tif (seenLinks.has(\"canonical\")) continue;\n\t\t\t\t\tseenLinks.add(\"canonical\");\n\t\t\t\t} else {\n\t\t\t\t\tconst dedupeKey = c.key ?? c.hreflang ?? c.href;\n\t\t\t\t\tif (seenLinks.has(dedupeKey)) continue;\n\t\t\t\t\tseenLinks.add(dedupeKey);\n\t\t\t\t}\n\t\t\t\tresult.links.push({\n\t\t\t\t\trel: c.rel,\n\t\t\t\t\thref: c.href,\n\t\t\t\t\t...(c.hreflang && { hreflang: c.hreflang }),\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"jsonld\": {\n\t\t\t\tif (c.id) {\n\t\t\t\t\tif (seenJsonLd.has(c.id)) continue;\n\t\t\t\t\tseenJsonLd.add(c.id);\n\t\t\t\t}\n\t\t\t\tresult.jsonld.push({\n\t\t\t\t\tid: c.id,\n\t\t\t\t\tjson: safeJsonLdSerialize(c.graph),\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\t// Unknown contribution kind -- skip silently at runtime.\n\t\t\t\t// TypeScript catches this at compile time for typed callers,\n\t\t\t\t// but sandboxed plugins may return unexpected shapes.\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// ── HTML rendering ──────────────────────────────────────────────\n\n/** Render resolved metadata to an HTML string for embedding in <head> */\nexport function renderPageMetadata(\n\tmetadata: ResolvedPageMetadata,\n\toptions: RenderPageMetadataOptions = {},\n): string {\n\tconst parts: string[] = [];\n\tconst includeJsonLd = options.includeJsonLd ?? true;\n\n\tfor (const m of metadata.meta) {\n\t\tparts.push(`<meta name=\"${escapeHtmlAttr(m.name)}\" content=\"${escapeHtmlAttr(m.content)}\">`);\n\t}\n\n\tfor (const p of metadata.properties) {\n\t\tparts.push(\n\t\t\t`<meta property=\"${escapeHtmlAttr(p.property)}\" content=\"${escapeHtmlAttr(p.content)}\">`,\n\t\t);\n\t}\n\n\tfor (const l of metadata.links) {\n\t\tlet tag = `<link rel=\"${escapeHtmlAttr(l.rel)}\" href=\"${escapeHtmlAttr(l.href)}\"`;\n\t\tif (l.hreflang) {\n\t\t\ttag += ` hreflang=\"${escapeHtmlAttr(l.hreflang)}\"`;\n\t\t}\n\t\ttag += \">\";\n\t\tparts.push(tag);\n\t}\n\n\tif (includeJsonLd) {\n\t\tfor (const j of metadata.jsonld) {\n\t\t\tparts.push(`<script type=\"application/ld+json\">${j.json}</script>`);\n\t\t}\n\t}\n\n\treturn parts.join(\"\\n\");\n}\n","/**\n * Page fragment collection and rendering\n *\n * Collects raw markup / script contributions from trusted plugins via\n * the page:fragments hook. Sandboxed plugins are never invoked.\n */\n\nimport type { PageFragmentContribution, PagePlacement } from \"../plugins/types.js\";\nimport { escapeHtmlAttr } from \"./metadata.js\";\n\n/** Escape sequences that would break out of a script tag */\nconst SCRIPT_CLOSE_RE = /<\\//g;\n\n// ── Dedupe and filter ───────────────────────────────────────────\n\n/**\n * Filter contributions to a specific placement and deduplicate.\n * - Contributions with the same `key + placement` are deduped (first wins).\n * - External scripts with the same `src + placement` are deduped.\n */\nexport function resolveFragments(\n\tcontributions: PageFragmentContribution[],\n\tplacement: PagePlacement,\n): PageFragmentContribution[] {\n\tconst filtered = contributions.filter((c) => c.placement === placement);\n\tconst seen = new Set<string>();\n\tconst result: PageFragmentContribution[] = [];\n\n\tfor (const c of filtered) {\n\t\t// Key-based dedupe\n\t\tif (c.key) {\n\t\t\tconst dedupeKey = `key:${c.key}`;\n\t\t\tif (seen.has(dedupeKey)) continue;\n\t\t\tseen.add(dedupeKey);\n\t\t} else if (c.kind === \"external-script\") {\n\t\t\tconst dedupeKey = `src:${c.src}`;\n\t\t\tif (seen.has(dedupeKey)) continue;\n\t\t\tseen.add(dedupeKey);\n\t\t}\n\n\t\tresult.push(c);\n\t}\n\n\treturn result;\n}\n\n// ── HTML rendering ──────────────────────────────────────────────\n\nconst EVENT_HANDLER_RE = /^on/i;\n\nfunction renderAttributes(attrs: Record<string, string>): string {\n\treturn Object.entries(attrs)\n\t\t.filter(([k]) => !EVENT_HANDLER_RE.test(k))\n\t\t.map(([k, v]) => ` ${escapeHtmlAttr(k)}=\"${escapeHtmlAttr(v)}\"`)\n\t\t.join(\"\");\n}\n\n/** Render a single fragment contribution to HTML */\nfunction renderFragment(c: PageFragmentContribution): string {\n\tswitch (c.kind) {\n\t\tcase \"external-script\": {\n\t\t\tlet tag = `<script src=\"${escapeHtmlAttr(c.src)}\"`;\n\t\t\tif (c.async) tag += \" async\";\n\t\t\tif (c.defer) tag += \" defer\";\n\t\t\tif (c.attributes) tag += renderAttributes(c.attributes);\n\t\t\ttag += \"></script>\";\n\t\t\treturn tag;\n\t\t}\n\t\tcase \"inline-script\": {\n\t\t\tlet tag = \"<script\";\n\t\t\tif (c.attributes) tag += renderAttributes(c.attributes);\n\t\t\t// Escape </ to <\\/ to prevent breaking out of the script tag.\n\t\t\t// This is valid JS and protects against code built from user data.\n\t\t\ttag += `>${c.code.replace(SCRIPT_CLOSE_RE, \"<\\\\/\")}</script>`;\n\t\t\treturn tag;\n\t\t}\n\t\tcase \"html\":\n\t\t\treturn c.html;\n\t}\n}\n\n/** Render a list of fragment contributions to an HTML string */\nexport function renderFragments(\n\tcontributions: PageFragmentContribution[],\n\tplacement: PagePlacement,\n): string {\n\tconst resolved = resolveFragments(contributions, placement);\n\treturn resolved.map(renderFragment).join(\"\\n\");\n}\n","/**\n * JSON-LD structured data builders\n *\n * Moved from template SEO.astro components into core so all JSON-LD\n * is serialized via safeJsonLdSerialize() and never hand-rolled in templates.\n */\n\nimport type { PublicPageContext } from \"../plugins/types.js\";\n\n/**\n * Remove null/undefined values from a JSON-LD object recursively.\n * JSON-LD validators prefer absent keys over null values.\n */\nexport function cleanJsonLd(obj: Record<string, unknown>): Record<string, unknown> {\n\tconst cleaned: Record<string, unknown> = {};\n\tfor (const [key, value] of Object.entries(obj)) {\n\t\tif (value !== undefined && value !== null) {\n\t\t\tif (typeof value === \"object\" && !Array.isArray(value)) {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- non-null, non-array object is safely treated as Record<string, unknown> for JSON-LD traversal\n\t\t\t\tcleaned[key] = cleanJsonLd(value as Record<string, unknown>);\n\t\t\t} else {\n\t\t\t\tcleaned[key] = value;\n\t\t\t}\n\t\t}\n\t}\n\treturn cleaned;\n}\n\n/**\n * Build a BlogPosting JSON-LD graph from page context.\n * Used for article-type content pages.\n *\n * @param page - Page context for the current request.\n * @param defaultOgImage - Optional site-wide fallback image URL, used when\n * the page has no own OG image. Matches the fallback applied to `og:image`\n * in `generateBaseSeoContributions`.\n */\nexport function buildBlogPostingJsonLd(\n\tpage: PublicPageContext,\n\tdefaultOgImage?: string | null,\n): Record<string, unknown> | null {\n\tif (page.pageType !== \"article\" || !page.canonical) return null;\n\n\tconst ogTitle = page.seo?.ogTitle ?? page.pageTitle ?? page.title;\n\tconst description = page.seo?.ogDescription || page.description;\n\tconst ogImage = page.seo?.ogImage || page.image || defaultOgImage || null;\n\tconst publishedTime = page.articleMeta?.publishedTime;\n\tconst modifiedTime = page.articleMeta?.modifiedTime;\n\tconst author = page.articleMeta?.author;\n\tconst siteName = page.siteName;\n\n\treturn cleanJsonLd({\n\t\t\"@context\": \"https://schema.org\",\n\t\t\"@type\": \"BlogPosting\",\n\t\theadline: ogTitle,\n\t\tdescription,\n\t\timage: ogImage || undefined,\n\t\turl: page.canonical,\n\t\tdatePublished: publishedTime || undefined,\n\t\tdateModified: modifiedTime || publishedTime || undefined,\n\t\tauthor: author\n\t\t\t? {\n\t\t\t\t\t\"@type\": \"Person\",\n\t\t\t\t\tname: author,\n\t\t\t\t}\n\t\t\t: undefined,\n\t\tpublisher: siteName\n\t\t\t? {\n\t\t\t\t\t\"@type\": \"Organization\",\n\t\t\t\t\tname: siteName,\n\t\t\t\t}\n\t\t\t: undefined,\n\t\tmainEntityOfPage: {\n\t\t\t\"@type\": \"WebPage\",\n\t\t\t\"@id\": page.canonical,\n\t\t},\n\t});\n}\n\n/**\n * Build a WebSite JSON-LD graph from page context.\n * Used for non-article pages (homepage, listing pages, etc.)\n */\nexport function buildWebSiteJsonLd(page: PublicPageContext): Record<string, unknown> | null {\n\tconst siteName = page.siteName;\n\tif (!siteName) return null;\n\n\t// Use configured public origin, falling back to page URL origin\n\tlet siteUrl: string;\n\tif (page.siteUrl) {\n\t\tsiteUrl = page.siteUrl;\n\t} else {\n\t\ttry {\n\t\t\tsiteUrl = new URL(page.url).origin;\n\t\t} catch {\n\t\t\tsiteUrl = page.canonical || page.url;\n\t\t}\n\t}\n\n\treturn cleanJsonLd({\n\t\t\"@context\": \"https://schema.org\",\n\t\t\"@type\": \"WebSite\",\n\t\tname: siteName,\n\t\turl: siteUrl,\n\t});\n}\n","/**\n * Generate base SEO metadata contributions from PublicPageContext.\n *\n * EmDashHead.astro composes the final contribution list as\n * `[...plugin, ...site, ...base]` and feeds it to `resolvePageMetadata()`,\n * which is first-wins. That ordering means plugin contributions override\n * site-level ones override base ones for any given key — base values are\n * the fallback, not the source of truth.\n *\n * This replaces the per-template SEO.astro components, eliminating\n * the class of XSS bugs where templates hand-rolled JSON-LD serialization.\n */\n\nimport type { PageMetadataContribution, PublicPageContext } from \"../plugins/types.js\";\nimport type { SeoSettings } from \"../settings/types.js\";\nimport { buildBlogPostingJsonLd, buildWebSiteJsonLd } from \"./jsonld.js\";\n\n/**\n * Generate base metadata contributions from a page context's SEO data.\n *\n * @param page - Page context produced by the runtime for the current request.\n * @param defaultOgImage - Optional site-wide fallback OG image URL, used when\n * the page has no own OG image (i.e., neither `seo.ogImage` nor `image`).\n * Sourced from `SiteSettings.seo.defaultOgImage` by `EmDashHead`.\n *\n * Returns an empty array if no SEO-relevant data is present.\n */\nexport function generateBaseSeoContributions(\n\tpage: PublicPageContext,\n\tdefaultOgImage?: string | null,\n): PageMetadataContribution[] {\n\tconst contributions: PageMetadataContribution[] = [];\n\n\tconst description = page.description;\n\tconst ogTitle = page.seo?.ogTitle ?? page.pageTitle ?? page.title;\n\tconst ogDescription = page.seo?.ogDescription || description;\n\tconst ogImage = page.seo?.ogImage || page.image || defaultOgImage || null;\n\tconst robots = page.seo?.robots;\n\tconst canonical = page.canonical;\n\tconst siteName = page.siteName;\n\n\t// -- Meta tags --\n\n\tif (description) {\n\t\tcontributions.push({ kind: \"meta\", name: \"description\", content: description });\n\t}\n\n\tif (robots) {\n\t\tcontributions.push({ kind: \"meta\", name: \"robots\", content: robots });\n\t}\n\n\t// -- Canonical link --\n\n\tif (canonical) {\n\t\tcontributions.push({ kind: \"link\", rel: \"canonical\", href: canonical });\n\t}\n\n\t// -- Open Graph --\n\n\tcontributions.push({\n\t\tkind: \"property\",\n\t\tproperty: \"og:type\",\n\t\tcontent: page.pageType === \"article\" ? \"article\" : \"website\",\n\t});\n\n\tif (ogTitle) {\n\t\tcontributions.push({ kind: \"property\", property: \"og:title\", content: ogTitle });\n\t}\n\n\tif (ogDescription) {\n\t\tcontributions.push({ kind: \"property\", property: \"og:description\", content: ogDescription });\n\t}\n\n\tif (ogImage) {\n\t\tcontributions.push({ kind: \"property\", property: \"og:image\", content: ogImage });\n\t}\n\n\tif (canonical) {\n\t\tcontributions.push({ kind: \"property\", property: \"og:url\", content: canonical });\n\t}\n\n\tif (siteName) {\n\t\tcontributions.push({ kind: \"property\", property: \"og:site_name\", content: siteName });\n\t}\n\n\t// -- Twitter Card --\n\n\tcontributions.push({\n\t\tkind: \"meta\",\n\t\tname: \"twitter:card\",\n\t\tcontent: ogImage ? \"summary_large_image\" : \"summary\",\n\t});\n\n\tif (ogTitle) {\n\t\tcontributions.push({ kind: \"meta\", name: \"twitter:title\", content: ogTitle });\n\t}\n\n\tif (ogDescription) {\n\t\tcontributions.push({ kind: \"meta\", name: \"twitter:description\", content: ogDescription });\n\t}\n\n\tif (ogImage) {\n\t\tcontributions.push({ kind: \"meta\", name: \"twitter:image\", content: ogImage });\n\t}\n\n\t// -- Article metadata --\n\n\tif (page.pageType === \"article\" && page.articleMeta) {\n\t\tconst { publishedTime, modifiedTime, author } = page.articleMeta;\n\t\tif (publishedTime) {\n\t\t\tcontributions.push({\n\t\t\t\tkind: \"property\",\n\t\t\t\tproperty: \"article:published_time\",\n\t\t\t\tcontent: publishedTime,\n\t\t\t});\n\t\t}\n\t\tif (modifiedTime) {\n\t\t\tcontributions.push({\n\t\t\t\tkind: \"property\",\n\t\t\t\tproperty: \"article:modified_time\",\n\t\t\t\tcontent: modifiedTime,\n\t\t\t});\n\t\t}\n\t\tif (author) {\n\t\t\tcontributions.push({\n\t\t\t\tkind: \"property\",\n\t\t\t\tproperty: \"article:author\",\n\t\t\t\tcontent: author,\n\t\t\t});\n\t\t}\n\t}\n\n\t// -- JSON-LD --\n\n\tif (page.pageType === \"article\") {\n\t\tconst blogPosting = buildBlogPostingJsonLd(page, defaultOgImage ?? null);\n\t\tif (blogPosting) {\n\t\t\tcontributions.push({ kind: \"jsonld\", id: \"primary\", graph: blogPosting });\n\t\t}\n\t} else if (siteName) {\n\t\tconst webSite = buildWebSiteJsonLd(page);\n\t\tif (webSite) {\n\t\t\tcontributions.push({ kind: \"jsonld\", id: \"primary\", graph: webSite });\n\t\t}\n\t}\n\n\treturn contributions;\n}\n\n/**\n * Generate site-level SEO metadata contributions from SiteSettings.seo.\n *\n * These tags apply to every page (search engine ownership verification),\n * so they're sourced from site settings rather than per-page context.\n * Returns an empty array when no relevant settings are configured.\n */\nexport function generateSiteSeoContributions(\n\tseoSettings: SeoSettings | undefined,\n): PageMetadataContribution[] {\n\tconst contributions: PageMetadataContribution[] = [];\n\n\tif (!seoSettings) {\n\t\treturn contributions;\n\t}\n\n\tif (seoSettings.googleVerification) {\n\t\tcontributions.push({\n\t\t\tkind: \"meta\",\n\t\t\tname: \"google-site-verification\",\n\t\t\tcontent: seoSettings.googleVerification,\n\t\t});\n\t}\n\n\tif (seoSettings.bingVerification) {\n\t\tcontributions.push({\n\t\t\tkind: \"meta\",\n\t\t\tname: \"msvalidate.01\",\n\t\t\tcontent: seoSettings.bingVerification,\n\t\t});\n\t}\n\n\treturn contributions;\n}\n","/**\n * emdash/page — Public page contribution API\n *\n * Template integration points for plugin-driven head metadata\n * and trusted body fragments.\n */\n\nimport type {\n\tPublicPageContext,\n\tPageMetadataContribution,\n\tPageFragmentContribution,\n} from \"../plugins/types.js\";\n\nexport { createPublicPageContext } from \"./context.js\";\nexport type { CreatePublicPageContextInput } from \"./context.js\";\n\nexport {\n\tresolvePageMetadata,\n\trenderPageMetadata,\n\tsafeJsonLdSerialize,\n\tescapeHtmlAttr,\n} from \"./metadata.js\";\nexport type { ResolvedPageMetadata } from \"./metadata.js\";\n\nexport { resolveFragments, renderFragments } from \"./fragments.js\";\n\nexport { generateBaseSeoContributions, generateSiteSeoContributions } from \"./seo-contributions.js\";\nexport { cleanJsonLd, buildBlogPostingJsonLd, buildWebSiteJsonLd } from \"./jsonld.js\";\n\n/**\n * Shape of the EmDash runtime methods used by the render components.\n * Extracted here so all three components share a single type definition.\n */\nexport interface EmDashPageRuntime {\n\tcollectPageMetadata: (page: PublicPageContext) => Promise<PageMetadataContribution[]>;\n\tcollectPageFragments: (page: PublicPageContext) => Promise<PageFragmentContribution[]>;\n}\n\n/**\n * Get the page runtime from Astro locals. Returns undefined when\n * EmDash is not initialized (components render nothing in that case).\n */\nexport function getPageRuntime(locals: Record<string, unknown>): EmDashPageRuntime | undefined {\n\tconst emdash = locals.emdash;\n\tif (\n\t\temdash &&\n\t\ttypeof emdash === \"object\" &&\n\t\t\"collectPageMetadata\" in emdash &&\n\t\t\"collectPageFragments\" in emdash\n\t) {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- structural check above confirms presence of required methods\n\t\treturn emdash as EmDashPageRuntime;\n\t}\n\treturn undefined;\n}\n\n// Astro render components are exported from \"emdash/ui\":\n// import { EmDashHead, EmDashBodyStart, EmDashBodyEnd } from \"emdash/ui\";\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/page/context.ts","../../src/page/metadata.ts","../../src/page/fragments.ts","../../src/page/jsonld.ts","../../src/page/seo-contributions.ts","../../src/page/index.ts"],"sourcesContent":["/**\n * Public page context builder\n *\n * Templates call this to describe the page being rendered.\n * The resulting context is passed to EmDashHead / EmDashBodyStart / EmDashBodyEnd.\n */\n\nimport type { BreadcrumbItem, PublicPageContext } from \"../plugins/types.js\";\n\n/** Fields shared by both input forms */\ninterface PageContextFields {\n\tkind: \"content\" | \"custom\";\n\tpageType?: string;\n\ttitle?: string | null;\n\tpageTitle?: string | null;\n\tdescription?: string | null;\n\tcanonical?: string | null;\n\timage?: string | null;\n\tcontent?: { collection: string; id: string; slug?: string | null };\n\t/** SEO overrides for OG/Twitter meta generation */\n\tseo?: {\n\t\togTitle?: string | null;\n\t\togDescription?: string | null;\n\t\togImage?: string | null;\n\t\trobots?: string | null;\n\t};\n\t/** Article metadata for Open Graph article: tags */\n\tarticleMeta?: {\n\t\tpublishedTime?: string | null;\n\t\tmodifiedTime?: string | null;\n\t\tauthor?: string | null;\n\t};\n\t/** Site name for structured data and og:site_name */\n\tsiteName?: string;\n\t/**\n\t * Breadcrumb trail for this page, root first. Pass an empty array\n\t * to explicitly opt out of breadcrumbs (e.g. homepage), or omit the\n\t * field to let consumers fall back to their own derivation.\n\t */\n\tbreadcrumbs?: BreadcrumbItem[];\n\t/** Public-facing site URL (origin) for structured data */\n\tsiteUrl?: string;\n}\n\n/** Input with Astro global -- used in .astro files */\ninterface AstroInput extends PageContextFields {\n\tAstro: { url: URL; currentLocale?: string };\n}\n\n/** Input with explicit URL -- used outside .astro files */\ninterface UrlInput extends PageContextFields {\n\turl: URL | string;\n\tlocale?: string;\n}\n\nexport type CreatePublicPageContextInput = AstroInput | UrlInput;\n\nfunction isAstroInput(input: CreatePublicPageContextInput): input is AstroInput {\n\treturn \"Astro\" in input;\n}\n\n/**\n * Build a PublicPageContext from template input.\n */\nexport function createPublicPageContext(input: CreatePublicPageContextInput): PublicPageContext {\n\tlet url: string;\n\tlet path: string;\n\tlet locale: string | null;\n\n\tif (isAstroInput(input)) {\n\t\turl = input.Astro.url.href;\n\t\tpath = input.Astro.url.pathname;\n\t\tlocale = input.Astro.currentLocale ?? null;\n\t} else {\n\t\tconst parsed = typeof input.url === \"string\" ? new URL(input.url) : input.url;\n\t\turl = parsed.href;\n\t\tpath = parsed.pathname;\n\t\tlocale = input.locale ?? null;\n\t}\n\n\treturn {\n\t\turl,\n\t\tpath,\n\t\tlocale,\n\t\tkind: input.kind,\n\t\tpageType: input.pageType ?? (input.kind === \"content\" ? \"article\" : \"website\"),\n\t\ttitle: input.title ?? null,\n\t\tpageTitle: input.pageTitle ?? null,\n\t\tdescription: input.description ?? null,\n\t\tcanonical: input.canonical ?? null,\n\t\timage: input.image ?? null,\n\t\tcontent: input.content\n\t\t\t? {\n\t\t\t\t\tcollection: input.content.collection,\n\t\t\t\t\tid: input.content.id,\n\t\t\t\t\tslug: input.content.slug ?? null,\n\t\t\t\t}\n\t\t\t: undefined,\n\t\tseo: input.seo,\n\t\tarticleMeta: input.articleMeta,\n\t\tsiteName: input.siteName,\n\t\tbreadcrumbs: input.breadcrumbs,\n\t\tsiteUrl: input.siteUrl,\n\t};\n}\n","/**\n * Page metadata collection and rendering\n *\n * Collects typed metadata contributions from plugins via the page:metadata hook,\n * validates them, and resolves them into a deduplicated structure ready to render.\n */\n\nimport type { PageMetadataContribution, PageMetadataLinkRel } from \"../plugins/types.js\";\n\n// ── Resolved output ─────────────────────────────────────────────\n\nexport interface ResolvedPageMetadata {\n\tmeta: Array<{ name: string; content: string }>;\n\tproperties: Array<{ property: string; content: string }>;\n\tlinks: Array<{\n\t\trel: PageMetadataLinkRel;\n\t\thref: string;\n\t\threflang?: string;\n\t}>;\n\tjsonld: Array<{ id?: string; json: string }>;\n}\n\ninterface RenderPageMetadataOptions {\n\tincludeJsonLd?: boolean;\n}\n\n// ── Validation ──────────────────────────────────────────────────\n\n/** Schemes safe for use in link href attributes */\nconst SAFE_HREF_RE = /^(https?|at):\\/\\//i;\nconst HTML_ESCAPE_MAP: Record<string, string> = {\n\t\"&\": \"&\",\n\t\"<\": \"<\",\n\t\">\": \">\",\n\t'\"': \""\",\n\t\"'\": \"'\",\n};\nconst HTML_ESCAPE_RE = /[&<>\"']/g;\n\n/** Escape a string for safe use in an HTML attribute value */\nexport function escapeHtmlAttr(value: string): string {\n\treturn value.replace(HTML_ESCAPE_RE, (ch) => HTML_ESCAPE_MAP[ch] ?? ch);\n}\n\n/** Validate that a URL uses a safe scheme (http, https, at) */\nfunction isSafeHref(url: string): boolean {\n\treturn SAFE_HREF_RE.test(url);\n}\n\n// ── JSON-LD serialization ───────────────────────────────────────\n\nconst JSONLD_LT_RE = /</g;\nconst JSONLD_GT_RE = />/g;\nconst JSONLD_U2028_RE = /\\u2028/g;\nconst JSONLD_U2029_RE = /\\u2029/g;\n\n/**\n * Safely serialize a value for embedding in a <script type=\"application/ld+json\"> tag.\n *\n * Plain JSON.stringify is not sufficient because:\n * - \"</script>\" in a nested string breaks out of the script tag\n * - \"<!--\" can open an HTML comment\n * - U+2028/U+2029 are line terminators in some JS engines\n */\nexport function safeJsonLdSerialize(value: unknown): string {\n\treturn JSON.stringify(value)\n\t\t.replace(JSONLD_LT_RE, \"\\\\u003c\")\n\t\t.replace(JSONLD_GT_RE, \"\\\\u003e\")\n\t\t.replace(JSONLD_U2028_RE, \"\\\\u2028\")\n\t\t.replace(JSONLD_U2029_RE, \"\\\\u2029\");\n}\n\nexport async function createSha256CspHash(value: string): Promise<string> {\n\tconst digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(value));\n\tconst bytes = new Uint8Array(digest);\n\tlet binary = \"\";\n\tfor (const byte of bytes) {\n\t\tbinary += String.fromCharCode(byte);\n\t}\n\treturn `sha256-${btoa(binary)}`;\n}\n\ninterface CspScriptHashSink {\n\tinsertScriptHash(hash: string): void;\n}\n\n/**\n * Register JSON-LD hashes with Astro's CSP runtime when CSP is enabled.\n *\n * The getter stays lazy because Astro warns when `Astro.csp` is accessed on a\n * project that has not enabled its built-in CSP support.\n */\nexport async function registerJsonLdCspHashes(\n\tenabled: boolean,\n\tgetCsp: () => CspScriptHashSink | undefined,\n\tscripts: ReadonlyArray<{ json: string }>,\n): Promise<void> {\n\tif (!enabled || scripts.length === 0) return;\n\n\tconst csp = getCsp();\n\tif (!csp) return;\n\n\tawait Promise.all(\n\t\tscripts.map(async ({ json }) => {\n\t\t\tcsp.insertScriptHash(await createSha256CspHash(json));\n\t\t}),\n\t);\n}\n\n// ── Merge / dedupe ──────────────────────────────────────────────\n\n/**\n * Resolve a flat list of contributions into deduplicated metadata.\n * First contribution wins for any given dedupe key.\n */\nexport function resolvePageMetadata(\n\tcontributions: PageMetadataContribution[],\n): ResolvedPageMetadata {\n\tconst result: ResolvedPageMetadata = {\n\t\tmeta: [],\n\t\tproperties: [],\n\t\tlinks: [],\n\t\tjsonld: [],\n\t};\n\n\tconst seenMeta = new Set<string>();\n\tconst seenProperties = new Set<string>();\n\tconst seenLinks = new Set<string>();\n\tconst seenJsonLd = new Set<string>();\n\n\tfor (const c of contributions) {\n\t\tswitch (c.kind) {\n\t\t\tcase \"meta\": {\n\t\t\t\tconst dedupeKey = c.key ?? c.name;\n\t\t\t\tif (seenMeta.has(dedupeKey)) continue;\n\t\t\t\tseenMeta.add(dedupeKey);\n\t\t\t\tresult.meta.push({ name: c.name, content: c.content });\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"property\": {\n\t\t\t\tconst dedupeKey = c.key ?? c.property;\n\t\t\t\tif (seenProperties.has(dedupeKey)) continue;\n\t\t\t\tseenProperties.add(dedupeKey);\n\t\t\t\tresult.properties.push({\n\t\t\t\t\tproperty: c.property,\n\t\t\t\t\tcontent: c.content,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"link\": {\n\t\t\t\tif (!isSafeHref(c.href)) {\n\t\t\t\t\tif (import.meta.env?.DEV) {\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`[page:metadata] Rejected link contribution with unsafe href scheme: ${c.href}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (c.rel === \"canonical\") {\n\t\t\t\t\tif (seenLinks.has(\"canonical\")) continue;\n\t\t\t\t\tseenLinks.add(\"canonical\");\n\t\t\t\t} else {\n\t\t\t\t\tconst dedupeKey = c.key ?? c.hreflang ?? c.href;\n\t\t\t\t\tif (seenLinks.has(dedupeKey)) continue;\n\t\t\t\t\tseenLinks.add(dedupeKey);\n\t\t\t\t}\n\t\t\t\tresult.links.push({\n\t\t\t\t\trel: c.rel,\n\t\t\t\t\thref: c.href,\n\t\t\t\t\t...(c.hreflang && { hreflang: c.hreflang }),\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"jsonld\": {\n\t\t\t\tif (c.id) {\n\t\t\t\t\tif (seenJsonLd.has(c.id)) continue;\n\t\t\t\t\tseenJsonLd.add(c.id);\n\t\t\t\t}\n\t\t\t\tresult.jsonld.push({\n\t\t\t\t\tid: c.id,\n\t\t\t\t\tjson: safeJsonLdSerialize(c.graph),\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\t// Unknown contribution kind -- skip silently at runtime.\n\t\t\t\t// TypeScript catches this at compile time for typed callers,\n\t\t\t\t// but sandboxed plugins may return unexpected shapes.\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn result;\n}\n\n// ── HTML rendering ──────────────────────────────────────────────\n\n/** Render resolved metadata to an HTML string for embedding in <head> */\nexport function renderPageMetadata(\n\tmetadata: ResolvedPageMetadata,\n\toptions: RenderPageMetadataOptions = {},\n): string {\n\tconst parts: string[] = [];\n\tconst includeJsonLd = options.includeJsonLd ?? true;\n\n\tfor (const m of metadata.meta) {\n\t\tparts.push(`<meta name=\"${escapeHtmlAttr(m.name)}\" content=\"${escapeHtmlAttr(m.content)}\">`);\n\t}\n\n\tfor (const p of metadata.properties) {\n\t\tparts.push(\n\t\t\t`<meta property=\"${escapeHtmlAttr(p.property)}\" content=\"${escapeHtmlAttr(p.content)}\">`,\n\t\t);\n\t}\n\n\tfor (const l of metadata.links) {\n\t\tlet tag = `<link rel=\"${escapeHtmlAttr(l.rel)}\" href=\"${escapeHtmlAttr(l.href)}\"`;\n\t\tif (l.hreflang) {\n\t\t\ttag += ` hreflang=\"${escapeHtmlAttr(l.hreflang)}\"`;\n\t\t}\n\t\ttag += \">\";\n\t\tparts.push(tag);\n\t}\n\n\tif (includeJsonLd) {\n\t\tfor (const j of metadata.jsonld) {\n\t\t\tparts.push(`<script type=\"application/ld+json\">${j.json}</script>`);\n\t\t}\n\t}\n\n\treturn parts.join(\"\\n\");\n}\n","/**\n * Page fragment collection and rendering\n *\n * Collects raw markup / script contributions from trusted plugins via\n * the page:fragments hook. Sandboxed plugins are never invoked.\n */\n\nimport type { PageFragmentContribution, PagePlacement } from \"../plugins/types.js\";\nimport { escapeHtmlAttr } from \"./metadata.js\";\n\n/** Escape sequences that would break out of a script tag */\nconst SCRIPT_CLOSE_RE = /<\\//g;\n\n// ── Dedupe and filter ───────────────────────────────────────────\n\n/**\n * Filter contributions to a specific placement and deduplicate.\n * - Contributions with the same `key + placement` are deduped (first wins).\n * - External scripts with the same `src + placement` are deduped.\n */\nexport function resolveFragments(\n\tcontributions: PageFragmentContribution[],\n\tplacement: PagePlacement,\n): PageFragmentContribution[] {\n\tconst filtered = contributions.filter((c) => c.placement === placement);\n\tconst seen = new Set<string>();\n\tconst result: PageFragmentContribution[] = [];\n\n\tfor (const c of filtered) {\n\t\t// Key-based dedupe\n\t\tif (c.key) {\n\t\t\tconst dedupeKey = `key:${c.key}`;\n\t\t\tif (seen.has(dedupeKey)) continue;\n\t\t\tseen.add(dedupeKey);\n\t\t} else if (c.kind === \"external-script\") {\n\t\t\tconst dedupeKey = `src:${c.src}`;\n\t\t\tif (seen.has(dedupeKey)) continue;\n\t\t\tseen.add(dedupeKey);\n\t\t}\n\n\t\tresult.push(c);\n\t}\n\n\treturn result;\n}\n\n// ── HTML rendering ──────────────────────────────────────────────\n\nconst EVENT_HANDLER_RE = /^on/i;\n\nfunction renderAttributes(attrs: Record<string, string>): string {\n\treturn Object.entries(attrs)\n\t\t.filter(([k]) => !EVENT_HANDLER_RE.test(k))\n\t\t.map(([k, v]) => ` ${escapeHtmlAttr(k)}=\"${escapeHtmlAttr(v)}\"`)\n\t\t.join(\"\");\n}\n\n/** Render a single fragment contribution to HTML */\nfunction renderFragment(c: PageFragmentContribution): string {\n\tswitch (c.kind) {\n\t\tcase \"external-script\": {\n\t\t\tlet tag = `<script src=\"${escapeHtmlAttr(c.src)}\"`;\n\t\t\tif (c.async) tag += \" async\";\n\t\t\tif (c.defer) tag += \" defer\";\n\t\t\tif (c.attributes) tag += renderAttributes(c.attributes);\n\t\t\ttag += \"></script>\";\n\t\t\treturn tag;\n\t\t}\n\t\tcase \"inline-script\": {\n\t\t\tlet tag = \"<script\";\n\t\t\tif (c.attributes) tag += renderAttributes(c.attributes);\n\t\t\t// Escape </ to <\\/ to prevent breaking out of the script tag.\n\t\t\t// This is valid JS and protects against code built from user data.\n\t\t\ttag += `>${c.code.replace(SCRIPT_CLOSE_RE, \"<\\\\/\")}</script>`;\n\t\t\treturn tag;\n\t\t}\n\t\tcase \"html\":\n\t\t\treturn c.html;\n\t}\n}\n\n/** Render a list of fragment contributions to an HTML string */\nexport function renderFragments(\n\tcontributions: PageFragmentContribution[],\n\tplacement: PagePlacement,\n): string {\n\tconst resolved = resolveFragments(contributions, placement);\n\treturn resolved.map(renderFragment).join(\"\\n\");\n}\n","/**\n * JSON-LD structured data builders\n *\n * Moved from template SEO.astro components into core so all JSON-LD\n * is serialized via safeJsonLdSerialize() and never hand-rolled in templates.\n */\n\nimport type { PublicPageContext } from \"../plugins/types.js\";\n\n/**\n * Remove null/undefined values from a JSON-LD object recursively.\n * JSON-LD validators prefer absent keys over null values.\n */\nexport function cleanJsonLd(obj: Record<string, unknown>): Record<string, unknown> {\n\tconst cleaned: Record<string, unknown> = {};\n\tfor (const [key, value] of Object.entries(obj)) {\n\t\tif (value !== undefined && value !== null) {\n\t\t\tif (typeof value === \"object\" && !Array.isArray(value)) {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- non-null, non-array object is safely treated as Record<string, unknown> for JSON-LD traversal\n\t\t\t\tcleaned[key] = cleanJsonLd(value as Record<string, unknown>);\n\t\t\t} else {\n\t\t\t\tcleaned[key] = value;\n\t\t\t}\n\t\t}\n\t}\n\treturn cleaned;\n}\n\n/**\n * Build a BlogPosting JSON-LD graph from page context.\n * Used for article-type content pages.\n *\n * @param page - Page context for the current request.\n * @param defaultOgImage - Optional site-wide fallback image URL, used when\n * the page has no own OG image. Matches the fallback applied to `og:image`\n * in `generateBaseSeoContributions`.\n */\nexport function buildBlogPostingJsonLd(\n\tpage: PublicPageContext,\n\tdefaultOgImage?: string | null,\n): Record<string, unknown> | null {\n\tif (page.pageType !== \"article\" || !page.canonical) return null;\n\n\tconst ogTitle = page.seo?.ogTitle ?? page.pageTitle ?? page.title;\n\tconst description = page.seo?.ogDescription || page.description;\n\tconst ogImage = page.seo?.ogImage || page.image || defaultOgImage || null;\n\tconst publishedTime = page.articleMeta?.publishedTime;\n\tconst modifiedTime = page.articleMeta?.modifiedTime;\n\tconst author = page.articleMeta?.author;\n\tconst siteName = page.siteName;\n\n\treturn cleanJsonLd({\n\t\t\"@context\": \"https://schema.org\",\n\t\t\"@type\": \"BlogPosting\",\n\t\theadline: ogTitle,\n\t\tdescription,\n\t\timage: ogImage || undefined,\n\t\turl: page.canonical,\n\t\tdatePublished: publishedTime || undefined,\n\t\tdateModified: modifiedTime || publishedTime || undefined,\n\t\tauthor: author\n\t\t\t? {\n\t\t\t\t\t\"@type\": \"Person\",\n\t\t\t\t\tname: author,\n\t\t\t\t}\n\t\t\t: undefined,\n\t\tpublisher: siteName\n\t\t\t? {\n\t\t\t\t\t\"@type\": \"Organization\",\n\t\t\t\t\tname: siteName,\n\t\t\t\t}\n\t\t\t: undefined,\n\t\tmainEntityOfPage: {\n\t\t\t\"@type\": \"WebPage\",\n\t\t\t\"@id\": page.canonical,\n\t\t},\n\t});\n}\n\n/**\n * Build a WebSite JSON-LD graph from page context.\n * Used for non-article pages (homepage, listing pages, etc.)\n */\nexport function buildWebSiteJsonLd(page: PublicPageContext): Record<string, unknown> | null {\n\tconst siteName = page.siteName;\n\tif (!siteName) return null;\n\n\t// Use configured public origin, falling back to page URL origin\n\tlet siteUrl: string;\n\tif (page.siteUrl) {\n\t\tsiteUrl = page.siteUrl;\n\t} else {\n\t\ttry {\n\t\t\tsiteUrl = new URL(page.url).origin;\n\t\t} catch {\n\t\t\tsiteUrl = page.canonical || page.url;\n\t\t}\n\t}\n\n\treturn cleanJsonLd({\n\t\t\"@context\": \"https://schema.org\",\n\t\t\"@type\": \"WebSite\",\n\t\tname: siteName,\n\t\turl: siteUrl,\n\t});\n}\n","/**\n * Generate base SEO metadata contributions from PublicPageContext.\n *\n * EmDashHead.astro composes the final contribution list as\n * `[...plugin, ...site, ...base]` and feeds it to `resolvePageMetadata()`,\n * which is first-wins. That ordering means plugin contributions override\n * site-level ones override base ones for any given key — base values are\n * the fallback, not the source of truth. For content pages, the entry's\n * SEO panel values are overlaid onto the page context before the base\n * contributions (and JSON-LD) are generated, so editor-set values\n * override the template-provided fields.\n *\n * This replaces the per-template SEO.astro components, eliminating\n * the class of XSS bugs where templates hand-rolled JSON-LD serialization.\n */\n\nimport type { ContentSeo } from \"../database/repositories/types.js\";\nimport type { PageMetadataContribution, PublicPageContext } from \"../plugins/types.js\";\nimport { buildSeoImageUrl, resolveSeoCanonicalUrl } from \"../seo/media-url.js\";\nimport { getSiteSettings } from \"../settings/index.js\";\nimport type { SeoSettings } from \"../settings/types.js\";\nimport { buildBlogPostingJsonLd, buildWebSiteJsonLd } from \"./jsonld.js\";\nimport { peekSeoPanel } from \"./seo-panel.js\";\n\n/**\n * Generate base metadata contributions from a page context's SEO data.\n *\n * @param page - Page context produced by the runtime for the current request.\n * @param defaultOgImage - Optional site-wide fallback OG image URL, used when\n * the page has no own OG image (i.e., neither `seo.ogImage` nor `image`).\n * Sourced from `SiteSettings.seo.defaultOgImage` by `EmDashHead`.\n *\n * Returns an empty array if no SEO-relevant data is present.\n */\nexport function generateBaseSeoContributions(\n\tpage: PublicPageContext,\n\tdefaultOgImage?: string | null,\n): PageMetadataContribution[] {\n\tconst contributions: PageMetadataContribution[] = [];\n\n\tconst description = page.description;\n\tconst ogTitle = page.seo?.ogTitle ?? page.pageTitle ?? page.title;\n\tconst ogDescription = page.seo?.ogDescription || description;\n\tconst ogImage = page.seo?.ogImage || page.image || defaultOgImage || null;\n\tconst robots = page.seo?.robots;\n\tconst canonical = page.canonical;\n\tconst siteName = page.siteName;\n\n\t// -- Meta tags --\n\n\tif (description) {\n\t\tcontributions.push({ kind: \"meta\", name: \"description\", content: description });\n\t}\n\n\tif (robots) {\n\t\tcontributions.push({ kind: \"meta\", name: \"robots\", content: robots });\n\t}\n\n\t// -- Canonical link --\n\n\tif (canonical) {\n\t\tcontributions.push({ kind: \"link\", rel: \"canonical\", href: canonical });\n\t}\n\n\t// -- Open Graph --\n\n\tcontributions.push({\n\t\tkind: \"property\",\n\t\tproperty: \"og:type\",\n\t\tcontent: page.pageType === \"article\" ? \"article\" : \"website\",\n\t});\n\n\tif (ogTitle) {\n\t\tcontributions.push({ kind: \"property\", property: \"og:title\", content: ogTitle });\n\t}\n\n\tif (ogDescription) {\n\t\tcontributions.push({ kind: \"property\", property: \"og:description\", content: ogDescription });\n\t}\n\n\tif (ogImage) {\n\t\tcontributions.push({ kind: \"property\", property: \"og:image\", content: ogImage });\n\t}\n\n\tif (canonical) {\n\t\tcontributions.push({ kind: \"property\", property: \"og:url\", content: canonical });\n\t}\n\n\tif (siteName) {\n\t\tcontributions.push({ kind: \"property\", property: \"og:site_name\", content: siteName });\n\t}\n\n\t// -- Twitter Card --\n\n\tcontributions.push({\n\t\tkind: \"meta\",\n\t\tname: \"twitter:card\",\n\t\tcontent: ogImage ? \"summary_large_image\" : \"summary\",\n\t});\n\n\tif (ogTitle) {\n\t\tcontributions.push({ kind: \"meta\", name: \"twitter:title\", content: ogTitle });\n\t}\n\n\tif (ogDescription) {\n\t\tcontributions.push({ kind: \"meta\", name: \"twitter:description\", content: ogDescription });\n\t}\n\n\tif (ogImage) {\n\t\tcontributions.push({ kind: \"meta\", name: \"twitter:image\", content: ogImage });\n\t}\n\n\t// -- Article metadata --\n\n\tif (page.pageType === \"article\" && page.articleMeta) {\n\t\tconst { publishedTime, modifiedTime, author } = page.articleMeta;\n\t\tif (publishedTime) {\n\t\t\tcontributions.push({\n\t\t\t\tkind: \"property\",\n\t\t\t\tproperty: \"article:published_time\",\n\t\t\t\tcontent: publishedTime,\n\t\t\t});\n\t\t}\n\t\tif (modifiedTime) {\n\t\t\tcontributions.push({\n\t\t\t\tkind: \"property\",\n\t\t\t\tproperty: \"article:modified_time\",\n\t\t\t\tcontent: modifiedTime,\n\t\t\t});\n\t\t}\n\t\tif (author) {\n\t\t\tcontributions.push({\n\t\t\t\tkind: \"property\",\n\t\t\t\tproperty: \"article:author\",\n\t\t\t\tcontent: author,\n\t\t\t});\n\t\t}\n\t}\n\n\t// -- JSON-LD --\n\n\tif (page.pageType === \"article\") {\n\t\tconst blogPosting = buildBlogPostingJsonLd(page, defaultOgImage ?? null);\n\t\tif (blogPosting) {\n\t\t\tcontributions.push({ kind: \"jsonld\", id: \"primary\", graph: blogPosting });\n\t\t}\n\t} else if (siteName) {\n\t\tconst webSite = buildWebSiteJsonLd(page);\n\t\tif (webSite) {\n\t\t\tcontributions.push({ kind: \"jsonld\", id: \"primary\", graph: webSite });\n\t\t}\n\t}\n\n\treturn contributions;\n}\n\n/**\n * Resolve the page context for rendering: overlay the entry's SEO panel\n * values when they were primed for this request.\n *\n * Used by `<EmDashHead>`, `<EmDashBodyStart>`, and `<EmDashBodyEnd>` so\n * head tags, JSON-LD, and every plugin hook — head and body fragments\n * alike — see the same overlaid context. Returns the context unchanged\n * for non-content pages or when nothing was primed. The peek is a\n * request-cache read; site settings are only consulted when a panel\n * exists (and are request-cached themselves), so this adds no queries.\n */\nexport async function resolveSeoPanelPage(\n\tpage: PublicPageContext,\n\tsiteUrl?: string,\n): Promise<PublicPageContext> {\n\tif (!page.content) return page;\n\tconst seo = await peekSeoPanel(page.content.collection, page.content.id);\n\tif (!seo) return page;\n\tconst resolvedSiteUrl =\n\t\tsiteUrl ||\n\t\tpage.siteUrl ||\n\t\t(await getSiteSettings()).url ||\n\t\t(URL.canParse(page.url) ? new URL(page.url).origin : \"\");\n\treturn applySeoPanelToPageContext(page, seo, { siteUrl: resolvedSiteUrl });\n}\n\n/**\n * Overlay a content entry's SEO panel data onto the page context.\n *\n * `<EmDashHead>` applies this overlay before anything consumes the context:\n * editor-set panel values override whatever the template passed in, and\n * because the overlaid context feeds plugin hooks, the base contributions,\n * and the JSON-LD builders alike, structured data and head tags always\n * agree. Plugins still override the rendered output via first-wins dedup.\n *\n * The `<title>` element itself stays the template's responsibility —\n * head components can't replace it — so `seo.title` feeds\n * `og:title` / `twitter:title` / the JSON-LD headline only. Templates that\n * want the panel title in `<title>` keep using `getSeoMeta()`.\n *\n * Unset panel fields fall back to the template-provided values, so pages\n * without SEO data are unaffected.\n */\nexport function applySeoPanelToPageContext(\n\tpage: PublicPageContext,\n\tseo: ContentSeo,\n\toptions: { siteUrl?: string | null } = {},\n): PublicPageContext {\n\tconst siteUrl = options.siteUrl ?? undefined;\n\tconst image = seo.image ? buildSeoImageUrl(seo.image, siteUrl) : null;\n\tconst canonical = seo.canonical ? resolveSeoCanonicalUrl(seo.canonical, siteUrl) : null;\n\n\treturn {\n\t\t...page,\n\t\tdescription: seo.description || page.description,\n\t\tcanonical: canonical || page.canonical,\n\t\t// Mirror the resolved image into the top-level field too, so consumers\n\t\t// reading page.image (e.g. page:metadata hooks) agree with og:image and\n\t\t// the JSON-LD graph.\n\t\timage: image || page.image,\n\t\tseo: {\n\t\t\t...page.seo,\n\t\t\togTitle: seo.title || page.seo?.ogTitle,\n\t\t\togDescription: seo.description || page.seo?.ogDescription,\n\t\t\togImage: image || page.seo?.ogImage,\n\t\t\trobots: seo.noIndex ? \"noindex, nofollow\" : page.seo?.robots,\n\t\t},\n\t};\n}\n\n/**\n * Generate site-level SEO metadata contributions from SiteSettings.seo.\n *\n * These tags apply to every page (search engine ownership verification),\n * so they're sourced from site settings rather than per-page context.\n * Returns an empty array when no relevant settings are configured.\n */\nexport function generateSiteSeoContributions(\n\tseoSettings: SeoSettings | undefined,\n): PageMetadataContribution[] {\n\tconst contributions: PageMetadataContribution[] = [];\n\n\tif (!seoSettings) {\n\t\treturn contributions;\n\t}\n\n\tif (seoSettings.googleVerification) {\n\t\tcontributions.push({\n\t\t\tkind: \"meta\",\n\t\t\tname: \"google-site-verification\",\n\t\t\tcontent: seoSettings.googleVerification,\n\t\t});\n\t}\n\n\tif (seoSettings.bingVerification) {\n\t\tcontributions.push({\n\t\t\tkind: \"meta\",\n\t\t\tname: \"msvalidate.01\",\n\t\t\tcontent: seoSettings.bingVerification,\n\t\t});\n\t}\n\n\treturn contributions;\n}\n","/**\n * emdash/page — Public page contribution API\n *\n * Template integration points for plugin-driven head metadata\n * and trusted body fragments.\n */\n\nimport type {\n\tPublicPageContext,\n\tPageMetadataContribution,\n\tPageFragmentContribution,\n} from \"../plugins/types.js\";\n\nexport { createPublicPageContext } from \"./context.js\";\nexport type { CreatePublicPageContextInput } from \"./context.js\";\n\nexport {\n\tresolvePageMetadata,\n\trenderPageMetadata,\n\tsafeJsonLdSerialize,\n\tescapeHtmlAttr,\n} from \"./metadata.js\";\nexport type { ResolvedPageMetadata } from \"./metadata.js\";\n\nexport { resolveFragments, renderFragments } from \"./fragments.js\";\n\nexport { generateBaseSeoContributions, generateSiteSeoContributions } from \"./seo-contributions.js\";\nexport { cleanJsonLd, buildBlogPostingJsonLd, buildWebSiteJsonLd } from \"./jsonld.js\";\n\n/**\n * Shape of the EmDash runtime methods used by the render components.\n * Extracted here so all three components share a single type definition.\n */\nexport interface EmDashPageRuntime {\n\tcollectPageMetadata: (page: PublicPageContext) => Promise<PageMetadataContribution[]>;\n\tcollectPageFragments: (page: PublicPageContext) => Promise<PageFragmentContribution[]>;\n}\n\n/**\n * Get the page runtime from Astro locals. Returns undefined when\n * EmDash is not initialized (components render nothing in that case).\n */\nexport function getPageRuntime(locals: Record<string, unknown>): EmDashPageRuntime | undefined {\n\tconst emdash = locals.emdash;\n\tif (\n\t\temdash &&\n\t\ttypeof emdash === \"object\" &&\n\t\t\"collectPageMetadata\" in emdash &&\n\t\t\"collectPageFragments\" in emdash\n\t) {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- structural check above confirms presence of required methods\n\t\treturn emdash as EmDashPageRuntime;\n\t}\n\treturn undefined;\n}\n\n// Astro render components are exported from \"emdash/ui\":\n// import { EmDashHead, EmDashBodyStart, EmDashBodyEnd } from \"emdash/ui\";\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as apiError } from "./error-
|
|
1
|
+
import { t as apiError } from "./error-BDcFyoRt.mjs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
|
|
4
4
|
//#region src/api/parse.ts
|
|
@@ -78,4 +78,4 @@ function isParseError(result) {
|
|
|
78
78
|
|
|
79
79
|
//#endregion
|
|
80
80
|
export { parseQuery as i, parseBody as n, parseOptionalBody as r, isParseError as t };
|
|
81
|
-
//# sourceMappingURL=parse-
|
|
81
|
+
//# sourceMappingURL=parse-WRg5C3NX.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-
|
|
1
|
+
{"version":3,"file":"parse-WRg5C3NX.mjs","names":[],"sources":["../src/api/parse.ts"],"sourcesContent":["/**\n * Request body and query parameter parsing with Zod validation.\n *\n * All API routes should use these utilities instead of `request.json() as T`\n * or raw `url.searchParams.get()` with manual coercion.\n */\n\nimport { z } from \"zod\";\n\nimport { apiError } from \"./error.js\";\n\n/** Maximum allowed JSON request body size (10 MB). */\nconst MAX_BODY_SIZE = 10 * 1024 * 1024;\n\n/**\n * Result of parsing: either the validated data or an error Response.\n * Routes should check `if (result instanceof Response) return result;`\n */\nexport type ParseResult<T> = T | Response;\n\n/**\n * Parse and validate a JSON request body against a Zod schema.\n *\n * Returns the validated data on success, or a 400 Response on failure.\n * Replaces all `(await request.json()) as T` casts.\n */\nexport async function parseBody<T extends z.ZodType>(\n\trequest: Request,\n\tschema: T,\n): Promise<ParseResult<z.infer<T>>> {\n\t// Best-effort size check via Content-Length (can be absent with chunked encoding)\n\tconst contentLength = request.headers.get(\"Content-Length\");\n\tif (contentLength && parseInt(contentLength, 10) > MAX_BODY_SIZE) {\n\t\treturn apiError(\"PAYLOAD_TOO_LARGE\", \"Request body too large\", 413);\n\t}\n\n\tlet raw: unknown;\n\ttry {\n\t\traw = await request.json();\n\t} catch {\n\t\treturn apiError(\"INVALID_JSON\", \"Request body must be valid JSON\", 400);\n\t}\n\n\treturn validate(schema, raw);\n}\n\n/**\n * Parse and validate an optional JSON request body.\n *\n * Returns `defaultValue` if the body is empty, or the validated data if present.\n * For endpoints where the body is optional (e.g., preview-url, confirm).\n */\nexport async function parseOptionalBody<T extends z.ZodType>(\n\trequest: Request,\n\tschema: T,\n\tdefaultValue: z.infer<T>,\n): Promise<ParseResult<z.infer<T>>> {\n\t// Best-effort size check via Content-Length (can be absent with chunked encoding)\n\tconst contentLength = request.headers.get(\"Content-Length\");\n\tif (contentLength && parseInt(contentLength, 10) > MAX_BODY_SIZE) {\n\t\treturn apiError(\"PAYLOAD_TOO_LARGE\", \"Request body too large\", 413);\n\t}\n\n\tlet text: string;\n\ttry {\n\t\ttext = await request.text();\n\t} catch {\n\t\treturn defaultValue;\n\t}\n\n\tif (!text.trim()) {\n\t\treturn defaultValue;\n\t}\n\n\tlet raw: unknown;\n\ttry {\n\t\traw = JSON.parse(text);\n\t} catch {\n\t\treturn apiError(\"INVALID_JSON\", \"Request body must be valid JSON\", 400);\n\t}\n\n\treturn validate(schema, raw);\n}\n\n/**\n * Parse and validate URL search params against a Zod schema.\n *\n * Converts searchParams to a plain object before validation.\n * Zod coercion handles string -> number/boolean conversion.\n * Replaces manual `url.searchParams.get()` + `parseInt()` patterns.\n */\nexport function parseQuery<T extends z.ZodType>(url: URL, schema: T): ParseResult<z.infer<T>> {\n\tconst raw: Record<string, string> = {};\n\tfor (const [key, value] of url.searchParams) {\n\t\traw[key] = value;\n\t}\n\treturn validate(schema, raw);\n}\n\n/**\n * Validate raw data against a schema. Returns data or error Response.\n */\nfunction validate<T extends z.ZodType>(schema: T, data: unknown): ParseResult<z.infer<T>> {\n\tconst result = schema.safeParse(data);\n\n\tif (result.success) {\n\t\treturn result.data;\n\t}\n\n\t// Format Zod errors into a readable structure\n\tconst issues = result.error.issues.map((issue: z.core.$ZodIssue) => ({\n\t\tpath: issue.path.join(\".\"),\n\t\tmessage: issue.message,\n\t}));\n\n\treturn apiError(\"VALIDATION_ERROR\", \"Invalid request data\", 400, { issues });\n}\n\n/**\n * Type guard to check if a ParseResult is an error Response.\n * Usage: `if (isParseError(result)) return result;`\n */\nexport function isParseError<T>(result: ParseResult<T>): result is Response {\n\treturn result instanceof Response;\n}\n"],"mappings":";;;;;AAYA,MAAM,gBAAgB,KAAK,OAAO;;;;;;;AAclC,eAAsB,UACrB,SACA,QACmC;CAEnC,MAAM,gBAAgB,QAAQ,QAAQ,IAAI,iBAAiB;AAC3D,KAAI,iBAAiB,SAAS,eAAe,GAAG,GAAG,cAClD,QAAO,SAAS,qBAAqB,0BAA0B,IAAI;CAGpE,IAAI;AACJ,KAAI;AACH,QAAM,MAAM,QAAQ,MAAM;SACnB;AACP,SAAO,SAAS,gBAAgB,mCAAmC,IAAI;;AAGxE,QAAO,SAAS,QAAQ,IAAI;;;;;;;;AAS7B,eAAsB,kBACrB,SACA,QACA,cACmC;CAEnC,MAAM,gBAAgB,QAAQ,QAAQ,IAAI,iBAAiB;AAC3D,KAAI,iBAAiB,SAAS,eAAe,GAAG,GAAG,cAClD,QAAO,SAAS,qBAAqB,0BAA0B,IAAI;CAGpE,IAAI;AACJ,KAAI;AACH,SAAO,MAAM,QAAQ,MAAM;SACpB;AACP,SAAO;;AAGR,KAAI,CAAC,KAAK,MAAM,CACf,QAAO;CAGR,IAAI;AACJ,KAAI;AACH,QAAM,KAAK,MAAM,KAAK;SACf;AACP,SAAO,SAAS,gBAAgB,mCAAmC,IAAI;;AAGxE,QAAO,SAAS,QAAQ,IAAI;;;;;;;;;AAU7B,SAAgB,WAAgC,KAAU,QAAoC;CAC7F,MAAM,MAA8B,EAAE;AACtC,MAAK,MAAM,CAAC,KAAK,UAAU,IAAI,aAC9B,KAAI,OAAO;AAEZ,QAAO,SAAS,QAAQ,IAAI;;;;;AAM7B,SAAS,SAA8B,QAAW,MAAwC;CACzF,MAAM,SAAS,OAAO,UAAU,KAAK;AAErC,KAAI,OAAO,QACV,QAAO,OAAO;AASf,QAAO,SAAS,oBAAoB,wBAAwB,KAAK,EAAE,QALpD,OAAO,MAAM,OAAO,KAAK,WAA6B;EACpE,MAAM,MAAM,KAAK,KAAK,IAAI;EAC1B,SAAS,MAAM;EACf,EAAE,EAEwE,CAAC;;;;;;AAO7E,SAAgB,aAAgB,QAA4C;AAC3E,QAAO,kBAAkB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"passkey-config-
|
|
1
|
+
{"version":3,"file":"passkey-config-qIdO-wF6.mjs","names":[],"sources":["../src/auth/passkey-config.ts"],"sourcesContent":["/**\n * Passkey configuration helper\n *\n * Extracts passkey configuration from the request URL.\n * This ensures the rpId and origin are correctly set for both\n * localhost development and production deployments.\n */\n\nexport interface PasskeyConfig {\n\trpName: string;\n\trpId: string;\n\t/**\n\t * Accepted client-data origins. First entry is the canonical/preferred origin;\n\t * additional entries support multi-origin deployments (e.g. apex + preview\n\t * subdomain sharing the same `rpId`). See `allowedOrigins` parameter.\n\t */\n\torigins: string[];\n}\n\n/**\n * Get passkey configuration from request URL\n *\n * @param url The request URL (typically `new URL(Astro.request.url)` or `new URL(request.url)`)\n * @param siteName Optional site name for rpName (defaults to hostname from `url` or public origin)\n * @param siteUrl Optional browser-facing origin (see `EmDashConfig.siteUrl`).\n * When set, the canonical **origin** and **rpId** are taken from this URL.\n * @param allowedOrigins Optional list of additional accepted origins for verification.\n * Each must share `rpId` with the canonical origin (WebAuthn requirement).\n * Typical use: apex + preview subdomain on the same registrable domain.\n * @throws If `siteUrl` is non-empty but not parseable by `new URL()`.\n */\nexport function getPasskeyConfig(\n\turl: URL,\n\tsiteName?: string,\n\tsiteUrl?: string,\n\tallowedOrigins?: string[],\n): PasskeyConfig {\n\tlet rpName: string;\n\tlet rpId: string;\n\tlet canonicalOrigin: string;\n\n\tif (siteUrl) {\n\t\tlet publicUrl: URL;\n\t\ttry {\n\t\t\tpublicUrl = new URL(siteUrl);\n\t\t} catch (e) {\n\t\t\tthrow new Error(`Invalid siteUrl: \"${siteUrl}\"`, { cause: e });\n\t\t}\n\t\trpName = siteName || publicUrl.hostname;\n\t\trpId = publicUrl.hostname;\n\t\tcanonicalOrigin = publicUrl.origin;\n\t} else {\n\t\trpName = siteName || url.hostname;\n\t\trpId = url.hostname;\n\t\tcanonicalOrigin = url.origin;\n\t}\n\n\tconst origins = [canonicalOrigin];\n\tif (allowedOrigins) {\n\t\tfor (const extra of allowedOrigins) {\n\t\t\tif (extra && !origins.includes(extra)) origins.push(extra);\n\t\t}\n\t}\n\n\treturn { rpName, rpId, origins };\n}\n"],"mappings":";;;;;;;;;;;;;AA+BA,SAAgB,iBACf,KACA,UACA,SACA,gBACgB;CAChB,IAAI;CACJ,IAAI;CACJ,IAAI;AAEJ,KAAI,SAAS;EACZ,IAAI;AACJ,MAAI;AACH,eAAY,IAAI,IAAI,QAAQ;WACpB,GAAG;AACX,SAAM,IAAI,MAAM,qBAAqB,QAAQ,IAAI,EAAE,OAAO,GAAG,CAAC;;AAE/D,WAAS,YAAY,UAAU;AAC/B,SAAO,UAAU;AACjB,oBAAkB,UAAU;QACtB;AACN,WAAS,YAAY,IAAI;AACzB,SAAO,IAAI;AACX,oBAAkB,IAAI;;CAGvB,MAAM,UAAU,CAAC,gBAAgB;AACjC,KAAI,gBACH;OAAK,MAAM,SAAS,eACnB,KAAI,SAAS,CAAC,QAAQ,SAAS,MAAM,CAAE,SAAQ,KAAK,MAAM;;AAI5D,QAAO;EAAE;EAAQ;EAAM;EAAS"}
|
|
@@ -142,4 +142,4 @@ function interpolateDestination(destination, params) {
|
|
|
142
142
|
|
|
143
143
|
//#endregion
|
|
144
144
|
export { validateDestinationParams as a, matchPattern as i, interpolateDestination as n, validatePattern as o, isPattern as r, compilePattern as t };
|
|
145
|
-
//# sourceMappingURL=patterns-
|
|
145
|
+
//# sourceMappingURL=patterns-DC8CLptu.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patterns-
|
|
1
|
+
{"version":3,"file":"patterns-DC8CLptu.mjs","names":[],"sources":["../src/redirects/patterns.ts"],"sourcesContent":["/**\n * URL pattern matching for redirects.\n *\n * Uses Astro's route syntax: [param] for named segments, [...rest] for catch-all.\n * Compiles patterns to safe regexes -- no user-supplied regex, no ReDoS risk.\n *\n * @example\n * ```ts\n * const compiled = compilePattern(\"/old-blog/[...path]\");\n * const match = matchPattern(compiled, \"/old-blog/2024/01/post\");\n * // match = { path: \"2024/01/post\" }\n *\n * interpolateDestination(\"/blog/[...path]\", match);\n * // \"/blog/2024/01/post\"\n * ```\n */\n\n/** Matches [paramName] placeholders */\nconst PARAM_PATTERN = /\\[(\\w+)\\]/g;\n\n/** Matches [...splatName] placeholders */\nconst SPLAT_PATTERN = /\\[\\.\\.\\.(\\w+)\\]/g;\n\n/** Combined pattern for validation: matches both [param] and [...splat] */\nconst ANY_PLACEHOLDER = /\\[(?:\\.\\.\\.)?(\\w+)\\]/g;\n\n/** Nested brackets check: [foo[ */\nconst NESTED_BRACKETS = /\\[[^\\]]*\\[/;\n\n/** Empty brackets: [] */\nconst EMPTY_BRACKETS = /\\[\\]/;\n\n/** Count open brackets */\nconst OPEN_BRACKET = /\\[/g;\n\n/** Count close brackets */\nconst CLOSE_BRACKET = /\\]/g;\n\n/** Split on capture groups in compiled regex string */\nconst CAPTURE_GROUP_SPLIT = /(\\([^)]+\\))/;\n\n/** Escape regex-special characters in literal parts */\nconst REGEX_SPECIAL_CHARS = /[.*+?^${}|\\\\]/g;\n\nexport interface CompiledPattern {\n\tregex: RegExp;\n\tparamNames: string[];\n\tsource: string;\n}\n\n/**\n * Returns true if a source string contains [param] or [...splat] placeholders.\n */\nexport function isPattern(source: string): boolean {\n\t// Use match() instead of test() to avoid lastIndex issues with the global regex\n\treturn source.match(ANY_PLACEHOLDER) !== null;\n}\n\n/**\n * Validate that a pattern string is well-formed.\n * Returns null if valid, or an error message if invalid.\n */\nexport function validatePattern(source: string): string | null {\n\tif (!source.startsWith(\"/\")) {\n\t\treturn \"Pattern must start with /\";\n\t}\n\n\t// Check for nested brackets\n\tif (NESTED_BRACKETS.test(source)) {\n\t\treturn \"Nested brackets are not allowed\";\n\t}\n\n\t// Check for empty brackets\n\tif (EMPTY_BRACKETS.test(source)) {\n\t\treturn \"Empty brackets are not allowed\";\n\t}\n\n\t// Check for unmatched brackets\n\tconst openCount = (source.match(OPEN_BRACKET) ?? []).length;\n\tconst closeCount = (source.match(CLOSE_BRACKET) ?? []).length;\n\tif (openCount !== closeCount) {\n\t\treturn \"Unmatched brackets\";\n\t}\n\n\t// Check that [...splat] is only in the last segment\n\tconst segments = source.split(\"/\").filter(Boolean);\n\tfor (let i = 0; i < segments.length; i++) {\n\t\tconst segment = segments[i];\n\t\tif (SPLAT_PATTERN.test(segment) && i !== segments.length - 1) {\n\t\t\tSPLAT_PATTERN.lastIndex = 0;\n\t\t\treturn \"Catch-all [...param] must be in the last segment\";\n\t\t}\n\t\tSPLAT_PATTERN.lastIndex = 0;\n\t}\n\n\t// Check that a segment is either all literal or a single placeholder\n\tfor (const segment of segments) {\n\t\tconst placeholders = segment.match(ANY_PLACEHOLDER);\n\t\tif (placeholders && placeholders.length > 1) {\n\t\t\treturn \"Each segment can contain at most one placeholder\";\n\t\t}\n\t\tif (placeholders && placeholders[0] !== segment) {\n\t\t\treturn \"A placeholder must be the entire segment, not mixed with literal text\";\n\t\t}\n\t}\n\n\t// Check for duplicate param names\n\tconst names: string[] = [];\n\tfor (const m of source.matchAll(ANY_PLACEHOLDER)) {\n\t\tconst name = m[1];\n\t\tif (names.includes(name)) {\n\t\t\treturn `Duplicate parameter name: ${name}`;\n\t\t}\n\t\tnames.push(name);\n\t}\n\n\treturn null;\n}\n\n/**\n * Validate that all placeholders in a destination exist in the source.\n * Returns null if valid, or an error message if invalid.\n */\nexport function validateDestinationParams(source: string, destination: string): string | null {\n\tconst sourceNames = new Set<string>();\n\tfor (const m of source.matchAll(ANY_PLACEHOLDER)) {\n\t\tsourceNames.add(m[1]);\n\t}\n\n\tfor (const m of destination.matchAll(ANY_PLACEHOLDER)) {\n\t\tconst name = m[1];\n\t\tif (!sourceNames.has(name)) {\n\t\t\treturn `Destination references [${name}] which is not captured in the source pattern`;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Compile a URL pattern into a regex for matching.\n *\n * - `[param]` matches a single path segment (`[^/]+`)\n * - `[...rest]` matches one or more remaining segments (`.+`)\n */\nexport function compilePattern(source: string): CompiledPattern {\n\tconst paramNames: string[] = [];\n\n\t// Replace [...splat] first (before [param]) since [...x] contains [x]\n\tlet regexStr = source.replace(SPLAT_PATTERN, (_match, name: string) => {\n\t\tparamNames.push(name);\n\t\treturn \"(.+)\";\n\t});\n\n\t// Then replace [param]\n\tregexStr = regexStr.replace(PARAM_PATTERN, (_match, name: string) => {\n\t\tparamNames.push(name);\n\t\treturn \"([^/]+)\";\n\t});\n\n\t// Escape any regex-special characters in the literal parts\n\t// We need to be careful: the replacement groups are already valid regex\n\t// Split on capture groups, escape literals, rejoin\n\tconst parts = regexStr.split(CAPTURE_GROUP_SPLIT);\n\tconst escaped = parts\n\t\t.map((part, i) => {\n\t\t\t// Odd indices are the capture groups -- leave them alone\n\t\t\tif (i % 2 === 1) return part;\n\t\t\t// Even indices are literal text -- escape special regex chars\n\t\t\treturn part.replace(REGEX_SPECIAL_CHARS, \"\\\\$&\");\n\t\t})\n\t\t.join(\"\");\n\n\treturn {\n\t\tregex: new RegExp(`^${escaped}$`),\n\t\tparamNames,\n\t\tsource,\n\t};\n}\n\n/**\n * Match a path against a compiled pattern.\n * Returns captured params or null if no match.\n */\nexport function matchPattern(\n\tcompiled: CompiledPattern,\n\tpath: string,\n): Record<string, string> | null {\n\tconst match = path.match(compiled.regex);\n\tif (!match) return null;\n\n\tconst params: Record<string, string> = {};\n\tfor (let i = 0; i < compiled.paramNames.length; i++) {\n\t\tconst value = match[i + 1];\n\t\tif (value !== undefined) {\n\t\t\tparams[compiled.paramNames[i]] = value;\n\t\t}\n\t}\n\treturn params;\n}\n\n/**\n * Interpolate captured params into a destination pattern.\n *\n * @example\n * interpolateDestination(\"/blog/[...path]\", { path: \"2024/01/post\" })\n * // \"/blog/2024/01/post\"\n */\nexport function interpolateDestination(\n\tdestination: string,\n\tparams: Record<string, string>,\n): string {\n\t// Replace [...splat] first\n\tlet result = destination.replace(SPLAT_PATTERN, (_match, name: string) => {\n\t\treturn params[name] ?? \"\";\n\t});\n\n\t// Then [param]\n\tresult = result.replace(PARAM_PATTERN, (_match, name: string) => {\n\t\treturn params[name] ?? \"\";\n\t});\n\n\treturn result;\n}\n"],"mappings":"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"}
|
|
@@ -303,4 +303,4 @@ declare function generatePlaceholder(buffer: Uint8Array, mimeType: string, dimen
|
|
|
303
303
|
}): Promise<PlaceholderData | null>;
|
|
304
304
|
//#endregion
|
|
305
305
|
export { MediaValue as _, ComponentEmbed as a, mediaItemToValue as b, EmbedResult as c, MediaListResult as d, MediaProvider as f, MediaUploadInput as g, MediaProviderItem as h, AudioEmbed as i, ImageEmbed as l, MediaProviderDescriptor as m, generatePlaceholder as n, CreateMediaProviderFn as o, MediaProviderCapabilities as p, normalizeMediaValue as r, EmbedOptions as s, PlaceholderData as t, MediaListOptions as u, ThumbnailOptions as v, VideoEmbed as y };
|
|
306
|
-
//# sourceMappingURL=placeholder-
|
|
306
|
+
//# sourceMappingURL=placeholder-COrvARyD.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"placeholder-
|
|
1
|
+
{"version":3,"file":"placeholder-COrvARyD.d.mts","names":[],"sources":["../src/media/types.ts","../src/media/normalize.ts","../src/media/placeholder.ts"],"mappings":"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"}
|
package/dist/plugin-types.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as MediaAfterUploadHandler, A as ContentScheduleStateChangeEvent, B as EmailDeliverEvent, C as ContentBeforeDeleteHandler, D as ContentHookEvent, E as ContentDeleteEvent, Gt as UpdateIfResult, Ht as UninstallEvent, I as EmailAfterSendEvent, J as LifecycleEvent, Kt as UserInfo, L as EmailAfterSendHandler, M as CronEvent, N as CronHandler, O as ContentPublishStateChangeEvent, Q as MediaAfterUploadEvent, R as EmailBeforeSendEvent, S as ContentAfterUnscheduleHandler, Ut as UninstallHandler, V as EmailDeliverHandler, Wt as UpdateIfArgs, Y as LifecycleHandler, _ as ContentAfterPublishHandler, a as CommentAfterCreateEvent, b as ContentAfterScheduleHandler, c as CommentAfterModerateHandler, d as CommentModerateEvent, et as MediaBeforeUploadHandler, f as CommentModerateHandler, g as ContentAfterDeleteHandler, it as NumericDelta, j as ContentStateChangeEvent, k as ContentRestoreStateChangeEvent, l as CommentBeforeCreateEvent, lt as PageMetadataEvent, m as ConditionalWriteResult, nt as MediaUploadEvent, o as CommentAfterCreateHandler, ot as PageFragmentEvent, p as ConditionalDeleteResult, qt as VersionedValue, s as CommentAfterModerateEvent, st as PageFragmentHandler, t as ActorInfo, u as CommentBeforeCreateHandler, ut as PageMetadataHandler, v as ContentAfterRestoreHandler, vt as PluginContext, w as ContentBeforeSaveHandler, x as ContentAfterUnpublishHandler, y as ContentAfterSaveHandler, z as EmailBeforeSendHandler } from "./types-BouXpOsa.mjs";
|
|
2
|
+
import { r as SandboxHookErrorEnvelope } from "./hook-result-BrshYHLx.mjs";
|
|
2
3
|
import { ZodType } from "zod";
|
|
3
4
|
import { Permission } from "@emdash-cms/auth";
|
|
4
5
|
|
|
@@ -140,12 +141,16 @@ interface SandboxedMcpTool {
|
|
|
140
141
|
* segments.
|
|
141
142
|
*/
|
|
142
143
|
interface SandboxedPlugin {
|
|
143
|
-
hooks?: { [K in keyof HookHandlers]?: HookEntry<K> };
|
|
144
|
+
hooks?: { [K in keyof HookHandlers]?: K extends "content:beforeSave" ? SandboxedContentBeforeSaveHandler | SandboxedContentBeforeSaveConfig : HookEntry<K> };
|
|
144
145
|
routes?: Record<string, RouteEntry>;
|
|
145
146
|
mcp?: {
|
|
146
147
|
tools: Record<string, SandboxedMcpTool>;
|
|
147
148
|
};
|
|
148
149
|
}
|
|
150
|
+
type SandboxedContentBeforeSaveHandler = (event: ContentHookEvent, ctx: PluginContext) => Promise<Record<string, unknown> | SandboxHookErrorEnvelope | void>;
|
|
151
|
+
interface SandboxedContentBeforeSaveConfig extends Omit<HookConfig<"content:beforeSave">, "handler"> {
|
|
152
|
+
handler: SandboxedContentBeforeSaveHandler;
|
|
153
|
+
}
|
|
149
154
|
//#endregion
|
|
150
|
-
export { type CommentAfterCreateEvent, type CommentAfterModerateEvent, type CommentBeforeCreateEvent, type CommentModerateEvent, type ContentDeleteEvent, type ContentHookEvent, type ContentPublishStateChangeEvent, type ContentRestoreStateChangeEvent, type ContentScheduleStateChangeEvent, type ContentStateChangeEvent, type CronEvent, type EmailAfterSendEvent, type EmailBeforeSendEvent, type EmailDeliverEvent, HookConfig, HookEntry, HookHandlers, type LifecycleEvent, type MediaAfterUploadEvent, type MediaUploadEvent, type PageFragmentEvent, type PageMetadataEvent, type PluginContext, RouteEntry, RouteHandler, SandboxedMcpTool, SandboxedPlugin, SandboxedRequest, SandboxedRouteContext, type UninstallEvent };
|
|
155
|
+
export { type ActorInfo, type CommentAfterCreateEvent, type CommentAfterModerateEvent, type CommentBeforeCreateEvent, type CommentModerateEvent, type ConditionalDeleteResult, type ConditionalWriteResult, type ContentDeleteEvent, type ContentHookEvent, type ContentPublishStateChangeEvent, type ContentRestoreStateChangeEvent, type ContentScheduleStateChangeEvent, type ContentStateChangeEvent, type CronEvent, type EmailAfterSendEvent, type EmailBeforeSendEvent, type EmailDeliverEvent, HookConfig, HookEntry, HookHandlers, type LifecycleEvent, type MediaAfterUploadEvent, type MediaUploadEvent, type NumericDelta, type PageFragmentEvent, type PageMetadataEvent, type PluginContext, RouteEntry, RouteHandler, type SandboxHookErrorEnvelope, SandboxedContentBeforeSaveConfig, SandboxedContentBeforeSaveHandler, SandboxedMcpTool, SandboxedPlugin, SandboxedRequest, SandboxedRouteContext, type UninstallEvent, type UpdateIfArgs, type UpdateIfResult, type VersionedValue };
|
|
151
156
|
//# sourceMappingURL=plugin-types.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-types.d.mts","names":[],"sources":["../src/plugin-types.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin-types.d.mts","names":[],"sources":["../src/plugin-types.ts"],"mappings":";;;;;;;;;;;;;UAoGiB,YAAA;EAChB,gBAAA,EAAkB,gBAAA;EAClB,iBAAA,EAAmB,gBAAA;EACnB,mBAAA,EAAqB,gBAAA;EACrB,kBAAA,EAAoB,gBAAA;EACpB,oBAAA,EAAsB,wBAAA;EACtB,mBAAA,EAAqB,uBAAA;EACrB,sBAAA,EAAwB,0BAAA;EACxB,qBAAA,EAAuB,yBAAA;EACvB,sBAAA,EAAwB,0BAAA;EACxB,wBAAA,EAA0B,4BAAA;EAC1B,sBAAA,EAAwB,0BAAA;EACxB,uBAAA,EAAyB,2BAAA;EACzB,yBAAA,EAA2B,6BAAA;EAC3B,oBAAA,EAAsB,wBAAA;EACtB,mBAAA,EAAqB,uBAAA;EACrB,IAAA,EAAM,WAAA;EACN,kBAAA,EAAoB,sBAAA;EACpB,eAAA,EAAiB,mBAAA;EACjB,iBAAA,EAAmB,qBAAA;EACnB,sBAAA,EAAwB,0BAAA;EACxB,kBAAA,EAAoB,sBAAA;EACpB,qBAAA,EAAuB,yBAAA;EACvB,uBAAA,EAAyB,2BAAA;EACzB,eAAA,EAAiB,mBAAA;EACjB,gBAAA,EAAkB,mBAAA;AAAA;;;;;;;UASF,UAAA,iBAA2B,YAAA;EAC3C,OAAA,EAAS,YAAA,CAAa,CAAA;EACtB,QAAA;EACA,OAAA;EACA,YAAA;EACA,WAAA;EACA,SAAA;AAAA;;;;;;KAQW,SAAA,iBAA0B,YAAA,IAAgB,YAAA,CAAa,CAAA,IAAK,UAAA,CAAW,CAAA;;;;;;;;;;;;AAAnF;;;;UAiBiB,gBAAA;EAChB,GAAA;EACA,MAAA;EACA,OAAA,EAAS,MAAA;AAAA;;;;;;;;;UAWO,qBAAA;EAChB,KAAA;EACA,OAAA,EAAS,gBAAA;EACT,WAAA;EAde;;;;;;EAqBf,IAAA,GAAO,QAAA;AAAA;;;;;;;;;;KAYI,YAAA,IACX,QAAA,EAAU,qBAAA,EACV,GAAA,EAAK,aAAA,KACD,OAAA;;AAHL;;;KASY,UAAA,GACT,YAAA;EAEA,OAAA,EAAS,YAAA;EACT,MAAA;EAVS;;;;;EAgBT,YAAA;EACA,KAAA;EACA,UAAA,GAAa,UAAA;AAAA;AAAA,UAGC,gBAAA;EAChB,WAAA;EACA,KAAA;EACA,KAAA,EAAO,OAAA;EACP,MAAA,GAAS,OAAA;EACT,WAAA;AAAA;;;;;;;;;;UAYgB,eAAA;EAChB,KAAA,iBACa,YAAA,IAAgB,CAAA,gCACzB,iCAAA,GAAoC,gCAAA,GACpC,SAAA,CAAU,CAAA;EAEd,MAAA,GAAS,MAAA,SAAe,UAAA;EACxB,GAAA;IAAQ,KAAA,EAAO,MAAA,SAAe,gBAAA;EAAA;AAAA;AAAA,KAGnB,iCAAA,IACX,KAAA,EAAO,gBAAA,EACP,GAAA,EAAK,aAAA,KACD,OAAA,CAAQ,MAAA,oBAA0B,wBAAA;AAAA,UAEtB,gCAAA,SAAyC,IAAA,CACzD,UAAA;EAGA,OAAA,EAAS,iCAAA;AAAA"}
|
package/dist/plugin-utils.d.mts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import "./options-
|
|
2
|
-
import "./types-
|
|
3
|
-
import "./types-
|
|
4
|
-
import "./
|
|
5
|
-
import "./
|
|
6
|
-
import "./runner-
|
|
7
|
-
import "./index-
|
|
8
|
-
import "./types-
|
|
9
|
-
import "./hreflang-
|
|
10
|
-
import "./validate-
|
|
1
|
+
import "./options-D8Y0VHc7.mjs";
|
|
2
|
+
import "./types-tJWDK__M.mjs";
|
|
3
|
+
import "./types-BouXpOsa.mjs";
|
|
4
|
+
import "./entry-lock-CGAtrwAR.mjs";
|
|
5
|
+
import "./config-CGAhyOjP.mjs";
|
|
6
|
+
import "./runner-CfwysRM0.mjs";
|
|
7
|
+
import "./index-1ECYpfiF.mjs";
|
|
8
|
+
import "./types-DaEg7KX2.mjs";
|
|
9
|
+
import "./hreflang-CQpu5bMy.mjs";
|
|
10
|
+
import "./validate-Df6Dvwbw.mjs";
|
|
11
11
|
import { EmDashHandlers } from "./astro/types.mjs";
|
|
12
12
|
|
|
13
13
|
//#region src/plugin-utils.d.ts
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import "../options-
|
|
2
|
-
import "../types-
|
|
3
|
-
import {
|
|
4
|
-
import "../
|
|
5
|
-
import {
|
|
6
|
-
import "../runner-
|
|
7
|
-
import "../index-
|
|
1
|
+
import "../options-D8Y0VHc7.mjs";
|
|
2
|
+
import "../types-tJWDK__M.mjs";
|
|
3
|
+
import { jt as ResolvedPlugin } from "../types-BouXpOsa.mjs";
|
|
4
|
+
import "../entry-lock-CGAtrwAR.mjs";
|
|
5
|
+
import { Ir as PluginDescriptor } from "../config-CGAhyOjP.mjs";
|
|
6
|
+
import "../runner-CfwysRM0.mjs";
|
|
7
|
+
import "../index-1ECYpfiF.mjs";
|
|
8
8
|
import { SandboxedPlugin } from "../plugin-types.mjs";
|
|
9
|
-
import "../types-
|
|
10
|
-
import "../hreflang-
|
|
11
|
-
import "../validate-
|
|
9
|
+
import "../types-DaEg7KX2.mjs";
|
|
10
|
+
import "../hreflang-CQpu5bMy.mjs";
|
|
11
|
+
import "../validate-Df6Dvwbw.mjs";
|
|
12
12
|
|
|
13
13
|
//#region src/plugins/adapt-sandbox-entry.d.ts
|
|
14
14
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as PLUGIN_CAPABILITIES, t as HOOK_NAMES } from "../manifest-schema-
|
|
2
|
-
import {
|
|
1
|
+
import { n as PLUGIN_CAPABILITIES, t as HOOK_NAMES } from "../manifest-schema-CILooI5J.mjs";
|
|
2
|
+
import { i as normalizeCapabilities } from "../types-A2cN6a4a.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/plugins/adapt-sandbox-entry.ts
|
|
5
5
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as getExactMigrationStatus, s as runMigrations } from "./runner-
|
|
1
|
+
import { i as getExactMigrationStatus, s as runMigrations } from "./runner-nEzvnogG.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/database/migrations/policy.ts
|
|
4
4
|
function parseMigrationMode(value, source) {
|
|
@@ -42,4 +42,4 @@ async function enforceRuntimeMigrationPolicy(db, mode) {
|
|
|
42
42
|
|
|
43
43
|
//#endregion
|
|
44
44
|
export { resolveRuntimeMigrationMode as i, enforceRuntimeMigrationPolicy as n, normalizeMigrationConfig as r, PendingMigrationsError as t };
|
|
45
|
-
//# sourceMappingURL=policy-
|
|
45
|
+
//# sourceMappingURL=policy-XCfb-IE9.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policy-
|
|
1
|
+
{"version":3,"file":"policy-XCfb-IE9.mjs","names":[],"sources":["../src/database/migrations/policy.ts"],"sourcesContent":["import type { Kysely } from \"kysely\";\n\nimport type { Database } from \"../types.js\";\nimport { getExactMigrationStatus, runMigrations } from \"./runner.js\";\n\nexport type RuntimeMigrationMode = \"auto\" | \"check\" | \"manual\";\n\nexport interface RuntimeMigrationConfig {\n\truntime: RuntimeMigrationMode;\n\tdev?: RuntimeMigrationMode;\n}\n\nfunction parseMigrationMode(value: unknown, source: string): RuntimeMigrationMode {\n\tif (value === \"auto\" || value === \"check\" || value === \"manual\") {\n\t\treturn value;\n\t}\n\tthrow new Error(\n\t\t`Invalid ${source} value ${JSON.stringify(value)}; expected \"auto\", \"check\", or \"manual\"`,\n\t);\n}\n\nexport function normalizeMigrationConfig(value: unknown): RuntimeMigrationConfig {\n\tif (value === undefined) return { runtime: \"auto\" };\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new Error(\"Invalid migrations configuration; expected an object\");\n\t}\n\n\tconst runtimeValue = Reflect.get(value, \"runtime\");\n\tconst devValue = Reflect.get(value, \"dev\");\n\tconst runtime = parseMigrationMode(runtimeValue, \"migrations.runtime\");\n\tconst dev = devValue === undefined ? undefined : parseMigrationMode(devValue, \"migrations.dev\");\n\treturn dev === undefined ? { runtime } : { runtime, dev };\n}\n\nexport function resolveRuntimeMigrationMode(\n\tconfig: RuntimeMigrationConfig | undefined,\n\toptions: { dev: boolean; override?: unknown },\n): RuntimeMigrationMode {\n\tif (options.override !== undefined) {\n\t\treturn parseMigrationMode(options.override, \"EMDASH_MIGRATIONS_MODE\");\n\t}\n\tif (options.dev) return config?.dev ?? \"auto\";\n\treturn config?.runtime ?? \"auto\";\n}\n\nexport class PendingMigrationsError extends Error {\n\treadonly pending: string[];\n\n\tconstructor(pending: readonly string[]) {\n\t\tsuper(`Database has pending EmDash migrations: ${pending.join(\", \")}`);\n\t\tthis.name = \"PendingMigrationsError\";\n\t\tthis.pending = [...pending];\n\t}\n}\n\nexport async function enforceRuntimeMigrationPolicy(\n\tdb: Kysely<Database>,\n\tmode: RuntimeMigrationMode,\n): Promise<void> {\n\tif (mode === \"manual\") return;\n\tif (mode === \"auto\") {\n\t\tawait runMigrations(db);\n\t\treturn;\n\t}\n\n\tconst status = await getExactMigrationStatus(db);\n\tif (status.pending.length > 0) {\n\t\tthrow new PendingMigrationsError(status.pending);\n\t}\n}\n"],"mappings":";;;AAYA,SAAS,mBAAmB,OAAgB,QAAsC;AACjF,KAAI,UAAU,UAAU,UAAU,WAAW,UAAU,SACtD,QAAO;AAER,OAAM,IAAI,MACT,WAAW,OAAO,SAAS,KAAK,UAAU,MAAM,CAAC,yCACjD;;AAGF,SAAgB,yBAAyB,OAAwC;AAChF,KAAI,UAAU,OAAW,QAAO,EAAE,SAAS,QAAQ;AACnD,KAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,MAAM,CACtE,OAAM,IAAI,MAAM,uDAAuD;CAGxE,MAAM,eAAe,QAAQ,IAAI,OAAO,UAAU;CAClD,MAAM,WAAW,QAAQ,IAAI,OAAO,MAAM;CAC1C,MAAM,UAAU,mBAAmB,cAAc,qBAAqB;CACtE,MAAM,MAAM,aAAa,SAAY,SAAY,mBAAmB,UAAU,iBAAiB;AAC/F,QAAO,QAAQ,SAAY,EAAE,SAAS,GAAG;EAAE;EAAS;EAAK;;AAG1D,SAAgB,4BACf,QACA,SACuB;AACvB,KAAI,QAAQ,aAAa,OACxB,QAAO,mBAAmB,QAAQ,UAAU,yBAAyB;AAEtE,KAAI,QAAQ,IAAK,QAAO,QAAQ,OAAO;AACvC,QAAO,QAAQ,WAAW;;AAG3B,IAAa,yBAAb,cAA4C,MAAM;CACjD,AAAS;CAET,YAAY,SAA4B;AACvC,QAAM,2CAA2C,QAAQ,KAAK,KAAK,GAAG;AACtE,OAAK,OAAO;AACZ,OAAK,UAAU,CAAC,GAAG,QAAQ;;;AAI7B,eAAsB,8BACrB,IACA,MACgB;AAChB,KAAI,SAAS,SAAU;AACvB,KAAI,SAAS,QAAQ;AACpB,QAAM,cAAc,GAAG;AACvB;;CAGD,MAAM,SAAS,MAAM,wBAAwB,GAAG;AAChD,KAAI,OAAO,QAAQ,SAAS,EAC3B,OAAM,IAAI,uBAAuB,OAAO,QAAQ"}
|
|
@@ -283,4 +283,4 @@ function convertDataForWrite(data, fields) {
|
|
|
283
283
|
|
|
284
284
|
//#endregion
|
|
285
285
|
export { portableTextToMarkdown as i, convertDataForWrite as n, markdownToPortableText as r, convertDataForRead as t };
|
|
286
|
-
//# sourceMappingURL=portable-text-
|
|
286
|
+
//# sourceMappingURL=portable-text-BS3d5n-0.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"portable-text-C8Tvp4_g.mjs","names":[],"sources":["../src/client/portable-text.ts"],"sourcesContent":["/**\n * Portable Text <-> Markdown conversion layer.\n *\n * Three tiers of block handling:\n * Tier 1: Standard PT blocks <-> standard Markdown (headings, paragraphs, lists, etc.)\n * Tier 2: EmDash custom blocks <-> Markdown directives (future)\n * Tier 3: Unknown blocks <-> opaque HTML comment fences (preserved, not editable)\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Minimal Portable Text block shape */\nexport interface PortableTextBlock {\n\t_type: string;\n\t_key?: string;\n\tstyle?: string;\n\tlevel?: number;\n\tlistItem?: string;\n\tmarkDefs?: MarkDef[];\n\tchildren?: PortableTextSpan[];\n\t[key: string]: unknown;\n}\n\ninterface PortableTextSpan {\n\t_type: string;\n\t_key?: string;\n\ttext?: string;\n\tmarks?: string[];\n\t[key: string]: unknown;\n}\n\ninterface MarkDef {\n\t_key: string;\n\t_type: string;\n\thref?: string;\n\t[key: string]: unknown;\n}\n\ninterface ParsedInline {\n\tspans: PortableTextSpan[];\n\tmarkDefs: MarkDef[];\n}\n\n// ---------------------------------------------------------------------------\n// PT -> Markdown\n// ---------------------------------------------------------------------------\n\n/**\n * Convert Portable Text blocks to Markdown.\n * Unknown block types are serialized as opaque fences.\n */\nexport function portableTextToMarkdown(blocks: PortableTextBlock[]): string {\n\tconst lines: string[] = [];\n\tlet prevWasList = false;\n\n\tfor (let i = 0; i < blocks.length; i++) {\n\t\tconst block = blocks[i];\n\n\t\tif (block._type === \"block\") {\n\t\t\tconst isList = !!block.listItem;\n\n\t\t\t// Blank line between non-contiguous block types\n\t\t\tif (i > 0 && (!isList || !prevWasList)) {\n\t\t\t\tlines.push(\"\");\n\t\t\t}\n\n\t\t\tlines.push(renderStandardBlock(block));\n\t\t\tprevWasList = isList;\n\t\t} else if (block._type === \"code\") {\n\t\t\tif (i > 0) lines.push(\"\");\n\t\t\tconst lang = (block.language as string) || \"\";\n\t\t\tconst code = (block.code as string) || \"\";\n\t\t\tlines.push(\"```\" + lang);\n\t\t\tlines.push(code);\n\t\t\tlines.push(\"```\");\n\t\t\tprevWasList = false;\n\t\t} else if (block._type === \"image\") {\n\t\t\tif (i > 0) lines.push(\"\");\n\t\t\tconst alt = (block.alt as string) || \"\";\n\t\t\tconst url = (block.asset as { url?: string })?.url || \"\";\n\t\t\tlines.push(``);\n\t\t\tprevWasList = false;\n\t\t} else {\n\t\t\t// Tier 3: Unknown block -> opaque fence\n\t\t\tif (i > 0) lines.push(\"\");\n\t\t\tlines.push(`<!--ec:block ${JSON.stringify(block)} -->`);\n\t\t\tprevWasList = false;\n\t\t}\n\t}\n\n\treturn lines.join(\"\\n\") + \"\\n\";\n}\n\nfunction renderStandardBlock(block: PortableTextBlock): string {\n\tconst text = renderSpans(block.children ?? [], block.markDefs ?? []);\n\n\t// List items\n\tif (block.listItem) {\n\t\tconst indent = \" \".repeat(Math.max(0, (block.level ?? 1) - 1));\n\t\tconst marker = block.listItem === \"number\" ? \"1.\" : \"-\";\n\t\treturn `${indent}${marker} ${text}`;\n\t}\n\n\t// Headings\n\tif (block.style && block.style.startsWith(\"h\")) {\n\t\tconst level = parseInt(block.style.substring(1), 10);\n\t\tif (level >= 1 && level <= 6) {\n\t\t\treturn `${\"#\".repeat(level)} ${text}`;\n\t\t}\n\t}\n\n\t// Blockquote\n\tif (block.style === \"blockquote\") {\n\t\treturn `> ${text}`;\n\t}\n\n\treturn text;\n}\n\nfunction renderSpans(spans: PortableTextSpan[], markDefs: MarkDef[]): string {\n\tlet result = \"\";\n\n\tfor (const span of spans) {\n\t\tif (span._type !== \"span\") continue;\n\n\t\tlet text = span.text ?? \"\";\n\t\tconst marks = span.marks ?? [];\n\n\t\tfor (const mark of marks) {\n\t\t\tconst def = markDefs.find((d) => d._key === mark);\n\t\t\tif (def) {\n\t\t\t\tif (def._type === \"link\") {\n\t\t\t\t\ttext = `[${text}](${def.href ?? \"\"})`;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tswitch (mark) {\n\t\t\t\t\tcase \"strong\":\n\t\t\t\t\t\ttext = `**${text}**`;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"em\":\n\t\t\t\t\t\ttext = `_${text}_`;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"code\":\n\t\t\t\t\t\ttext = `\\`${text}\\``;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"strike-through\":\n\t\t\t\t\tcase \"strikethrough\":\n\t\t\t\t\t\ttext = `~~${text}~~`;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tresult += text;\n\t}\n\n\treturn result;\n}\n\n// ---------------------------------------------------------------------------\n// Markdown -> PT\n// ---------------------------------------------------------------------------\n\n// Regex patterns for markdown parsing\nconst OPAQUE_FENCE_PATTERN = /^<!--ec:block (.+) -->$/;\nconst HEADING_PATTERN = /^(#{1,6})\\s+(.+)$/;\nconst UNORDERED_LIST_PATTERN = /^(\\s*)[-*+]\\s+(.+)$/;\nconst ORDERED_LIST_PATTERN = /^(\\s*)\\d+\\.\\s+(.+)$/;\nconst IMAGE_PATTERN = /^!\\[([^\\]]*)\\]\\(([^)]+)\\)$/;\nconst INLINE_MARKDOWN_PATTERN =\n\t/(\\*\\*(.+?)\\*\\*)|(_(.+?)_)|(`(.+?)`)|(\\[(.+?)\\]\\((.+?)\\))|(~~(.+?)~~)/g;\n\n/**\n * Convert Markdown to Portable Text blocks.\n * Opaque fences (<!--ec:block ... -->) are deserialized and spliced back in.\n */\nexport function markdownToPortableText(markdown: string): PortableTextBlock[] {\n\tconst blocks: PortableTextBlock[] = [];\n\tconst lines = markdown.split(\"\\n\");\n\tlet i = 0;\n\n\twhile (i < lines.length) {\n\t\tconst line = lines[i];\n\n\t\t// Opaque fence\n\t\tconst opaqueMatch = line.match(OPAQUE_FENCE_PATTERN);\n\t\tif (opaqueMatch) {\n\t\t\ttry {\n\t\t\t\tblocks.push(JSON.parse(opaqueMatch[1]) as PortableTextBlock);\n\t\t\t} catch {\n\t\t\t\tblocks.push(makeBlock(line));\n\t\t\t}\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Code fence\n\t\tif (line.startsWith(\"```\")) {\n\t\t\tconst lang = line.slice(3).trim();\n\t\t\tconst codeLines: string[] = [];\n\t\t\ti++;\n\t\t\twhile (i < lines.length && !lines[i].startsWith(\"```\")) {\n\t\t\t\tcodeLines.push(lines[i]);\n\t\t\t\ti++;\n\t\t\t}\n\t\t\tblocks.push({\n\t\t\t\t_type: \"code\",\n\t\t\t\t_key: generateKey(),\n\t\t\t\tlanguage: lang || undefined,\n\t\t\t\tcode: codeLines.join(\"\\n\"),\n\t\t\t});\n\t\t\ti++; // skip closing ```\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Blank line\n\t\tif (line.trim() === \"\") {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Heading\n\t\tconst headingMatch = line.match(HEADING_PATTERN);\n\t\tif (headingMatch) {\n\t\t\tblocks.push(makeBlock(headingMatch[2], `h${headingMatch[1].length}`));\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Blockquote\n\t\tif (line.startsWith(\"> \")) {\n\t\t\tblocks.push(makeBlock(line.slice(2), \"blockquote\"));\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Unordered list\n\t\tconst ulMatch = line.match(UNORDERED_LIST_PATTERN);\n\t\tif (ulMatch) {\n\t\t\tconst level = Math.floor(ulMatch[1].length / 2) + 1;\n\t\t\tblocks.push(makeListBlock(ulMatch[2], \"bullet\", level));\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Ordered list\n\t\tconst olMatch = line.match(ORDERED_LIST_PATTERN);\n\t\tif (olMatch) {\n\t\t\tconst level = Math.floor(olMatch[1].length / 2) + 1;\n\t\t\tblocks.push(makeListBlock(olMatch[2], \"number\", level));\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Image\n\t\tconst imgMatch = line.match(IMAGE_PATTERN);\n\t\tif (imgMatch) {\n\t\t\tblocks.push({\n\t\t\t\t_type: \"image\",\n\t\t\t\t_key: generateKey(),\n\t\t\t\talt: imgMatch[1],\n\t\t\t\tasset: { url: imgMatch[2] },\n\t\t\t});\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Paragraph\n\t\tblocks.push(makeBlock(line));\n\t\ti++;\n\t}\n\n\treturn blocks;\n}\n\n// ---------------------------------------------------------------------------\n// Block builders\n// ---------------------------------------------------------------------------\n\nfunction makeBlock(text: string, style: string = \"normal\"): PortableTextBlock {\n\tconst { spans, markDefs } = parseInline(text);\n\treturn { _type: \"block\", _key: generateKey(), style, markDefs, children: spans };\n}\n\nfunction makeListBlock(text: string, listItem: string, level: number): PortableTextBlock {\n\tconst { spans, markDefs } = parseInline(text);\n\treturn {\n\t\t_type: \"block\",\n\t\t_key: generateKey(),\n\t\tstyle: \"normal\",\n\t\tlistItem,\n\t\tlevel,\n\t\tmarkDefs,\n\t\tchildren: spans,\n\t};\n}\n\n/**\n * Parse inline markdown (bold, italic, code, links, strikethrough) into PT spans + markDefs.\n */\nfunction parseInline(text: string): ParsedInline {\n\tconst spans: PortableTextSpan[] = [];\n\tconst markDefs: MarkDef[] = [];\n\tconst regex = INLINE_MARKDOWN_PATTERN;\n\n\tlet lastIndex = 0;\n\tlet match: RegExpExecArray | null;\n\n\twhile ((match = regex.exec(text)) !== null) {\n\t\tif (match.index > lastIndex) {\n\t\t\tspans.push({\n\t\t\t\t_type: \"span\",\n\t\t\t\t_key: generateKey(),\n\t\t\t\ttext: text.slice(lastIndex, match.index),\n\t\t\t\tmarks: [],\n\t\t\t});\n\t\t}\n\n\t\tif (match[2] != null) {\n\t\t\tspans.push({ _type: \"span\", _key: generateKey(), text: match[2], marks: [\"strong\"] });\n\t\t} else if (match[4] != null) {\n\t\t\tspans.push({ _type: \"span\", _key: generateKey(), text: match[4], marks: [\"em\"] });\n\t\t} else if (match[6] != null) {\n\t\t\tspans.push({ _type: \"span\", _key: generateKey(), text: match[6], marks: [\"code\"] });\n\t\t} else if (match[8] != null && match[9] != null) {\n\t\t\tconst key = generateKey();\n\t\t\tmarkDefs.push({ _key: key, _type: \"link\", href: match[9] });\n\t\t\tspans.push({ _type: \"span\", _key: generateKey(), text: match[8], marks: [key] });\n\t\t} else if (match[11] != null) {\n\t\t\tspans.push({\n\t\t\t\t_type: \"span\",\n\t\t\t\t_key: generateKey(),\n\t\t\t\ttext: match[11],\n\t\t\t\tmarks: [\"strike-through\"],\n\t\t\t});\n\t\t}\n\n\t\tlastIndex = match.index + match[0].length;\n\t}\n\n\tif (lastIndex < text.length) {\n\t\tspans.push({ _type: \"span\", _key: generateKey(), text: text.slice(lastIndex), marks: [] });\n\t}\n\n\tif (spans.length === 0) {\n\t\tspans.push({ _type: \"span\", _key: generateKey(), text, marks: [] });\n\t}\n\n\treturn { spans, markDefs };\n}\n\n// ---------------------------------------------------------------------------\n// Key generation\n// ---------------------------------------------------------------------------\n\nlet keyCounter = 0;\n\nfunction generateKey(): string {\n\treturn `k${(keyCounter++).toString(36)}`;\n}\n\n/** Reset key counter (useful for testing) */\nexport function resetKeyCounter(): void {\n\tkeyCounter = 0;\n}\n\n// ---------------------------------------------------------------------------\n// Schema-aware conversion helpers\n// ---------------------------------------------------------------------------\n\nexport interface FieldSchema {\n\tslug: string;\n\ttype: string;\n}\n\n/**\n * Convert content data for reading: PT fields -> markdown strings.\n * Only converts fields with type \"portableText\" that contain arrays.\n */\nexport function convertDataForRead(\n\tdata: Record<string, unknown>,\n\tfields: FieldSchema[],\n\traw: boolean = false,\n): Record<string, unknown> {\n\tif (raw) return data;\n\n\tconst result = { ...data };\n\tfor (const field of fields) {\n\t\tif (field.type === \"portableText\" && Array.isArray(result[field.slug])) {\n\t\t\tresult[field.slug] = portableTextToMarkdown(result[field.slug] as PortableTextBlock[]);\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Convert content data for writing: markdown strings -> PT arrays.\n * Only converts fields with type \"portableText\" that contain strings.\n */\nexport function convertDataForWrite(\n\tdata: Record<string, unknown>,\n\tfields: FieldSchema[],\n): Record<string, unknown> {\n\tconst result = { ...data };\n\tfor (const field of fields) {\n\t\tif (field.type === \"portableText\" && typeof result[field.slug] === \"string\") {\n\t\t\tresult[field.slug] = markdownToPortableText(result[field.slug] as string);\n\t\t}\n\t}\n\treturn result;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"portable-text-BS3d5n-0.mjs","names":[],"sources":["../src/client/portable-text.ts"],"sourcesContent":["/**\n * Portable Text <-> Markdown conversion layer.\n *\n * Three tiers of block handling:\n * Tier 1: Standard PT blocks <-> standard Markdown (headings, paragraphs, lists, etc.)\n * Tier 2: EmDash custom blocks <-> Markdown directives (future)\n * Tier 3: Unknown blocks <-> opaque HTML comment fences (preserved, not editable)\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Minimal Portable Text block shape */\nexport interface PortableTextBlock {\n\t_type: string;\n\t_key?: string;\n\tstyle?: string;\n\tlevel?: number;\n\tlistItem?: string;\n\tmarkDefs?: MarkDef[];\n\tchildren?: PortableTextSpan[];\n\t[key: string]: unknown;\n}\n\ninterface PortableTextSpan {\n\t_type: string;\n\t_key?: string;\n\ttext?: string;\n\tmarks?: string[];\n\t[key: string]: unknown;\n}\n\ninterface MarkDef {\n\t_key: string;\n\t_type: string;\n\thref?: string;\n\t[key: string]: unknown;\n}\n\ninterface ParsedInline {\n\tspans: PortableTextSpan[];\n\tmarkDefs: MarkDef[];\n}\n\n// ---------------------------------------------------------------------------\n// PT -> Markdown\n// ---------------------------------------------------------------------------\n\n/**\n * Convert Portable Text blocks to Markdown.\n * Unknown block types are serialized as opaque fences.\n */\nexport function portableTextToMarkdown(blocks: PortableTextBlock[]): string {\n\tconst lines: string[] = [];\n\tlet prevWasList = false;\n\n\tfor (let i = 0; i < blocks.length; i++) {\n\t\tconst block = blocks[i];\n\n\t\tif (block._type === \"block\") {\n\t\t\tconst isList = !!block.listItem;\n\n\t\t\t// Blank line between non-contiguous block types\n\t\t\tif (i > 0 && (!isList || !prevWasList)) {\n\t\t\t\tlines.push(\"\");\n\t\t\t}\n\n\t\t\tlines.push(renderStandardBlock(block));\n\t\t\tprevWasList = isList;\n\t\t} else if (block._type === \"code\") {\n\t\t\tif (i > 0) lines.push(\"\");\n\t\t\tconst lang = (block.language as string) || \"\";\n\t\t\tconst code = (block.code as string) || \"\";\n\t\t\tlines.push(\"```\" + lang);\n\t\t\tlines.push(code);\n\t\t\tlines.push(\"```\");\n\t\t\tprevWasList = false;\n\t\t} else if (block._type === \"image\") {\n\t\t\tif (i > 0) lines.push(\"\");\n\t\t\tconst alt = (block.alt as string) || \"\";\n\t\t\tconst url = (block.asset as { url?: string })?.url || \"\";\n\t\t\tlines.push(``);\n\t\t\tprevWasList = false;\n\t\t} else {\n\t\t\t// Tier 3: Unknown block -> opaque fence\n\t\t\tif (i > 0) lines.push(\"\");\n\t\t\tlines.push(`<!--ec:block ${JSON.stringify(block)} -->`);\n\t\t\tprevWasList = false;\n\t\t}\n\t}\n\n\treturn lines.join(\"\\n\") + \"\\n\";\n}\n\nfunction renderStandardBlock(block: PortableTextBlock): string {\n\tconst text = renderSpans(block.children ?? [], block.markDefs ?? []);\n\n\t// List items\n\tif (block.listItem) {\n\t\tconst indent = \" \".repeat(Math.max(0, (block.level ?? 1) - 1));\n\t\tconst marker = block.listItem === \"number\" ? \"1.\" : \"-\";\n\t\treturn `${indent}${marker} ${text}`;\n\t}\n\n\t// Headings\n\tif (block.style && block.style.startsWith(\"h\")) {\n\t\tconst level = parseInt(block.style.substring(1), 10);\n\t\tif (level >= 1 && level <= 6) {\n\t\t\treturn `${\"#\".repeat(level)} ${text}`;\n\t\t}\n\t}\n\n\t// Blockquote\n\tif (block.style === \"blockquote\") {\n\t\treturn `> ${text}`;\n\t}\n\n\treturn text;\n}\n\nfunction renderSpans(spans: PortableTextSpan[], markDefs: MarkDef[]): string {\n\tlet result = \"\";\n\n\tfor (const span of spans) {\n\t\tif (span._type !== \"span\") continue;\n\n\t\tlet text = span.text ?? \"\";\n\t\tconst marks = span.marks ?? [];\n\n\t\tfor (const mark of marks) {\n\t\t\tconst def = markDefs.find((d) => d._key === mark);\n\t\t\tif (def) {\n\t\t\t\tif (def._type === \"link\") {\n\t\t\t\t\ttext = `[${text}](${def.href ?? \"\"})`;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tswitch (mark) {\n\t\t\t\t\tcase \"strong\":\n\t\t\t\t\t\ttext = `**${text}**`;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"em\":\n\t\t\t\t\t\ttext = `_${text}_`;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"code\":\n\t\t\t\t\t\ttext = `\\`${text}\\``;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"strike-through\":\n\t\t\t\t\tcase \"strikethrough\":\n\t\t\t\t\t\ttext = `~~${text}~~`;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tresult += text;\n\t}\n\n\treturn result;\n}\n\n// ---------------------------------------------------------------------------\n// Markdown -> PT\n// ---------------------------------------------------------------------------\n\n// Regex patterns for markdown parsing\nconst OPAQUE_FENCE_PATTERN = /^<!--ec:block (.+) -->$/;\nconst HEADING_PATTERN = /^(#{1,6})\\s+(.+)$/;\nconst UNORDERED_LIST_PATTERN = /^(\\s*)[-*+]\\s+(.+)$/;\nconst ORDERED_LIST_PATTERN = /^(\\s*)\\d+\\.\\s+(.+)$/;\nconst IMAGE_PATTERN = /^!\\[([^\\]]*)\\]\\(([^)]+)\\)$/;\nconst INLINE_MARKDOWN_PATTERN =\n\t/(\\*\\*(.+?)\\*\\*)|(_(.+?)_)|(`(.+?)`)|(\\[(.+?)\\]\\((.+?)\\))|(~~(.+?)~~)/g;\n\n/**\n * Convert Markdown to Portable Text blocks.\n * Opaque fences (<!--ec:block ... -->) are deserialized and spliced back in.\n */\nexport function markdownToPortableText(markdown: string): PortableTextBlock[] {\n\tconst blocks: PortableTextBlock[] = [];\n\tconst lines = markdown.split(\"\\n\");\n\tlet i = 0;\n\n\twhile (i < lines.length) {\n\t\tconst line = lines[i];\n\n\t\t// Opaque fence\n\t\tconst opaqueMatch = line.match(OPAQUE_FENCE_PATTERN);\n\t\tif (opaqueMatch) {\n\t\t\ttry {\n\t\t\t\tblocks.push(JSON.parse(opaqueMatch[1]) as PortableTextBlock);\n\t\t\t} catch {\n\t\t\t\tblocks.push(makeBlock(line));\n\t\t\t}\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Code fence\n\t\tif (line.startsWith(\"```\")) {\n\t\t\tconst lang = line.slice(3).trim();\n\t\t\tconst codeLines: string[] = [];\n\t\t\ti++;\n\t\t\twhile (i < lines.length && !lines[i].startsWith(\"```\")) {\n\t\t\t\tcodeLines.push(lines[i]);\n\t\t\t\ti++;\n\t\t\t}\n\t\t\tblocks.push({\n\t\t\t\t_type: \"code\",\n\t\t\t\t_key: generateKey(),\n\t\t\t\tlanguage: lang || undefined,\n\t\t\t\tcode: codeLines.join(\"\\n\"),\n\t\t\t});\n\t\t\ti++; // skip closing ```\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Blank line\n\t\tif (line.trim() === \"\") {\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Heading\n\t\tconst headingMatch = line.match(HEADING_PATTERN);\n\t\tif (headingMatch) {\n\t\t\tblocks.push(makeBlock(headingMatch[2], `h${headingMatch[1].length}`));\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Blockquote\n\t\tif (line.startsWith(\"> \")) {\n\t\t\tblocks.push(makeBlock(line.slice(2), \"blockquote\"));\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Unordered list\n\t\tconst ulMatch = line.match(UNORDERED_LIST_PATTERN);\n\t\tif (ulMatch) {\n\t\t\tconst level = Math.floor(ulMatch[1].length / 2) + 1;\n\t\t\tblocks.push(makeListBlock(ulMatch[2], \"bullet\", level));\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Ordered list\n\t\tconst olMatch = line.match(ORDERED_LIST_PATTERN);\n\t\tif (olMatch) {\n\t\t\tconst level = Math.floor(olMatch[1].length / 2) + 1;\n\t\t\tblocks.push(makeListBlock(olMatch[2], \"number\", level));\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Image\n\t\tconst imgMatch = line.match(IMAGE_PATTERN);\n\t\tif (imgMatch) {\n\t\t\tblocks.push({\n\t\t\t\t_type: \"image\",\n\t\t\t\t_key: generateKey(),\n\t\t\t\talt: imgMatch[1],\n\t\t\t\tasset: { url: imgMatch[2] },\n\t\t\t});\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Paragraph\n\t\tblocks.push(makeBlock(line));\n\t\ti++;\n\t}\n\n\treturn blocks;\n}\n\n// ---------------------------------------------------------------------------\n// Block builders\n// ---------------------------------------------------------------------------\n\nfunction makeBlock(text: string, style: string = \"normal\"): PortableTextBlock {\n\tconst { spans, markDefs } = parseInline(text);\n\treturn { _type: \"block\", _key: generateKey(), style, markDefs, children: spans };\n}\n\nfunction makeListBlock(text: string, listItem: string, level: number): PortableTextBlock {\n\tconst { spans, markDefs } = parseInline(text);\n\treturn {\n\t\t_type: \"block\",\n\t\t_key: generateKey(),\n\t\tstyle: \"normal\",\n\t\tlistItem,\n\t\tlevel,\n\t\tmarkDefs,\n\t\tchildren: spans,\n\t};\n}\n\n/**\n * Parse inline markdown (bold, italic, code, links, strikethrough) into PT spans + markDefs.\n */\nfunction parseInline(text: string): ParsedInline {\n\tconst spans: PortableTextSpan[] = [];\n\tconst markDefs: MarkDef[] = [];\n\tconst regex = INLINE_MARKDOWN_PATTERN;\n\n\tlet lastIndex = 0;\n\tlet match: RegExpExecArray | null;\n\n\twhile ((match = regex.exec(text)) !== null) {\n\t\tif (match.index > lastIndex) {\n\t\t\tspans.push({\n\t\t\t\t_type: \"span\",\n\t\t\t\t_key: generateKey(),\n\t\t\t\ttext: text.slice(lastIndex, match.index),\n\t\t\t\tmarks: [],\n\t\t\t});\n\t\t}\n\n\t\tif (match[2] != null) {\n\t\t\tspans.push({ _type: \"span\", _key: generateKey(), text: match[2], marks: [\"strong\"] });\n\t\t} else if (match[4] != null) {\n\t\t\tspans.push({ _type: \"span\", _key: generateKey(), text: match[4], marks: [\"em\"] });\n\t\t} else if (match[6] != null) {\n\t\t\tspans.push({ _type: \"span\", _key: generateKey(), text: match[6], marks: [\"code\"] });\n\t\t} else if (match[8] != null && match[9] != null) {\n\t\t\tconst key = generateKey();\n\t\t\tmarkDefs.push({ _key: key, _type: \"link\", href: match[9] });\n\t\t\tspans.push({ _type: \"span\", _key: generateKey(), text: match[8], marks: [key] });\n\t\t} else if (match[11] != null) {\n\t\t\tspans.push({\n\t\t\t\t_type: \"span\",\n\t\t\t\t_key: generateKey(),\n\t\t\t\ttext: match[11],\n\t\t\t\tmarks: [\"strike-through\"],\n\t\t\t});\n\t\t}\n\n\t\tlastIndex = match.index + match[0].length;\n\t}\n\n\tif (lastIndex < text.length) {\n\t\tspans.push({ _type: \"span\", _key: generateKey(), text: text.slice(lastIndex), marks: [] });\n\t}\n\n\tif (spans.length === 0) {\n\t\tspans.push({ _type: \"span\", _key: generateKey(), text, marks: [] });\n\t}\n\n\treturn { spans, markDefs };\n}\n\n// ---------------------------------------------------------------------------\n// Key generation\n// ---------------------------------------------------------------------------\n\nlet keyCounter = 0;\n\nfunction generateKey(): string {\n\treturn `k${(keyCounter++).toString(36)}`;\n}\n\n/** Reset key counter (useful for testing) */\nexport function resetKeyCounter(): void {\n\tkeyCounter = 0;\n}\n\n// ---------------------------------------------------------------------------\n// Schema-aware conversion helpers\n// ---------------------------------------------------------------------------\n\nexport interface FieldSchema {\n\tslug: string;\n\ttype: string;\n}\n\n/**\n * Convert content data for reading: PT fields -> markdown strings.\n * Only converts fields with type \"portableText\" that contain arrays.\n */\nexport function convertDataForRead(\n\tdata: Record<string, unknown>,\n\tfields: FieldSchema[],\n\traw: boolean = false,\n): Record<string, unknown> {\n\tif (raw) return data;\n\n\tconst result = { ...data };\n\tfor (const field of fields) {\n\t\tif (field.type === \"portableText\" && Array.isArray(result[field.slug])) {\n\t\t\tresult[field.slug] = portableTextToMarkdown(result[field.slug] as PortableTextBlock[]);\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Convert content data for writing: markdown strings -> PT arrays.\n * Only converts fields with type \"portableText\" that contain strings.\n */\nexport function convertDataForWrite(\n\tdata: Record<string, unknown>,\n\tfields: FieldSchema[],\n): Record<string, unknown> {\n\tconst result = { ...data };\n\tfor (const field of fields) {\n\t\tif (field.type === \"portableText\" && typeof result[field.slug] === \"string\") {\n\t\t\tresult[field.slug] = markdownToPortableText(result[field.slug] as string);\n\t\t}\n\t}\n\treturn result;\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as generatePreviewToken } from "./tokens-
|
|
1
|
+
import { t as generatePreviewToken } from "./tokens-CDk8ox9p.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/preview/urls.ts
|
|
4
4
|
/**
|
|
@@ -104,4 +104,4 @@ function getPreviewToken(url) {
|
|
|
104
104
|
|
|
105
105
|
//#endregion
|
|
106
106
|
export { getPreviewUrl as i, isPreviewRequest as n, buildPreviewUrl as r, getPreviewToken as t };
|
|
107
|
-
//# sourceMappingURL=preview-
|
|
107
|
+
//# sourceMappingURL=preview-BxwsGgGp.mjs.map
|