Calendar translate (#3249)

Hello and thank you for wanting to contribute to the MagicMirror²
project

**Please make sure that you have followed these 4 rules before
submitting your Pull Request:**

> 1. Base your pull requests against the `develop` branch.

DONE ;D

> 2. Include these infos in the description:
> - Does the pull request solve a **related** issue?

NO
> - What does the pull request accomplish? Use a list if needed.

For calendar entries containing a year (e.g. DOB) in the title, the age
can be calculated.

Example before:

![grafik](https://github.com/MichMich/MagicMirror/assets/54073894/67ca65f4-24c3-46a8-bee8-0519e4bba3f5)
after:

![grafik](https://github.com/MichMich/MagicMirror/assets/54073894/0b4af07d-d3d9-4644-a4a6-e8c402598208)

Achieved by adding a new keyword `transform` to customEvents
```
customEvents: [
                        {keyword: 'Geburtstag', symbol: 'birthday-cake', color: 'Gold', transform: { search: '^([^\']*) \'(\\d{4})$' , replace: '$1 ($2.)', yearmatchgroup: 2}},
                        {keyword: 'in Hamburg', transform: { search: ' in Hamburg$' , replace: ''}} 
		],
```

and therewith obsoleting `titleReplace`; a backward compatibility part
is already included.

If `yearmatchgroup` is unset, behaviour is as in previous code (some
additions to which RegExes are accepted, though)

If `yearmatchgroup` is set, it is considered the RegEx match group id,
which will be used for calculating the age.



> - If it includes major visual changes please add screenshots.

NO

> 3. Please run `npm run lint:prettier` before submitting so that style
issues are fixed.

DONE

> 4. Don't forget to add an entry about your changes to the CHANGELOG.md
file.

DONE

> Thanks again and have a nice day!

You too and if any questions, feel free to let me know.

---------

Co-authored-by: veeck <michael.veeck@nebenan.de>
This commit is contained in:
kaennchenstruggle 2023-11-01 00:07:56 +01:00 committed by GitHub
parent 3a01acd389
commit 2a6e2aacdc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 16 deletions

View File

@ -12,10 +12,12 @@ _This release is scheduled to be released on 2024-01-01._
### Added ### Added
- Added node 21 to the test matrix - Added node 21 to the test matrix
- Added transform object to calendar:customEvents
### Removed ### Removed
- Removed Codecov workflow (not working anymore, other workflow required) (#3107) - Removed Codecov workflow (not working anymore, other workflow required) (#3107)
- Removed titleReplace from calendar, replaced + extended by customEvents (backward compatibility included)
### Updated ### Updated

View File

@ -155,6 +155,14 @@ Module.register("calendar", {
this.addCalendar(calendar.url, calendar.auth, calendarConfig); 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(); 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) { if (this.config.customEvents.length > 0) {
for (let ev in this.config.customEvents) { for (let ev in this.config.customEvents) {
let needle = new RegExp(this.config.customEvents[ev].keyword, "gi"); let needle = new RegExp(this.config.customEvents[ev].keyword, "gi");
if (needle.test(event.title)) { 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 !== "") { if (typeof this.config.customEvents[ev].color !== "undefined" && this.config.customEvents[ev].color !== "") {
// Respect parameter ColoredSymbolOnly also for custom events // Respect parameter ColoredSymbolOnly also for custom events
if (this.config.coloredText) { 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; titleWrapper.innerHTML = CalendarUtils.shorten(transformedTitle, this.config.maxTitleLength, this.config.wrapEvents, this.config.maxTitleLines) + repeatingCountTitle;
const titleClass = this.titleClassForUrl(event.url); const titleClass = this.titleClassForUrl(event.url);

View File

@ -90,24 +90,40 @@ const CalendarUtils = {
/** /**
* Transforms the title of an event for usage. * Transforms the title of an event for usage.
* Replaces parts of the text as defined in config.titleReplace. * 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 {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. * @returns {string} The transformed title.
*/ */
titleTransform: function (title, titleReplace) { titleTransform: function (title, titleReplace) {
let transformedTitle = title; let transformedTitle = title;
for (let needle in titleReplace) { for (let tr in titleReplace) {
const replacement = titleReplace[needle]; let transform = titleReplace[tr];
if (typeof transform === "object") {
const regParts = needle.match(/^\/(.+)\/([gim]*)$/); 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) { if (regParts) {
// the parsed pattern is a regexp. // the parsed pattern is a regexp with flags.
needle = new RegExp(regParts[1], regParts[2]); 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; return transformedTitle;
} }
}; };

View File

@ -138,11 +138,16 @@ describe("Calendar utils tests", () => {
describe("titleTransform and shorten combined", () => { describe("titleTransform and shorten combined", () => {
it("should replace the birthday and wrap nicely", () => { it("should replace the birthday and wrap nicely", () => {
const transformedTitle = CalendarUtils.titleTransform("Michael Teeuw's birthday", { const transformedTitle = CalendarUtils.titleTransform("Michael Teeuw's birthday", [{ search: "'s birthday", replace: "" }]);
"De verjaardag van ": "",
"'s birthday": ""
});
expect(CalendarUtils.shorten(transformedTitle, 10, true, 2)).toBe("Michael <br>Teeuw"); expect(CalendarUtils.shorten(transformedTitle, 10, true, 2)).toBe("Michael <br>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);
});
});
}); });