@xleddyl/nuxt-cms 0.9.4 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/module.d.mts +20 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +1037 -148
- package/dist/runtime/app/blocks/CmsBlocks.d.vue.ts +1 -1
- package/dist/runtime/app/blocks/CmsBlocks.vue +57 -9
- package/dist/runtime/app/blocks/CmsBlocks.vue.d.ts +1 -1
- package/dist/runtime/app/blocks/CmsField.d.ts +24 -0
- package/dist/runtime/app/blocks/CmsField.js +16 -0
- package/dist/runtime/app/blocks/node.d.ts +37 -0
- package/dist/runtime/app/blocks/node.js +17 -0
- package/dist/runtime/app/blocks/resolve.d.ts +18 -0
- package/dist/runtime/app/blocks/resolve.js +34 -0
- package/dist/runtime/app/components/cms/BlockPicker.d.vue.ts +22 -0
- package/dist/runtime/app/components/cms/BlockPicker.vue +87 -0
- package/dist/runtime/app/components/cms/BlockPicker.vue.d.ts +22 -0
- package/dist/runtime/app/components/cms/BlockPickerPopover.d.vue.ts +38 -0
- package/dist/runtime/app/components/cms/BlockPickerPopover.vue +44 -0
- package/dist/runtime/app/components/cms/BlockPickerPopover.vue.d.ts +38 -0
- package/dist/runtime/app/components/cms/BlockTree.d.vue.ts +29 -0
- package/dist/runtime/app/components/cms/BlockTree.vue +322 -0
- package/dist/runtime/app/components/cms/BlockTree.vue.d.ts +29 -0
- package/dist/runtime/app/components/cms/BlocksField.vue +569 -219
- package/dist/runtime/app/components/cms/BrandMark.vue +7 -13
- package/dist/runtime/app/components/cms/ConfirmGroups.vue +15 -13
- package/dist/runtime/app/components/cms/{BlockPalette.vue.d.ts → EditorHistory.d.vue.ts} +6 -5
- package/dist/runtime/app/components/cms/EditorHistory.vue +34 -0
- package/dist/runtime/app/components/cms/{BlockPalette.d.vue.ts → EditorHistory.vue.d.ts} +6 -5
- package/dist/runtime/app/components/cms/EntryDrawer.d.vue.ts +11 -5
- package/dist/runtime/app/components/cms/EntryDrawer.vue +183 -152
- package/dist/runtime/app/components/cms/EntryDrawer.vue.d.ts +11 -5
- package/dist/runtime/app/components/cms/EntryForm.d.vue.ts +16 -4
- package/dist/runtime/app/components/cms/EntryForm.vue +106 -147
- package/dist/runtime/app/components/cms/EntryForm.vue.d.ts +16 -4
- package/dist/runtime/app/components/cms/FieldInput.vue +10 -2
- package/dist/runtime/app/components/cms/FormSections.d.vue.ts +22 -0
- package/dist/runtime/app/components/cms/FormSections.vue +71 -0
- package/dist/runtime/app/components/cms/FormSections.vue.d.ts +22 -0
- package/dist/runtime/app/components/cms/ImportModal.vue +46 -58
- package/dist/runtime/app/components/cms/LinkField.d.vue.ts +16 -0
- package/dist/runtime/app/components/cms/LinkField.vue +250 -0
- package/dist/runtime/app/components/cms/LinkField.vue.d.ts +16 -0
- package/dist/runtime/app/components/cms/ListFilters.vue +10 -12
- package/dist/runtime/app/components/cms/LocaleSwitch.d.vue.ts +2 -1
- package/dist/runtime/app/components/cms/LocaleSwitch.vue +19 -11
- package/dist/runtime/app/components/cms/LocaleSwitch.vue.d.ts +2 -1
- package/dist/runtime/app/components/cms/MediaDetail.d.vue.ts +2 -0
- package/dist/runtime/app/components/cms/MediaDetail.vue +112 -83
- package/dist/runtime/app/components/cms/MediaDetail.vue.d.ts +2 -0
- package/dist/runtime/app/components/cms/MediaField.vue +35 -25
- package/dist/runtime/app/components/cms/MediaFolderPicker.vue +26 -71
- package/dist/runtime/app/components/cms/MediaGallery.d.vue.ts +1 -0
- package/dist/runtime/app/components/cms/MediaGallery.vue +442 -419
- package/dist/runtime/app/components/cms/MediaGallery.vue.d.ts +1 -0
- package/dist/runtime/app/components/cms/MediaThumb.vue +9 -25
- package/dist/runtime/app/components/cms/MediaUpload.vue +1 -1
- package/dist/runtime/app/components/cms/{BlockOutline.d.vue.ts → NestedBlockList.d.vue.ts} +5 -5
- package/dist/runtime/app/components/cms/NestedBlockList.vue +87 -0
- package/dist/runtime/app/components/cms/{BlockOutline.vue.d.ts → NestedBlockList.vue.d.ts} +5 -5
- package/dist/runtime/app/components/cms/PoweredBy.vue +12 -5
- package/dist/runtime/app/components/cms/PresetModal.d.vue.ts +18 -0
- package/dist/runtime/app/components/cms/PresetModal.vue +70 -0
- package/dist/runtime/app/components/cms/PresetModal.vue.d.ts +18 -0
- package/dist/runtime/app/components/cms/RelationField.vue +2 -8
- package/dist/runtime/app/components/cms/SettingsAccount.vue +60 -71
- package/dist/runtime/app/components/cms/SettingsColumns.vue +47 -69
- package/dist/runtime/app/components/cms/SettingsEmptyAdd.d.vue.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsEmptyAdd.vue +21 -0
- package/dist/runtime/app/components/cms/SettingsEmptyAdd.vue.d.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsEntries.d.vue.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsEntries.vue +50 -0
- package/dist/runtime/app/components/cms/SettingsEntries.vue.d.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsEntry.d.vue.ts +1 -10
- package/dist/runtime/app/components/cms/SettingsEntry.vue +11 -95
- package/dist/runtime/app/components/cms/SettingsEntry.vue.d.ts +1 -10
- package/dist/runtime/app/components/cms/SettingsEntryActions.d.vue.ts +7 -0
- package/dist/runtime/app/components/cms/SettingsEntryActions.vue +40 -0
- package/dist/runtime/app/components/cms/SettingsEntryActions.vue.d.ts +7 -0
- package/dist/runtime/app/components/cms/SettingsEntryTabs.d.vue.ts +7 -0
- package/dist/runtime/app/components/cms/SettingsEntryTabs.vue +21 -0
- package/dist/runtime/app/components/cms/SettingsEntryTabs.vue.d.ts +7 -0
- package/dist/runtime/app/components/cms/SettingsFormAction.d.vue.ts +3 -0
- package/dist/runtime/app/components/cms/SettingsFormAction.vue +17 -0
- package/dist/runtime/app/components/cms/SettingsFormAction.vue.d.ts +3 -0
- package/dist/runtime/app/components/cms/SettingsLayout.vue +18 -14
- package/dist/runtime/app/components/cms/SettingsPresetForm.d.vue.ts +11 -0
- package/dist/runtime/app/components/cms/SettingsPresetForm.vue +60 -0
- package/dist/runtime/app/components/cms/SettingsPresetForm.vue.d.ts +11 -0
- package/dist/runtime/app/components/cms/SettingsPresets.d.vue.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsPresets.vue +65 -0
- package/dist/runtime/app/components/cms/SettingsPresets.vue.d.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsRecordActions.d.vue.ts +32 -0
- package/dist/runtime/app/components/cms/SettingsRecordActions.vue +45 -0
- package/dist/runtime/app/components/cms/SettingsRecordActions.vue.d.ts +32 -0
- package/dist/runtime/app/components/cms/SettingsRedirectActions.d.vue.ts +3 -0
- package/dist/runtime/app/components/cms/SettingsRedirectActions.vue +59 -0
- package/dist/runtime/app/components/cms/SettingsRedirectActions.vue.d.ts +3 -0
- package/dist/runtime/app/components/cms/SettingsRedirectForm.d.vue.ts +11 -0
- package/dist/runtime/app/components/cms/SettingsRedirectForm.vue +77 -0
- package/dist/runtime/app/components/cms/SettingsRedirectForm.vue.d.ts +11 -0
- package/dist/runtime/app/components/cms/SettingsRedirects.d.vue.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsRedirects.vue +117 -0
- package/dist/runtime/app/components/cms/SettingsRedirects.vue.d.ts +13 -0
- package/dist/runtime/app/components/cms/SettingsSecretCard.d.vue.ts +17 -0
- package/dist/runtime/app/components/cms/SettingsSecretCard.vue +43 -0
- package/dist/runtime/app/components/cms/SettingsSecretCard.vue.d.ts +17 -0
- package/dist/runtime/app/components/cms/SettingsSite.d.vue.ts +3 -0
- package/dist/runtime/app/components/cms/SettingsSite.vue +140 -0
- package/dist/runtime/app/components/cms/SettingsSite.vue.d.ts +3 -0
- package/dist/runtime/app/components/cms/SettingsUserCreate.d.vue.ts +8 -0
- package/dist/runtime/app/components/cms/SettingsUserCreate.vue +82 -0
- package/dist/runtime/app/components/cms/SettingsUserCreate.vue.d.ts +8 -0
- package/dist/runtime/app/components/cms/SettingsUserDetail.d.vue.ts +11 -0
- package/dist/runtime/app/components/cms/SettingsUserDetail.vue +179 -0
- package/dist/runtime/app/components/cms/SettingsUserDetail.vue.d.ts +11 -0
- package/dist/runtime/app/components/cms/SettingsUsers.d.vue.ts +9 -6
- package/dist/runtime/app/components/cms/SettingsUsers.vue +88 -234
- package/dist/runtime/app/components/cms/SettingsUsers.vue.d.ts +9 -6
- package/dist/runtime/app/components/cms/SharePreview.d.vue.ts +18 -0
- package/dist/runtime/app/components/cms/SharePreview.vue +219 -0
- package/dist/runtime/app/components/cms/SharePreview.vue.d.ts +18 -0
- package/dist/runtime/app/components/cms/SlugField.vue +5 -3
- package/dist/runtime/app/components/cms/StatusBadge.vue +8 -8
- package/dist/runtime/app/components/cms/TranslationBadges.d.vue.ts +7 -0
- package/dist/runtime/app/components/cms/TranslationBadges.vue +44 -0
- package/dist/runtime/app/components/cms/TranslationBadges.vue.d.ts +7 -0
- package/dist/runtime/app/components/cms/TranslationMenu.d.vue.ts +17 -0
- package/dist/runtime/app/components/cms/TranslationMenu.vue +28 -0
- package/dist/runtime/app/components/cms/TranslationMenu.vue.d.ts +17 -0
- package/dist/runtime/app/components/cms/VisualEditor.d.vue.ts +22 -4
- package/dist/runtime/app/components/cms/VisualEditor.vue +1153 -338
- package/dist/runtime/app/components/cms/VisualEditor.vue.d.ts +22 -4
- package/dist/runtime/app/components/cms/WelcomeModal.vue +32 -50
- package/dist/runtime/app/composables/cms-clipboard.d.ts +8 -0
- package/dist/runtime/app/composables/cms-clipboard.js +38 -0
- package/dist/runtime/app/composables/cms-confirm.d.ts +6 -8
- package/dist/runtime/app/composables/cms-confirm.js +5 -7
- package/dist/runtime/app/composables/cms-entry-disabled.d.ts +5 -1
- package/dist/runtime/app/composables/cms-entry-disabled.js +7 -0
- package/dist/runtime/app/composables/cms-entry-form.d.ts +15 -0
- package/dist/runtime/app/composables/cms-entry-form.js +40 -0
- package/dist/runtime/app/composables/cms-entry-settings.d.ts +30 -0
- package/dist/runtime/app/composables/cms-entry-settings.js +122 -0
- package/dist/runtime/app/composables/cms-entry.d.ts +5 -1
- package/dist/runtime/app/composables/cms-entry.js +36 -11
- package/dist/runtime/app/composables/cms-history.d.ts +10 -0
- package/dist/runtime/app/composables/cms-history.js +24 -0
- package/dist/runtime/app/composables/cms-link-targets.d.ts +10 -0
- package/dist/runtime/app/composables/cms-link-targets.js +40 -0
- package/dist/runtime/app/composables/cms-link-usage.d.ts +1 -0
- package/dist/runtime/app/composables/cms-link-usage.js +45 -0
- package/dist/runtime/app/composables/cms-media-library.d.ts +19 -9
- package/dist/runtime/app/composables/cms-media-library.js +31 -13
- package/dist/runtime/app/composables/cms-media-uploader.js +6 -20
- package/dist/runtime/app/composables/cms-permissions.d.ts +18 -0
- package/dist/runtime/app/composables/cms-permissions.js +54 -0
- package/dist/runtime/app/composables/cms-presets.d.ts +11 -0
- package/dist/runtime/app/composables/cms-presets.js +40 -0
- package/dist/runtime/app/composables/cms-preview-mode.d.ts +4 -0
- package/dist/runtime/app/composables/cms-preview-mode.js +8 -0
- package/dist/runtime/app/composables/cms-query.d.ts +3 -0
- package/dist/runtime/app/composables/cms-query.js +45 -20
- package/dist/runtime/app/composables/cms-record-list.d.ts +31 -0
- package/dist/runtime/app/composables/cms-record-list.js +75 -0
- package/dist/runtime/app/composables/cms-route.d.ts +6 -0
- package/dist/runtime/app/composables/cms-route.js +36 -0
- package/dist/runtime/app/composables/cms-runtime.d.ts +1 -0
- package/dist/runtime/app/composables/cms-save-handoff.d.ts +4 -0
- package/dist/runtime/app/composables/cms-save-handoff.js +19 -0
- package/dist/runtime/app/composables/cms-seo.d.ts +12 -0
- package/dist/runtime/app/composables/cms-seo.js +69 -0
- package/dist/runtime/app/composables/cms-settings-form.d.ts +13 -0
- package/dist/runtime/app/composables/cms-settings-form.js +29 -0
- package/dist/runtime/app/composables/cms-settings-sections.d.ts +26 -0
- package/dist/runtime/app/composables/cms-settings-sections.js +181 -0
- package/dist/runtime/app/composables/cms-settings-stores.d.ts +52 -0
- package/dist/runtime/app/composables/cms-settings-stores.js +156 -0
- package/dist/runtime/app/composables/cms-settings.d.ts +3 -3
- package/dist/runtime/app/composables/cms-settings.js +14 -8
- package/dist/runtime/app/composables/cms-site-disabled.d.ts +7 -0
- package/dist/runtime/app/composables/cms-site-disabled.js +8 -0
- package/dist/runtime/app/composables/cms-site.d.ts +7 -0
- package/dist/runtime/app/composables/cms-site.js +22 -0
- package/dist/runtime/app/composables/cms-toast.d.ts +2 -8
- package/dist/runtime/app/composables/cms-toast.js +3 -9
- package/dist/runtime/app/composables/cms-translation-actions.d.ts +15 -0
- package/dist/runtime/app/composables/cms-translation-actions.js +108 -0
- package/dist/runtime/app/css-url.d.ts +4 -0
- package/dist/runtime/app/image/CmsImage.d.vue.ts +89 -0
- package/dist/runtime/app/image/CmsImage.vue +91 -0
- package/dist/runtime/app/image/CmsImage.vue.d.ts +89 -0
- package/dist/runtime/app/layouts/cms-admin.d.vue.ts +2 -2
- package/dist/runtime/app/layouts/cms-admin.vue +98 -76
- package/dist/runtime/app/layouts/cms-admin.vue.d.ts +2 -2
- package/dist/runtime/app/layouts/cms-editor.vue +7 -2
- package/dist/runtime/app/links/CmsLink.d.vue.ts +18 -0
- package/dist/runtime/app/links/CmsLink.vue +18 -0
- package/dist/runtime/app/links/CmsLink.vue.d.ts +18 -0
- package/dist/runtime/app/middleware/cms-auth.js +13 -1
- package/dist/runtime/app/pages/admin-collection.vue +473 -297
- package/dist/runtime/app/pages/admin-content.vue +191 -54
- package/dist/runtime/app/pages/admin-entry.vue +79 -75
- package/dist/runtime/app/pages/admin-index.vue +18 -5
- package/dist/runtime/app/pages/admin-login.vue +1 -1
- package/dist/runtime/app/pages/admin-logout.vue +1 -1
- package/dist/runtime/app/pages/admin-media.vue +3 -3
- package/dist/runtime/app/pages/admin-preview.vue +112 -24
- package/dist/runtime/app/plugins/cms-field.d.ts +2 -0
- package/dist/runtime/app/plugins/cms-field.js +8 -0
- package/dist/runtime/app/plugins/cms-preview-banner.client.d.ts +2 -0
- package/dist/runtime/app/plugins/cms-preview-banner.client.js +19 -0
- package/dist/runtime/app/plugins/cms-preview.d.ts +2 -0
- package/dist/runtime/app/plugins/cms-preview.js +27 -0
- package/dist/runtime/app/preview/CmsPreviewBanner.d.vue.ts +7 -0
- package/dist/runtime/app/preview/CmsPreviewBanner.vue +63 -0
- package/dist/runtime/app/preview/CmsPreviewBanner.vue.d.ts +7 -0
- package/dist/runtime/app/preview/PreviewOverlay.d.vue.ts +17 -3
- package/dist/runtime/app/preview/PreviewOverlay.vue +629 -166
- package/dist/runtime/app/preview/PreviewOverlay.vue.d.ts +17 -3
- package/dist/runtime/app/preview/field-marker.d.ts +12 -0
- package/dist/runtime/app/preview/field-marker.js +20 -0
- package/dist/runtime/app/preview/inline-text.d.ts +15 -0
- package/dist/runtime/app/preview/inline-text.js +158 -0
- package/dist/runtime/app/utils/block-editor.d.ts +22 -0
- package/dist/runtime/app/utils/block-editor.js +12 -0
- package/dist/runtime/app/utils/keyboard.d.ts +6 -0
- package/dist/runtime/app/utils/keyboard.js +52 -0
- package/dist/runtime/app/utils/redirects.d.ts +6 -0
- package/dist/runtime/app/utils/redirects.js +7 -0
- package/dist/runtime/app/utils/ui.d.ts +8 -0
- package/dist/runtime/app/utils/ui.js +15 -1
- package/dist/runtime/app/utils/users.d.ts +15 -0
- package/dist/runtime/app/utils/users.js +14 -0
- package/dist/runtime/assets/cms.css +1 -1
- package/dist/runtime/generate.js +16 -2
- package/dist/runtime/server/api/collection-export.get.js +3 -2
- package/dist/runtime/server/api/collection-import.post.js +39 -11
- package/dist/runtime/server/api/collection.get.js +27 -9
- package/dist/runtime/server/api/collection.post.js +28 -11
- package/dist/runtime/server/api/collection.put.js +35 -13
- package/dist/runtime/server/api/item.delete.js +19 -7
- package/dist/runtime/server/api/item.get.js +3 -2
- package/dist/runtime/server/api/item.put.js +52 -18
- package/dist/runtime/server/api/link-usage.post.d.ts +5 -0
- package/dist/runtime/server/api/link-usage.post.js +21 -0
- package/dist/runtime/server/api/media-delete.post.js +4 -2
- package/dist/runtime/server/api/media-download.get.js +2 -2
- package/dist/runtime/server/api/media-folder.delete.js +8 -2
- package/dist/runtime/server/api/media-folder.patch.js +10 -2
- package/dist/runtime/server/api/media-folder.post.js +4 -2
- package/dist/runtime/server/api/media-move.post.js +7 -4
- package/dist/runtime/server/api/media-presign.post.js +2 -2
- package/dist/runtime/server/api/media-upload.put.js +2 -2
- package/dist/runtime/server/api/media-usage.post.d.ts +2 -4
- package/dist/runtime/server/api/media-usage.post.js +13 -9
- package/dist/runtime/server/api/media.delete.js +4 -2
- package/dist/runtime/server/api/media.get.js +22 -7
- package/dist/runtime/server/api/media.post.js +4 -2
- package/dist/runtime/server/api/media.put.js +33 -16
- package/dist/runtime/server/api/preset.delete.d.ts +4 -0
- package/dist/runtime/server/api/preset.delete.js +9 -0
- package/dist/runtime/server/api/preset.put.d.ts +3 -0
- package/dist/runtime/server/api/preset.put.js +23 -0
- package/dist/runtime/server/api/presets-field.get.d.ts +3 -0
- package/dist/runtime/server/api/presets-field.get.js +13 -0
- package/dist/runtime/server/api/presets-field.post.d.ts +3 -0
- package/dist/runtime/server/api/presets-field.post.js +36 -0
- package/dist/runtime/server/api/presets.get.d.ts +3 -0
- package/dist/runtime/server/api/presets.get.js +7 -0
- package/dist/runtime/server/api/preview-link.delete.d.ts +4 -0
- package/dist/runtime/server/api/preview-link.delete.js +15 -0
- package/dist/runtime/server/api/preview-links.get.d.ts +3 -0
- package/dist/runtime/server/api/preview-links.get.js +10 -0
- package/dist/runtime/server/api/preview-links.post.d.ts +3 -0
- package/dist/runtime/server/api/preview-links.post.js +17 -0
- package/dist/runtime/server/api/preview.get.d.ts +3 -0
- package/dist/runtime/server/api/preview.get.js +7 -0
- package/dist/runtime/server/api/redirect.delete.d.ts +4 -0
- package/dist/runtime/server/api/redirect.delete.js +10 -0
- package/dist/runtime/server/api/redirect.put.d.ts +3 -0
- package/dist/runtime/server/api/redirect.put.js +8 -0
- package/dist/runtime/server/api/redirects-import.post.d.ts +3 -0
- package/dist/runtime/server/api/redirects-import.post.js +13 -0
- package/dist/runtime/server/api/redirects.get.d.ts +3 -0
- package/dist/runtime/server/api/redirects.get.js +7 -0
- package/dist/runtime/server/api/redirects.post.d.ts +3 -0
- package/dist/runtime/server/api/redirects.post.js +7 -0
- package/dist/runtime/server/api/search.get.js +8 -3
- package/dist/runtime/server/api/settings.delete.js +2 -2
- package/dist/runtime/server/api/settings.get.js +4 -2
- package/dist/runtime/server/api/settings.put.js +2 -2
- package/dist/runtime/server/api/site.get.d.ts +3 -0
- package/dist/runtime/server/api/site.get.js +7 -0
- package/dist/runtime/server/api/site.put.d.ts +3 -0
- package/dist/runtime/server/api/site.put.js +16 -0
- package/dist/runtime/server/api/tags.get.js +3 -2
- package/dist/runtime/server/api/user.delete.js +8 -2
- package/dist/runtime/server/api/user.put.js +14 -4
- package/dist/runtime/server/api/users.get.js +2 -2
- package/dist/runtime/server/api/users.post.js +8 -4
- package/dist/runtime/server/middleware/hidden-site.d.ts +2 -0
- package/dist/runtime/server/middleware/hidden-site.js +8 -0
- package/dist/runtime/server/middleware/preview-links.d.ts +2 -0
- package/dist/runtime/server/middleware/preview-links.js +6 -0
- package/dist/runtime/server/middleware/redirects.d.ts +2 -0
- package/dist/runtime/server/middleware/redirects.js +18 -0
- package/dist/runtime/server/plugins/session-validate.js +4 -1
- package/dist/runtime/server/plugins/webhooks.d.ts +3 -0
- package/dist/runtime/server/plugins/webhooks.js +27 -0
- package/dist/runtime/server/routes/graphql.js +5 -3
- package/dist/runtime/server/routes/robots.d.ts +2 -0
- package/dist/runtime/server/routes/robots.js +16 -0
- package/dist/runtime/server/routes/sitemap.d.ts +2 -0
- package/dist/runtime/server/routes/sitemap.js +67 -0
- package/dist/runtime/server/utils/cached-value.d.ts +5 -0
- package/dist/runtime/server/utils/cached-value.js +24 -0
- package/dist/runtime/server/utils/content-routes.d.ts +5 -0
- package/dist/runtime/server/utils/content-routes.js +29 -0
- package/dist/runtime/server/utils/field-rules.d.ts +19 -0
- package/dist/runtime/server/utils/field-rules.js +72 -0
- package/dist/runtime/server/utils/graphql.d.ts +3 -1
- package/dist/runtime/server/utils/graphql.js +143 -28
- package/dist/runtime/server/utils/hooks.d.ts +14 -0
- package/dist/runtime/server/utils/hooks.js +71 -0
- package/dist/runtime/server/utils/import.d.ts +7 -2
- package/dist/runtime/server/utils/import.js +108 -14
- package/dist/runtime/server/utils/link-usage.d.ts +4 -0
- package/dist/runtime/server/utils/link-usage.js +28 -0
- package/dist/runtime/server/utils/media-references.d.ts +6 -1
- package/dist/runtime/server/utils/media-references.js +49 -20
- package/dist/runtime/server/utils/media-usage.d.ts +2 -0
- package/dist/runtime/server/utils/media-usage.js +5 -3
- package/dist/runtime/server/utils/page-rows.d.ts +2 -0
- package/dist/runtime/server/utils/page-rows.js +42 -29
- package/dist/runtime/server/utils/permissions.d.ts +14 -0
- package/dist/runtime/server/utils/permissions.js +43 -0
- package/dist/runtime/server/utils/presets.d.ts +18 -0
- package/dist/runtime/server/utils/presets.js +68 -0
- package/dist/runtime/server/utils/preview-links.d.ts +207 -0
- package/dist/runtime/server/utils/preview-links.js +161 -0
- package/dist/runtime/server/utils/redirects.d.ts +31 -0
- package/dist/runtime/server/utils/redirects.js +240 -0
- package/dist/runtime/server/utils/registry.js +4 -1
- package/dist/runtime/server/utils/relations.d.ts +8 -0
- package/dist/runtime/server/utils/relations.js +25 -6
- package/dist/runtime/server/utils/require-admin.d.ts +0 -1
- package/dist/runtime/server/utils/require-admin.js +4 -8
- package/dist/runtime/server/utils/search.d.ts +1 -0
- package/dist/runtime/server/utils/search.js +44 -19
- package/dist/runtime/server/utils/site.d.ts +23 -0
- package/dist/runtime/server/utils/site.js +79 -0
- package/dist/runtime/server/utils/sitemap.d.ts +12 -0
- package/dist/runtime/server/utils/sitemap.js +109 -0
- package/dist/runtime/server/utils/user-management.d.ts +4 -0
- package/dist/runtime/server/utils/user-management.js +20 -0
- package/dist/runtime/server/utils/users.d.ts +1 -1
- package/dist/runtime/server/utils/users.js +1 -1
- package/dist/runtime/server/utils/visibility.d.ts +1 -0
- package/dist/runtime/server/utils/visibility.js +6 -1
- package/dist/runtime/server/utils/webhooks.d.ts +24 -0
- package/dist/runtime/server/utils/webhooks.js +90 -0
- package/dist/runtime/shared/block-paths.d.ts +66 -0
- package/dist/runtime/shared/block-paths.js +310 -0
- package/dist/runtime/shared/block-picker.d.ts +18 -0
- package/dist/runtime/shared/block-picker.js +31 -0
- package/dist/runtime/shared/block-signature.d.ts +4 -0
- package/dist/runtime/shared/block-signature.js +46 -0
- package/dist/runtime/shared/clipboard.d.ts +31 -0
- package/dist/runtime/shared/clipboard.js +206 -0
- package/dist/runtime/shared/conditions.d.ts +36 -0
- package/dist/runtime/shared/conditions.js +100 -0
- package/dist/runtime/shared/content-routes.d.ts +42 -0
- package/dist/runtime/shared/content-routes.js +237 -0
- package/dist/runtime/shared/duplicate.js +2 -1
- package/dist/runtime/shared/editor-layout.d.ts +18 -0
- package/dist/runtime/shared/editor-layout.js +9 -0
- package/dist/runtime/shared/field-options.d.ts +21 -0
- package/dist/runtime/shared/field-options.js +90 -0
- package/dist/runtime/shared/graphql-sdl.d.ts +1 -0
- package/dist/runtime/shared/graphql-sdl.js +50 -26
- package/dist/runtime/shared/history.d.ts +27 -0
- package/dist/runtime/shared/history.js +123 -0
- package/dist/runtime/shared/hooks.d.ts +45 -0
- package/dist/runtime/shared/hooks.js +28 -0
- package/dist/runtime/shared/index.d.ts +90 -21
- package/dist/runtime/shared/index.js +121 -37
- package/dist/runtime/shared/inline-text.d.ts +38 -0
- package/dist/runtime/shared/inline-text.js +85 -0
- package/dist/runtime/shared/layout.d.ts +2 -1
- package/dist/runtime/shared/layout.js +3 -0
- package/dist/runtime/shared/links.d.ts +48 -0
- package/dist/runtime/shared/links.js +155 -0
- package/dist/runtime/shared/list-filters.d.ts +2 -0
- package/dist/runtime/shared/list-filters.js +2 -0
- package/dist/runtime/shared/media-focal.d.ts +30 -0
- package/dist/runtime/shared/media-focal.js +52 -0
- package/dist/runtime/shared/migrations-dir.d.ts +14 -0
- package/dist/runtime/shared/migrations-dir.js +48 -2
- package/dist/runtime/shared/presets.d.ts +67 -0
- package/dist/runtime/shared/presets.js +127 -0
- package/dist/runtime/shared/preview-links.d.ts +64 -0
- package/dist/runtime/shared/preview-links.js +54 -0
- package/dist/runtime/shared/preview.d.ts +124 -21
- package/dist/runtime/shared/preview.js +419 -81
- package/dist/runtime/shared/redirects.d.ts +75 -0
- package/dist/runtime/shared/redirects.js +230 -0
- package/dist/runtime/shared/roles.d.ts +57 -0
- package/dist/runtime/shared/roles.js +293 -0
- package/dist/runtime/shared/save-state.d.ts +8 -0
- package/dist/runtime/shared/save-state.js +15 -0
- package/dist/runtime/shared/search.d.ts +16 -1
- package/dist/runtime/shared/search.js +41 -7
- package/dist/runtime/shared/seo.d.ts +167 -0
- package/dist/runtime/shared/seo.js +335 -0
- package/dist/runtime/shared/transfer.js +2 -1
- package/dist/runtime/shared/translations.d.ts +29 -0
- package/dist/runtime/shared/translations.js +123 -0
- package/dist/runtime/shared/users.d.ts +1 -1
- package/dist/runtime/shared/validation.d.ts +23 -1
- package/dist/runtime/shared/validation.js +214 -64
- package/dist/runtime/webhooks.d.ts +33 -0
- package/dist/runtime/webhooks.js +57 -0
- package/dist/types.d.mts +5 -1
- package/package.json +6 -2
- package/dist/runtime/app/components/cms/BlockOutline.vue +0 -88
- package/dist/runtime/app/components/cms/BlockPalette.vue +0 -31
- package/dist/runtime/app/components/cms/SettingsModal.d.vue.ts +0 -12
- package/dist/runtime/app/components/cms/SettingsModal.vue +0 -126
- package/dist/runtime/app/components/cms/SettingsModal.vue.d.ts +0 -12
- package/dist/runtime/app/composables/cms-field-focus.d.ts +0 -4
- package/dist/runtime/app/composables/cms-field-focus.js +0 -20
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CmsBlockPath } from './block-paths.js';
|
|
1
2
|
import type { CmsConfig, CmsEntryKind } from './index.js';
|
|
2
3
|
export declare const CMS_SEARCH_MIN_LENGTH = 2;
|
|
3
4
|
export declare const CMS_SEARCH_MAX_LENGTH = 200;
|
|
@@ -35,8 +36,12 @@ export interface CmsSearchFocus {
|
|
|
35
36
|
field?: string;
|
|
36
37
|
locale?: string | null;
|
|
37
38
|
block?: number | null;
|
|
39
|
+
blockPath?: CmsBlockPath | null;
|
|
38
40
|
tab?: string;
|
|
39
41
|
}
|
|
42
|
+
export type CmsSearchLinkFocus = Omit<CmsSearchFocus, 'block' | 'blockPath'> & {
|
|
43
|
+
block?: number | string | null;
|
|
44
|
+
};
|
|
40
45
|
export declare function normalizeSearchQuery(value: string): string;
|
|
41
46
|
export declare function isSearchableQuery(value: string): boolean;
|
|
42
47
|
export declare function searchLikePattern(term: string): string;
|
|
@@ -44,7 +49,17 @@ export declare function decodeHtmlEntities(value: string): string;
|
|
|
44
49
|
export declare function stripMarkup(html: string): string;
|
|
45
50
|
export declare function searchSnippet(text: string, term: string): CmsSearchSnippet | null;
|
|
46
51
|
export declare function searchFieldPath(...labels: string[]): string;
|
|
47
|
-
export declare
|
|
52
|
+
export declare const CMS_TAB_QUERY = "tab";
|
|
53
|
+
export declare function cmsSearchLink(path: string, focus?: CmsSearchLinkFocus): string;
|
|
54
|
+
export declare const CMS_ENTRY_ROUTE_KEY = "entry";
|
|
55
|
+
export declare const CMS_ENTRY_TAB_ROUTE_KEY = "entrytab";
|
|
56
|
+
export declare const CMS_ENTRY_FOCUS_KEYS: readonly ["field", "locale", "block"];
|
|
57
|
+
export declare function cmsHashLink(path: string, entries: Record<string, string | number | null | undefined>): string;
|
|
58
|
+
export declare function cmsPageKey(route: {
|
|
59
|
+
path: string;
|
|
60
|
+
query: Record<string, unknown>;
|
|
61
|
+
}, omit?: string[]): string;
|
|
62
|
+
export declare function cmsEntryLink(collection: string, id: string, focus?: CmsSearchLinkFocus): string;
|
|
48
63
|
export declare function readSearchFocus(query: Record<string, unknown>): CmsSearchFocus | null;
|
|
49
64
|
export declare function searchCmsLabels(config: CmsConfig, query: string, limit?: number): {
|
|
50
65
|
hits: CmsSearchHit[];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { parseBlockPath } from "./block-paths.js";
|
|
1
2
|
import { entryTabs, fieldTab, pageAllFields, pageRoutes } from "./index.js";
|
|
2
3
|
export const CMS_SEARCH_MIN_LENGTH = 2;
|
|
3
4
|
export const CMS_SEARCH_MAX_LENGTH = 200;
|
|
@@ -57,29 +58,58 @@ export function searchSnippet(text, term) {
|
|
|
57
58
|
export function searchFieldPath(...labels) {
|
|
58
59
|
return labels.join(CMS_SEARCH_PATH_SEPARATOR);
|
|
59
60
|
}
|
|
61
|
+
export const CMS_TAB_QUERY = "tab";
|
|
60
62
|
export function cmsSearchLink(path, focus = {}) {
|
|
61
63
|
const params = new URLSearchParams();
|
|
62
64
|
if (focus.field) params.set("field", focus.field);
|
|
63
65
|
if (focus.locale) params.set("locale", focus.locale);
|
|
64
66
|
if (focus.block != null) params.set("block", String(focus.block));
|
|
65
|
-
if (focus.tab) params.set(
|
|
67
|
+
if (focus.tab) params.set(CMS_TAB_QUERY, focus.tab);
|
|
66
68
|
const query = params.toString();
|
|
67
69
|
return query ? `${path}?${query}` : path;
|
|
68
70
|
}
|
|
71
|
+
export const CMS_ENTRY_ROUTE_KEY = "entry";
|
|
72
|
+
export const CMS_ENTRY_TAB_ROUTE_KEY = "entrytab";
|
|
73
|
+
export const CMS_ENTRY_FOCUS_KEYS = ["field", "locale", "block"];
|
|
74
|
+
function escapeHashValue(value) {
|
|
75
|
+
return value.replace(/[%&]/g, (char) => char === "%" ? "%25" : "%26");
|
|
76
|
+
}
|
|
77
|
+
export function cmsHashLink(path, entries) {
|
|
78
|
+
const text = Object.entries(entries).filter(([, value]) => value != null && value !== "").map(([key, value]) => `${key}/${escapeHashValue(String(value))}`).join("&");
|
|
79
|
+
return text ? `${path}#${text}` : path;
|
|
80
|
+
}
|
|
81
|
+
export function cmsPageKey(route, omit = []) {
|
|
82
|
+
const query = Object.fromEntries(
|
|
83
|
+
Object.entries(route.query).filter(([key]) => !omit.includes(key))
|
|
84
|
+
);
|
|
85
|
+
return `${route.path}${JSON.stringify(query)}`;
|
|
86
|
+
}
|
|
87
|
+
export function cmsEntryLink(collection, id, focus = {}) {
|
|
88
|
+
return cmsHashLink(`/cms/${collection}`, {
|
|
89
|
+
[CMS_ENTRY_ROUTE_KEY]: id,
|
|
90
|
+
field: focus.field,
|
|
91
|
+
locale: focus.locale,
|
|
92
|
+
block: focus.block,
|
|
93
|
+
[CMS_ENTRY_TAB_ROUTE_KEY]: focus.tab
|
|
94
|
+
});
|
|
95
|
+
}
|
|
69
96
|
export function readSearchFocus(query) {
|
|
70
97
|
const text = (value) => {
|
|
71
98
|
const first = Array.isArray(value) ? value[0] : value;
|
|
72
99
|
return typeof first === "string" && first ? first : void 0;
|
|
73
100
|
};
|
|
74
101
|
const field = text(query.field);
|
|
75
|
-
const tab = text(query
|
|
102
|
+
const tab = text(query[CMS_TAB_QUERY]);
|
|
76
103
|
if (!field && !tab) return null;
|
|
77
|
-
const
|
|
104
|
+
const blockText = text(query.block);
|
|
105
|
+
const block = Number.parseInt(blockText ?? "", 10);
|
|
106
|
+
const blockPath = field && blockText ? parseBlockPath(`${field}.${blockText}`) : null;
|
|
78
107
|
return {
|
|
79
108
|
...field ? { field } : {},
|
|
80
109
|
...tab ? { tab } : {},
|
|
81
110
|
locale: text(query.locale) ?? null,
|
|
82
|
-
block: Number.isInteger(block) && block >= 0 ? block : null
|
|
111
|
+
block: Number.isInteger(block) && block >= 0 ? block : null,
|
|
112
|
+
blockPath: blockPath && blockPath.length % 2 === 0 ? blockPath : null
|
|
83
113
|
};
|
|
84
114
|
}
|
|
85
115
|
function entryPath(name) {
|
|
@@ -104,14 +134,14 @@ function fieldLink(name, entry, key, overridePaths) {
|
|
|
104
134
|
function overridePathsOf(entry, key) {
|
|
105
135
|
return Object.entries(entry.overrides ?? {}).filter(([, fields]) => !!fields[key]).map(([path]) => path);
|
|
106
136
|
}
|
|
107
|
-
function blockCandidates(key, field, link) {
|
|
137
|
+
function blockCandidates(key, field, link, labels = [field.label]) {
|
|
108
138
|
const candidates = [];
|
|
109
139
|
for (const block of Object.values(field.blocks ?? {})) {
|
|
110
140
|
candidates.push({
|
|
111
141
|
type: "block",
|
|
112
142
|
...link,
|
|
113
143
|
field: key,
|
|
114
|
-
fieldLabel: searchFieldPath(
|
|
144
|
+
fieldLabel: searchFieldPath(...labels, block.label),
|
|
115
145
|
texts: [block.label]
|
|
116
146
|
});
|
|
117
147
|
for (const blockField of Object.values(block.fields)) {
|
|
@@ -119,9 +149,13 @@ function blockCandidates(key, field, link) {
|
|
|
119
149
|
type: "field",
|
|
120
150
|
...link,
|
|
121
151
|
field: key,
|
|
122
|
-
fieldLabel: searchFieldPath(
|
|
152
|
+
fieldLabel: searchFieldPath(...labels, block.label, blockField.label),
|
|
123
153
|
texts: [blockField.label]
|
|
124
154
|
});
|
|
155
|
+
if (blockField.type === "blocks")
|
|
156
|
+
candidates.push(
|
|
157
|
+
...blockCandidates(key, blockField, link, [...labels, block.label, blockField.label])
|
|
158
|
+
);
|
|
125
159
|
}
|
|
126
160
|
}
|
|
127
161
|
return candidates;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import type { CmsLocalePath } from './content-routes.js';
|
|
2
|
+
export declare const CMS_SITE_SETTINGS_KEY = "cms:site";
|
|
3
|
+
export declare const DEFAULT_TITLE_TEMPLATE = "%s | %siteName";
|
|
4
|
+
export declare const TITLE_PLACEHOLDER = "%s";
|
|
5
|
+
export declare const SITE_NAME_PLACEHOLDER = "%siteName";
|
|
6
|
+
export declare const SITEMAP_PATH = "/sitemap.xml";
|
|
7
|
+
export declare const ROBOTS_PATH = "/robots.txt";
|
|
8
|
+
export declare const SITEMAP_MAX_URLS = 50000;
|
|
9
|
+
export declare const SEO_ADMIN_PREFIX = "/cms";
|
|
10
|
+
export declare const HIDDEN_SITE_ROBOTS = "noindex, nofollow";
|
|
11
|
+
export declare const SITE_TEXT_LIMITS: {
|
|
12
|
+
readonly name: 200;
|
|
13
|
+
readonly titleTemplate: 200;
|
|
14
|
+
readonly description: 1000;
|
|
15
|
+
};
|
|
16
|
+
export declare const SITEMAP_CONFLICT_MODULES: string[];
|
|
17
|
+
export declare const ROBOTS_CONFLICT_MODULES: string[];
|
|
18
|
+
export type CmsLocaleText = Record<string, string> | null;
|
|
19
|
+
export interface CmsSiteSettings {
|
|
20
|
+
name: CmsLocaleText;
|
|
21
|
+
titleTemplate: string | null;
|
|
22
|
+
description: CmsLocaleText;
|
|
23
|
+
image: string | null;
|
|
24
|
+
hidden: boolean;
|
|
25
|
+
}
|
|
26
|
+
export declare const EMPTY_SITE_SETTINGS: CmsSiteSettings;
|
|
27
|
+
export declare function coerceSiteSettings(value: unknown): CmsSiteSettings;
|
|
28
|
+
export interface CmsSeoMedia {
|
|
29
|
+
url: string | null;
|
|
30
|
+
type?: string | null;
|
|
31
|
+
alt?: string | null;
|
|
32
|
+
width?: number | null;
|
|
33
|
+
height?: number | null;
|
|
34
|
+
mime?: string | null;
|
|
35
|
+
}
|
|
36
|
+
export interface CmsSite {
|
|
37
|
+
name: string | null;
|
|
38
|
+
titleTemplate: string | null;
|
|
39
|
+
description: string | null;
|
|
40
|
+
image: CmsSeoMedia | null;
|
|
41
|
+
hidden: boolean;
|
|
42
|
+
}
|
|
43
|
+
export interface CmsSeoSource {
|
|
44
|
+
title?: string | null;
|
|
45
|
+
seoTitle?: string | null;
|
|
46
|
+
description?: string | null;
|
|
47
|
+
excerpt?: string | null;
|
|
48
|
+
seoDescription?: string | null;
|
|
49
|
+
cover?: CmsSeoMedia | null;
|
|
50
|
+
seoImage?: CmsSeoMedia | null;
|
|
51
|
+
seoNoindex?: boolean | null;
|
|
52
|
+
path?: string | null;
|
|
53
|
+
paths?: readonly CmsLocalePath[] | null;
|
|
54
|
+
publishedAt?: string | null;
|
|
55
|
+
updatedAt?: string | null;
|
|
56
|
+
}
|
|
57
|
+
export type CmsSeoType = 'website' | 'article';
|
|
58
|
+
export interface CmsSeoOverrides {
|
|
59
|
+
title?: string | null;
|
|
60
|
+
description?: string | null;
|
|
61
|
+
image?: string | CmsSeoMedia | null;
|
|
62
|
+
path?: string | null;
|
|
63
|
+
alternates?: readonly CmsLocalePath[] | null;
|
|
64
|
+
noindex?: boolean | null;
|
|
65
|
+
type?: CmsSeoType;
|
|
66
|
+
titleTemplate?: string | false | null;
|
|
67
|
+
}
|
|
68
|
+
export interface CmsSeoContext {
|
|
69
|
+
siteUrl: string;
|
|
70
|
+
path: string;
|
|
71
|
+
defaultLocale: string;
|
|
72
|
+
}
|
|
73
|
+
export interface CmsSeoAlternate {
|
|
74
|
+
hreflang: string;
|
|
75
|
+
href: string;
|
|
76
|
+
}
|
|
77
|
+
export interface CmsSeoImage {
|
|
78
|
+
url: string;
|
|
79
|
+
alt: string | null;
|
|
80
|
+
width: number | null;
|
|
81
|
+
height: number | null;
|
|
82
|
+
type: string | null;
|
|
83
|
+
}
|
|
84
|
+
export interface CmsSeoMeta {
|
|
85
|
+
title: string;
|
|
86
|
+
pageTitle: string | null;
|
|
87
|
+
description: string | null;
|
|
88
|
+
canonical: string;
|
|
89
|
+
image: CmsSeoImage | null;
|
|
90
|
+
robots: string | null;
|
|
91
|
+
alternates: CmsSeoAlternate[];
|
|
92
|
+
type: CmsSeoType;
|
|
93
|
+
siteName: string | null;
|
|
94
|
+
publishedTime: string | null;
|
|
95
|
+
modifiedTime: string | null;
|
|
96
|
+
}
|
|
97
|
+
export declare function localeText(value: CmsLocaleText | undefined, locale: string, defaultLocale: string): string | null;
|
|
98
|
+
export declare function normalizeSiteUrl(url: string | null | undefined): string;
|
|
99
|
+
export declare function isAbsoluteUrl(value: string): boolean;
|
|
100
|
+
export declare function absoluteUrl(siteUrl: string, pathOrUrl: string): string;
|
|
101
|
+
export declare function applyTitleTemplate(template: string | null | undefined, title: string | null | undefined, siteName: string | null | undefined): string;
|
|
102
|
+
export declare function titleTemplateErrors(template: string): string[];
|
|
103
|
+
export declare function plainText(value: string | null | undefined): string | null;
|
|
104
|
+
export declare function seoAlternates(paths: readonly CmsLocalePath[] | null | undefined, siteUrl: string, defaultLocale: string): CmsSeoAlternate[];
|
|
105
|
+
export declare function resolveSeoMeta(source: CmsSeoSource | null | undefined, site: CmsSite | null | undefined, context: CmsSeoContext, overrides?: CmsSeoOverrides): CmsSeoMeta;
|
|
106
|
+
export interface SitemapUrl {
|
|
107
|
+
loc: string;
|
|
108
|
+
lastmod?: string | null;
|
|
109
|
+
alternates?: CmsSeoAlternate[];
|
|
110
|
+
}
|
|
111
|
+
export declare function escapeXml(value: string): string;
|
|
112
|
+
export declare const SITEMAP_URLSET_OPEN = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\" xmlns:xhtml=\"http://www.w3.org/1999/xhtml\">\n";
|
|
113
|
+
export declare const SITEMAP_URLSET_CLOSE = "</urlset>\n";
|
|
114
|
+
export declare function renderSitemapUrl(url: SitemapUrl): string;
|
|
115
|
+
export declare function renderSitemap(urls: readonly SitemapUrl[]): string;
|
|
116
|
+
export declare function renderSitemapIndex(locs: readonly string[]): string;
|
|
117
|
+
export declare function sitemapUrlsForPaths(paths: readonly CmsLocalePath[], siteUrl: string, defaultLocale: string, lastmod: string | null): SitemapUrl[];
|
|
118
|
+
export declare function isAdminPath(path: string): boolean;
|
|
119
|
+
export declare function hiddenSiteHeaderApplies(path: string): boolean;
|
|
120
|
+
export declare function sitemapLastmod(value: unknown): string | null;
|
|
121
|
+
export declare function pageSitemapUrls(paths: readonly string[], rows: readonly Record<string, unknown>[], siteUrl: string): SitemapUrl[];
|
|
122
|
+
export interface SitemapSourceSize {
|
|
123
|
+
source: string;
|
|
124
|
+
count: number;
|
|
125
|
+
urlsPerItem: number;
|
|
126
|
+
}
|
|
127
|
+
export interface SitemapChunk {
|
|
128
|
+
source: string;
|
|
129
|
+
offset: number;
|
|
130
|
+
limit: number;
|
|
131
|
+
}
|
|
132
|
+
export declare function sitemapUrlCount(sizes: readonly SitemapSourceSize[]): number;
|
|
133
|
+
export declare function planSitemapChunks(sizes: readonly SitemapSourceSize[], maxUrls?: number): SitemapChunk[];
|
|
134
|
+
export declare function sitemapPartUrl(siteUrl: string, part: number): string;
|
|
135
|
+
export interface RobotsOptions {
|
|
136
|
+
hidden: boolean;
|
|
137
|
+
sitemapUrl: string | null;
|
|
138
|
+
}
|
|
139
|
+
export declare function renderRobotsTxt(options: RobotsOptions): string;
|
|
140
|
+
export interface CmsSeoModuleOptions {
|
|
141
|
+
sitemap?: boolean;
|
|
142
|
+
robots?: boolean;
|
|
143
|
+
}
|
|
144
|
+
export interface CmsSiteModuleOptions {
|
|
145
|
+
url?: string;
|
|
146
|
+
trustForwardedHost?: boolean;
|
|
147
|
+
}
|
|
148
|
+
export declare const SEO_ROUTE_CACHE_CONTROL = "public, max-age=600, s-maxage=600";
|
|
149
|
+
export declare const SEO_ROUTE_PRIVATE_CACHE_CONTROL = "private, no-store";
|
|
150
|
+
export declare function seoRouteCacheControl(configuredSiteUrl: string | null | undefined): string;
|
|
151
|
+
export declare function isForwardedHostTrusted(value: unknown): boolean;
|
|
152
|
+
export declare function missingSiteUrlWarning(routes: {
|
|
153
|
+
sitemap: boolean;
|
|
154
|
+
robots: boolean;
|
|
155
|
+
}): string | null;
|
|
156
|
+
export declare function siteUrlErrors(url: unknown, at?: string): string[];
|
|
157
|
+
export declare function seoOptionErrors(seo: unknown, site: unknown): string[];
|
|
158
|
+
export interface SeoConflicts {
|
|
159
|
+
sitemap: string[];
|
|
160
|
+
robots: string[];
|
|
161
|
+
}
|
|
162
|
+
export interface ResolvedSeoSwitches {
|
|
163
|
+
sitemap: boolean;
|
|
164
|
+
robots: boolean;
|
|
165
|
+
warnings: string[];
|
|
166
|
+
}
|
|
167
|
+
export declare function resolveSeoSwitches(seo: CmsSeoModuleOptions | undefined, conflicts: SeoConflicts): ResolvedSeoSwitches;
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import { normalizeTimestamp } from "./timestamps.js";
|
|
2
|
+
export const CMS_SITE_SETTINGS_KEY = "cms:site";
|
|
3
|
+
export const DEFAULT_TITLE_TEMPLATE = "%s | %siteName";
|
|
4
|
+
export const TITLE_PLACEHOLDER = "%s";
|
|
5
|
+
export const SITE_NAME_PLACEHOLDER = "%siteName";
|
|
6
|
+
export const SITEMAP_PATH = "/sitemap.xml";
|
|
7
|
+
export const ROBOTS_PATH = "/robots.txt";
|
|
8
|
+
export const SITEMAP_MAX_URLS = 5e4;
|
|
9
|
+
export const SEO_ADMIN_PREFIX = "/cms";
|
|
10
|
+
export const HIDDEN_SITE_ROBOTS = "noindex, nofollow";
|
|
11
|
+
export const SITE_TEXT_LIMITS = { name: 200, titleTemplate: 200, description: 1e3 };
|
|
12
|
+
export const SITEMAP_CONFLICT_MODULES = ["@nuxtjs/sitemap", "nuxt-simple-sitemap"];
|
|
13
|
+
export const ROBOTS_CONFLICT_MODULES = ["@nuxtjs/robots", "nuxt-simple-robots"];
|
|
14
|
+
export const EMPTY_SITE_SETTINGS = {
|
|
15
|
+
name: null,
|
|
16
|
+
titleTemplate: null,
|
|
17
|
+
description: null,
|
|
18
|
+
image: null,
|
|
19
|
+
hidden: false
|
|
20
|
+
};
|
|
21
|
+
function coerceLocaleText(value) {
|
|
22
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
23
|
+
const entries = Object.entries(value).filter(
|
|
24
|
+
(entry) => typeof entry[1] === "string" && !!entry[1].trim()
|
|
25
|
+
);
|
|
26
|
+
return entries.length ? Object.fromEntries(entries) : null;
|
|
27
|
+
}
|
|
28
|
+
export function coerceSiteSettings(value) {
|
|
29
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
30
|
+
return { ...EMPTY_SITE_SETTINGS };
|
|
31
|
+
const raw = value;
|
|
32
|
+
return {
|
|
33
|
+
name: coerceLocaleText(raw.name),
|
|
34
|
+
titleTemplate: typeof raw.titleTemplate === "string" && raw.titleTemplate.trim() ? raw.titleTemplate : null,
|
|
35
|
+
description: coerceLocaleText(raw.description),
|
|
36
|
+
image: typeof raw.image === "string" && raw.image ? raw.image : null,
|
|
37
|
+
hidden: raw.hidden === true
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export function localeText(value, locale, defaultLocale) {
|
|
41
|
+
if (!value) return null;
|
|
42
|
+
const pick = (candidate) => typeof candidate === "string" && candidate.trim() ? candidate.trim() : null;
|
|
43
|
+
return pick(value[locale]) ?? pick(value[defaultLocale]) ?? Object.values(value).map(pick).find(Boolean) ?? null;
|
|
44
|
+
}
|
|
45
|
+
export function normalizeSiteUrl(url) {
|
|
46
|
+
return (url ?? "").trim().replace(/\/+$/, "");
|
|
47
|
+
}
|
|
48
|
+
export function isAbsoluteUrl(value) {
|
|
49
|
+
return /^[a-z][a-z\d+.-]*:/i.test(value) || value.startsWith("//");
|
|
50
|
+
}
|
|
51
|
+
export function absoluteUrl(siteUrl, pathOrUrl) {
|
|
52
|
+
if (isAbsoluteUrl(pathOrUrl)) return pathOrUrl;
|
|
53
|
+
const base = normalizeSiteUrl(siteUrl);
|
|
54
|
+
const path = pathOrUrl.startsWith("/") ? pathOrUrl : `/${pathOrUrl}`;
|
|
55
|
+
return `${base}${path}`;
|
|
56
|
+
}
|
|
57
|
+
function hasTitlePlaceholder(template) {
|
|
58
|
+
return template.split(SITE_NAME_PLACEHOLDER).join("").includes(TITLE_PLACEHOLDER);
|
|
59
|
+
}
|
|
60
|
+
export function applyTitleTemplate(template, title, siteName) {
|
|
61
|
+
const page = title?.trim() || "";
|
|
62
|
+
const site = siteName?.trim() || "";
|
|
63
|
+
if (!page) return site;
|
|
64
|
+
const pattern = template?.trim() || (site ? DEFAULT_TITLE_TEMPLATE : TITLE_PLACEHOLDER);
|
|
65
|
+
if (!hasTitlePlaceholder(pattern)) return page;
|
|
66
|
+
if (pattern.includes(SITE_NAME_PLACEHOLDER) && !site) return page;
|
|
67
|
+
if (site && page === site) return page;
|
|
68
|
+
return pattern.split(SITE_NAME_PLACEHOLDER).map((part) => part.split(TITLE_PLACEHOLDER).join(page)).join(site);
|
|
69
|
+
}
|
|
70
|
+
export function titleTemplateErrors(template) {
|
|
71
|
+
return hasTitlePlaceholder(template) ? [] : [`The title template needs ${TITLE_PLACEHOLDER} where the page title goes`];
|
|
72
|
+
}
|
|
73
|
+
const ENTITIES = {
|
|
74
|
+
amp: "&",
|
|
75
|
+
lt: "<",
|
|
76
|
+
gt: ">",
|
|
77
|
+
quot: '"',
|
|
78
|
+
apos: "'",
|
|
79
|
+
nbsp: " ",
|
|
80
|
+
"#39": "'"
|
|
81
|
+
};
|
|
82
|
+
export function plainText(value) {
|
|
83
|
+
if (typeof value !== "string") return null;
|
|
84
|
+
const text = value.replace(/<[^>]*>/g, " ").replace(/&(amp|lt|gt|quot|apos|nbsp|#39);/g, (_, name) => ENTITIES[name] ?? "").replace(/\s+/g, " ").trim();
|
|
85
|
+
return text || null;
|
|
86
|
+
}
|
|
87
|
+
export function seoAlternates(paths, siteUrl, defaultLocale) {
|
|
88
|
+
const byLocale = /* @__PURE__ */ new Map();
|
|
89
|
+
for (const { locale, path } of paths ?? []) {
|
|
90
|
+
if (locale && path && !byLocale.has(locale)) byLocale.set(locale, path);
|
|
91
|
+
}
|
|
92
|
+
if (new Set(byLocale.values()).size < 2) return [];
|
|
93
|
+
const links = [...byLocale].map(([locale, path]) => ({
|
|
94
|
+
hreflang: locale,
|
|
95
|
+
href: absoluteUrl(siteUrl, path)
|
|
96
|
+
}));
|
|
97
|
+
const fallback = byLocale.get(defaultLocale) ?? byLocale.values().next().value;
|
|
98
|
+
links.push({ hreflang: "x-default", href: absoluteUrl(siteUrl, fallback) });
|
|
99
|
+
return links;
|
|
100
|
+
}
|
|
101
|
+
function cleanText(value) {
|
|
102
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
103
|
+
}
|
|
104
|
+
function seoImageOf(media, siteUrl) {
|
|
105
|
+
if (!media?.url) return null;
|
|
106
|
+
if (media.type && media.type !== "image") return null;
|
|
107
|
+
return {
|
|
108
|
+
url: absoluteUrl(siteUrl, media.url),
|
|
109
|
+
alt: media.alt ?? null,
|
|
110
|
+
width: media.width ?? null,
|
|
111
|
+
height: media.height ?? null,
|
|
112
|
+
type: media.mime ?? null
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function pickImage(candidates, siteUrl) {
|
|
116
|
+
for (const candidate of candidates) {
|
|
117
|
+
const image = typeof candidate === "string" ? seoImageOf({ url: candidate }, siteUrl) : seoImageOf(candidate, siteUrl);
|
|
118
|
+
if (image) return image;
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
export function resolveSeoMeta(source, site, context, overrides = {}) {
|
|
123
|
+
const item = source ?? {};
|
|
124
|
+
const siteName = cleanText(site?.name);
|
|
125
|
+
const pageTitle = cleanText(overrides.title) ?? cleanText(item.seoTitle) ?? cleanText(item.title) ?? null;
|
|
126
|
+
const template = overrides.titleTemplate === false ? TITLE_PLACEHOLDER : cleanText(overrides.titleTemplate) ?? cleanText(site?.titleTemplate);
|
|
127
|
+
const description = plainText(overrides.description) ?? plainText(item.seoDescription) ?? plainText(item.excerpt) ?? plainText(item.description) ?? plainText(site?.description);
|
|
128
|
+
const path = cleanText(overrides.path) ?? cleanText(item.path) ?? context.path;
|
|
129
|
+
const hidden = !!site?.hidden;
|
|
130
|
+
const noindex = overrides.noindex ?? item.seoNoindex ?? false;
|
|
131
|
+
return {
|
|
132
|
+
title: applyTitleTemplate(template, pageTitle, siteName),
|
|
133
|
+
pageTitle,
|
|
134
|
+
description,
|
|
135
|
+
canonical: absoluteUrl(context.siteUrl, path.replace(/[?#].*$/, "") || "/"),
|
|
136
|
+
image: pickImage(
|
|
137
|
+
overrides.image !== void 0 ? [overrides.image] : [item.seoImage, item.cover, site?.image],
|
|
138
|
+
context.siteUrl
|
|
139
|
+
),
|
|
140
|
+
robots: hidden ? HIDDEN_SITE_ROBOTS : noindex ? "noindex" : null,
|
|
141
|
+
alternates: seoAlternates(
|
|
142
|
+
overrides.alternates ?? item.paths,
|
|
143
|
+
context.siteUrl,
|
|
144
|
+
context.defaultLocale
|
|
145
|
+
),
|
|
146
|
+
type: overrides.type ?? (item.publishedAt ? "article" : "website"),
|
|
147
|
+
siteName,
|
|
148
|
+
publishedTime: cleanText(item.publishedAt),
|
|
149
|
+
modifiedTime: cleanText(item.updatedAt)
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
export function escapeXml(value) {
|
|
153
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
154
|
+
}
|
|
155
|
+
export const SITEMAP_URLSET_OPEN = '<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">\n';
|
|
156
|
+
export const SITEMAP_URLSET_CLOSE = "</urlset>\n";
|
|
157
|
+
export function renderSitemapUrl(url) {
|
|
158
|
+
const lines = [" <url>", ` <loc>${escapeXml(url.loc)}</loc>`];
|
|
159
|
+
if (url.lastmod) lines.push(` <lastmod>${escapeXml(url.lastmod)}</lastmod>`);
|
|
160
|
+
for (const alternate of url.alternates ?? []) {
|
|
161
|
+
lines.push(
|
|
162
|
+
` <xhtml:link rel="alternate" hreflang="${escapeXml(
|
|
163
|
+
alternate.hreflang
|
|
164
|
+
)}" href="${escapeXml(alternate.href)}"/>`
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
lines.push(" </url>");
|
|
168
|
+
return `${lines.join("\n")}
|
|
169
|
+
`;
|
|
170
|
+
}
|
|
171
|
+
export function renderSitemap(urls) {
|
|
172
|
+
return `${SITEMAP_URLSET_OPEN}${urls.map(renderSitemapUrl).join("")}${SITEMAP_URLSET_CLOSE}`;
|
|
173
|
+
}
|
|
174
|
+
export function renderSitemapIndex(locs) {
|
|
175
|
+
const items = locs.map((loc) => ` <sitemap>
|
|
176
|
+
<loc>${escapeXml(loc)}</loc>
|
|
177
|
+
</sitemap>
|
|
178
|
+
`);
|
|
179
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
180
|
+
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
181
|
+
${items.join(
|
|
182
|
+
""
|
|
183
|
+
)}</sitemapindex>
|
|
184
|
+
`;
|
|
185
|
+
}
|
|
186
|
+
export function sitemapUrlsForPaths(paths, siteUrl, defaultLocale, lastmod) {
|
|
187
|
+
const alternates = seoAlternates(paths, siteUrl, defaultLocale);
|
|
188
|
+
const seen = /* @__PURE__ */ new Set();
|
|
189
|
+
const urls = [];
|
|
190
|
+
for (const { path } of paths) {
|
|
191
|
+
if (!path || seen.has(path) || isAdminPath(path)) continue;
|
|
192
|
+
seen.add(path);
|
|
193
|
+
urls.push({
|
|
194
|
+
loc: absoluteUrl(siteUrl, path),
|
|
195
|
+
lastmod,
|
|
196
|
+
...alternates.length ? { alternates } : {}
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
return urls;
|
|
200
|
+
}
|
|
201
|
+
export function isAdminPath(path) {
|
|
202
|
+
return path === SEO_ADMIN_PREFIX || path.startsWith(`${SEO_ADMIN_PREFIX}/`);
|
|
203
|
+
}
|
|
204
|
+
const ROBOTS_HEADER_SKIPPED_PREFIXES = ["/_nuxt/", "/__nuxt"];
|
|
205
|
+
export function hiddenSiteHeaderApplies(path) {
|
|
206
|
+
const bare = path.replace(/[?#].*$/, "");
|
|
207
|
+
return !isAdminPath(bare) && !ROBOTS_HEADER_SKIPPED_PREFIXES.some((prefix) => bare.startsWith(prefix));
|
|
208
|
+
}
|
|
209
|
+
export function sitemapLastmod(value) {
|
|
210
|
+
const normalized = normalizeTimestamp(value);
|
|
211
|
+
return typeof normalized === "string" && normalized ? normalized : null;
|
|
212
|
+
}
|
|
213
|
+
export function pageSitemapUrls(paths, rows, siteUrl) {
|
|
214
|
+
const byPath = new Map(rows.map((row) => [row.path, row]));
|
|
215
|
+
const urls = [];
|
|
216
|
+
for (const path of paths) {
|
|
217
|
+
if (!path.startsWith("/") || /[[\]:*]/.test(path) || isAdminPath(path)) continue;
|
|
218
|
+
const row = byPath.get(path);
|
|
219
|
+
if (row?.seoNoindex === true) continue;
|
|
220
|
+
urls.push({ loc: absoluteUrl(siteUrl, path), lastmod: sitemapLastmod(row?.updatedAt) });
|
|
221
|
+
}
|
|
222
|
+
return urls;
|
|
223
|
+
}
|
|
224
|
+
export function sitemapUrlCount(sizes) {
|
|
225
|
+
return sizes.reduce((total, size) => total + size.count * Math.max(1, size.urlsPerItem), 0);
|
|
226
|
+
}
|
|
227
|
+
export function planSitemapChunks(sizes, maxUrls = SITEMAP_MAX_URLS) {
|
|
228
|
+
const chunks = [];
|
|
229
|
+
for (const { source, count, urlsPerItem } of sizes) {
|
|
230
|
+
const perChunk = Math.max(1, Math.floor(maxUrls / Math.max(1, urlsPerItem)));
|
|
231
|
+
for (let offset = 0; offset < count; offset += perChunk) {
|
|
232
|
+
chunks.push({ source, offset, limit: Math.min(perChunk, count - offset) });
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return chunks;
|
|
236
|
+
}
|
|
237
|
+
export function sitemapPartUrl(siteUrl, part) {
|
|
238
|
+
return absoluteUrl(siteUrl, `${SITEMAP_PATH}?part=${part}`);
|
|
239
|
+
}
|
|
240
|
+
export function renderRobotsTxt(options) {
|
|
241
|
+
const lines = ["User-agent: *", `Disallow: ${SEO_ADMIN_PREFIX}/`];
|
|
242
|
+
if (!options.hidden && options.sitemapUrl) lines.push("", `Sitemap: ${options.sitemapUrl}`);
|
|
243
|
+
return `${lines.join("\n")}
|
|
244
|
+
`;
|
|
245
|
+
}
|
|
246
|
+
const SEO_OPTION_KEYS = ["sitemap", "robots"];
|
|
247
|
+
const SITE_OPTION_KEYS = ["url", "trustForwardedHost"];
|
|
248
|
+
export const SEO_ROUTE_CACHE_CONTROL = "public, max-age=600, s-maxage=600";
|
|
249
|
+
export const SEO_ROUTE_PRIVATE_CACHE_CONTROL = "private, no-store";
|
|
250
|
+
export function seoRouteCacheControl(configuredSiteUrl) {
|
|
251
|
+
return configuredSiteUrl ? SEO_ROUTE_CACHE_CONTROL : SEO_ROUTE_PRIVATE_CACHE_CONTROL;
|
|
252
|
+
}
|
|
253
|
+
export function isForwardedHostTrusted(value) {
|
|
254
|
+
return value === true || value === "true" || value === 1 || value === "1";
|
|
255
|
+
}
|
|
256
|
+
export function missingSiteUrlWarning(routes) {
|
|
257
|
+
const served = [
|
|
258
|
+
routes.sitemap ? "/sitemap.xml" : null,
|
|
259
|
+
routes.robots ? "/robots.txt" : null
|
|
260
|
+
].filter((path) => !!path);
|
|
261
|
+
if (!served.length) return null;
|
|
262
|
+
return `[nuxt-cms] ${served.join(" and ")} ${served.length > 1 ? "are" : "is"} served but no site URL is set: set cms.site.url (or NUXT_PUBLIC_SITE_URL), otherwise the URLs come from the request host and the responses are sent with Cache-Control: private, no-store.`;
|
|
263
|
+
}
|
|
264
|
+
function isPlainObject(value) {
|
|
265
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
266
|
+
}
|
|
267
|
+
export function siteUrlErrors(url, at = "cms.site.url") {
|
|
268
|
+
if (typeof url !== "string") return [`${at} must be a string`];
|
|
269
|
+
if (!url.trim()) return [];
|
|
270
|
+
let parsed;
|
|
271
|
+
try {
|
|
272
|
+
parsed = new URL(url.trim());
|
|
273
|
+
} catch {
|
|
274
|
+
return [`${at} must be an absolute URL like https://example.com, got '${url}'`];
|
|
275
|
+
}
|
|
276
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:")
|
|
277
|
+
return [`${at} must use http or https, got '${url}'`];
|
|
278
|
+
if (parsed.search || parsed.hash || url.includes("?") || url.includes("#"))
|
|
279
|
+
return [`${at} cannot hold a query or a hash, got '${url}'`];
|
|
280
|
+
if (parsed.username || parsed.password) return [`${at} cannot hold credentials`];
|
|
281
|
+
return [];
|
|
282
|
+
}
|
|
283
|
+
export function seoOptionErrors(seo, site) {
|
|
284
|
+
const errors = [];
|
|
285
|
+
if (seo !== void 0) {
|
|
286
|
+
if (!isPlainObject(seo)) {
|
|
287
|
+
errors.push("cms.seo must be an object like { sitemap: true, robots: true }");
|
|
288
|
+
} else {
|
|
289
|
+
for (const [key, value] of Object.entries(seo)) {
|
|
290
|
+
if (!SEO_OPTION_KEYS.includes(key))
|
|
291
|
+
errors.push(`cms.seo.${key} is not an option (use ${SEO_OPTION_KEYS.join(", ")})`);
|
|
292
|
+
else if (value !== void 0 && typeof value !== "boolean")
|
|
293
|
+
errors.push(`cms.seo.${key} must be true or false`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (site !== void 0) {
|
|
298
|
+
if (!isPlainObject(site)) {
|
|
299
|
+
errors.push("cms.site must be an object like { url: 'https://example.com' }");
|
|
300
|
+
} else {
|
|
301
|
+
for (const [key, value] of Object.entries(site)) {
|
|
302
|
+
if (!SITE_OPTION_KEYS.includes(key))
|
|
303
|
+
errors.push(`cms.site.${key} is not an option (use ${SITE_OPTION_KEYS.join(", ")})`);
|
|
304
|
+
else if (key === "trustForwardedHost") {
|
|
305
|
+
if (value !== void 0 && typeof value !== "boolean")
|
|
306
|
+
errors.push("cms.site.trustForwardedHost must be true or false");
|
|
307
|
+
} else if (value !== void 0) errors.push(...siteUrlErrors(value));
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return errors;
|
|
312
|
+
}
|
|
313
|
+
function resolveSwitch(key, option, conflicts, route) {
|
|
314
|
+
if (option === false) return { enabled: false, warning: null };
|
|
315
|
+
if (!conflicts.length) return { enabled: true, warning: null };
|
|
316
|
+
const found = conflicts.join(", ");
|
|
317
|
+
if (option === true)
|
|
318
|
+
return {
|
|
319
|
+
enabled: true,
|
|
320
|
+
warning: `[nuxt-cms] cms.seo.${key} is on but ${found} also serves ${route}; only one of them answers. Set cms.seo.${key} to false to keep the other one.`
|
|
321
|
+
};
|
|
322
|
+
return {
|
|
323
|
+
enabled: false,
|
|
324
|
+
warning: `[nuxt-cms] ${found} found, so the cms ${route} is off. Set cms.seo.${key} to true or false to silence this.`
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
export function resolveSeoSwitches(seo, conflicts) {
|
|
328
|
+
const sitemap = resolveSwitch("sitemap", seo?.sitemap, conflicts.sitemap, SITEMAP_PATH);
|
|
329
|
+
const robots = resolveSwitch("robots", seo?.robots, conflicts.robots, ROBOTS_PATH);
|
|
330
|
+
return {
|
|
331
|
+
sitemap: sitemap.enabled,
|
|
332
|
+
robots: robots.enabled,
|
|
333
|
+
warnings: [sitemap.warning, robots.warning].filter((warning) => !!warning)
|
|
334
|
+
};
|
|
335
|
+
}
|
|
@@ -136,7 +136,8 @@ export function csvCellValue(field, text) {
|
|
|
136
136
|
return { error: "Not a boolean (true or false)" };
|
|
137
137
|
}
|
|
138
138
|
if (field.type === "tags" && !text.trim().startsWith("[")) return { value: text.split(",") };
|
|
139
|
-
if (field.type === "
|
|
139
|
+
if (field.type === "link" && !text.trim().startsWith("{")) return { value: { url: text.trim() } };
|
|
140
|
+
if (field.type === "json" || field.type === "link" || isStringListField(field)) {
|
|
140
141
|
try {
|
|
141
142
|
return { value: JSON.parse(text) };
|
|
142
143
|
} catch {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { CmsEntry, CmsI18n, FieldConfig } from './index.js';
|
|
2
|
+
export declare const TRANSLATIONS_COLUMN = "_translations";
|
|
3
|
+
export type TranslationState = 'complete' | 'partial' | 'missing';
|
|
4
|
+
export interface TranslationLocaleProgress {
|
|
5
|
+
filled: number;
|
|
6
|
+
total: number;
|
|
7
|
+
values: number;
|
|
8
|
+
state: TranslationState;
|
|
9
|
+
}
|
|
10
|
+
export type TranslationProgress = Record<string, TranslationLocaleProgress>;
|
|
11
|
+
export interface TranslationChange {
|
|
12
|
+
values: Record<string, unknown>;
|
|
13
|
+
count: number;
|
|
14
|
+
}
|
|
15
|
+
type Values = Record<string, unknown>;
|
|
16
|
+
export declare function isTranslationFilled(field: FieldConfig, value: unknown): boolean;
|
|
17
|
+
export declare function hasTranslatableContent(fields: Record<string, FieldConfig>): boolean;
|
|
18
|
+
export declare function entryHasTranslations(entry: Pick<CmsEntry, 'fields'> & Partial<Pick<CmsEntry, 'kind' | 'overrides'>>): boolean;
|
|
19
|
+
export declare function hasTranslationsColumn(entry: Pick<CmsEntry, 'kind' | 'fields'>, i18n: Pick<CmsI18n, 'locales'>): boolean;
|
|
20
|
+
export declare function translationProgress(fields: Record<string, FieldConfig>, values: Values | null | undefined, i18n: CmsI18n, keys?: readonly string[]): TranslationProgress;
|
|
21
|
+
export declare function translationSummary(progress: TranslationLocaleProgress | undefined): string;
|
|
22
|
+
export interface TranslationCopyOptions {
|
|
23
|
+
from: string;
|
|
24
|
+
to: string;
|
|
25
|
+
overwrite?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export declare function copyTranslations(fields: Record<string, FieldConfig>, values: Values, i18n: CmsI18n, { from, to, overwrite }: TranslationCopyOptions): TranslationChange;
|
|
28
|
+
export declare function clearTranslations(fields: Record<string, FieldConfig>, values: Values, i18n: CmsI18n, locale: string): TranslationChange;
|
|
29
|
+
export {};
|