From 1e317997c4c70099c354b0e000976e88fdcc4aa1 Mon Sep 17 00:00:00 2001 From: Mark Rapson Date: Mon, 14 Sep 2026 00:07:49 +0100 Subject: [PATCH] Document time date placeholder transforms --- CHANGELOG.md | 1 + src/player/regions/time-date.js | 2 +- src/web/public/js/regions/type/time-date.js | 7 ++++-- test/player-time-date-region.test.js | 25 +++++++++++++++++++++ 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7cb344..21857e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file. - Fixed the template designer empty background message moving when the background image is removed. - Fixed cached API and RSS images not being served by the player after being downloaded. - Fixed blank time/date regions displaying the default clock format on the player. +- Fixed the time/date placeholder popup omitting text and math transform help. ## 2.13.2 - 2026-09-11 diff --git a/src/player/regions/time-date.js b/src/player/regions/time-date.js index a38b1fa..73bb0bc 100644 --- a/src/player/regions/time-date.js +++ b/src/player/regions/time-date.js @@ -203,7 +203,7 @@ function getTimeDateFormattedParts(timeZone, date) { dddd: toTitleCase(getPart(weekdayLong, 'weekday')), MMM: toTitleCase(getPart(monthShort, 'month')), MMMM: toTitleCase(getPart(monthLong, 'month')), - a: toTitleCase(getPart(ampm, 'dayPeriod')), + a: String(getPart(ampm, 'dayPeriod') || '').toLowerCase(), tz: getPart(timezoneShort, 'timeZoneName'), tz_long: resolvedTimeZone, date: getPart(numericParts, 'year') + '-' + getPart(numericParts, 'month') + '-' + getPart(numericParts, 'day'), diff --git a/src/web/public/js/regions/type/time-date.js b/src/web/public/js/regions/type/time-date.js index 28bcdfe..09e9cd6 100644 --- a/src/web/public/js/regions/type/time-date.js +++ b/src/web/public/js/regions/type/time-date.js @@ -155,7 +155,7 @@ dddd: toTitleCase(getPart(weekdayLong, 'weekday')), MMM: toTitleCase(getPart(monthShort, 'month')), MMMM: toTitleCase(getPart(monthLong, 'month')), - a: toTitleCase(getPart(ampm, 'dayPeriod')), + a: String(getPart(ampm, 'dayPeriod') || '').toLowerCase(), tz: getPart(getFormatter('tz-short:' + resolvedTimeZone, { timeZone: resolvedTimeZone, timeZoneName: 'short' @@ -296,7 +296,10 @@ var table = '
' + placeholders.map(function (item) { return ''; }).join('') + '
PlaceholderOutputDescription
{{' + escapeHtml(item.token) + '}}' + escapeHtml(item.output) + '' + escapeHtml(item.description) + '
'; - return window.placeholderInfo.render(regionId, 'Time and date placeholders', table); + var transforms = '' + + (typeof window.placeholderInfo.renderTextTransforms === 'function' ? window.placeholderInfo.renderTextTransforms() : '') + + (typeof window.placeholderInfo.renderMathTransforms === 'function' ? window.placeholderInfo.renderMathTransforms() : ''); + return window.placeholderInfo.render(regionId, 'Time and date placeholders', table + transforms); } function renderEditorCard(context) { diff --git a/test/player-time-date-region.test.js b/test/player-time-date-region.test.js index c8e3553..aff5559 100644 --- a/test/player-time-date-region.test.js +++ b/test/player-time-date-region.test.js @@ -64,6 +64,31 @@ test('time/date region renders placeholder tokens on the player side', () => { assert.match(markup, /

\d{2}:\d{2}<\/p>/); }); +test('time/date lowercase day period renders in lowercase', () => { + const module = loadTimeDateModule(); + const markup = module.renderRegion( + { + pixelWidth: 320, + pixelHeight: 180, + canvasScale: 1, + baseStyle: 'position:absolute;' + }, + { + value: '{{a}}', + timezone: 'UTC' + } + ); + + assert.match(markup, /

(am|pm)<\/p>/); +}); + +test('time/date editor popup documents text and math transforms', () => { + const editorSource = fs.readFileSync(require.resolve('../src/web/public/js/regions/type/time-date.js'), 'utf8'); + + assert.match(editorSource, /renderTextTransforms\(\)/); + assert.match(editorSource, /renderMathTransforms\(\)/); +}); + test('time/date region stays blank when its format is blank', () => { const module = loadTimeDateModule(); const markup = module.renderRegion(