diff --git a/CHANGELOG.md b/CHANGELOG.md index 59b52e7145..9a170d3316 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,10 +12,12 @@ _This release is scheduled to be released on 2024-01-01._ ### Added - Added node 21 to the test matrix +- Added transform object to calendar:customEvents ### Removed - Removed Codecov workflow (not working anymore, other workflow required) (#3107) +- Removed titleReplace from calendar, replaced + extended by customEvents (backward compatibility included) ### Updated diff --git a/modules/default/calendar/calendar.js b/modules/default/calendar/calendar.js index c923ee50de..287a424a73 100644 --- a/modules/default/calendar/calendar.js +++ b/modules/default/calendar/calendar.js @@ -155,6 +155,14 @@ Module.register("calendar", { this.addCalendar(calendar.url, calendar.auth, calendarConfig); }); + // for backward compatibility titleReplace + if (typeof this.config.titleReplace !== "undefined") { + Log.warn("Deprecation warning: Please consider upgrading your calendar titleReplace configuration to customEvents."); + for (const [titlesearchstr, titlereplacestr] of Object.entries(this.config.titleReplace)) { + this.config.customEvents.push({ keyword: ".*", transform: { search: titlesearchstr, replace: titlereplacestr } }); + } + } + this.selfUpdate(); }, @@ -326,11 +334,16 @@ Module.register("calendar", { } } - // Color events if custom color or eventClass are specified + var transformedTitle = event.title; + + // Color events if custom color or eventClass are specified, transform title if required if (this.config.customEvents.length > 0) { for (let ev in this.config.customEvents) { let needle = new RegExp(this.config.customEvents[ev].keyword, "gi"); if (needle.test(event.title)) { + if (typeof this.config.customEvents[ev].transform === "object") { + transformedTitle = CalendarUtils.titleTransform(transformedTitle, [this.config.customEvents[ev].transform]); + } if (typeof this.config.customEvents[ev].color !== "undefined" && this.config.customEvents[ev].color !== "") { // Respect parameter ColoredSymbolOnly also for custom events if (this.config.coloredText) { @@ -348,7 +361,6 @@ Module.register("calendar", { } } - const transformedTitle = CalendarUtils.titleTransform(event.title, this.config.titleReplace); titleWrapper.innerHTML = CalendarUtils.shorten(transformedTitle, this.config.maxTitleLength, this.config.wrapEvents, this.config.maxTitleLines) + repeatingCountTitle; const titleClass = this.titleClassForUrl(event.url); diff --git a/modules/default/calendar/calendarutils.js b/modules/default/calendar/calendarutils.js index e953b6352c..1bfdf15992 100644 --- a/modules/default/calendar/calendarutils.js +++ b/modules/default/calendar/calendarutils.js @@ -90,23 +90,39 @@ const CalendarUtils = { /** * Transforms the title of an event for usage. * Replaces parts of the text as defined in config.titleReplace. - * Shortens title based on config.maxTitleLength and config.wrapEvents * @param {string} title The title to transform. - * @param {object} titleReplace Pairs of strings to be replaced in the title + * @param {object} titleReplace object definition of parts to be replaced in the title + * object definition: + * search: {string,required} RegEx in format //x or simple string to be searched. For (birthday) year calcluation, the element matching the year must be in a RegEx group + * replace: {string,required} Replacement string, may contain match group references (latter is required for year calculation) + * yearmatchgroup: {number,optional} match group for year element * @returns {string} The transformed title. */ titleTransform: function (title, titleReplace) { let transformedTitle = title; - for (let needle in titleReplace) { - const replacement = titleReplace[needle]; + for (let tr in titleReplace) { + let transform = titleReplace[tr]; + if (typeof transform === "object") { + if (typeof transform.search !== "undefined" && transform.search !== "" && typeof transform.replace !== "undefined") { + let regParts = transform.search.match(/^\/(.+)\/([gim]*)$/); + let needle = new RegExp(transform.search, "g"); + if (regParts) { + // the parsed pattern is a regexp with flags. + needle = new RegExp(regParts[1], regParts[2]); + } - const regParts = needle.match(/^\/(.+)\/([gim]*)$/); - if (regParts) { - // the parsed pattern is a regexp. - needle = new RegExp(regParts[1], regParts[2]); + let replacement = transform.replace; + if (typeof transform.yearmatchgroup !== "undefined" && transform.yearmatchgroup !== "") { + const yearmatch = [...title.matchAll(needle)]; + if (yearmatch[0].length >= transform.yearmatchgroup + 1 && yearmatch[0][transform.yearmatchgroup] * 1 >= 1900) { + let calcage = new Date().getFullYear() - yearmatch[0][transform.yearmatchgroup] * 1; + let searchstr = `$${transform.yearmatchgroup}`; + replacement = replacement.replace(searchstr, calcage); + } + } + transformedTitle = transformedTitle.replace(needle, replacement); + } } - - transformedTitle = transformedTitle.replace(needle, replacement); } return transformedTitle; } diff --git a/tests/unit/modules/default/calendar/calendar_utils_spec.js b/tests/unit/modules/default/calendar/calendar_utils_spec.js index 7cf896c137..ff37299fe9 100644 --- a/tests/unit/modules/default/calendar/calendar_utils_spec.js +++ b/tests/unit/modules/default/calendar/calendar_utils_spec.js @@ -138,11 +138,16 @@ describe("Calendar utils tests", () => { describe("titleTransform and shorten combined", () => { it("should replace the birthday and wrap nicely", () => { - const transformedTitle = CalendarUtils.titleTransform("Michael Teeuw's birthday", { - "De verjaardag van ": "", - "'s birthday": "" - }); + const transformedTitle = CalendarUtils.titleTransform("Michael Teeuw's birthday", [{ search: "'s birthday", replace: "" }]); expect(CalendarUtils.shorten(transformedTitle, 10, true, 2)).toBe("Michael
Teeuw"); }); }); + + describe("titleTransform with yearmatchgroup", () => { + it("should replace the birthday and wrap nicely", () => { + const transformedTitle = CalendarUtils.titleTransform("Luciella '2000", [{ search: "^([^']*) '(\\d{4})$", replace: "$1 ($2.)", yearmatchgroup: 2 }]); + const expectedResult = `Luciella (${new Date().getFullYear() - 2000}.)`; + expect(transformedTitle).toBe(expectedResult); + }); + }); });