rimecms 0.33.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter-sqlite/auth.server.d.ts +2 -2
- package/dist/adapter-sqlite/columns.server.js +2 -2
- package/dist/adapter-sqlite/connect.server.d.ts +12 -0
- package/dist/adapter-sqlite/connect.server.js +31 -0
- package/dist/adapter-sqlite/generate-schema/index.server.js +11 -3
- package/dist/adapter-sqlite/generate-schema/root.server.d.ts +13 -4
- package/dist/adapter-sqlite/generate-schema/root.server.js +75 -131
- package/dist/adapter-sqlite/generate-schema/templates.server.d.ts +27 -6
- package/dist/adapter-sqlite/generate-schema/templates.server.js +52 -10
- package/dist/adapter-sqlite/index.server.d.ts +13 -5
- package/dist/adapter-sqlite/index.server.js +9 -6
- package/dist/adapter-sqlite/naming.server.d.ts +6 -8
- package/dist/adapter-sqlite/naming.server.js +22 -4
- package/dist/adapter-sqlite/paths.server.d.ts +10 -0
- package/dist/adapter-sqlite/paths.server.js +122 -0
- package/dist/adapter-sqlite/read.server.d.ts +10 -1
- package/dist/adapter-sqlite/read.server.js +22 -10
- package/dist/adapter-sqlite/select.server.d.ts +19 -0
- package/dist/adapter-sqlite/select.server.js +71 -63
- package/dist/adapter-sqlite/table.server.d.ts +2 -2
- package/dist/adapter-sqlite/transform.server.js +33 -3
- package/dist/adapter-sqlite/types.server.d.ts +10 -3
- package/dist/adapter-sqlite/where.server.d.ts +2 -3
- package/dist/adapter-sqlite/where.server.js +19 -1
- package/dist/core/adapter.d.ts +94 -0
- package/dist/core/auth/better-auth/config.server.d.ts +3 -3
- package/dist/core/auth/better-auth/instance.server.d.ts +6 -6
- package/dist/core/auth/handler/index.server.js +1 -1
- package/dist/core/auth/staff/derive.js +1 -1
- package/dist/core/auth/validate-config.js +3 -5
- package/dist/core/boot.server.d.ts +6 -6
- package/dist/core/config/types.d.ts +43 -5
- package/dist/core/config/validate.server.js +34 -51
- package/dist/core/dev/cli/commands/build.js +21 -6
- package/dist/core/dev/cli/commands/init.server.d.ts +2 -1
- package/dist/core/dev/cli/commands/init.server.js +32 -6
- package/dist/core/dev/cli/index.js +1 -0
- package/dist/core/dev/cli/templates/init.d.ts +6 -1
- package/dist/core/dev/cli/templates/init.js +30 -2
- package/dist/core/dev/cli/util/package-manager.server.d.ts +1 -0
- package/dist/core/dev/cli/util/package-manager.server.js +11 -8
- package/dist/core/dev/cli/util/package.server.d.ts +9 -0
- package/dist/core/dev/cli/util/package.server.js +43 -0
- package/dist/core/dev/codegen/types/contributions.server.d.ts +3 -2
- package/dist/core/dev/codegen/types/contributions.server.js +10 -3
- package/dist/core/dev/vite.server.js +4 -3
- package/dist/core/fields/blank.d.ts +21 -0
- package/dist/core/fields/blank.js +37 -0
- package/dist/core/fields/builders/field-builder.d.ts +53 -0
- package/dist/core/fields/builders/field-builder.js +14 -1
- package/dist/core/fields/builders/form-field-builder.d.ts +8 -0
- package/dist/core/fields/builders/form-field-builder.js +14 -1
- package/dist/core/fields/util.d.ts +9 -2
- package/dist/core/fields/util.js +123 -135
- package/dist/core/fields/walk.d.ts +44 -0
- package/dist/core/fields/walk.js +55 -0
- package/dist/core/handler.server.js +4 -0
- package/dist/core/i18n/context.d.ts +5 -0
- package/dist/core/i18n/context.js +6 -0
- package/dist/core/i18n/en/common.d.ts +71 -0
- package/dist/core/i18n/en/common.js +72 -1
- package/dist/core/i18n/en/fields.d.ts +68 -0
- package/dist/core/i18n/en/fields.js +69 -1
- package/dist/core/i18n/fr/common.d.ts +71 -0
- package/dist/core/i18n/fr/common.js +72 -1
- package/dist/core/i18n/fr/fields.d.ts +68 -0
- package/dist/core/i18n/fr/fields.js +69 -1
- package/dist/core/i18n/index.d.ts +29 -3
- package/dist/core/i18n/index.js +55 -29
- package/dist/core/locale/copy.server.js +3 -3
- package/dist/core/logger.server.js +15 -6
- package/dist/core/pipeline/build-document.server.d.ts +3 -0
- package/dist/core/pipeline/build-document.server.js +10 -7
- package/dist/core/pipeline/config-map/index.d.ts +9 -0
- package/dist/core/pipeline/config-map/index.js +16 -50
- package/dist/core/pipeline/hooks/process-document-fields.server.d.ts +3 -0
- package/dist/core/pipeline/hooks/process-document-fields.server.js +48 -12
- package/dist/core/pipeline/hooks/set-default-values.server.d.ts +1 -0
- package/dist/core/pipeline/hooks/set-default-values.server.js +1 -0
- package/dist/core/pipeline/persist/blocks/extract.server.js +1 -1
- package/dist/core/pipeline/persist/relations/extract.server.js +2 -0
- package/dist/core/pipeline/populate-relations.server.d.ts +27 -0
- package/dist/core/pipeline/populate-relations.server.js +42 -0
- package/dist/core/pipeline/run.server.d.ts +17 -6
- package/dist/core/pipeline/run.server.js +44 -30
- package/dist/core/plugins/cache/module.server.d.ts +1 -1
- package/dist/core/plugins/cache/module.server.js +5 -5
- package/dist/core/prototype/area/api.server.js +1 -2
- package/dist/core/prototype/area/definition.js +1 -10
- package/dist/core/prototype/area/definition.server.js +4 -5
- package/dist/core/prototype/area/hooks.server.js +3 -2
- package/dist/core/prototype/area/operations/find.js +2 -0
- package/dist/core/prototype/blank.d.ts +26 -0
- package/dist/core/prototype/blank.js +22 -0
- package/dist/core/prototype/collection/api.server.d.ts +29 -3
- package/dist/core/prototype/collection/api.server.js +47 -4
- package/dist/core/prototype/collection/definition.js +0 -3
- package/dist/core/prototype/collection/hooks/merge-with-blank.server.d.ts +5 -1
- package/dist/core/prototype/collection/hooks/merge-with-blank.server.js +8 -22
- package/dist/core/prototype/collection/hooks.server.js +11 -5
- package/dist/core/prototype/collection/nested/module.server.js +3 -1
- package/dist/core/prototype/collection/nested/tree.d.ts +12 -0
- package/dist/core/prototype/collection/nested/tree.js +42 -0
- package/dist/core/prototype/collection/operations/find-by-id.js +2 -0
- package/dist/core/prototype/collection/operations/find-by-ids.d.ts +19 -0
- package/dist/core/prototype/collection/operations/find-by-ids.js +54 -0
- package/dist/core/prototype/collection/operations/find.js +21 -27
- package/dist/core/prototype/collection/operations/update-slug-by-id.d.ts +20 -0
- package/dist/core/prototype/collection/operations/update-slug-by-id.js +53 -0
- package/dist/core/prototype/collection/rest/index.server.js +3 -1
- package/dist/core/prototype/collection/rest/update-slug-by-id.server.d.ts +2 -0
- package/dist/core/prototype/collection/rest/update-slug-by-id.server.js +20 -0
- package/dist/core/prototype/collection/thumbnail/find-thumbnail.d.ts +2 -1
- package/dist/core/prototype/collection/thumbnail/find-thumbnail.js +4 -27
- package/dist/core/prototype/collection/upload/directories/derive.js +3 -1
- package/dist/core/prototype/collection/upload/disk/delete.server.js +1 -2
- package/dist/core/prototype/define.js +2 -0
- package/dist/core/prototype/shared/metas/fields.js +2 -1
- package/dist/core/prototype/shared/title/find-title.d.ts +2 -1
- package/dist/core/prototype/shared/title/find-title.js +5 -28
- package/dist/core/prototype/shared/url/addresses.server.d.ts +26 -0
- package/dist/core/prototype/shared/url/addresses.server.js +119 -0
- package/dist/core/prototype/shared/url/doc-type.d.ts +6 -0
- package/dist/core/prototype/shared/url/doc-type.js +9 -0
- package/dist/core/prototype/shared/url/format.server.d.ts +27 -0
- package/dist/core/prototype/shared/url/format.server.js +38 -0
- package/dist/core/prototype/shared/url/hooks/create-paths.server.d.ts +2 -0
- package/dist/core/prototype/shared/url/hooks/create-paths.server.js +9 -0
- package/dist/core/prototype/shared/url/hooks/detach-paths.server.d.ts +5 -0
- package/dist/core/prototype/shared/url/hooks/detach-paths.server.js +18 -0
- package/dist/core/prototype/shared/url/hooks/index.server.d.ts +5 -1
- package/dist/core/prototype/shared/url/hooks/index.server.js +5 -1
- package/dist/core/prototype/shared/url/hooks/set-area-url.server.d.ts +2 -0
- package/dist/core/prototype/shared/url/hooks/set-area-url.server.js +8 -0
- package/dist/core/prototype/shared/url/hooks/set-live-url.server.d.ts +5 -0
- package/dist/core/prototype/shared/url/hooks/set-live-url.server.js +19 -0
- package/dist/core/prototype/shared/url/hooks/sync-paths.server.d.ts +7 -0
- package/dist/core/prototype/shared/url/hooks/sync-paths.server.js +37 -0
- package/dist/core/prototype/shared/url/refresh.server.d.ts +36 -0
- package/dist/core/prototype/shared/url/refresh.server.js +58 -0
- package/dist/core/prototype/shared/versions/configure.server.js +3 -0
- package/dist/core/routes/context.server.d.ts +2 -1
- package/dist/fields/blocks/component/AddBlockButton.svelte +48 -137
- package/dist/fields/blocks/component/Block.svelte +153 -117
- package/dist/fields/blocks/component/Block.svelte.d.ts +11 -5
- package/dist/fields/blocks/component/BlockActions.svelte +76 -26
- package/dist/fields/blocks/component/BlockActions.svelte.d.ts +3 -0
- package/dist/fields/blocks/component/Blocks.svelte +248 -91
- package/dist/fields/blocks/component/focus/BlocksFocus.svelte +680 -0
- package/dist/fields/blocks/component/focus/BlocksFocus.svelte.d.ts +7 -0
- package/dist/fields/blocks/component/focus/Layers.svelte +145 -0
- package/dist/fields/blocks/component/focus/Layers.svelte.d.ts +9 -0
- package/dist/fields/blocks/component/focus/LayersList.svelte +304 -0
- package/dist/fields/blocks/component/focus/LayersList.svelte.d.ts +10 -0
- package/dist/fields/blocks/component/focus/Palette.svelte +135 -0
- package/dist/fields/blocks/component/focus/Palette.svelte.d.ts +9 -0
- package/dist/fields/blocks/component/focus/RenderPlaceholder.svelte +77 -0
- package/dist/fields/blocks/component/focus/RenderPlaceholder.svelte.d.ts +10 -0
- package/dist/fields/blocks/component/focus/Renders.svelte +302 -0
- package/dist/fields/blocks/component/focus/Renders.svelte.d.ts +11 -0
- package/dist/fields/blocks/component/focus/Stage.svelte +190 -0
- package/dist/fields/blocks/component/focus/Stage.svelte.d.ts +8 -0
- package/dist/fields/blocks/component/focus/StagePlaceholder.svelte +69 -0
- package/dist/fields/blocks/component/focus/StagePlaceholder.svelte.d.ts +3 -0
- package/dist/fields/blocks/component/focus/focus.svelte.d.ts +140 -0
- package/dist/fields/blocks/component/focus/focus.svelte.js +424 -0
- package/dist/fields/blocks/component/picker/BlockPicker.svelte +88 -0
- package/dist/fields/blocks/component/picker/BlockPicker.svelte.d.ts +10 -0
- package/dist/fields/blocks/component/picker/BlockTile.svelte +121 -0
- package/dist/fields/blocks/component/picker/BlockTile.svelte.d.ts +12 -0
- package/dist/fields/blocks/index.d.ts +49 -7
- package/dist/fields/blocks/index.js +61 -12
- package/dist/fields/checkbox/component/Checkbox.svelte +11 -37
- package/dist/fields/checkbox/component/Checkbox.svelte.d.ts +1 -0
- package/dist/fields/combobox/component/ComboBox.svelte +37 -7
- package/dist/fields/combobox/component/combobox.css +26 -10
- package/dist/fields/date/component/Date.svelte +43 -12
- package/dist/fields/group/component/Group.svelte +110 -41
- package/dist/fields/group/index.d.ts +5 -1
- package/dist/fields/group/index.js +10 -2
- package/dist/fields/link/component/Link.svelte +184 -143
- package/dist/fields/link/component/RessourceInput.svelte +26 -24
- package/dist/fields/link/index.d.ts +1 -0
- package/dist/fields/link/module.server.js +2 -4
- package/dist/fields/number/component/Number.svelte +38 -20
- package/dist/fields/number/component/number.css +22 -20
- package/dist/fields/number/index.d.ts +1 -0
- package/dist/fields/radio/component/Radio.svelte +12 -0
- package/dist/fields/radio/index.js +1 -1
- package/dist/fields/relation/component/Relation.svelte +169 -40
- package/dist/fields/relation/component/RelationInline.svelte +258 -0
- package/dist/fields/relation/component/RelationInline.svelte.d.ts +26 -0
- package/dist/fields/relation/component/default/Default.svelte +210 -100
- package/dist/fields/relation/component/default/Default.svelte.d.ts +14 -1
- package/dist/fields/relation/component/types.d.ts +4 -0
- package/dist/fields/relation/component/upload/Browse.svelte +619 -88
- package/dist/fields/relation/component/upload/Browse.svelte.d.ts +10 -2
- package/dist/fields/relation/component/upload/Create.svelte +41 -0
- package/dist/fields/relation/component/upload/Create.svelte.d.ts +13 -0
- package/dist/fields/relation/component/upload/Upload.svelte +287 -101
- package/dist/fields/relation/component/upload/Upload.svelte.d.ts +6 -1
- package/dist/fields/relation/component/upload/upload.css +5 -81
- package/dist/fields/relation/module.server.js +7 -1
- package/dist/fields/relation/value.d.ts +25 -0
- package/dist/fields/relation/value.js +27 -0
- package/dist/fields/rich-text/component/RichText.svelte +12 -80
- package/dist/fields/rich-text/component/RichText.svelte.d.ts +1 -1
- package/dist/fields/rich-text/component/RichTextInline.svelte +28 -0
- package/dist/fields/rich-text/component/RichTextInline.svelte.d.ts +11 -0
- package/dist/fields/rich-text/component/bubble-menu/bubble-menu.css +4 -3
- package/dist/fields/rich-text/component/bubble-menu/bubble-menu.svelte +3 -1
- package/dist/fields/rich-text/component/bubble-menu/icon-button/icon-button.css +2 -2
- package/dist/fields/rich-text/component/bubble-menu/node-selector/node-selector.css +7 -10
- package/dist/fields/rich-text/component/drag-handle/drag-handle.css +0 -2
- package/dist/fields/rich-text/component/styles/editor.css +111 -0
- package/dist/fields/rich-text/component/styles/field.css +71 -0
- package/dist/fields/rich-text/component/suggestion/suggestion.svelte +41 -56
- package/dist/fields/rich-text/core/build-editor-config.js +1 -1
- package/dist/fields/rich-text/core/extensions/drag-handle/drag-handle-plugin.js +29 -3
- package/dist/fields/rich-text/core/extensions/drag-handle/drag-handle.d.ts +1 -0
- package/dist/fields/rich-text/core/extensions/drag-handle/drag-handle.js +2 -1
- package/dist/fields/rich-text/core/features/fields/fields.css +2 -3
- package/dist/fields/rich-text/core/features/hr/hr.css +4 -4
- package/dist/fields/rich-text/core/features/link/component/link-selector.css +0 -4
- package/dist/fields/rich-text/core/features/link/component/link-selector.svelte +24 -8
- package/dist/fields/rich-text/core/features/resource/resource.svelte +20 -6
- package/dist/fields/rich-text/core/features/upload/upload.svelte +20 -8
- package/dist/fields/rich-text/core/rich-text-editor-core.svelte +103 -0
- package/dist/fields/rich-text/core/rich-text-editor-core.svelte.d.ts +15 -0
- package/dist/fields/select/component/Select.svelte +67 -28
- package/dist/fields/slug/component/Slug.svelte +26 -53
- package/dist/fields/slug/index.d.ts +1 -0
- package/dist/fields/slug/index.js +1 -1
- package/dist/fields/tabs/component/Tabs.svelte +28 -22
- package/dist/fields/tabs/index.d.ts +4 -1
- package/dist/fields/tabs/index.js +17 -5
- package/dist/fields/text/index.d.ts +1 -0
- package/dist/fields/textarea/component/TextArea.svelte +28 -13
- package/dist/fields/textarea/index.d.ts +1 -0
- package/dist/fields/time/component/Time.svelte +9 -2
- package/dist/fields/toggle/component/Toggle.svelte +8 -25
- package/dist/fields/toggle/component/Toggle.svelte.d.ts +1 -0
- package/dist/fields/toggle/index.d.ts +1 -0
- package/dist/fields/tree/component/AddItemButton.svelte +18 -5
- package/dist/fields/tree/component/Tree.svelte +48 -19
- package/dist/fields/tree/component/TreeBlock.svelte +318 -104
- package/dist/fields/tree/component/TreeBlockActions.svelte +71 -7
- package/dist/fields/tree/component/TreeBlockActions.svelte.d.ts +4 -0
- package/dist/fields/tree/component/props.d.ts +2 -1
- package/dist/fields/tree/index.d.ts +13 -1
- package/dist/fields/tree/index.js +35 -9
- package/dist/fields/types.d.ts +3 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +3 -2
- package/dist/panel/components/Root.svelte +16 -44
- package/dist/panel/components/Root.svelte.d.ts +1 -1
- package/dist/panel/components/fields/Error.svelte +18 -3
- package/dist/panel/components/fields/FieldsPreview.svelte +30 -17
- package/dist/panel/components/fields/FieldsPreviewTrigger.svelte +25 -3
- package/dist/panel/components/fields/Hint.svelte +51 -8
- package/dist/panel/components/fields/Hint.svelte.d.ts +11 -0
- package/dist/panel/components/fields/Label.svelte +2 -0
- package/dist/panel/components/fields/LabelFor.svelte +7 -2
- package/dist/panel/components/fields/RenderFields.svelte +10 -3
- package/dist/panel/components/fields/fieldset.svelte.d.ts +4 -1
- package/dist/panel/components/fields/fieldset.svelte.js +9 -2
- package/dist/panel/components/fields/index.d.ts +1 -0
- package/dist/panel/components/fields/setting.css +82 -0
- package/dist/panel/components/sections/auth/AuthForm.svelte +25 -26
- package/dist/panel/components/sections/collection/Avatar.svelte +61 -0
- package/dist/panel/components/sections/collection/Avatar.svelte.d.ts +9 -0
- package/dist/panel/components/sections/collection/DocStatus.svelte +28 -0
- package/dist/panel/components/sections/collection/DocStatus.svelte.d.ts +7 -0
- package/dist/panel/components/sections/collection/Empty.svelte +3 -3
- package/dist/panel/components/sections/collection/StatusDot.svelte +7 -5
- package/dist/panel/components/sections/collection/When.svelte +33 -0
- package/dist/panel/components/sections/collection/When.svelte.d.ts +8 -0
- package/dist/panel/components/sections/collection/bulk-upload/BulkUploadDialog.svelte +65 -21
- package/dist/panel/components/sections/collection/bulk-upload/BulkUploadDialog.svelte.d.ts +3 -2
- package/dist/panel/components/sections/collection/bulk-upload/DropZone.svelte +45 -162
- package/dist/panel/components/sections/collection/bulk-upload/DropZone.svelte.d.ts +3 -2
- package/dist/panel/components/sections/collection/bulk-upload/FileDrop.svelte +151 -0
- package/dist/panel/components/sections/collection/bulk-upload/FileDrop.svelte.d.ts +17 -0
- package/dist/panel/components/sections/collection/bulk-upload/PageDrop.svelte +177 -0
- package/dist/panel/components/sections/collection/bulk-upload/PageDrop.svelte.d.ts +12 -0
- package/dist/panel/components/sections/collection/bulk-upload/UploadProgress.svelte +75 -0
- package/dist/panel/components/sections/collection/bulk-upload/UploadProgress.svelte.d.ts +8 -0
- package/dist/panel/components/sections/collection/folder/Folder.svelte +18 -3
- package/dist/panel/components/sections/collection/folder/FolderEdit.svelte +26 -18
- package/dist/panel/components/sections/collection/folder/FolderWithActions.svelte +98 -58
- package/dist/panel/components/sections/collection/folder/FolderWithActions.svelte.d.ts +0 -1
- package/dist/panel/components/sections/collection/folder/Folders.svelte +60 -0
- package/dist/panel/components/sections/collection/folder/Folders.svelte.d.ts +7 -0
- package/dist/panel/components/sections/collection/grid/CollectionGrid.svelte +31 -71
- package/dist/panel/components/sections/collection/grid/CollectionGrid.svelte.d.ts +1 -0
- package/dist/panel/components/sections/collection/grid/create-directory-dialog/CreateDirectoryDialog.svelte +5 -3
- package/dist/panel/components/sections/collection/grid/grid-item/GridItem.svelte +250 -37
- package/dist/panel/components/sections/collection/grid/grid-item/GridItem.svelte.d.ts +2 -0
- package/dist/panel/components/sections/collection/header/ButtonCreate.svelte +43 -18
- package/dist/panel/components/sections/collection/header/ButtonCreate.svelte.d.ts +6 -4
- package/dist/panel/components/sections/collection/header/DisplayMode.svelte +69 -58
- package/dist/panel/components/sections/collection/header/DisplayMode.svelte.d.ts +0 -1
- package/dist/panel/components/sections/collection/header/FilterMenu.svelte +60 -0
- package/dist/panel/components/sections/collection/header/FilterMenu.svelte.d.ts +14 -0
- package/dist/panel/components/sections/collection/header/SearchInput.svelte +17 -26
- package/dist/panel/components/sections/collection/header/SelectUI.svelte +19 -34
- package/dist/panel/components/sections/collection/list/CollectionList.svelte +99 -68
- package/dist/panel/components/sections/collection/list/columns.d.ts +21 -0
- package/dist/panel/components/sections/collection/list/columns.js +23 -0
- package/dist/panel/components/sections/collection/list/header/Header.svelte +99 -51
- package/dist/panel/components/sections/collection/list/row/Row.svelte +165 -82
- package/dist/panel/components/sections/collection/list/row/Row.svelte.d.ts +4 -0
- package/dist/panel/components/sections/collection/tree/CollectionTree.svelte +92 -44
- package/dist/panel/components/sections/collection/tree/CollectionTree.svelte.d.ts +1 -0
- package/dist/panel/components/sections/collection/tree/CollectionTreeNode.svelte +139 -43
- package/dist/panel/components/sections/collection/tree/CollectionTreeNode.svelte.d.ts +2 -0
- package/dist/panel/components/sections/collection/upload-thumb-cell/UploadThumbCell.svelte +1 -1
- package/dist/panel/components/sections/commands/CommandButton.svelte +99 -0
- package/dist/panel/components/sections/commands/CommandButton.svelte.d.ts +10 -0
- package/dist/panel/components/sections/commands/CommandPalette.svelte +275 -0
- package/dist/panel/components/sections/commands/CommandPalette.svelte.d.ts +8 -0
- package/dist/panel/components/sections/commands/Commands.svelte +18 -0
- package/dist/panel/components/sections/commands/Commands.svelte.d.ts +9 -0
- package/dist/panel/components/sections/document/AuthAPIKeyDialog.svelte +23 -7
- package/dist/panel/components/sections/document/AuthFooter.svelte +31 -12
- package/dist/panel/components/sections/document/AutoSaveBanner.svelte +24 -7
- package/dist/panel/components/sections/document/ButtonSave.svelte +32 -21
- package/dist/panel/components/sections/document/ButtonSave.svelte.d.ts +5 -5
- package/dist/panel/components/sections/document/ButtonStatus.svelte +68 -20
- package/dist/panel/components/sections/document/ChangeSlugDialog.svelte +199 -0
- package/dist/panel/components/sections/document/ChangeSlugDialog.svelte.d.ts +10 -0
- package/dist/panel/components/sections/document/CurrentlyEdited.svelte +2 -2
- package/dist/panel/components/sections/document/Document.svelte +96 -65
- package/dist/panel/components/sections/document/DocumentChildren.svelte +175 -0
- package/dist/panel/components/sections/document/DocumentChildren.svelte.d.ts +8 -0
- package/dist/panel/components/sections/document/DocumentUrl.svelte +119 -0
- package/dist/panel/components/sections/document/DocumentUrl.svelte.d.ts +9 -0
- package/dist/panel/components/sections/document/Header.svelte +171 -94
- package/dist/panel/components/sections/document/Settings.svelte +255 -110
- package/dist/panel/components/sections/document/Settings.svelte.d.ts +0 -1
- package/dist/panel/components/sections/document/Versions.svelte +5 -3
- package/dist/panel/components/sections/document/upload-header/UploadHeader.svelte +112 -53
- package/dist/panel/components/sections/document/upload-header/UploadHeader.svelte.d.ts +2 -2
- package/dist/panel/components/sections/document/upload-header/drop-zone/DropZone.svelte +74 -41
- package/dist/panel/components/sections/document/upload-header/drop-zone/DropZone.svelte.d.ts +1 -1
- package/dist/panel/components/sections/live/LiveEdit.svelte +2 -2
- package/dist/panel/components/sections/live/LiveFloatingUI.svelte +30 -11
- package/dist/panel/components/sections/live/live-edit-panel.css +2 -2
- package/dist/panel/components/sections/page-layout/Page.svelte +13 -1
- package/dist/panel/components/ui/breadcrumb/BreadCrumb.svelte +55 -27
- package/dist/panel/components/ui/button/button.svelte +81 -54
- package/dist/panel/components/ui/button/index.d.ts +7 -3
- package/dist/panel/components/ui/button/index.js +2 -2
- package/dist/panel/components/ui/calendar/calendar.css +27 -27
- package/dist/panel/components/ui/calendar/calendar.svelte.d.ts +1 -1
- package/dist/panel/components/ui/card/card-description.svelte +1 -1
- package/dist/panel/components/ui/card/card.svelte +21 -4
- package/dist/panel/components/ui/card-document/card-document.svelte +24 -12
- package/dist/panel/components/ui/card-resource/card-resource.svelte +26 -8
- package/dist/panel/components/ui/checkbox/checkbox.css +8 -10
- package/dist/panel/components/ui/command/command-dialog.css +28 -4
- package/dist/panel/components/ui/command/command-dialog.svelte +4 -1
- package/dist/panel/components/ui/command/command-dialog.svelte.d.ts +2 -0
- package/dist/panel/components/ui/command/command-empty.css +1 -1
- package/dist/panel/components/ui/command/command-group.css +3 -3
- package/dist/panel/components/ui/command/command-input-select.svelte +3 -3
- package/dist/panel/components/ui/command/command-input.svelte +38 -14
- package/dist/panel/components/ui/command/command-input.svelte.d.ts +6 -1
- package/dist/panel/components/ui/command/command-item.css +2 -2
- package/dist/panel/components/ui/command/command-list.css +1 -1
- package/dist/panel/components/ui/command/command-separator.css +1 -1
- package/dist/panel/components/ui/context-menu/context-menu-item.css +2 -2
- package/dist/panel/components/ui/context-menu/context-menu.css +6 -7
- package/dist/panel/components/ui/dialog/dialog-content.css +8 -10
- package/dist/panel/components/ui/dialog/dialog-content.svelte +19 -0
- package/dist/panel/components/ui/dialog/dialog-description.css +1 -1
- package/dist/panel/components/ui/dialog/dialog-footer.svelte +5 -1
- package/dist/panel/components/ui/dialog/dialog-overlay.css +1 -1
- package/dist/panel/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +19 -5
- package/dist/panel/components/ui/dropdown-menu/dropdown-menu-content.css +6 -4
- package/dist/panel/components/ui/dropdown-menu/dropdown-menu-item.css +1 -1
- package/dist/panel/components/ui/dropdown-menu/dropdown-menu-radio-item.css +1 -1
- package/dist/panel/components/ui/dropdown-menu/dropdown-menu-separator.css +1 -1
- package/dist/panel/components/ui/input/input.svelte +57 -31
- package/dist/panel/components/ui/kbd/Kbd.svelte +90 -0
- package/dist/panel/components/ui/kbd/Kbd.svelte.d.ts +11 -0
- package/dist/panel/components/ui/kbd/index.d.ts +1 -0
- package/dist/panel/components/ui/kbd/index.js +1 -0
- package/dist/panel/components/ui/label/label.css +5 -3
- package/dist/panel/components/ui/language-switcher/LanguageSwitcher.svelte +27 -15
- package/dist/panel/components/ui/nav/Nav.svelte +180 -110
- package/dist/panel/components/ui/nav/Nav.svelte.d.ts +0 -2
- package/dist/panel/components/ui/nav/NavGroup.svelte +87 -73
- package/dist/panel/components/ui/nav/NavItemButton.svelte +69 -29
- package/dist/panel/components/ui/nav/UserButton.svelte +132 -71
- package/dist/panel/components/ui/page-header/PageHeader.svelte +140 -42
- package/dist/panel/components/ui/page-header/PageHeader.svelte.d.ts +8 -1
- package/dist/panel/components/ui/popover/popover-content.css +4 -3
- package/dist/panel/components/ui/radio-group/radio-group.css +4 -6
- package/dist/panel/components/ui/radio-row-group/radio-row-group.css +19 -7
- package/dist/panel/components/ui/scroll-area/scroll-area.css +2 -2
- package/dist/panel/components/ui/separator/separator.svelte +1 -1
- package/dist/panel/components/ui/sheet/index.d.ts +4 -4
- package/dist/panel/components/ui/sheet/index.js +5 -5
- package/dist/panel/components/ui/sheet/sheet.css +50 -11
- package/dist/panel/components/ui/sonner/sonner.css +11 -8
- package/dist/panel/components/ui/switch/switch.css +13 -18
- package/dist/panel/components/ui/tabs/tabs.css +44 -35
- package/dist/panel/components/ui/tag/tag.svelte +20 -6
- package/dist/panel/components/ui/tooltip/tooltip-content.svelte +14 -4
- package/dist/panel/components/ui/tree/tree-rows.css +146 -0
- package/dist/panel/context/blocks-ops.d.ts +78 -0
- package/dist/panel/context/blocks-ops.js +170 -0
- package/dist/panel/context/collection.svelte.d.ts +28 -0
- package/dist/panel/context/collection.svelte.js +120 -65
- package/dist/panel/context/commands.svelte.d.ts +80 -0
- package/dist/panel/context/commands.svelte.js +108 -0
- package/dist/panel/context/documentForm.svelte.d.ts +34 -2
- package/dist/panel/context/documentForm.svelte.js +105 -102
- package/dist/panel/context/live.svelte.js +2 -73
- package/dist/panel/context/nav.svelte.d.ts +23 -0
- package/dist/panel/context/nav.svelte.js +56 -0
- package/dist/panel/fonts/Geist-VariableFont_wght.ttf +0 -0
- package/dist/panel/fonts/GeistMono-VariableFont_wght.ttf +0 -0
- package/dist/panel/index.d.ts +7 -1
- package/dist/panel/index.js +10 -1
- package/dist/panel/pages/auth/forgot-password/ForgotPassword.svelte +16 -1
- package/dist/panel/pages/collection/CollectionPage.svelte +236 -61
- package/dist/panel/pages/collection/load.server.js +1 -1
- package/dist/panel/pages/dashboard/Dashboard.svelte +135 -90
- package/dist/panel/pages/dashboard/DashboardCard.svelte +109 -0
- package/dist/panel/pages/dashboard/DashboardCard.svelte.d.ts +14 -0
- package/dist/panel/pages/dashboard/DashboardCollection.svelte +180 -57
- package/dist/panel/pages/dashboard/DashboardCollection.svelte.d.ts +1 -0
- package/dist/panel/pages/dashboard/DashboardRow.svelte +93 -0
- package/dist/panel/pages/dashboard/DashboardRow.svelte.d.ts +16 -0
- package/dist/panel/pages/dashboard/load.server.js +49 -25
- package/dist/panel/pages/dashboard/time.d.ts +19 -0
- package/dist/panel/pages/dashboard/time.js +29 -0
- package/dist/panel/pages/dashboard/types.d.ts +9 -2
- package/dist/panel/pages/live/Live.svelte +53 -50
- package/dist/panel/style/font.css +21 -32
- package/dist/panel/style/index.css +191 -122
- package/dist/panel/style/mixins/index.css +14 -0
- package/dist/panel/style/palette.css +35 -26
- package/dist/panel/style/postcss/size-function.d.ts +4 -0
- package/dist/panel/style/postcss/size-function.js +24 -0
- package/dist/panel/style/radius.css +4 -5
- package/dist/panel/style/scheme.css +111 -0
- package/dist/panel/style/size.css +3 -0
- package/dist/panel/util/Sortable.js +9 -4
- package/dist/panel/util/keys.d.ts +24 -0
- package/dist/panel/util/keys.js +63 -0
- package/dist/panel/util/populate.d.ts +8 -0
- package/dist/panel/util/populate.js +49 -0
- package/dist/panel/util/time.d.ts +12 -0
- package/dist/panel/util/time.js +35 -0
- package/dist/panel/util/upload-file.d.ts +106 -0
- package/dist/panel/util/upload-file.js +165 -0
- package/dist/util/index.d.ts +7 -10
- package/dist/util/index.js +7 -8
- package/dist/util/object.d.ts +10 -0
- package/dist/util/object.js +22 -1
- package/dist/util/string.d.ts +17 -0
- package/dist/util/string.js +23 -0
- package/package.json +1 -3
- package/dist/core/pipeline/config-map/build-tree-map.d.ts +0 -4
- package/dist/core/pipeline/config-map/build-tree-map.js +0 -30
- package/dist/core/prototype/doc.d.ts +0 -31
- package/dist/core/prototype/doc.js +0 -118
- package/dist/core/prototype/shared/url/augment.d.ts +0 -13
- package/dist/core/prototype/shared/url/augment.js +0 -11
- package/dist/core/prototype/shared/url/hooks/populate-url.server.d.ts +0 -4
- package/dist/core/prototype/shared/url/hooks/populate-url.server.js +0 -120
- package/dist/fields/rich-text/component/styles/rich-text.css +0 -183
- package/dist/panel/components/sections/collection/header/Header.svelte +0 -17
- package/dist/panel/components/sections/collection/header/Header.svelte.d.ts +0 -3
- package/dist/panel/components/sections/collection/header/Separator.svelte +0 -8
- package/dist/panel/components/sections/collection/header/Separator.svelte.d.ts +0 -26
- package/dist/panel/components/sections/collection/tree/util.d.ts +0 -12
- package/dist/panel/components/sections/collection/tree/util.js +0 -22
- package/dist/panel/fonts/ChivoMono-Italic-VariableFont_wght.ttf +0 -0
- package/dist/panel/fonts/ChivoMono-VariableFont_wght.ttf +0 -0
- package/dist/panel/fonts/Inter-VariableFont_slnt,wght.ttf +0 -0
- package/dist/panel/fonts/Lora-Italic-VariableFont_wght.ttf +0 -0
- package/dist/panel/fonts/Lora-VariableFont_wght.ttf +0 -0
- package/dist/panel/style/shadow.css +0 -10
- package/dist/util/path.d.ts +0 -16
- package/dist/util/path.js +0 -19
|
@@ -1,7 +1,46 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
password: 'mot de passe',
|
|
3
3
|
write_something: 'Écrivez quelque chose...',
|
|
4
|
+
write_or_slash: 'Écrivez, ou tapez / pour insérer…',
|
|
4
5
|
new_tab: 'Nouvel onglet',
|
|
6
|
+
link_url: 'URL',
|
|
7
|
+
link_email: 'E-mail',
|
|
8
|
+
link_tel: 'Téléphone',
|
|
9
|
+
link_anchor: 'Ancre',
|
|
10
|
+
focus: 'Focus',
|
|
11
|
+
add: 'Ajouter',
|
|
12
|
+
block: 'Bloc',
|
|
13
|
+
paste_after: 'Coller après',
|
|
14
|
+
exit_focus: 'Quitter le focus',
|
|
15
|
+
inspector: 'Inspecteur',
|
|
16
|
+
pick_a_block: 'Sélectionnez un bloc pour le modifier.',
|
|
17
|
+
selected_count: '$1 sélectionné(s)',
|
|
18
|
+
done: 'Terminé',
|
|
19
|
+
choose_media: 'Choisir un média',
|
|
20
|
+
choose_medias: 'Choisir des médias',
|
|
21
|
+
edit_selection: 'Modifier la sélection',
|
|
22
|
+
replace: 'Remplacer',
|
|
23
|
+
remove: 'Retirer',
|
|
24
|
+
layers: 'Calques',
|
|
25
|
+
blocks: 'Blocs',
|
|
26
|
+
search_blocks: 'Rechercher un bloc…',
|
|
27
|
+
picker_add: 'pour ajouter',
|
|
28
|
+
blocks_count: '$1 {bloc|bloc|blocs|blocs}',
|
|
29
|
+
no_blocks_yet: 'Aucun bloc pour l’instant. Ajoutez-en un à droite, ou avec ⌘K.',
|
|
30
|
+
no_blocks_yet_render: 'Aucun bloc pour l’instant. Ajoutez-en un avec ⌘K.',
|
|
31
|
+
render_failed: 'Le rendu de ce bloc a échoué.',
|
|
32
|
+
go_to: 'Aller à',
|
|
33
|
+
move_up: 'Monter',
|
|
34
|
+
move_down: 'Descendre',
|
|
35
|
+
move_into: 'Déplacer dans $1',
|
|
36
|
+
copy_block: 'Copier',
|
|
37
|
+
paste_block: 'Coller',
|
|
38
|
+
paste_refused: 'Rien à coller ici',
|
|
39
|
+
collapse_all: 'Tout replier',
|
|
40
|
+
expand_all: 'Tout déplier',
|
|
41
|
+
edit: 'Modifier',
|
|
42
|
+
remove_with_children_title: 'Supprimer ce bloc ?',
|
|
43
|
+
remove_with_children_text: 'Les blocs qu’il contient partent avec lui.',
|
|
5
44
|
add_block: 'Ajouter un bloc',
|
|
6
45
|
no_block: 'Aucun bloc',
|
|
7
46
|
delete_block: 'Supprimer le bloc',
|
|
@@ -10,5 +49,34 @@ export default {
|
|
|
10
49
|
get_data_from: 'Importer les données',
|
|
11
50
|
filter_by_type: 'Filtrer par type',
|
|
12
51
|
all_types: 'Tous les types',
|
|
13
|
-
select: 'Sélectionner'
|
|
52
|
+
select: 'Sélectionner',
|
|
53
|
+
choose_from_library: 'Choisir dans la médiathèque',
|
|
54
|
+
choose_in_library: 'choisissez dans la médiathèque',
|
|
55
|
+
upload: 'Importer',
|
|
56
|
+
uploading: 'Import de $1 sur $2…',
|
|
57
|
+
upload_progress: '$1 sur $2 importé(s)',
|
|
58
|
+
upload_failed: 'Non importé(s) : $1',
|
|
59
|
+
clear: 'Effacer',
|
|
60
|
+
add_images: 'Ajouter $1 {image|image|images|images}',
|
|
61
|
+
add_files: 'Ajouter $1 {fichier|fichier|fichiers|fichiers}',
|
|
62
|
+
remove_item: 'Retirer $1',
|
|
63
|
+
open_editor: 'Ouvrir l’éditeur',
|
|
64
|
+
open_in_editor: 'Ouvrir dans l’éditeur',
|
|
65
|
+
add_a_block: 'Ajouter un bloc',
|
|
66
|
+
block_actions: 'Actions du bloc',
|
|
67
|
+
fold: 'Replier',
|
|
68
|
+
unfold: 'Déplier',
|
|
69
|
+
item_actions: 'Actions de l’élément',
|
|
70
|
+
delete_item: 'Supprimer l’élément',
|
|
71
|
+
inside: 'Dans $1',
|
|
72
|
+
nothing_inside: 'Rien dedans pour l’instant : déposez un élément ici, ou ajoutez-en un.',
|
|
73
|
+
type_to_add_block: 'Tapez $1 pour ajouter un bloc',
|
|
74
|
+
slug_hint: 'Lettres minuscules, chiffres et tirets.',
|
|
75
|
+
build_from: 'Le générer depuis le champ $1',
|
|
76
|
+
choose: 'Choisir…',
|
|
77
|
+
nothing_to_select: 'Pas de $1 à sélectionner',
|
|
78
|
+
file_name: 'Nom du fichier',
|
|
79
|
+
file_size: 'Taille',
|
|
80
|
+
file_type: 'Type',
|
|
81
|
+
select_date: 'Choisir une date'
|
|
14
82
|
};
|
|
@@ -5,9 +5,35 @@ export type Namespace = (typeof namespaces)[number];
|
|
|
5
5
|
export type Dictionaries = Record<string, Record<string, string>>;
|
|
6
6
|
export type TranslationKey = `${Namespace}.${string}`;
|
|
7
7
|
export type ModifiedKey = `${TranslationKey}|${'m' | 'f'}` | `${TranslationKey}|${'m' | 'f'}|p`;
|
|
8
|
+
export type Translate = (key: TranslationKey | ModifiedKey | string, ...params: string[]) => string;
|
|
9
|
+
/** A translator over one set of dictionaries. */
|
|
10
|
+
export type I18n = {
|
|
11
|
+
t__: Translate;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* A translator over the dictionaries it is given, sharing nothing with any other.
|
|
15
|
+
*
|
|
16
|
+
* Dictionaries are keyed by namespace, then by key. A key whose namespace or entry is not there
|
|
17
|
+
* comes back as is. `$1`, `$2`… take the parameters in order. A `{he|she|they|they}` variant in
|
|
18
|
+
* a text is picked by the modifiers on the key: `|m`, `|f`, `|m|p`, `|f|p`.
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* const { t__ } = createI18n({ site: { hello: 'Hello $1', more: 'more' } });
|
|
22
|
+
* t__('site.hello', 'Ada') // 'Hello Ada'
|
|
23
|
+
* t__('shop.more') // 'shop.more'
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* A function reads the dictionaries on every call. In a Svelte component, a function over `data`
|
|
27
|
+
* follows a locale switch on its own:
|
|
28
|
+
*
|
|
29
|
+
* ```ts
|
|
30
|
+
* setI18nContext(createI18n(() => data.dictionary));
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare function createI18n(source?: Dictionaries | (() => Dictionaries)): I18n;
|
|
8
34
|
declare const i18n: {
|
|
9
|
-
init: (
|
|
10
|
-
t__:
|
|
35
|
+
init: (loaded: Partial<Dictionaries>) => void;
|
|
36
|
+
t__: Translate;
|
|
11
37
|
};
|
|
12
|
-
export declare const t__:
|
|
38
|
+
export declare const t__: Translate;
|
|
13
39
|
export default i18n;
|
package/dist/core/i18n/index.js
CHANGED
|
@@ -1,12 +1,32 @@
|
|
|
1
1
|
export const languages = ['fr', 'en'];
|
|
2
2
|
export const namespaces = ['errors', 'fields', 'common', 'mail'];
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* A translator over the dictionaries it is given, sharing nothing with any other.
|
|
5
|
+
*
|
|
6
|
+
* Dictionaries are keyed by namespace, then by key. A key whose namespace or entry is not there
|
|
7
|
+
* comes back as is. `$1`, `$2`… take the parameters in order. A `{he|she|they|they}` variant in
|
|
8
|
+
* a text is picked by the modifiers on the key: `|m`, `|f`, `|m|p`, `|f|p`.
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* const { t__ } = createI18n({ site: { hello: 'Hello $1', more: 'more' } });
|
|
12
|
+
* t__('site.hello', 'Ada') // 'Hello Ada'
|
|
13
|
+
* t__('shop.more') // 'shop.more'
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* A function reads the dictionaries on every call. In a Svelte component, a function over `data`
|
|
17
|
+
* follows a locale switch on its own:
|
|
18
|
+
*
|
|
19
|
+
* ```ts
|
|
20
|
+
* setI18nContext(createI18n(() => data.dictionary));
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export function createI18n(source = {}) {
|
|
24
|
+
const read = typeof source === 'function' ? source : () => source;
|
|
5
25
|
const templateCache = new Map();
|
|
6
26
|
const compileTemplate = (text) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
27
|
+
const cached = templateCache.get(text);
|
|
28
|
+
if (cached)
|
|
29
|
+
return cached;
|
|
10
30
|
const compiled = (gender, plural) => {
|
|
11
31
|
return text.replace(/\{([^}]+)\}/g, (_, options) => {
|
|
12
32
|
const variants = options.split('|');
|
|
@@ -24,35 +44,41 @@ function createI18n() {
|
|
|
24
44
|
return compiled;
|
|
25
45
|
};
|
|
26
46
|
const t__ = (key, ...params) => {
|
|
27
|
-
const isNamespacedKey = namespaces.some((ns) => key.startsWith(`${ns}.`));
|
|
28
|
-
if (!isNamespacedKey) {
|
|
29
|
-
return key;
|
|
30
|
-
}
|
|
31
47
|
const [baseKey, gender, plural] = key.split('|');
|
|
32
|
-
const
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const resolved =
|
|
48
|
+
const dot = baseKey.indexOf('.');
|
|
49
|
+
if (dot === -1)
|
|
50
|
+
return key;
|
|
51
|
+
const text = read()[baseKey.slice(0, dot)]?.[baseKey.slice(dot + 1)];
|
|
52
|
+
if (text === undefined)
|
|
53
|
+
return key;
|
|
54
|
+
const resolved = compileTemplate(text)(gender, plural);
|
|
39
55
|
return resolved.replace(/\$(\d+)/g, (_, index) => params[index - 1] ?? '');
|
|
40
56
|
};
|
|
41
|
-
|
|
42
|
-
|
|
57
|
+
return { t__ };
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The panel's translator, in the panel language the config names.
|
|
61
|
+
*
|
|
62
|
+
* On the server, one instance for the whole process, filled once at boot. In the browser, one per
|
|
63
|
+
* tab, filled by the panel's root layout. An app's own texts go through `createI18n`: feeding
|
|
64
|
+
* this one from a layout would translate the panel for everyone in the language of the last
|
|
65
|
+
* request.
|
|
66
|
+
*/
|
|
67
|
+
function createPanelI18n() {
|
|
68
|
+
let dictionaries = {};
|
|
69
|
+
const { t__ } = createI18n(() => dictionaries);
|
|
70
|
+
const init = (loaded) => {
|
|
71
|
+
dictionaries = loaded;
|
|
43
72
|
};
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
73
|
+
const translate = (key, ...params) => {
|
|
74
|
+
const namespace = key.split('|')[0].split('.')[0];
|
|
75
|
+
if (namespaces.includes(namespace) && !dictionaries[namespace]) {
|
|
76
|
+
console.warn(`Namespace ${namespace} not loaded`);
|
|
77
|
+
}
|
|
78
|
+
return t__(key, ...params);
|
|
47
79
|
};
|
|
80
|
+
return { init, t__: translate };
|
|
48
81
|
}
|
|
49
|
-
|
|
50
|
-
const getInstance = () => {
|
|
51
|
-
if (instance)
|
|
52
|
-
return instance;
|
|
53
|
-
instance = createI18n();
|
|
54
|
-
return instance;
|
|
55
|
-
};
|
|
56
|
-
const i18n = getInstance();
|
|
82
|
+
const i18n = createPanelI18n();
|
|
57
83
|
export const t__ = i18n.t__;
|
|
58
84
|
export default i18n;
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { buildConfigMap } from '../pipeline/config-map/index.js';
|
|
2
|
-
import { BlocksBuilder } from '../../fields/blocks/index.js';
|
|
3
|
-
import { TreeBuilder } from '../../fields/tree/index.js';
|
|
4
2
|
import { getValueAtPath, isObjectLiteral, matchStructure, omitId, setValueAtPath } from '../../util/object.js';
|
|
5
3
|
/**
|
|
6
4
|
* Copies the other locales of one row onto another, as `duplicate` does for a copy and
|
|
@@ -39,14 +37,16 @@ export const copyLocales = async (args) => {
|
|
|
39
37
|
const written = Object.entries(configMap).some(([key, field]) => field.get.localized && !field.use.isEmpty(getValueAtPath(key, data)));
|
|
40
38
|
if (!written)
|
|
41
39
|
continue;
|
|
40
|
+
// Only the fields stored as rows of their own carry ids to keep or drop.
|
|
42
41
|
for (const [key, field] of Object.entries(configMap)) {
|
|
43
|
-
if (!(
|
|
42
|
+
if (!field.use.nodes().some((node) => node.storage))
|
|
44
43
|
continue;
|
|
45
44
|
if (field.get.localized) {
|
|
46
45
|
const value = (getValueAtPath(key, data) ?? []).map((block) => omitId(block));
|
|
47
46
|
data = setValueAtPath(key, data, value);
|
|
48
47
|
continue;
|
|
49
48
|
}
|
|
49
|
+
// A tree row has no type; a block keeps its id only across the same type.
|
|
50
50
|
const sameType = (a, b) => field.type === 'tree' || a.type === b.type;
|
|
51
51
|
const targetBlocks = getValueAtPath(key, target.doc) ?? [];
|
|
52
52
|
targetBlocks.forEach((block, index) => {
|
|
@@ -43,8 +43,14 @@ const formatMessage = (args) => {
|
|
|
43
43
|
/**
|
|
44
44
|
* Clean up old log files that exceed the maximum retention period
|
|
45
45
|
*/
|
|
46
|
+
// The cleanup lists the log directory; once an hour is plenty, once a line was every request.
|
|
47
|
+
const CLEANUP_INTERVAL_MS = 60 * 60 * 1000;
|
|
48
|
+
let lastCleanup = 0;
|
|
49
|
+
|
|
46
50
|
const cleanupOldLogs = async () => {
|
|
47
51
|
if (!LOG_TO_FILE) return;
|
|
52
|
+
if (Date.now() - lastCleanup < CLEANUP_INTERVAL_MS) return;
|
|
53
|
+
lastCleanup = Date.now();
|
|
48
54
|
|
|
49
55
|
try {
|
|
50
56
|
// Create logs directory if it doesn't exist
|
|
@@ -129,13 +135,16 @@ const isLevelEnabled = (level) => {
|
|
|
129
135
|
return level >= currentLogLevel;
|
|
130
136
|
};
|
|
131
137
|
|
|
138
|
+
// One formatter, built once: `toLocaleTimeString` with options builds one per call.
|
|
139
|
+
const localTime = new Intl.DateTimeFormat(undefined, {
|
|
140
|
+
hour: 'numeric',
|
|
141
|
+
minute: '2-digit',
|
|
142
|
+
second: '2-digit',
|
|
143
|
+
hour12: true
|
|
144
|
+
});
|
|
145
|
+
|
|
132
146
|
function getFormattedLocalTime(date) {
|
|
133
|
-
return
|
|
134
|
-
hour: 'numeric',
|
|
135
|
-
minute: '2-digit',
|
|
136
|
-
second: '2-digit',
|
|
137
|
-
hour12: true
|
|
138
|
-
});
|
|
147
|
+
return localTime.format(date);
|
|
139
148
|
}
|
|
140
149
|
|
|
141
150
|
const rimeFormatted = chalk.bold(chalk.gray('[rime]'));
|
|
@@ -2,6 +2,7 @@ import type { DocumentRows } from '../adapter.js';
|
|
|
2
2
|
import type { BuiltArea, BuiltCollection } from '../config/types.js';
|
|
3
3
|
import type { GenericDoc } from '../prototype/types.js';
|
|
4
4
|
import type { RequestEvent } from '@sveltejs/kit';
|
|
5
|
+
import { type Populated } from './populate-relations.server.js';
|
|
5
6
|
/**
|
|
6
7
|
* Assembles one document out of the rows it is stored across.
|
|
7
8
|
*
|
|
@@ -15,6 +16,8 @@ export declare const buildDocument: <T extends GenericDoc = GenericDoc>(rows: Do
|
|
|
15
16
|
event: RequestEvent;
|
|
16
17
|
locale?: string | undefined;
|
|
17
18
|
depth?: number;
|
|
19
|
+
/** What the relations point at, read ahead for the whole list. Read when `depth > 0`. */
|
|
20
|
+
populated?: Populated;
|
|
18
21
|
/** Merge the blank document, so every field the config declares is present. */
|
|
19
22
|
withBlank?: boolean;
|
|
20
23
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { isObjectLiteral, omit } from '../../util/object.js';
|
|
2
|
-
import deepmerge from 'deepmerge';
|
|
1
|
+
import { isObjectLiteral, omit, withDefaults } from '../../util/object.js';
|
|
3
2
|
import { unflatten } from 'flat';
|
|
4
3
|
import { logger } from '../logger.server.js';
|
|
4
|
+
import { populatedKey } from './populate-relations.server.js';
|
|
5
5
|
/**
|
|
6
6
|
* Assembles one document out of the rows it is stored across.
|
|
7
7
|
*
|
|
@@ -11,7 +11,7 @@ import { logger } from '../logger.server.js';
|
|
|
11
11
|
* happens to them from here is a question about documents.
|
|
12
12
|
*/
|
|
13
13
|
export const buildDocument = async (rows, args) => {
|
|
14
|
-
const { config, event, locale, depth = 0, withBlank = true, withRowMeta = false } = args;
|
|
14
|
+
const { config, event, locale, depth = 0, populated, withBlank = true, withRowMeta = false } = args;
|
|
15
15
|
const { rime } = event.locals;
|
|
16
16
|
const flatDoc = { ...rows.base };
|
|
17
17
|
for (const block of rows.blocks) {
|
|
@@ -40,9 +40,12 @@ export const buildDocument = async (rows, args) => {
|
|
|
40
40
|
}
|
|
41
41
|
let output;
|
|
42
42
|
if (depth > 0) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
const target = populated?.get(populatedKey(relation.relationTo, relation.locale, relation.documentId));
|
|
44
|
+
// Missing, or not readable by this reader: the relation is left out.
|
|
45
|
+
if (!target)
|
|
46
|
+
continue;
|
|
47
|
+
// A copy per placement: two documents never share an object a hook could change.
|
|
48
|
+
output = structuredClone(target);
|
|
46
49
|
}
|
|
47
50
|
else {
|
|
48
51
|
output = (withRowMeta ? relation : omit(['position', 'ownerId', 'path'], relation));
|
|
@@ -54,7 +57,7 @@ export const buildDocument = async (rows, args) => {
|
|
|
54
57
|
const blank = rime.config.isCollection(config.slug)
|
|
55
58
|
? rime.collection(config.slug).blank()
|
|
56
59
|
: rime.area(config.slug).blank();
|
|
57
|
-
doc =
|
|
60
|
+
doc = withDefaults(doc, blank);
|
|
58
61
|
}
|
|
59
62
|
return doc;
|
|
60
63
|
};
|
|
@@ -3,4 +3,13 @@ import type { GenericDoc } from '../../prototype/types.js';
|
|
|
3
3
|
import type { Field } from '../../../fields/types.js';
|
|
4
4
|
import type { DeepPartial } from '../../../util/types.js';
|
|
5
5
|
import type { ConfigMap } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Every field a document carries, keyed by the path its value sits at.
|
|
8
|
+
*
|
|
9
|
+
* The keys are the on-disk path format, so the block type the walk names is stripped:
|
|
10
|
+
*
|
|
11
|
+
* ```
|
|
12
|
+
* layout.0:hero.title -> layout.0.title
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
6
15
|
export declare const buildConfigMap: (data: DeepPartial<GenericDoc>, incomingFields: FieldBuilder<Field>[]) => ConfigMap;
|
|
@@ -1,54 +1,20 @@
|
|
|
1
1
|
import { isFormField } from '../../fields/util.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import { walkValues } from '../../fields/walk.js';
|
|
3
|
+
import { normalizeFieldPath } from '../../../util/string.js';
|
|
4
|
+
/**
|
|
5
|
+
* Every field a document carries, keyed by the path its value sits at.
|
|
6
|
+
*
|
|
7
|
+
* The keys are the on-disk path format, so the block type the walk names is stripped:
|
|
8
|
+
*
|
|
9
|
+
* ```
|
|
10
|
+
* layout.0:hero.title -> layout.0.title
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
7
13
|
export const buildConfigMap = (data, incomingFields) => {
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
if (
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
for (const field of fields) {
|
|
14
|
-
if (field instanceof TabsBuilder) {
|
|
15
|
-
for (const tab of field.get.tabs) {
|
|
16
|
-
if (tab.name in data) {
|
|
17
|
-
traverseData(data[tab.name], tab.get.fields, tab.name);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
continue;
|
|
21
|
-
}
|
|
22
|
-
if (!isFormField(field))
|
|
23
|
-
continue;
|
|
24
|
-
if (!(field.name in data))
|
|
25
|
-
continue;
|
|
26
|
-
const value = data[field.name];
|
|
27
|
-
const path = `${basePath}${field.name}`;
|
|
28
|
-
map[path] = field;
|
|
29
|
-
if (field instanceof BlocksBuilder && value && Array.isArray(value)) {
|
|
30
|
-
const blocks = value;
|
|
31
|
-
for (const [index, block] of blocks.entries()) {
|
|
32
|
-
try {
|
|
33
|
-
const blockConfig = field.get.blocks.find((b) => b.name === block.type);
|
|
34
|
-
if (blockConfig) {
|
|
35
|
-
traverseData(block, blockConfig.get.fields, `${path}.${index}`);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
catch {
|
|
39
|
-
console.warn(`block at path ${path} and postition ${index} not found but there are some residual data owned by this block`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
else if (field instanceof TreeBuilder && value && Array.isArray(value)) {
|
|
44
|
-
const treeMap = buildTreeFieldsMap(field, value, path);
|
|
45
|
-
map = { ...map, ...treeMap };
|
|
46
|
-
}
|
|
47
|
-
else if (field instanceof GroupFieldBuilder) {
|
|
48
|
-
traverseData(value, field.get.fields, path);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
traverseData(data, incomingFields, '');
|
|
14
|
+
const map = {};
|
|
15
|
+
for (const { field, path } of walkValues(incomingFields, data)) {
|
|
16
|
+
if (isFormField(field))
|
|
17
|
+
map[normalizeFieldPath(path)] = field;
|
|
18
|
+
}
|
|
53
19
|
return map;
|
|
54
20
|
};
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Walks every field of the document on the way out: drops what the reader may not see, fills an
|
|
3
3
|
* empty one from its default, and hands each value to the field's own `hooks.beforeRead`.
|
|
4
|
+
*
|
|
5
|
+
* One copy of the document, walked in place. A config-map key is already normalized, so it is
|
|
6
|
+
* its segments and nothing else; a copy of the document per key was most of this hook.
|
|
4
7
|
*/
|
|
5
8
|
export declare const processDocumentFields: import("../types.js").Hook<"raw", "read", "before">;
|
|
@@ -1,31 +1,35 @@
|
|
|
1
1
|
import { Hooks } from '../define-hook.js';
|
|
2
2
|
import { logger } from '../../logger.server.js';
|
|
3
|
-
import { deleteValueAtPath, getValueAtPath, setValueAtPath } from '../../../util/object.js';
|
|
4
3
|
import { buildConfigMap } from '../config-map/index.js';
|
|
5
4
|
import { getDefaultValue } from './set-default-values.server.js';
|
|
6
5
|
/**
|
|
7
6
|
* Walks every field of the document on the way out: drops what the reader may not see, fills an
|
|
8
7
|
* empty one from its default, and hands each value to the field's own `hooks.beforeRead`.
|
|
8
|
+
*
|
|
9
|
+
* One copy of the document, walked in place. A config-map key is already normalized, so it is
|
|
10
|
+
* its segments and nothing else; a copy of the document per key was most of this hook.
|
|
9
11
|
*/
|
|
10
12
|
export const processDocumentFields = Hooks.beforeRead(async function processDocumentFields(args) {
|
|
11
13
|
const { event } = args;
|
|
12
|
-
|
|
14
|
+
const doc = { ...args.doc };
|
|
13
15
|
const configMap = buildConfigMap(doc, args.config.fields);
|
|
14
16
|
for (const [key, config] of Object.entries(configMap)) {
|
|
15
|
-
|
|
16
|
-
let isEmpty;
|
|
17
|
+
const parts = key.split('.');
|
|
17
18
|
if (!config.use.accessRead(event.locals.user)) {
|
|
18
|
-
|
|
19
|
+
deleteAt(doc, parts);
|
|
19
20
|
continue;
|
|
20
21
|
}
|
|
21
|
-
|
|
22
|
+
let value = getAt(doc, parts);
|
|
23
|
+
// A field with no hook has nothing to wait for.
|
|
24
|
+
if (value !== undefined && value !== null && config.get.hooks?.beforeRead?.length) {
|
|
22
25
|
value = await config.use.beforeRead(value, {
|
|
23
26
|
event,
|
|
24
27
|
operation: args.context,
|
|
25
28
|
documentId: doc.id
|
|
26
29
|
});
|
|
27
|
-
doc
|
|
30
|
+
setAt(doc, parts, value);
|
|
28
31
|
}
|
|
32
|
+
let isEmpty;
|
|
29
33
|
try {
|
|
30
34
|
isEmpty = config.use.isEmpty(value);
|
|
31
35
|
}
|
|
@@ -35,10 +39,10 @@ export const processDocumentFields = Hooks.beforeRead(async function processDocu
|
|
|
35
39
|
}
|
|
36
40
|
if (isEmpty && config.get.defaultValue !== undefined) {
|
|
37
41
|
value = await getDefaultValue({ key, config, adapter: args.event.locals.rime.adapter });
|
|
38
|
-
doc
|
|
42
|
+
setAt(doc, parts, value);
|
|
39
43
|
}
|
|
40
44
|
if (config.type === 'blocks') {
|
|
41
|
-
const
|
|
45
|
+
const blocks = getAt(doc, parts);
|
|
42
46
|
// Filter out possible undefined block or residual
|
|
43
47
|
// Case undefined : When in dev mode, if a block table is deleted in a migration, a blocks array value could includes undefined ex :
|
|
44
48
|
// * blocks: [ { ... }, undefined, { ... } ]
|
|
@@ -47,16 +51,48 @@ export const processDocumentFields = Hooks.beforeRead(async function processDocu
|
|
|
47
51
|
// * blocks: [ { id:..., values,... }, { image: {...}} ]
|
|
48
52
|
// ^
|
|
49
53
|
// * the image has been placed but the block doesn't exist anymore
|
|
50
|
-
if (
|
|
51
|
-
const withoutResidualBlock =
|
|
54
|
+
if (blocks) {
|
|
55
|
+
const withoutResidualBlock = blocks
|
|
52
56
|
.filter((b) => b && 'id' in b) // get only blocks that have .id
|
|
53
57
|
.map((b, index) => ({
|
|
54
58
|
...b,
|
|
55
59
|
position: index
|
|
56
60
|
}));
|
|
57
|
-
doc
|
|
61
|
+
setAt(doc, parts, withoutResidualBlock);
|
|
58
62
|
}
|
|
59
63
|
}
|
|
60
64
|
}
|
|
61
65
|
return { ...args, doc };
|
|
62
66
|
});
|
|
67
|
+
/** The value the segments lead to, `undefined` past a missing one. */
|
|
68
|
+
const getAt = (doc, parts) => {
|
|
69
|
+
let current = doc;
|
|
70
|
+
for (const part of parts) {
|
|
71
|
+
if (current === undefined || current === null)
|
|
72
|
+
return undefined;
|
|
73
|
+
current = current[part];
|
|
74
|
+
}
|
|
75
|
+
return current;
|
|
76
|
+
};
|
|
77
|
+
/** Writes at the segments, opening an object — an array before an index — where one is missing. */
|
|
78
|
+
const setAt = (doc, parts, value) => {
|
|
79
|
+
let current = doc;
|
|
80
|
+
for (let index = 0; index < parts.length - 1; index++) {
|
|
81
|
+
const part = parts[index];
|
|
82
|
+
if (!current[part])
|
|
83
|
+
current[part] = /^\d+$/.test(parts[index + 1]) ? [] : {};
|
|
84
|
+
current = current[part];
|
|
85
|
+
}
|
|
86
|
+
current[parts[parts.length - 1]] = value;
|
|
87
|
+
};
|
|
88
|
+
/** Removes what the segments lead to; nothing, past a missing one. */
|
|
89
|
+
const deleteAt = (doc, parts) => {
|
|
90
|
+
let current = doc;
|
|
91
|
+
for (const part of parts.slice(0, -1)) {
|
|
92
|
+
if (current === undefined || current === null || !(part in current))
|
|
93
|
+
return;
|
|
94
|
+
current = current[part];
|
|
95
|
+
}
|
|
96
|
+
if (current !== undefined && current !== null)
|
|
97
|
+
delete current[parts[parts.length - 1]];
|
|
98
|
+
};
|
|
@@ -12,5 +12,6 @@ type GetDefaultValue = (args: {
|
|
|
12
12
|
config: FormFieldBuilder;
|
|
13
13
|
adapter: Adapter;
|
|
14
14
|
}) => Promise<any>;
|
|
15
|
+
/** A relation's default is ids; they become junction rows, checked against the collection. */
|
|
15
16
|
export declare const getDefaultValue: GetDefaultValue;
|
|
16
17
|
export {};
|
|
@@ -71,6 +71,7 @@ const defaultRelationValue = async (config, key, adapter) => {
|
|
|
71
71
|
};
|
|
72
72
|
return await buildRelation(config.use.defaultValue({ event: getRequestEvent() }));
|
|
73
73
|
};
|
|
74
|
+
/** A relation's default is ids; they become junction rows, checked against the collection. */
|
|
74
75
|
export const getDefaultValue = async ({ key, config, adapter }) => {
|
|
75
76
|
if (config instanceof RelationFieldBuilder) {
|
|
76
77
|
return await defaultRelationValue(config, key, adapter);
|
|
@@ -2,6 +2,8 @@ import { RelationFieldBuilder } from '../../../../fields/relation/index.js';
|
|
|
2
2
|
import { getValueAtPath } from '../../../../util/object.js';
|
|
3
3
|
export const extractRelations = ({ ownerId, data, configMap, locale }) => {
|
|
4
4
|
const relations = [];
|
|
5
|
+
// The config map keys every field the document holds; relations are the ones stored as junction
|
|
6
|
+
// rows, and the key is the `path` those rows carry.
|
|
5
7
|
for (const [path, config] of Object.entries(configMap)) {
|
|
6
8
|
if (config instanceof RelationFieldBuilder) {
|
|
7
9
|
const value = getValueAtPath(path, data);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { DocumentRows } from '../adapter.js';
|
|
2
|
+
import type { GenericDoc } from '../prototype/types.js';
|
|
3
|
+
import type { RequestEvent } from '@sveltejs/kit';
|
|
4
|
+
/**
|
|
5
|
+
* The documents a list's relations point at, keyed by `populatedKey`.
|
|
6
|
+
*
|
|
7
|
+
* Read for one operation, by one reader, and dropped with it.
|
|
8
|
+
*/
|
|
9
|
+
export type Populated = Map<string, GenericDoc>;
|
|
10
|
+
export declare const populatedKey: (slug: string, locale: string | undefined, id: string) => string;
|
|
11
|
+
/**
|
|
12
|
+
* Reads what the relations of a whole list point at, one `findByIds` per collection and locale.
|
|
13
|
+
*
|
|
14
|
+
* ```ts
|
|
15
|
+
* // 20 pages, 2 relations each, 22 distinct targets
|
|
16
|
+
* // 40 × findById -> 1 × findByIds({ ids: [...22] })
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* A relation row keeps its own locale, or none: the target is read in that locale, else in the
|
|
20
|
+
* request's, as `findById` would. A target that is missing or refused to this reader is absent
|
|
21
|
+
* from the map.
|
|
22
|
+
*/
|
|
23
|
+
export declare const populateRelations: (rows: DocumentRows[], args: {
|
|
24
|
+
event: RequestEvent;
|
|
25
|
+
locale?: string;
|
|
26
|
+
depth: number;
|
|
27
|
+
}) => Promise<Populated>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export const populatedKey = (slug, locale, id) => `${slug}:${locale ?? ''}:${id}`;
|
|
2
|
+
/**
|
|
3
|
+
* Reads what the relations of a whole list point at, one `findByIds` per collection and locale.
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* // 20 pages, 2 relations each, 22 distinct targets
|
|
7
|
+
* // 40 × findById -> 1 × findByIds({ ids: [...22] })
|
|
8
|
+
* ```
|
|
9
|
+
*
|
|
10
|
+
* A relation row keeps its own locale, or none: the target is read in that locale, else in the
|
|
11
|
+
* request's, as `findById` would. A target that is missing or refused to this reader is absent
|
|
12
|
+
* from the map.
|
|
13
|
+
*/
|
|
14
|
+
export const populateRelations = async (rows, args) => {
|
|
15
|
+
const { event, locale, depth } = args;
|
|
16
|
+
const groups = new Map();
|
|
17
|
+
for (const relation of rows.flatMap((row) => row.relations)) {
|
|
18
|
+
if (!relation.documentId)
|
|
19
|
+
continue;
|
|
20
|
+
// A row written in another locale is not part of this read.
|
|
21
|
+
if (relation.locale && relation.locale !== locale)
|
|
22
|
+
continue;
|
|
23
|
+
const key = `${relation.relationTo}:${relation.locale ?? ''}`;
|
|
24
|
+
const group = groups.get(key) ?? {
|
|
25
|
+
slug: relation.relationTo,
|
|
26
|
+
locale: relation.locale ?? undefined,
|
|
27
|
+
ids: new Set()
|
|
28
|
+
};
|
|
29
|
+
group.ids.add(relation.documentId);
|
|
30
|
+
groups.set(key, group);
|
|
31
|
+
}
|
|
32
|
+
const populated = new Map();
|
|
33
|
+
await Promise.all([...groups.values()].map(async (group) => {
|
|
34
|
+
const docs = await event.locals.rime
|
|
35
|
+
.collection(group.slug)
|
|
36
|
+
.findByIds({ ids: [...group.ids], locale: group.locale, depth: depth - 1 });
|
|
37
|
+
for (const doc of docs) {
|
|
38
|
+
populated.set(populatedKey(group.slug, group.locale, doc.id), doc);
|
|
39
|
+
}
|
|
40
|
+
}));
|
|
41
|
+
return populated;
|
|
42
|
+
};
|