decap-cms-core 3.13.0 → 3.14.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.
Files changed (41) hide show
  1. package/dist/decap-cms-core.js +18 -18
  2. package/dist/decap-cms-core.js.map +1 -1
  3. package/dist/esm/actions/config.js +14 -1
  4. package/dist/esm/actions/entries.js +15 -4
  5. package/dist/esm/backend.js +2 -0
  6. package/dist/esm/bootstrap.js +2 -2
  7. package/dist/esm/components/App/App.js +12 -5
  8. package/dist/esm/components/App/Header.js +18 -18
  9. package/dist/esm/components/Collection/Entries/EntryCard.js +30 -15
  10. package/dist/esm/components/Collection/NestedCollection.js +20 -11
  11. package/dist/esm/components/Editor/EditorPreviewPane/EditorPreviewPane.js +22 -6
  12. package/dist/esm/components/UI/ErrorBoundary.js +2 -2
  13. package/dist/esm/components/UI/SettingsDropdown.js +25 -27
  14. package/dist/esm/constants/configSchema.js +1 -1
  15. package/dist/esm/lib/registry.js +4 -1
  16. package/dist/esm/reducers/entryDraft.js +36 -3
  17. package/index.d.ts +17 -1
  18. package/package.json +2 -2
  19. package/src/__tests__/backend.spec.js +214 -0
  20. package/src/actions/__tests__/config.spec.js +14 -0
  21. package/src/actions/__tests__/entries.spec.js +36 -1
  22. package/src/actions/config.ts +13 -1
  23. package/src/actions/entries.ts +22 -7
  24. package/src/backend.ts +2 -0
  25. package/src/components/App/App.js +22 -13
  26. package/src/components/App/Header.js +36 -11
  27. package/src/components/Collection/Entries/EntryCard.js +13 -3
  28. package/src/components/Collection/NestedCollection.js +14 -7
  29. package/src/components/Collection/__tests__/NestedCollection.spec.js +1 -1
  30. package/src/components/Collection/__tests__/__snapshots__/NestedCollection.spec.js.snap +0 -68
  31. package/src/components/Editor/EditorPreviewPane/EditorPreviewPane.js +6 -5
  32. package/src/components/Editor/__tests__/__snapshots__/EditorToolbar.spec.js.snap +104 -72
  33. package/src/components/UI/SettingsDropdown.js +36 -9
  34. package/src/constants/__tests__/configSchema.spec.js +9 -6
  35. package/src/constants/configSchema.js +1 -1
  36. package/src/lib/__tests__/formatters.spec.js +16 -4
  37. package/src/lib/__tests__/registry.spec.js +3 -3
  38. package/src/lib/registry.js +4 -1
  39. package/src/reducers/__tests__/entryDraft.spec.js +117 -0
  40. package/src/reducers/entryDraft.js +43 -3
  41. package/src/types/redux.ts +19 -2
@@ -1,8 +1,9 @@
1
1
  import { Map, List, fromJS } from 'immutable';
2
2
  import { v4 as uuid } from 'uuid';
3
3
  import get from 'lodash/get';
4
- import { join } from 'path';
4
+ import { join, basename } from 'path';
5
5
 
6
+ import { sanitizeSlug } from '../lib/urlHelper';
6
7
  import {
7
8
  DRAFT_CREATE_FROM_ENTRY,
8
9
  DRAFT_CREATE_EMPTY,
@@ -204,15 +205,54 @@ function entryDraftReducer(state = Map(), action) {
204
205
  }
205
206
  }
206
207
 
