includio-cms 0.1.3 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +76 -0
- package/ROADMAP.md +23 -13
- package/dist/admin/api/accept-invite.js +1 -5
- package/dist/admin/api/invite.js +7 -16
- package/dist/admin/client/account/account-page.svelte +20 -50
- package/dist/admin/client/account/lang.d.ts +15 -23
- package/dist/admin/client/account/lang.js +51 -67
- package/dist/admin/client/account/preferences-section.svelte +26 -84
- package/dist/admin/client/account/profile-section.svelte +60 -40
- package/dist/admin/client/account/schema.d.ts +11 -3
- package/dist/admin/client/account/schema.js +25 -16
- package/dist/admin/client/account/security-section.svelte +139 -105
- package/dist/admin/client/account/sessions-section.svelte +35 -34
- package/dist/admin/client/admin/admin-after-login-layout-content.svelte +3 -5
- package/dist/admin/client/admin/admin-layout.svelte +3 -2
- package/dist/admin/client/admin/admin-preloader.svelte +36 -0
- package/dist/admin/client/admin/admin-preloader.svelte.d.ts +18 -0
- package/dist/admin/client/admin/dashboard-page.svelte +55 -41
- package/dist/admin/client/collection/a11y-score-cell.svelte +45 -0
- package/dist/admin/client/collection/a11y-score-cell.svelte.d.ts +6 -0
- package/dist/admin/client/collection/bulk-actions-bar.svelte +83 -0
- package/dist/admin/client/collection/bulk-actions-bar.svelte.d.ts +9 -0
- package/dist/admin/client/collection/collection-entries.svelte +255 -256
- package/dist/admin/client/collection/collection-view.svelte.d.ts +4 -3
- package/dist/admin/client/collection/collection-view.svelte.js +9 -5
- package/dist/admin/client/collection/collection.svelte +22 -12
- package/dist/admin/client/collection/data-table.svelte +50 -39
- package/dist/admin/client/collection/data-table.svelte.d.ts +1 -0
- package/dist/admin/client/collection/date-cell.svelte +7 -5
- package/dist/admin/client/collection/date-cell.svelte.d.ts +1 -1
- package/dist/admin/client/collection/empty-state.svelte +28 -0
- package/dist/admin/client/collection/empty-state.svelte.d.ts +9 -0
- package/dist/admin/client/collection/entry-link.svelte +10 -4
- package/dist/admin/client/collection/entry-link.svelte.d.ts +1 -0
- package/dist/admin/client/collection/grid-view.svelte +21 -23
- package/dist/admin/client/collection/grid-view.svelte.d.ts +1 -2
- package/dist/admin/client/collection/row-actions.svelte +60 -0
- package/dist/admin/client/collection/row-actions.svelte.d.ts +9 -0
- package/dist/admin/client/collection/status-badge.svelte +7 -8
- package/dist/admin/client/collection/table-pagination.svelte +122 -79
- package/dist/admin/client/collection/table-pagination.svelte.d.ts +1 -0
- package/dist/admin/client/collection/table-toolbar.svelte +108 -88
- package/dist/admin/client/collection/table-toolbar.svelte.d.ts +8 -9
- package/dist/admin/client/entry/entry-form.svelte +109 -1
- package/dist/admin/client/entry/entry-header.svelte +96 -37
- package/dist/admin/client/entry/entry-header.svelte.d.ts +5 -0
- package/dist/admin/client/entry/entry.svelte +171 -60
- package/dist/admin/client/entry/header/a11y-validator.d.ts +46 -0
- package/dist/admin/client/entry/header/a11y-validator.js +311 -0
- package/dist/admin/client/entry/header/publish-panel.svelte +373 -131
- package/dist/admin/client/entry/header/publish-panel.svelte.d.ts +4 -0
- package/dist/admin/client/entry/header/save-indicator.svelte +33 -23
- package/dist/admin/client/entry/header/schedule-popover.svelte +1 -1
- package/dist/admin/client/entry/header/status-badge.svelte +25 -118
- package/dist/admin/client/entry/header/version-history-sheet.svelte +314 -98
- package/dist/admin/client/form/form-submission/form-submission.svelte +271 -83
- package/dist/admin/client/form/form-submission/submission-field.svelte +12 -12
- package/dist/admin/client/form/form-submissions.svelte +421 -139
- package/dist/admin/client/form/submission-link.svelte +8 -2
- package/dist/admin/client/form/submission-link.svelte.d.ts +1 -0
- package/dist/admin/client/form/submission-status-badge.svelte +18 -4
- package/dist/admin/client/form/submission-status-badge.svelte.d.ts +1 -0
- package/dist/admin/client/login/lang.d.ts +32 -0
- package/dist/admin/client/login/lang.js +66 -2
- package/dist/admin/client/login/login-form.svelte +237 -95
- package/dist/admin/client/login/login-form.svelte.d.ts +2 -17
- package/dist/admin/client/login/login-page.svelte +34 -98
- package/dist/admin/client/login/reset-password-page.svelte +235 -0
- package/dist/admin/client/login/reset-password-page.svelte.d.ts +4 -0
- package/dist/admin/client/login/schema.d.ts +15 -0
- package/dist/admin/client/login/schema.js +21 -0
- package/dist/admin/client/users/accept-invite-page.svelte +166 -37
- package/dist/admin/client/users/create-user-dialog.svelte +15 -7
- package/dist/admin/client/users/delete-user-dialog.svelte +81 -16
- package/dist/admin/client/users/delete-user-dialog.svelte.d.ts +4 -1
- package/dist/admin/client/users/edit-user-dialog.svelte +3 -0
- package/dist/admin/client/users/invite-user-dialog.svelte +16 -3
- package/dist/admin/client/users/lang.d.ts +27 -0
- package/dist/admin/client/users/lang.js +64 -10
- package/dist/admin/client/users/pending-invitations.svelte +59 -23
- package/dist/admin/client/users/users-page.svelte +471 -72
- package/dist/admin/components/accessibility/accessibility-overview.svelte +2 -7
- package/dist/admin/components/dashboard/a11y-gauge.svelte +90 -0
- package/dist/admin/components/dashboard/a11y-gauge.svelte.d.ts +18 -0
- package/dist/admin/components/dashboard/accessibility-hub.svelte +13 -12
- package/dist/admin/components/dashboard/form-submissions-widget.svelte +71 -113
- package/dist/admin/components/dashboard/index.d.ts +4 -2
- package/dist/admin/components/dashboard/index.js +4 -2
- package/dist/admin/components/dashboard/recent-activity.svelte +53 -75
- package/dist/admin/components/dashboard/recent-entries.svelte +94 -0
- package/dist/admin/components/dashboard/recent-entries.svelte.d.ts +18 -0
- package/dist/admin/components/dashboard/stat-card.svelte +2 -2
- package/dist/admin/components/dashboard/tip-of-the-day.svelte +109 -0
- package/dist/admin/components/dashboard/tip-of-the-day.svelte.d.ts +3 -0
- package/dist/admin/components/dashboard/welcome-header.svelte +45 -0
- package/dist/admin/components/dashboard/welcome-header.svelte.d.ts +3 -0
- package/dist/admin/components/fields/{array-field.svelte → blocks-field.svelte} +4 -4
- package/dist/admin/components/fields/{array-field.svelte.d.ts → blocks-field.svelte.d.ts} +5 -5
- package/dist/admin/components/fields/content-field.svelte +27 -0
- package/dist/admin/components/fields/content-field.svelte.d.ts +31 -0
- package/dist/admin/components/fields/field-renderer.svelte +9 -7
- package/dist/admin/components/fields/image-field.svelte +2 -2
- package/dist/admin/components/fields/media-field.svelte +2 -2
- package/dist/admin/components/fields/seo-field.svelte +205 -25
- package/dist/admin/components/fields/simple-array-field.svelte +289 -0
- package/dist/admin/components/fields/simple-array-field.svelte.d.ts +30 -0
- package/dist/admin/components/fields/slug-field.svelte +3 -2
- package/dist/admin/components/fields/standalone-field-renderer.svelte +148 -0
- package/dist/admin/components/fields/standalone-field-renderer.svelte.d.ts +9 -0
- package/dist/admin/components/fields/text-field-wrapper.svelte +13 -1
- package/dist/admin/components/fields/text-field-wrapper.svelte.d.ts +2 -2
- package/dist/admin/components/fields/url-field.svelte +5 -4
- package/dist/admin/components/layout/app-sidebar.svelte +27 -24
- package/dist/admin/components/layout/lang.d.ts +6 -0
- package/dist/admin/components/layout/lang.js +13 -1
- package/dist/admin/components/layout/layout-renderer.svelte +352 -0
- package/dist/admin/components/layout/layout-renderer.svelte.d.ts +14 -0
- package/dist/admin/components/layout/nav-breadcrumbs.svelte +4 -4
- package/dist/admin/components/layout/nav-collections.svelte +65 -36
- package/dist/admin/components/layout/nav-footer.svelte +31 -0
- package/dist/admin/components/layout/nav-footer.svelte.d.ts +18 -0
- package/dist/admin/components/layout/nav-forms.svelte +55 -30
- package/dist/admin/components/layout/nav-main.svelte +14 -52
- package/dist/admin/components/layout/nav-search.svelte +4 -3
- package/dist/admin/components/layout/nav-singletons.svelte +59 -17
- package/dist/admin/components/layout/nav-singletons.svelte.d.ts +17 -8
- package/dist/admin/components/layout/site-header.svelte +74 -13
- package/dist/admin/components/media/alt-input.svelte +32 -22
- package/dist/admin/components/media/bulk-action-bar.svelte +139 -150
- package/dist/admin/components/media/file/file-details.svelte +299 -217
- package/dist/admin/components/media/file/file-miniature.svelte +54 -41
- package/dist/admin/components/media/file/file-miniature.svelte.d.ts +1 -0
- package/dist/admin/components/media/file/file-preview.svelte +1 -1
- package/dist/admin/components/media/file-upload.svelte +24 -26
- package/dist/admin/components/media/files-list.svelte +112 -40
- package/dist/admin/components/media/files-list.svelte.d.ts +2 -0
- package/dist/admin/components/media/focal-point-input.svelte +122 -26
- package/dist/admin/components/media/media-library.svelte +127 -70
- package/dist/admin/components/media/media-search.svelte +6 -6
- package/dist/admin/components/media/media-sort.svelte +3 -1
- package/dist/admin/components/media/multi-file-summary.svelte +88 -68
- package/dist/admin/components/media/tag-combobox.svelte +141 -66
- package/dist/admin/components/media/tag-combobox.svelte.d.ts +1 -0
- package/dist/admin/components/media/tag-sidebar.svelte +139 -121
- package/dist/admin/components/tiptap/FigureNodeView.svelte +144 -15
- package/dist/admin/components/tiptap/InlineBlockNodeView.svelte +254 -0
- package/dist/admin/components/tiptap/InlineBlockNodeView.svelte.d.ts +4 -0
- package/dist/admin/components/tiptap/SlashCommandPopup.svelte +212 -0
- package/dist/admin/components/tiptap/SlashCommandPopup.svelte.d.ts +8 -0
- package/dist/admin/components/tiptap/content-editor.svelte +280 -0
- package/dist/admin/components/tiptap/content-editor.svelte.d.ts +9 -0
- package/dist/admin/components/tiptap/editor-toolbar.svelte +230 -0
- package/dist/admin/components/tiptap/editor-toolbar.svelte.d.ts +16 -0
- package/dist/admin/components/tiptap/heading-a11y-plugin.d.ts +2 -0
- package/dist/admin/components/tiptap/heading-a11y-plugin.js +67 -0
- package/dist/admin/components/tiptap/image-dialog.svelte +172 -11
- package/dist/admin/components/tiptap/inline-block-node.d.ts +19 -0
- package/dist/admin/components/tiptap/inline-block-node.js +98 -0
- package/dist/admin/components/tiptap/link-dialog.svelte +9 -4
- package/dist/admin/components/tiptap/slash-command.d.ts +17 -0
- package/dist/admin/components/tiptap/slash-command.js +181 -0
- package/dist/admin/components/tiptap/structured-content-utils.d.ts +21 -0
- package/dist/admin/components/tiptap/structured-content-utils.js +150 -0
- package/dist/admin/components/tiptap/tiptap-editor.svelte +18 -190
- package/dist/admin/email/invite-template.d.ts +8 -0
- package/dist/admin/email/invite-template.js +99 -0
- package/dist/admin/email/reset-password-template.d.ts +7 -0
- package/dist/admin/email/reset-password-template.js +96 -0
- package/dist/admin/remote/ai.remote.d.ts +1 -0
- package/dist/admin/remote/ai.remote.js +4 -1
- package/dist/admin/remote/entry.remote.d.ts +8 -0
- package/dist/admin/remote/entry.remote.js +53 -4
- package/dist/admin/remote/preview.remote.js +2 -1
- package/dist/admin/shared/password-schema.d.ts +5 -0
- package/dist/admin/shared/password-schema.js +10 -0
- package/dist/admin/styles/admin.css +1530 -151
- package/dist/admin/utils/formatDate.d.ts +1 -0
- package/dist/admin/utils/formatDate.js +8 -0
- package/dist/admin/utils/roleLabel.d.ts +2 -0
- package/dist/admin/utils/roleLabel.js +13 -0
- package/dist/ai-claude/index.d.ts +2 -0
- package/dist/ai-claude/index.js +56 -0
- package/dist/cms/runtime/api.d.ts +6 -1
- package/dist/cms/runtime/api.js +3 -0
- package/dist/cms/runtime/schemas.d.ts +9 -1
- package/dist/cms/runtime/schemas.js +8 -0
- package/dist/cms/runtime/types.d.ts +82 -10
- package/dist/cms/runtime/types.js +4 -0
- package/dist/components/ui/accordion/accordion.stories.svelte +39 -0
- package/dist/components/ui/accordion/accordion.stories.svelte.d.ts +27 -0
- package/dist/components/ui/alert/alert.stories.svelte +53 -0
- package/dist/components/ui/alert/alert.stories.svelte.d.ts +27 -0
- package/dist/components/ui/alert/alert.svelte +5 -0
- package/dist/components/ui/alert/alert.svelte.d.ts +9 -0
- package/dist/components/ui/avatar/avatar.stories.svelte +16 -0
- package/dist/components/ui/avatar/avatar.stories.svelte.d.ts +27 -0
- package/dist/components/ui/badge/badge.stories.svelte +33 -0
- package/dist/components/ui/badge/badge.stories.svelte.d.ts +27 -0
- package/dist/components/ui/breadcrumb/breadcrumb.stories.svelte +33 -0
- package/dist/components/ui/breadcrumb/breadcrumb.stories.svelte.d.ts +27 -0
- package/dist/components/ui/button/button.stories.svelte +43 -0
- package/dist/components/ui/button/button.stories.svelte.d.ts +27 -0
- package/dist/components/ui/button/button.svelte +1 -2
- package/dist/components/ui/button/button.svelte.d.ts +0 -3
- package/dist/components/ui/button-group/button-group-separator.svelte.d.ts +1 -1
- package/dist/components/ui/card/card.stories.svelte +42 -0
- package/dist/components/ui/card/card.stories.svelte.d.ts +27 -0
- package/dist/components/ui/command/command.stories.svelte +51 -0
- package/dist/components/ui/command/command.stories.svelte.d.ts +27 -0
- package/dist/components/ui/dialog/dialog.stories.svelte +29 -0
- package/dist/components/ui/dialog/dialog.stories.svelte.d.ts +27 -0
- package/dist/components/ui/field/field-label.svelte.d.ts +1 -1
- package/dist/components/ui/field/field.stories.svelte +21 -0
- package/dist/components/ui/field/field.stories.svelte.d.ts +27 -0
- package/dist/components/ui/input/input.stories.svelte +40 -0
- package/dist/components/ui/input/input.stories.svelte.d.ts +27 -0
- package/dist/components/ui/input/input.svelte +2 -4
- package/dist/components/ui/item/item-separator.svelte.d.ts +1 -1
- package/dist/components/ui/label/label.stories.svelte +20 -0
- package/dist/components/ui/label/label.stories.svelte.d.ts +27 -0
- package/dist/components/ui/popover/popover.stories.svelte +29 -0
- package/dist/components/ui/popover/popover.stories.svelte.d.ts +27 -0
- package/dist/components/ui/select/select-group-heading.svelte.d.ts +1 -1
- package/dist/components/ui/select/select.stories.svelte +23 -0
- package/dist/components/ui/select/select.stories.svelte.d.ts +27 -0
- package/dist/components/ui/separator/separator.stories.svelte +24 -0
- package/dist/components/ui/separator/separator.stories.svelte.d.ts +27 -0
- package/dist/components/ui/sheet/sheet.stories.svelte +29 -0
- package/dist/components/ui/sheet/sheet.stories.svelte.d.ts +27 -0
- package/dist/components/ui/sidebar/sidebar-group.svelte +3 -3
- package/dist/components/ui/sidebar/sidebar-group.svelte.d.ts +2 -2
- package/dist/components/ui/sidebar/sidebar-menu-button.svelte +28 -30
- package/dist/components/ui/sidebar/sidebar-menu-button.svelte.d.ts +7 -7
- package/dist/components/ui/sidebar/sidebar-separator.svelte.d.ts +1 -1
- package/dist/components/ui/sidebar/sidebar-trigger.svelte +4 -4
- package/dist/components/ui/sonner/sonner.stories.svelte +22 -0
- package/dist/components/ui/sonner/sonner.stories.svelte.d.ts +26 -0
- package/dist/components/ui/sonner/sonner.svelte +8 -2
- package/dist/components/ui/sonner/toast-demo.svelte +29 -0
- package/dist/components/ui/sonner/toast-demo.svelte.d.ts +6 -0
- package/dist/components/ui/textarea/textarea.stories.svelte +22 -0
- package/dist/components/ui/textarea/textarea.stories.svelte.d.ts +27 -0
- package/dist/components/ui/textarea/textarea.svelte +0 -2
- package/dist/components/ui/toggle/toggle.stories.svelte +22 -0
- package/dist/components/ui/toggle/toggle.stories.svelte.d.ts +27 -0
- package/dist/components/ui/toggle-group/toggle-group.stories.svelte +17 -0
- package/dist/components/ui/toggle-group/toggle-group.stories.svelte.d.ts +27 -0
- package/dist/components/ui/tooltip/tooltip.stories.svelte +26 -0
- package/dist/components/ui/tooltip/tooltip.stories.svelte.d.ts +27 -0
- package/dist/core/fields/fieldSchemaToTs.d.ts +1 -0
- package/dist/core/fields/fieldSchemaToTs.js +133 -1
- package/dist/core/fields/layoutUtils.d.ts +17 -0
- package/dist/core/fields/layoutUtils.js +149 -0
- package/dist/core/fields/structuredToHtml.d.ts +9 -0
- package/dist/core/fields/structuredToHtml.js +161 -0
- package/dist/core/server/entries/operations/create.js +2 -1
- package/dist/core/server/entries/operations/get.js +8 -6
- package/dist/core/server/entries/operations/update.d.ts +3 -0
- package/dist/core/server/entries/operations/update.js +30 -2
- package/dist/core/server/fields/queryStructuredContent.d.ts +15 -0
- package/dist/core/server/fields/queryStructuredContent.js +65 -0
- package/dist/core/server/fields/resolveImageFields.js +51 -2
- package/dist/core/server/fields/resolveRelationFields.js +2 -2
- package/dist/core/server/fields/resolveRichtextLinks.js +80 -13
- package/dist/core/server/fields/resolveUrlFields.js +57 -6
- package/dist/core/server/fields/slugResolver.d.ts +10 -0
- package/dist/core/server/fields/slugResolver.js +34 -0
- package/dist/core/server/generator/fields.js +15 -4
- package/dist/core/server/generator/generator.js +3 -2
- package/dist/files-local/index.js +126 -64
- package/dist/paraglide/.prettierignore +3 -0
- package/dist/paraglide/messages/_index.d.ts +36 -0
- package/dist/paraglide/messages/_index.js +72 -0
- package/dist/paraglide/messages/en.d.ts +5 -0
- package/dist/paraglide/messages/en.js +14 -0
- package/dist/paraglide/messages/pl.d.ts +5 -0
- package/dist/paraglide/messages/pl.js +14 -0
- package/dist/paraglide/messages.d.ts +2 -0
- package/dist/paraglide/messages.js +4 -0
- package/dist/paraglide/registry.d.ts +21 -0
- package/dist/paraglide/registry.js +31 -0
- package/dist/paraglide/runtime.d.ts +583 -0
- package/dist/paraglide/runtime.js +1402 -0
- package/dist/paraglide/server.d.ts +67 -0
- package/dist/paraglide/server.js +175 -0
- package/dist/server/auth.d.ts +5 -0
- package/dist/server/auth.js +12 -1
- package/dist/sveltekit/components/structured-content.svelte +204 -0
- package/dist/sveltekit/components/structured-content.svelte.d.ts +21 -0
- package/dist/sveltekit/config.d.ts +13 -3
- package/dist/sveltekit/index.d.ts +3 -0
- package/dist/sveltekit/index.js +3 -0
- package/dist/sveltekit/server/handle.js +1 -0
- package/dist/types/config.d.ts +3 -0
- package/dist/types/fields.d.ts +19 -2
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +2 -0
- package/dist/types/layout.d.ts +54 -0
- package/dist/types/layout.js +6 -0
- package/dist/types/structured-content.d.ts +63 -0
- package/dist/types/structured-content.js +1 -0
- package/dist/updates/0.1.4/index.d.ts +2 -0
- package/dist/updates/0.1.4/index.js +11 -0
- package/dist/updates/0.1.5/index.d.ts +2 -0
- package/dist/updates/0.1.5/index.js +18 -0
- package/dist/updates/0.2.0/index.d.ts +2 -0
- package/dist/updates/0.2.0/index.js +11 -0
- package/dist/updates/0.2.2/index.d.ts +2 -0
- package/dist/updates/0.2.2/index.js +13 -0
- package/dist/updates/0.5.0/index.d.ts +2 -0
- package/dist/updates/0.5.0/index.js +14 -0
- package/dist/updates/index.js +6 -1
- package/package.json +17 -10
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export default Tooltip;
|
|
2
|
+
type Tooltip = SvelteComponent<{
|
|
3
|
+
[x: string]: never;
|
|
4
|
+
}, {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
}, {}> & {
|
|
7
|
+
$$bindings?: string | undefined;
|
|
8
|
+
};
|
|
9
|
+
declare const Tooltip: $$__sveltets_2_IsomorphicComponent<{
|
|
10
|
+
[x: string]: never;
|
|
11
|
+
}, {
|
|
12
|
+
[evt: string]: CustomEvent<any>;
|
|
13
|
+
}, {}, {}, string>;
|
|
14
|
+
import { Tooltip } from './index.js';
|
|
15
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
16
|
+
new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
|
|
17
|
+
$$bindings?: Bindings;
|
|
18
|
+
} & Exports;
|
|
19
|
+
(internal: unknown, props: {
|
|
20
|
+
$$events?: Events;
|
|
21
|
+
$$slots?: Slots;
|
|
22
|
+
}): Exports & {
|
|
23
|
+
$set?: any;
|
|
24
|
+
$on?: any;
|
|
25
|
+
};
|
|
26
|
+
z_$$bindings?: Bindings;
|
|
27
|
+
}
|
|
@@ -3,6 +3,7 @@ import { z } from 'zod';
|
|
|
3
3
|
type AnyZodObject = z.ZodObject<any, any>;
|
|
4
4
|
interface GenerateZodSchemaOptions {
|
|
5
5
|
parentRequired?: boolean;
|
|
6
|
+
localized?: boolean;
|
|
6
7
|
}
|
|
7
8
|
export declare function generateZodSchemaFromField(field: Field, languages: string[], options?: GenerateZodSchemaOptions): z.ZodType;
|
|
8
9
|
export declare function generateZodSchemaFromFields(fields: Field[], languages: string[], options?: GenerateZodSchemaOptions): AnyZodObject;
|
|
@@ -2,6 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
export function generateZodSchemaFromField(field, languages, options = {
|
|
3
3
|
parentRequired: true
|
|
4
4
|
}) {
|
|
5
|
+
const localized = options.localized !== false;
|
|
5
6
|
switch (field.type) {
|
|
6
7
|
case 'text': {
|
|
7
8
|
let schema = z.string();
|
|
@@ -13,14 +14,92 @@ export function generateZodSchemaFromField(field, languages, options = {
|
|
|
13
14
|
schema = schema.max(field.maxLength, { message: `Maksimum ${field.maxLength} znaków` });
|
|
14
15
|
if (field.pattern !== undefined)
|
|
15
16
|
schema = schema.regex(new RegExp(field.pattern), { message: 'Nieprawidłowy format' });
|
|
17
|
+
if (!localized)
|
|
18
|
+
return schema;
|
|
16
19
|
return z.object(Object.fromEntries(languages.map((lang) => [lang, schema])));
|
|
17
20
|
}
|
|
18
21
|
case 'richtext': {
|
|
19
22
|
let schema = z.string();
|
|
20
23
|
if (field.required)
|
|
21
24
|
schema = schema.min(1, { message: 'Pole wymagane' });
|
|
25
|
+
if (!localized)
|
|
26
|
+
return schema;
|
|
22
27
|
return z.object(Object.fromEntries(languages.map((lang) => [lang, schema])));
|
|
23
28
|
}
|
|
29
|
+
case 'content': {
|
|
30
|
+
const markSchema = z.object({
|
|
31
|
+
type: z.string(),
|
|
32
|
+
attrs: z.record(z.string(), z.unknown()).optional()
|
|
33
|
+
});
|
|
34
|
+
const nodeSchema = z.lazy(() => z.object({
|
|
35
|
+
type: z.string(),
|
|
36
|
+
attrs: z.record(z.string(), z.unknown()).optional(),
|
|
37
|
+
content: z.array(nodeSchema).optional(),
|
|
38
|
+
marks: z.array(markSchema).optional(),
|
|
39
|
+
text: z.string().optional()
|
|
40
|
+
}));
|
|
41
|
+
let docSchema = z.object({
|
|
42
|
+
type: z.literal('doc'),
|
|
43
|
+
content: z.array(nodeSchema)
|
|
44
|
+
});
|
|
45
|
+
// If inline blocks defined, validate their blockData
|
|
46
|
+
if (field.inlineBlocks && field.inlineBlocks.length > 0) {
|
|
47
|
+
const blockSchemas = new Map();
|
|
48
|
+
for (const blockDef of field.inlineBlocks) {
|
|
49
|
+
blockSchemas.set(blockDef.slug, generateZodSchemaFromFields(blockDef.fields, languages, {
|
|
50
|
+
parentRequired: false,
|
|
51
|
+
localized: false
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
54
|
+
docSchema = z
|
|
55
|
+
.object({
|
|
56
|
+
type: z.literal('doc'),
|
|
57
|
+
content: z.array(nodeSchema)
|
|
58
|
+
})
|
|
59
|
+
.superRefine((doc, ctx) => {
|
|
60
|
+
for (let i = 0; i < doc.content.length; i++) {
|
|
61
|
+
const node = doc.content[i];
|
|
62
|
+
if (node.type !== 'inlineBlock')
|
|
63
|
+
continue;
|
|
64
|
+
const blockType = node.attrs?.blockType;
|
|
65
|
+
const blockData = node.attrs?.blockData;
|
|
66
|
+
const schema = blockSchemas.get(blockType);
|
|
67
|
+
if (!schema) {
|
|
68
|
+
ctx.addIssue({
|
|
69
|
+
code: z.ZodIssueCode.custom,
|
|
70
|
+
message: `Nieznany typ bloku: ${blockType}`,
|
|
71
|
+
path: ['content', i, 'attrs', 'blockType']
|
|
72
|
+
});
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
let data = blockData;
|
|
76
|
+
if (typeof data === 'string') {
|
|
77
|
+
try {
|
|
78
|
+
data = JSON.parse(data);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
ctx.addIssue({
|
|
82
|
+
code: z.ZodIssueCode.custom,
|
|
83
|
+
message: 'Nieprawidłowe dane bloku',
|
|
84
|
+
path: ['content', i, 'attrs', 'blockData']
|
|
85
|
+
});
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const result = schema.safeParse(data);
|
|
90
|
+
if (!result.success) {
|
|
91
|
+
for (const issue of result.error.issues) {
|
|
92
|
+
ctx.addIssue({
|
|
93
|
+
...issue,
|
|
94
|
+
path: ['content', i, 'attrs', 'blockData', ...issue.path]
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return z.object(Object.fromEntries(languages.map((lang) => [lang, docSchema])));
|
|
102
|
+
}
|
|
24
103
|
case 'number': {
|
|
25
104
|
let schema = z.number({ message: 'Wymagana liczba' });
|
|
26
105
|
if (field.min !== undefined)
|
|
@@ -68,7 +147,7 @@ export function generateZodSchemaFromField(field, languages, options = {
|
|
|
68
147
|
data: finalData
|
|
69
148
|
});
|
|
70
149
|
}
|
|
71
|
-
case '
|
|
150
|
+
case 'blocks': {
|
|
72
151
|
const schemas = field.of.map((f) => generateZodSchemaFromField(f, languages, { parentRequired: field.required }));
|
|
73
152
|
const itemSchema = schemas.length > 1
|
|
74
153
|
? z.discriminatedUnion('slug', schemas)
|
|
@@ -94,6 +173,37 @@ export function generateZodSchemaFromField(field, languages, options = {
|
|
|
94
173
|
}
|
|
95
174
|
return schema.default([]); // Default to empty array if not required
|
|
96
175
|
}
|
|
176
|
+
case 'array': {
|
|
177
|
+
let itemSchema;
|
|
178
|
+
switch (field.of) {
|
|
179
|
+
case 'text':
|
|
180
|
+
itemSchema = field.localized
|
|
181
|
+
? z.record(z.string(), z.string())
|
|
182
|
+
: z.string();
|
|
183
|
+
break;
|
|
184
|
+
case 'number':
|
|
185
|
+
itemSchema = z.number();
|
|
186
|
+
break;
|
|
187
|
+
case 'url':
|
|
188
|
+
itemSchema = z.object({
|
|
189
|
+
id: z.string().optional(),
|
|
190
|
+
url: z.record(z.string(), z.string()),
|
|
191
|
+
text: z.record(z.string(), z.string()).optional(),
|
|
192
|
+
newTab: z.boolean().optional()
|
|
193
|
+
});
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
let schema = z.array(itemSchema);
|
|
197
|
+
if (field.minItems !== undefined)
|
|
198
|
+
schema = schema.min(field.minItems, {
|
|
199
|
+
message: `Minimum ${field.minItems} elementów`
|
|
200
|
+
});
|
|
201
|
+
if (field.maxItems !== undefined)
|
|
202
|
+
schema = schema.max(field.maxItems, {
|
|
203
|
+
message: `Maksimum ${field.maxItems} elementów`
|
|
204
|
+
});
|
|
205
|
+
return schema.default([]);
|
|
206
|
+
}
|
|
97
207
|
case 'slug': {
|
|
98
208
|
let schema = z.string();
|
|
99
209
|
if (field.required)
|
|
@@ -101,6 +211,17 @@ export function generateZodSchemaFromField(field, languages, options = {
|
|
|
101
211
|
return schema;
|
|
102
212
|
}
|
|
103
213
|
case 'seo': {
|
|
214
|
+
if (!localized) {
|
|
215
|
+
return z.object({
|
|
216
|
+
slug: z.string(),
|
|
217
|
+
canonicalUrl: z.string().optional(),
|
|
218
|
+
title: z.string(),
|
|
219
|
+
description: z.string(),
|
|
220
|
+
keywords: z.string().optional(),
|
|
221
|
+
ogImage: z.string(),
|
|
222
|
+
customCode: z.string().optional()
|
|
223
|
+
});
|
|
224
|
+
}
|
|
104
225
|
return z.object({
|
|
105
226
|
slug: z.object(Object.fromEntries(languages.map((lang) => [lang, z.string()]))),
|
|
106
227
|
canonicalUrl: z.object(Object.fromEntries(languages.map((lang) => [lang, z.string().optional()]))),
|
|
@@ -112,6 +233,17 @@ export function generateZodSchemaFromField(field, languages, options = {
|
|
|
112
233
|
});
|
|
113
234
|
}
|
|
114
235
|
case 'url': {
|
|
236
|
+
if (!localized) {
|
|
237
|
+
const flatShape = {
|
|
238
|
+
url: z.string().default(''),
|
|
239
|
+
id: z.string().optional()
|
|
240
|
+
};
|
|
241
|
+
if (field.text)
|
|
242
|
+
flatShape.text = z.string().default('');
|
|
243
|
+
if (field.newTab)
|
|
244
|
+
flatShape.newTab = z.boolean().optional();
|
|
245
|
+
return z.object(flatShape);
|
|
246
|
+
}
|
|
115
247
|
const langString = z.string().default('');
|
|
116
248
|
const urlShape = {
|
|
117
249
|
url: z.object(Object.fromEntries(languages.map((lang) => [lang, langString]))),
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Field } from '../../types/fields.js';
|
|
2
|
+
import type { ConfigBase } from '../../types/config.js';
|
|
3
|
+
import type { Layout, LayoutNode } from '../../types/layout.js';
|
|
4
|
+
export declare function getFieldsFromConfig(config: ConfigBase): Field[];
|
|
5
|
+
export declare function hasLayout(config: ConfigBase): boolean;
|
|
6
|
+
/** Collect all field slugs referenced in layout nodes (depth-first order) */
|
|
7
|
+
export declare function collectFieldSlugs(nodes: LayoutNode[]): string[];
|
|
8
|
+
export interface LayoutValidationError {
|
|
9
|
+
type: 'missing_field' | 'duplicate_field' | 'depth_exceeded' | 'columns_mismatch';
|
|
10
|
+
message: string;
|
|
11
|
+
}
|
|
12
|
+
/** Validate layout against fields — returns errors or empty array */
|
|
13
|
+
export declare function validateLayout(nodes: LayoutNode[], fields: Field[]): LayoutValidationError[];
|
|
14
|
+
/** Expand a preset into LayoutNode[] */
|
|
15
|
+
export declare function resolveLayout(layout: Layout, fields: Field[]): LayoutNode[];
|
|
16
|
+
/** Resolve layout + append orphan fields in a trailing section */
|
|
17
|
+
export declare function resolveLayoutWithOrphans(config: ConfigBase): LayoutNode[];
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { isLayoutBranch, isLayoutLeaf } from '../../types/layout.js';
|
|
2
|
+
export function getFieldsFromConfig(config) {
|
|
3
|
+
return config.fields;
|
|
4
|
+
}
|
|
5
|
+
export function hasLayout(config) {
|
|
6
|
+
return !!config.layout;
|
|
7
|
+
}
|
|
8
|
+
/** Collect all field slugs referenced in layout nodes (depth-first order) */
|
|
9
|
+
export function collectFieldSlugs(nodes) {
|
|
10
|
+
const slugs = [];
|
|
11
|
+
for (const node of nodes) {
|
|
12
|
+
if (isLayoutLeaf(node)) {
|
|
13
|
+
slugs.push(...node.fields);
|
|
14
|
+
}
|
|
15
|
+
if (isLayoutBranch(node)) {
|
|
16
|
+
slugs.push(...collectFieldSlugs(node.children));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return slugs;
|
|
20
|
+
}
|
|
21
|
+
/** Count columns expected by a ratio string */
|
|
22
|
+
function columnCount(ratio) {
|
|
23
|
+
return ratio.split(' ').length;
|
|
24
|
+
}
|
|
25
|
+
/** Validate layout against fields — returns errors or empty array */
|
|
26
|
+
export function validateLayout(nodes, fields) {
|
|
27
|
+
const errors = [];
|
|
28
|
+
const fieldSlugs = new Set(fields.map((f) => f.slug));
|
|
29
|
+
const referencedSlugs = collectFieldSlugs(nodes);
|
|
30
|
+
// Check for missing fields
|
|
31
|
+
for (const slug of referencedSlugs) {
|
|
32
|
+
if (!fieldSlugs.has(slug)) {
|
|
33
|
+
errors.push({ type: 'missing_field', message: `Field "${slug}" not found in fields[]` });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// Check for duplicates
|
|
37
|
+
const seen = new Set();
|
|
38
|
+
for (const slug of referencedSlugs) {
|
|
39
|
+
if (seen.has(slug)) {
|
|
40
|
+
errors.push({ type: 'duplicate_field', message: `Field "${slug}" referenced multiple times` });
|
|
41
|
+
}
|
|
42
|
+
seen.add(slug);
|
|
43
|
+
}
|
|
44
|
+
// Check depth + columns
|
|
45
|
+
function walk(nodeList, depth) {
|
|
46
|
+
if (depth > 2) {
|
|
47
|
+
errors.push({ type: 'depth_exceeded', message: `Nesting depth ${depth} exceeds max of 2` });
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
for (const node of nodeList) {
|
|
51
|
+
if (node.type === 'columns') {
|
|
52
|
+
const expected = columnCount(node.ratio);
|
|
53
|
+
const actual = node.children?.length ?? 0;
|
|
54
|
+
if (actual !== expected) {
|
|
55
|
+
errors.push({
|
|
56
|
+
type: 'columns_mismatch',
|
|
57
|
+
message: `Columns ratio "${node.ratio}" expects ${expected} children, got ${actual}`
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (isLayoutBranch(node)) {
|
|
62
|
+
walk(node.children, depth + 1);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
walk(nodes, 0);
|
|
67
|
+
return errors;
|
|
68
|
+
}
|
|
69
|
+
/** Expand a preset into LayoutNode[] */
|
|
70
|
+
export function resolveLayout(layout, fields) {
|
|
71
|
+
if (Array.isArray(layout))
|
|
72
|
+
return layout;
|
|
73
|
+
return expandPreset(layout, fields);
|
|
74
|
+
}
|
|
75
|
+
/** Resolve layout + append orphan fields in a trailing section */
|
|
76
|
+
export function resolveLayoutWithOrphans(config) {
|
|
77
|
+
if (!config.layout) {
|
|
78
|
+
// No layout — single section with all fields
|
|
79
|
+
return [
|
|
80
|
+
{
|
|
81
|
+
type: 'section',
|
|
82
|
+
label: { en: 'Fields', pl: 'Pola' },
|
|
83
|
+
fields: config.fields.map((f) => f.slug)
|
|
84
|
+
}
|
|
85
|
+
];
|
|
86
|
+
}
|
|
87
|
+
const nodes = resolveLayout(config.layout, config.fields);
|
|
88
|
+
const referenced = new Set(collectFieldSlugs(nodes));
|
|
89
|
+
const orphans = config.fields.filter((f) => !referenced.has(f.slug)).map((f) => f.slug);
|
|
90
|
+
if (orphans.length === 0)
|
|
91
|
+
return nodes;
|
|
92
|
+
return [
|
|
93
|
+
...nodes,
|
|
94
|
+
{
|
|
95
|
+
type: 'section',
|
|
96
|
+
label: { en: 'Other', pl: 'Pozostałe' },
|
|
97
|
+
fields: orphans
|
|
98
|
+
}
|
|
99
|
+
];
|
|
100
|
+
}
|
|
101
|
+
function expandPreset(preset, fields) {
|
|
102
|
+
const allSlugs = fields.map((f) => f.slug);
|
|
103
|
+
if (preset === 'sidebar-right') {
|
|
104
|
+
// Heuristic: last 2 fields → sidebar
|
|
105
|
+
const sidebarSlugs = allSlugs.slice(-2);
|
|
106
|
+
const mainSlugs = allSlugs.slice(0, -2);
|
|
107
|
+
return buildSidebarRight(mainSlugs, sidebarSlugs);
|
|
108
|
+
}
|
|
109
|
+
if (preset === 'two-column') {
|
|
110
|
+
const half = Math.ceil(allSlugs.length / 2);
|
|
111
|
+
return buildTwoColumn(allSlugs.slice(0, half), allSlugs.slice(half));
|
|
112
|
+
}
|
|
113
|
+
if (typeof preset === 'object' && preset.preset === 'sidebar-right') {
|
|
114
|
+
const sidebarSet = new Set(preset.sidebar);
|
|
115
|
+
const mainSlugs = allSlugs.filter((s) => !sidebarSet.has(s));
|
|
116
|
+
return buildSidebarRight(mainSlugs, preset.sidebar);
|
|
117
|
+
}
|
|
118
|
+
if (typeof preset === 'object' && preset.preset === 'two-column') {
|
|
119
|
+
const leftSet = new Set(preset.left ?? []);
|
|
120
|
+
const left = preset.left ?? allSlugs.slice(0, Math.ceil(allSlugs.length / 2));
|
|
121
|
+
const right = allSlugs.filter((s) => !leftSet.has(s));
|
|
122
|
+
return buildTwoColumn(left, right);
|
|
123
|
+
}
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
function buildSidebarRight(main, sidebar) {
|
|
127
|
+
return [
|
|
128
|
+
{
|
|
129
|
+
type: 'columns',
|
|
130
|
+
ratio: '2fr 1fr',
|
|
131
|
+
children: [
|
|
132
|
+
{ type: 'stack', fields: main },
|
|
133
|
+
{ type: 'stack', fields: sidebar }
|
|
134
|
+
]
|
|
135
|
+
}
|
|
136
|
+
];
|
|
137
|
+
}
|
|
138
|
+
function buildTwoColumn(left, right) {
|
|
139
|
+
return [
|
|
140
|
+
{
|
|
141
|
+
type: 'columns',
|
|
142
|
+
ratio: '1fr 1fr',
|
|
143
|
+
children: [
|
|
144
|
+
{ type: 'stack', fields: left },
|
|
145
|
+
{ type: 'stack', fields: right }
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
];
|
|
149
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { StructuredContentDoc } from '../../types/structured-content.js';
|
|
2
|
+
export interface StructuredToHtmlOptions {
|
|
3
|
+
/** Custom renderer for inline blocks. Return HTML string. */
|
|
4
|
+
inlineBlock?: (blockType: string, blockData: Record<string, unknown>) => string;
|
|
5
|
+
/** Base URL prefix for relative URLs (useful for RSS feeds). */
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
}
|
|
8
|
+
/** Convert a StructuredContentDoc to an HTML string. */
|
|
9
|
+
export declare function structuredToHtml(doc: StructuredContentDoc, options?: StructuredToHtmlOptions): string;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
const VOID_TAGS = new Set(['hr', 'br', 'img']);
|
|
2
|
+
function escapeHtml(str) {
|
|
3
|
+
return str
|
|
4
|
+
.replace(/&/g, '&')
|
|
5
|
+
.replace(/</g, '<')
|
|
6
|
+
.replace(/>/g, '>')
|
|
7
|
+
.replace(/"/g, '"');
|
|
8
|
+
}
|
|
9
|
+
function resolveUrl(url, baseUrl) {
|
|
10
|
+
if (!baseUrl || !url)
|
|
11
|
+
return url;
|
|
12
|
+
if (url.startsWith('http://') || url.startsWith('https://') || url.startsWith('//'))
|
|
13
|
+
return url;
|
|
14
|
+
return `${baseUrl.replace(/\/$/, '')}${url.startsWith('/') ? '' : '/'}${url}`;
|
|
15
|
+
}
|
|
16
|
+
function renderMarks(text, marks, options) {
|
|
17
|
+
if (!marks?.length)
|
|
18
|
+
return escapeHtml(text);
|
|
19
|
+
let html = escapeHtml(text);
|
|
20
|
+
for (const mark of marks) {
|
|
21
|
+
switch (mark.type) {
|
|
22
|
+
case 'bold':
|
|
23
|
+
html = `<strong>${html}</strong>`;
|
|
24
|
+
break;
|
|
25
|
+
case 'italic':
|
|
26
|
+
html = `<em>${html}</em>`;
|
|
27
|
+
break;
|
|
28
|
+
case 'underline':
|
|
29
|
+
html = `<u>${html}</u>`;
|
|
30
|
+
break;
|
|
31
|
+
case 'strike':
|
|
32
|
+
html = `<s>${html}</s>`;
|
|
33
|
+
break;
|
|
34
|
+
case 'code':
|
|
35
|
+
html = `<code>${html}</code>`;
|
|
36
|
+
break;
|
|
37
|
+
case 'highlight':
|
|
38
|
+
html = `<mark>${html}</mark>`;
|
|
39
|
+
break;
|
|
40
|
+
case 'link': {
|
|
41
|
+
const attrs = mark.attrs ?? {};
|
|
42
|
+
const href = resolveUrl(attrs.href ?? '', options.baseUrl);
|
|
43
|
+
const target = attrs.target;
|
|
44
|
+
const title = attrs.title;
|
|
45
|
+
const ariaLabel = attrs['aria-label'];
|
|
46
|
+
let attrStr = ` href="${escapeHtml(href)}"`;
|
|
47
|
+
if (target === '_blank') {
|
|
48
|
+
attrStr += ` target="_blank" rel="noopener noreferrer"`;
|
|
49
|
+
}
|
|
50
|
+
else if (target) {
|
|
51
|
+
attrStr += ` target="${escapeHtml(target)}"`;
|
|
52
|
+
}
|
|
53
|
+
if (title)
|
|
54
|
+
attrStr += ` title="${escapeHtml(title)}"`;
|
|
55
|
+
if (ariaLabel)
|
|
56
|
+
attrStr += ` aria-label="${escapeHtml(ariaLabel)}"`;
|
|
57
|
+
html = `<a${attrStr}>${html}</a>`;
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return html;
|
|
63
|
+
}
|
|
64
|
+
function renderNode(node, options) {
|
|
65
|
+
const children = node.content?.map((c) => renderNode(c, options)).join('') ?? '';
|
|
66
|
+
switch (node.type) {
|
|
67
|
+
case 'doc':
|
|
68
|
+
return children;
|
|
69
|
+
case 'text':
|
|
70
|
+
return renderMarks(node.text ?? '', node.marks, options);
|
|
71
|
+
case 'paragraph':
|
|
72
|
+
return `<p>${children}</p>`;
|
|
73
|
+
case 'heading': {
|
|
74
|
+
const level = node.attrs?.level ?? 2;
|
|
75
|
+
return `<h${level}>${children}</h${level}>`;
|
|
76
|
+
}
|
|
77
|
+
case 'blockquote':
|
|
78
|
+
return `<blockquote>${children}</blockquote>`;
|
|
79
|
+
case 'bulletList':
|
|
80
|
+
return `<ul>${children}</ul>`;
|
|
81
|
+
case 'orderedList':
|
|
82
|
+
return `<ol>${children}</ol>`;
|
|
83
|
+
case 'listItem':
|
|
84
|
+
return `<li>${children}</li>`;
|
|
85
|
+
case 'codeBlock': {
|
|
86
|
+
const lang = node.attrs?.language;
|
|
87
|
+
const langAttr = lang ? ` class="language-${escapeHtml(lang)}"` : '';
|
|
88
|
+
return `<pre><code${langAttr}>${children}</code></pre>`;
|
|
89
|
+
}
|
|
90
|
+
case 'horizontalRule':
|
|
91
|
+
return '<hr>';
|
|
92
|
+
case 'hardBreak':
|
|
93
|
+
return '<br>';
|
|
94
|
+
case 'figure': {
|
|
95
|
+
const attrs = node.attrs ?? {};
|
|
96
|
+
const src = resolveUrl(attrs.src ?? '', options.baseUrl);
|
|
97
|
+
const alt = escapeHtml(attrs.alt ?? '');
|
|
98
|
+
const caption = attrs.caption;
|
|
99
|
+
const width = attrs.width;
|
|
100
|
+
const height = attrs.height;
|
|
101
|
+
let imgAttrs = ` src="${escapeHtml(src)}" alt="${alt}"`;
|
|
102
|
+
if (width)
|
|
103
|
+
imgAttrs += ` width="${width}"`;
|
|
104
|
+
if (height)
|
|
105
|
+
imgAttrs += ` height="${height}"`;
|
|
106
|
+
let html = `<figure><img${imgAttrs}>`;
|
|
107
|
+
if (caption)
|
|
108
|
+
html += `<figcaption>${escapeHtml(caption)}</figcaption>`;
|
|
109
|
+
html += '</figure>';
|
|
110
|
+
return html;
|
|
111
|
+
}
|
|
112
|
+
case 'image': {
|
|
113
|
+
const attrs = node.attrs ?? {};
|
|
114
|
+
const src = resolveUrl(attrs.src ?? '', options.baseUrl);
|
|
115
|
+
const alt = escapeHtml(attrs.alt ?? '');
|
|
116
|
+
const width = attrs.width;
|
|
117
|
+
const height = attrs.height;
|
|
118
|
+
let imgAttrs = ` src="${escapeHtml(src)}" alt="${alt}"`;
|
|
119
|
+
if (width)
|
|
120
|
+
imgAttrs += ` width="${width}"`;
|
|
121
|
+
if (height)
|
|
122
|
+
imgAttrs += ` height="${height}"`;
|
|
123
|
+
return `<img${imgAttrs}>`;
|
|
124
|
+
}
|
|
125
|
+
case 'video': {
|
|
126
|
+
const attrs = node.attrs ?? {};
|
|
127
|
+
const src = resolveUrl(attrs.src ?? '', options.baseUrl);
|
|
128
|
+
const poster = attrs.poster;
|
|
129
|
+
const width = attrs.width;
|
|
130
|
+
const height = attrs.height;
|
|
131
|
+
let videoAttrs = ' controls';
|
|
132
|
+
if (poster)
|
|
133
|
+
videoAttrs += ` poster="${escapeHtml(resolveUrl(poster, options.baseUrl))}"`;
|
|
134
|
+
if (width)
|
|
135
|
+
videoAttrs += ` width="${width}"`;
|
|
136
|
+
if (height)
|
|
137
|
+
videoAttrs += ` height="${height}"`;
|
|
138
|
+
return `<video${videoAttrs}><source src="${escapeHtml(src)}"></video>`;
|
|
139
|
+
}
|
|
140
|
+
case 'table':
|
|
141
|
+
return `<table>${children}</table>`;
|
|
142
|
+
case 'tableRow':
|
|
143
|
+
return `<tr>${children}</tr>`;
|
|
144
|
+
case 'tableCell':
|
|
145
|
+
return `<td>${children}</td>`;
|
|
146
|
+
case 'tableHeader':
|
|
147
|
+
return `<th>${children}</th>`;
|
|
148
|
+
case 'inlineBlock': {
|
|
149
|
+
const attrs = node.attrs ?? {};
|
|
150
|
+
const blockType = attrs.blockType;
|
|
151
|
+
const blockData = attrs.blockData ?? {};
|
|
152
|
+
return options.inlineBlock?.(blockType, blockData) ?? '';
|
|
153
|
+
}
|
|
154
|
+
default:
|
|
155
|
+
return children;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/** Convert a StructuredContentDoc to an HTML string. */
|
|
159
|
+
export function structuredToHtml(doc, options = {}) {
|
|
160
|
+
return renderNode(doc, options);
|
|
161
|
+
}
|
|
@@ -4,6 +4,7 @@ import { entryTypes } from '../../../../types/entries.js';
|
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
import { getDbEntryOrThrow } from './get.js';
|
|
6
6
|
import { generateZodSchemaFromFields } from '../../../fields/fieldSchemaToTs.js';
|
|
7
|
+
import { getFieldsFromConfig } from '../../../fields/layoutUtils.js';
|
|
7
8
|
export const createEntrySchema = z.object({
|
|
8
9
|
slug: z.string(),
|
|
9
10
|
type: z.enum(entryTypes)
|
|
@@ -32,7 +33,7 @@ export const createEntryVersion = async (data, options) => {
|
|
|
32
33
|
const entry = await getDbEntryOrThrow({ id: data.entryId });
|
|
33
34
|
const config = getCMS().getBySlug(entry.slug);
|
|
34
35
|
const languages = getCMS().languages;
|
|
35
|
-
const schema = generateZodSchemaFromFields(config
|
|
36
|
+
const schema = generateZodSchemaFromFields(getFieldsFromConfig(config), languages);
|
|
36
37
|
const parsedData = schema.safeParse(data.data);
|
|
37
38
|
if (!parsedData.success) {
|
|
38
39
|
throw Error('Invalid data: ' + JSON.stringify(parsedData.error.flatten()));
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getCMS } from '../../../cms.js';
|
|
2
2
|
import { populateEntryData } from '../../fields/populateEntry.js';
|
|
3
|
+
import { getFieldsFromConfig } from '../../../fields/layoutUtils.js';
|
|
3
4
|
// Helper function to transform string values to localized objects
|
|
4
5
|
function transformDataValuesToLocalized(dataValues, defaultLanguage) {
|
|
5
6
|
const result = {};
|
|
@@ -70,16 +71,17 @@ export const getRawEntries = async (options) => {
|
|
|
70
71
|
const scheduledVersion = publishedOrScheduledVersion && isScheduled
|
|
71
72
|
? publishedOrScheduledVersion
|
|
72
73
|
: null;
|
|
73
|
-
// Draft = latest version by versionNumber
|
|
74
|
-
const
|
|
75
|
-
.
|
|
74
|
+
// Draft = latest non-published version by versionNumber
|
|
75
|
+
const draftVersion = versions
|
|
76
|
+
.filter((v) => v.id !== entry.publishedVersionId)
|
|
77
|
+
.sort((a, b) => b.versionNumber - a.versionNumber)[0] || null;
|
|
76
78
|
return {
|
|
77
79
|
...entry,
|
|
78
80
|
collection: getCMS().getBySlug(entry.slug),
|
|
79
81
|
versions: versions.sort((a, b) => b.versionNumber - a.versionNumber),
|
|
80
82
|
publishedVersion,
|
|
81
83
|
scheduledVersion,
|
|
82
|
-
draftVersion
|
|
84
|
+
draftVersion
|
|
83
85
|
};
|
|
84
86
|
}
|
|
85
87
|
catch {
|
|
@@ -237,7 +239,7 @@ export const getEntries = async (options = {}) => {
|
|
|
237
239
|
const config = getCMS().getBySlug(dbEntry.slug);
|
|
238
240
|
return {
|
|
239
241
|
...dbEntry,
|
|
240
|
-
data: await populateEntryData(version.data, config
|
|
242
|
+
data: await populateEntryData(version.data, getFieldsFromConfig(config), language),
|
|
241
243
|
status,
|
|
242
244
|
publishedAt: dbEntry.publishedAt,
|
|
243
245
|
populated: true
|
|
@@ -295,7 +297,7 @@ export const getEntryVersion = async (options) => {
|
|
|
295
297
|
const config = getCMS().getBySlug(dbEntry.slug);
|
|
296
298
|
return {
|
|
297
299
|
...dbEntry,
|
|
298
|
-
data: await populateEntryData(dbEntryVersion.data, config
|
|
300
|
+
data: await populateEntryData(dbEntryVersion.data, getFieldsFromConfig(config), language)
|
|
299
301
|
};
|
|
300
302
|
}
|
|
301
303
|
catch (error) {
|
|
@@ -17,4 +17,7 @@ export declare const updateEntryVersion: (id: string, data: Partial<DbEntryVersi
|
|
|
17
17
|
export declare const updateEntryVersionCommandTypes: readonly ["draft", "published-now", "published-scheduled", "cancel-published"];
|
|
18
18
|
export type UpdateEntryVersionCommandType = (typeof updateEntryVersionCommandTypes)[number];
|
|
19
19
|
export declare const pruneOldDraftVersions: (entryId: string) => Promise<void>;
|
|
20
|
+
export declare const upsertDraftVersion: (entryId: string, data: Record<string, unknown>, options?: {
|
|
21
|
+
skipValidation?: boolean;
|
|
22
|
+
}) => Promise<DbEntryVersion>;
|
|
20
23
|
export declare const unpublishEntry: (entryId: string) => Promise<void>;
|