From ef24c3465adb66cc42280e0141126e37dc1862ef Mon Sep 17 00:00:00 2001 From: fiona rowan <8798775+fionaRowan@users.noreply.github.com> Date: Tue, 14 Oct 2025 15:52:22 -0400 Subject: [PATCH 1/2] fix(6801): slugFormatter uses date from entry if it exists --- .../src/lib/__tests__/formatters.spec.js | 18 ++++++++++++++++-- packages/decap-cms-core/src/lib/formatters.ts | 7 ++++++- .../src/stringTemplate.ts | 13 ++++++++++++- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/packages/decap-cms-core/src/lib/__tests__/formatters.spec.js b/packages/decap-cms-core/src/lib/__tests__/formatters.spec.js index 8deb7a4415fb..a391e0dc30c8 100644 --- a/packages/decap-cms-core/src/lib/__tests__/formatters.spec.js +++ b/packages/decap-cms-core/src/lib/__tests__/formatters.spec.js @@ -274,8 +274,8 @@ describe('formatters', () => { }; describe('slugFormatter', () => { - const date = new Date('2020-01-01'); - jest.spyOn(global, 'Date').mockImplementation(() => date); + const date = new Date('2020-01-01').valueOf(); + Date.now = jest.spyOn(Date, 'now').mockImplementation(() => date); const { selectIdentifier } = require('../../reducers/collections'); @@ -312,6 +312,20 @@ describe('formatters', () => { ).toBe('entry-slug'); }); + it('should see date filters applied to date from entry if it exists', () => { + const { selectInferredField } = require('../../reducers/collections'); + selectInferredField.mockReturnValue('date'); + const entryDate = new Date('2026-10-20'); + + expect( + slugFormatter( + Map({ slug: '{{year}}-{{month}}-{{day}}-{{title}}' }), + Map({ date: entryDate, title: 'post title' }), + slugConfig, + ), + ).toBe('2026-10-20-post-title'); + }); + it('should return slug', () => { selectIdentifier.mockReturnValueOnce('title'); diff --git a/packages/decap-cms-core/src/lib/formatters.ts b/packages/decap-cms-core/src/lib/formatters.ts index 9ee5f41ff97a..a958cd148e14 100644 --- a/packages/decap-cms-core/src/lib/formatters.ts +++ b/packages/decap-cms-core/src/lib/formatters.ts @@ -21,6 +21,7 @@ import type { Map } from 'immutable'; const { compileStringTemplate, parseDateFromEntry, + parseDateFromEntryData, SLUG_MISSING_REQUIRED_DATE, keyToPathArray, addFileTemplateFields, @@ -129,7 +130,11 @@ export function slugFormatter( } const processSegment = getProcessSegment(slugConfig); - const date = new Date(); + const date = + parseDateFromEntryData( + entryData as unknown as Map, + selectInferredField(collection, 'date'), + ) || new Date(Date.now()); const slug = compileStringTemplate(slugTemplate, date, identifier, entryData, processSegment); if (!collection.has('path')) { diff --git a/packages/decap-cms-lib-widgets/src/stringTemplate.ts b/packages/decap-cms-lib-widgets/src/stringTemplate.ts index d7e357b5a18d..baf3ee3b005e 100644 --- a/packages/decap-cms-lib-widgets/src/stringTemplate.ts +++ b/packages/decap-cms-lib-widgets/src/stringTemplate.ts @@ -61,7 +61,18 @@ export function parseDateFromEntry(entry: Map, dateFieldName?: return; } - const dateValue = entry.getIn(['data', dateFieldName]); + const entryData = entry.getIn(['data']); + return parseDateFromEntryData(entryData, dateFieldName); +} + +export function parseDateFromEntryData( + entryData: Map, + dateFieldName?: string | null, +) { + if (!dateFieldName) { + return; + } + const dateValue = entryData.getIn([dateFieldName]); const dateDayjs = dateValue && dayjs(dateValue); if (dateDayjs && dateDayjs.isValid()) { return dateDayjs.toDate(); From e0128c50da446782083e16542f109d01bf364151 Mon Sep 17 00:00:00 2001 From: fiona rowan <8798775+fionaRowan@users.noreply.github.com> Date: Thu, 16 Oct 2025 11:00:34 -0400 Subject: [PATCH 2/2] test: date synonym handling --- .../src/lib/__tests__/formatters.spec.js | 14 +++++++ .../reducers/__tests__/collections.spec.js | 39 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/packages/decap-cms-core/src/lib/__tests__/formatters.spec.js b/packages/decap-cms-core/src/lib/__tests__/formatters.spec.js index a391e0dc30c8..efa44e5bd1f8 100644 --- a/packages/decap-cms-core/src/lib/__tests__/formatters.spec.js +++ b/packages/decap-cms-core/src/lib/__tests__/formatters.spec.js @@ -326,6 +326,20 @@ describe('formatters', () => { ).toBe('2026-10-20-post-title'); }); + it('should see date filters applied to publishDate from entry if it exists', () => { + const { selectInferredField } = require('../../reducers/collections'); + selectInferredField.mockReturnValue('publishDate'); + const entryDate = new Date('2026-10-20'); + + expect( + slugFormatter( + Map({ slug: '{{year}}-{{month}}-{{day}}-{{title}}' }), + Map({ publishDate: entryDate, title: 'post title' }), + slugConfig, + ), + ).toBe('2026-10-20-post-title'); + }); + it('should return slug', () => { selectIdentifier.mockReturnValueOnce('title'); diff --git a/packages/decap-cms-core/src/reducers/__tests__/collections.spec.js b/packages/decap-cms-core/src/reducers/__tests__/collections.spec.js index 1314b9ae4184..9c597148a5b9 100644 --- a/packages/decap-cms-core/src/reducers/__tests__/collections.spec.js +++ b/packages/decap-cms-core/src/reducers/__tests__/collections.spec.js @@ -11,6 +11,7 @@ import collections, { getFieldsNames, selectField, updateFieldByKey, + selectInferredField, } from '../collections'; import { FILES, FOLDER } from '../../constants/collectionTypes'; @@ -568,4 +569,42 @@ describe('collections', () => { ); }); }); + + describe("selectInferredField(collection, 'date')", () => { + it('should return publishDate if set', () => { + const collection = fromJS({ + fields: [{ name: 'title' }, { name: 'publishDate', widget: 'datetime' }], + }); + + expect(selectInferredField(collection, 'date')).toEqual('publishDate'); + }); + + it('should return publish_date if set', () => { + const collection = fromJS({ + fields: [{ name: 'title' }, { name: 'publish_date', widget: 'datetime' }], + }); + + expect(selectInferredField(collection, 'date')).toEqual('publish_date'); + }); + + it('should return date if set', () => { + const collection = fromJS({ + fields: [{ name: 'title' }, { name: 'date', widget: 'datetime' }], + }); + + expect(selectInferredField(collection, 'date')).toEqual('date'); + }); + + it('should return first date field if multiple synonyms are present', () => { + const collection = fromJS({ + fields: [ + { name: 'title' }, + { name: 'publishDate', widget: 'datetime' }, + { name: 'date', widget: 'datetime' }, + ], + }); + + expect(selectInferredField(collection, 'date')).toEqual('publishDate'); + }); + }); });