208
+ function cleanTitleForFilename(title) {
209
+ if (!title) return 'untitled';
210
+
211
+ const cleanedTitle = sanitizeSlug(title.toString().toLowerCase().trim(), {
212
+ sanitize_replacement: '-',
213
+ encoding: 'unicode',
214
+ });
215
+
216
+ return cleanedTitle || 'untitled';
217
+ }
218
+
207
219
  export function selectCustomPath(collection, entryDraft) {
208
220
  if (!selectHasMetaPath(collection)) {
209
221
  return;
210
222
  }
211
223
  const meta = entryDraft.getIn(['entry', 'meta']);
212
224
  const path = meta && meta.get('path');
213
- const indexFile = get(collection.toJS(), ['meta', 'path', 'index_file']);
225
+
226
+ if (!path) {
227
+ return;
228
+ }
229
+
214
230
  const extension = selectFolderEntryExtension(collection);
215
- const customPath = path && join(collection.get('folder'), path, `${indexFile}.${extension}`);
231
+ const indexFile = get(collection.toJS(), ['meta', 'path', 'index_file']);
232
+
233
+ // If index_file is specified, use the old behavior for backward compatibility
234
+ if (indexFile) {
235
+ const customPath = join(collection.get('folder'), path, `${indexFile}.${extension}`);
236
+ return customPath;
237
+ }
238
+
239
+ // New behavior: generate filename from entry title
240
+ const isNewEntry = entryDraft.getIn(['entry', 'newRecord']);
241
+ const currentPath = entryDraft.getIn(['entry', 'path']);
242
+
243
+ let filename;
244
+ if (isNewEntry || !currentPath) {
245
+ // For new entries, generate filename from title
246
+ const entryData = entryDraft.getIn(['entry', 'data']);
247
+ const title = entryData && entryData.get('title');
248
+ filename = cleanTitleForFilename(title);
249
+ } else {
250
+ // For existing entries, preserve the current filename
251
+ const currentFilename = basename(currentPath, `.${extension}`);
252
+ filename = currentFilename;
253
+ }
254
+
255
+ const customPath = join(collection.get('folder'), path, `${filename}.${extension}`);
216
256
  return customPath;
217
257
  }
218
258
 
@@ -185,6 +185,21 @@ export interface CmsFieldMarkdown {
185
185
  editorComponents?: string[];
186
186
  }
187
187
 
188
+ export interface CmsFieldRichText {
189
+ widget: 'richtext';
190
+ default?: string;
191
+
192
+ minimal?: boolean;
193
+ buttons?: CmsMarkdownWidgetButton[];
194
+ editor_components?: string[];
195
+ modes?: ('raw' | 'rich_text')[];
196
+
197
+ /**
198
+ * @deprecated Use editor_components instead
199
+ */
200
+ editorComponents?: string[];
201
+ }
202
+
188
203
  export interface CmsFieldNumber {
189
204
  widget: 'number';
190
205
  default?: string | number;
@@ -258,7 +273,7 @@ export interface CmsFieldMeta {
258
273
  label: string;
259
274
  widget: string;
260
275
  required: boolean;
261
- index_file: string;
276
+ index_file?: string;
262
277
  meta: boolean;
263
278
  }
264
279
 
@@ -272,6 +287,7 @@ export type CmsField = CmsFieldBase &
272
287
  | CmsFieldList
273
288
  | CmsFieldMap
274
289
  | CmsFieldMarkdown
290
+ | CmsFieldRichText
275
291
  | CmsFieldNumber
276
292
  | CmsFieldObject
277
293
  | CmsFieldRelation
@@ -340,7 +356,7 @@ export interface CmsCollection {
340
356
  depth: number;
341
357
  };
342
358
  type: typeof FOLDER | typeof FILES;
343
- meta?: { path?: { label: string; widget: string; index_file: string } };
359
+ meta?: { path?: { label: string; widget: string; index_file?: string } };
344
360
 
345
361
  /**
346
362
  * It accepts the following values: yml, yaml, toml, json, md, markdown, html
@@ -580,6 +596,7 @@ export type EntryField = StaticallyTypedRecord<{
580
596
  name: string;
581
597
  default: string | null | boolean | List<unknown>;
582
598
  media_folder?: string;
599
+ multiple?: boolean;
583
600
  public_folder?: string;
584
601
  comment?: string;
585
602
  meta?: boolean;