Skip to content

Commit 56ad4f0

Browse files
refactor: extract icon normalization helper
Moved normalizeIconName out of CALEXT2_Event into lib/icon-helpers to keep Event focused on rendering. CALEXT2_Event now uses IconHelpers.normalizeIconName, getScripts loads the new helper, and tests were added to cover both legacy and modern icon formats.
1 parent 5eeb50b commit 56ad4f0

4 files changed

Lines changed: 88 additions & 21 deletions

File tree

CALEXT2_Event.js

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* global dayjs */
1+
/* global dayjs IconHelpers */
22
// eslint-disable-next-line no-unused-vars
33
class Event {
44
constructor (data, slot) {
@@ -116,7 +116,7 @@ class Event {
116116
if (event.icon) {
117117
const iconDom = document.createElement("iconify-icon");
118118
iconDom.classList.add("eventIcon");
119-
iconDom.setAttribute("icon", Event.normalizeIconName(event.icon));
119+
iconDom.setAttribute("icon", IconHelpers.normalizeIconName(event.icon));
120120
mainDom.appendChild(iconDom);
121121
}
122122
const title = document.createElement("div");
@@ -166,25 +166,6 @@ class Event {
166166
return eventDom;
167167
}
168168

169-
/**
170-
* Normalize icon name from legacy Iconify v1 format (prefix-name) to v2+
171-
* format (prefix:name). If the name already contains ":", it is returned
172-
* as-is to support the modern format directly.
173-
* TODO: Remove this backwards-compatibility function after a suitable deprecation period (so maybe in 2028).
174-
* @param {string} name - The icon name to normalize
175-
* @returns {string} Normalized icon name with ":" separator
176-
*/
177-
static normalizeIconName (name) {
178-
if (name.includes(":")) return name;
179-
const dashIndex = name.indexOf("-");
180-
if (dashIndex > 0) {
181-
const converted = `${name.substring(0, dashIndex)}:${name.substring(dashIndex + 1)}`;
182-
// eslint-disable-next-line no-console
183-
console.warn(`[CALEXT2] Deprecated icon name format "${name}" — use "${converted}" instead (prefix:name).`);
184-
return converted;
185-
}
186-
return name;
187-
}
188169

189170
/**
190171
* Applies category CSS classes and data-attribute to eventDom,

MMM-CalendarExt2.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ Module.register("MMM-CalendarExt2", {
224224
getScripts () {
225225
const scripts = [
226226
this.file("lib/slot-date-helpers.js"),
227+
this.file("lib/icon-helpers.js"),
227228
this.file("node_modules/dayjs/dayjs.min.js"),
228229
this.file("node_modules/dayjs/plugin/utc.js"),
229230
this.file("node_modules/dayjs/plugin/timezone.js"),

lib/icon-helpers.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Icon name normalization from Iconify v1 legacy format to v2+ format.
3+
* Dual-mode: works as a browser global and Node.js module.
4+
*/
5+
6+
/**
7+
* Normalize icon name from legacy Iconify v1 format (prefix-name) to v2+
8+
* format (prefix:name). If the name already contains ":", it is returned
9+
* as-is to support the modern format directly.
10+
* TODO: Remove this backwards-compatibility function after a suitable deprecation period (so maybe in 2028).
11+
* @param {string} name - The icon name to normalize
12+
* @returns {string} Normalized icon name with ":" separator
13+
*/
14+
const normalizeIconName = (name) => {
15+
if (name.includes(":")) return name;
16+
const dashIndex = name.indexOf("-");
17+
if (dashIndex > 0) {
18+
const converted = `${name.substring(0, dashIndex)}:${name.substring(dashIndex + 1)}`;
19+
// eslint-disable-next-line no-console
20+
console.warn(`[CALEXT2] Deprecated icon name format "${name}" — use "${converted}" instead (prefix:name).`);
21+
return converted;
22+
}
23+
return name;
24+
};
25+
26+
const IconHelpers = {normalizeIconName};
27+
28+
if (typeof module !== "undefined" && module.exports) {
29+
module.exports = IconHelpers;
30+
}

test/icon-helpers.test.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
const assert = require("node:assert/strict");
2+
const {describe, it} = require("node:test");
3+
4+
const IconHelpers = require("../lib/icon-helpers.js");
5+
6+
describe("normalizeIconName", () => {
7+
it("returns modern format unchanged", () => {
8+
assert.equal(IconHelpers.normalizeIconName("mdi:home"), "mdi:home");
9+
});
10+
11+
it("converts legacy format prefix-name to prefix:name", () => {
12+
assert.equal(IconHelpers.normalizeIconName("mdi-home"), "mdi:home");
13+
});
14+
15+
it("handles multiple dashes, converting only first to colon", () => {
16+
assert.equal(IconHelpers.normalizeIconName("mdi-home-outline"), "mdi:home-outline");
17+
});
18+
19+
it("returns name unchanged if no dash present", () => {
20+
assert.equal(IconHelpers.normalizeIconName("home"), "home");
21+
});
22+
23+
it("handles single-char prefix", () => {
24+
assert.equal(IconHelpers.normalizeIconName("i-check"), "i:check");
25+
});
26+
27+
it("warns to console on legacy format conversion", () => {
28+
const messages = [];
29+
// eslint-disable-next-line no-console
30+
const originalWarn = console.warn;
31+
// eslint-disable-next-line no-console
32+
console.warn = (msg) => messages.push(msg);
33+
34+
IconHelpers.normalizeIconName("mdi-home");
35+
36+
// eslint-disable-next-line no-console
37+
console.warn = originalWarn;
38+
assert.equal(messages.length, 1);
39+
assert.match(messages[0], /Deprecated icon name format/u);
40+
});
41+
42+
it("does not warn on modern format", () => {
43+
const messages = [];
44+
// eslint-disable-next-line no-console
45+
const originalWarn = console.warn;
46+
// eslint-disable-next-line no-console
47+
console.warn = (msg) => messages.push(msg);
48+
49+
IconHelpers.normalizeIconName("mdi:home");
50+
51+
// eslint-disable-next-line no-console
52+
console.warn = originalWarn;
53+
assert.equal(messages.length, 0);
54+
});
55+
});

0 commit comments

Comments
 (0)