Skip to content

Commit d276a7d

Browse files
Use template literals instead of string concatenation (#3066)
We have used it inconsistently till now. Template literals are more modern and easier to maintain in my opinion. Because that's a large amount of changes, here's a way to reproduce it: I added the rule `"prefer-template": "error"` to the `.eslintrc.json` and did an autofix. Since this caused a new problem in line 409 of `newsfeed.js`, I reversed it in that line and also removed the rule from the eslint config file. The rule is described here: https://eslint.org/docs/latest/rules/prefer-template Note: I've played around with some other linter rules as well, and some seem to point to some specific, non-cosmetic, issues. But before I dive even deeper and then introduce even bigger and hardly understandable changes at once, I thought I'd start with this simple cosmetic rule.
1 parent 8f8945d commit d276a7d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+222
-237
lines changed

.eslintrc.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@
2222
}
2323
},
2424
"rules": {
25-
"prettier/prettier": "error",
2625
"eqeqeq": "error",
2726
"no-prototype-builtins": "off",
2827
"no-unused-vars": "off",
29-
"no-useless-return": "error"
28+
"no-useless-return": "error",
29+
"prefer-template": "error"
3030
}
3131
}

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ _This release is scheduled to be released on 2023-04-01._
5555
- Fix wrong vertical alignment of calendar title column when wrapEvents is true (#3053)
5656
- Fix empty news feed stopping the reload forever
5757
- Fix e2e tests (failed after async changes) by running calendar and newsfeed tests last
58+
- Lint: Use template literals instead of string concatenation
5859
- Fix default alert module to render HTML for title and message
5960

6061
## [2.22.0] - 2023-01-01

js/app.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const envsub = require("envsub");
1818

1919
// Get version number.
2020
global.version = require(`${__dirname}/../package.json`).version;
21-
Log.log("Starting MagicMirror: v" + global.version);
21+
Log.log(`Starting MagicMirror: v${global.version}`);
2222

2323
// global absolute root path
2424
global.root_path = path.resolve(`${__dirname}/../`);
@@ -64,7 +64,7 @@ function App() {
6464
// For this check proposed to TestSuite
6565
// https://forum.magicmirror.builders/topic/1456/test-suite-for-magicmirror/8
6666
const configFilename = path.resolve(global.configuration_file || `${global.root_path}/config/config.js`);
67-
let templateFile = configFilename + ".template";
67+
let templateFile = `${configFilename}.template`;
6868

6969
// check if templateFile exists
7070
try {
@@ -78,21 +78,21 @@ function App() {
7878
// save current config.js
7979
try {
8080
if (fs.existsSync(configFilename)) {
81-
fs.copyFileSync(configFilename, configFilename + "_" + Date.now());
81+
fs.copyFileSync(configFilename, `${configFilename}_${Date.now()}`);
8282
}
8383
} catch (err) {
84-
Log.warn("Could not copy " + configFilename + ": " + err.message);
84+
Log.warn(`Could not copy ${configFilename}: ${err.message}`);
8585
}
8686

8787
// check if config.env exists
8888
const envFiles = [];
89-
const configEnvFile = configFilename.substr(0, configFilename.lastIndexOf(".")) + ".env";
89+
const configEnvFile = `${configFilename.substr(0, configFilename.lastIndexOf("."))}.env`;
9090
try {
9191
if (fs.existsSync(configEnvFile)) {
9292
envFiles.push(configEnvFile);
9393
}
9494
} catch (err) {
95-
Log.debug(configEnvFile + " does not exist. " + err.message);
95+
Log.debug(`${configEnvFile} does not exist. ${err.message}`);
9696
}
9797

9898
let options = {
@@ -110,7 +110,7 @@ function App() {
110110
try {
111111
await envsub({ templateFile, outputFile, options });
112112
} catch (err) {
113-
Log.error("Could not envsubst variables: " + err.message);
113+
Log.error(`Could not envsubst variables: ${err.message}`);
114114
}
115115
}
116116

js/loader.js

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const Loader = (function () {
4444
// Starting modules also hides any modules that have requested to be initially hidden
4545
for (const thisModule of moduleObjects) {
4646
if (thisModule.data.hiddenOnStartup) {
47-
Log.info("Initially hiding " + thisModule.name);
47+
Log.info(`Initially hiding ${thisModule.name}`);
4848
thisModule.hide();
4949
}
5050
}
@@ -73,10 +73,10 @@ const Loader = (function () {
7373

7474
const elements = module.split("/");
7575
const moduleName = elements[elements.length - 1];
76-
let moduleFolder = config.paths.modules + "/" + module;
76+
let moduleFolder = `${config.paths.modules}/${module}`;
7777

7878
if (defaultModules.indexOf(moduleName) !== -1) {
79-
moduleFolder = config.paths.modules + "/default/" + module;
79+
moduleFolder = `${config.paths.modules}/default/${module}`;
8080
}
8181

8282
if (moduleData.disabled === true) {
@@ -85,16 +85,16 @@ const Loader = (function () {
8585

8686
moduleFiles.push({
8787
index: index,
88-
identifier: "module_" + index + "_" + module,
88+
identifier: `module_${index}_${module}`,
8989
name: moduleName,
90-
path: moduleFolder + "/",
91-
file: moduleName + ".js",
90+
path: `${moduleFolder}/`,
91+
file: `${moduleName}.js`,
9292
position: moduleData.position,
9393
hiddenOnStartup: moduleData.hiddenOnStartup,
9494
header: moduleData.header,
9595
configDeepMerge: typeof moduleData.configDeepMerge === "boolean" ? moduleData.configDeepMerge : false,
9696
config: moduleData.config,
97-
classes: typeof moduleData.classes !== "undefined" ? moduleData.classes + " " + module : module
97+
classes: typeof moduleData.classes !== "undefined" ? `${moduleData.classes} ${module}` : module
9898
});
9999
});
100100

@@ -136,17 +136,17 @@ const Loader = (function () {
136136
* @param {Module} mObj Modules instance.
137137
*/
138138
const bootstrapModule = async function (module, mObj) {
139-
Log.info("Bootstrapping module: " + module.name);
139+
Log.info(`Bootstrapping module: ${module.name}`);
140140
mObj.setData(module);
141141

142142
await mObj.loadScripts();
143-
Log.log("Scripts loaded for: " + module.name);
143+
Log.log(`Scripts loaded for: ${module.name}`);
144144

145145
await mObj.loadStyles();
146-
Log.log("Styles loaded for: " + module.name);
146+
Log.log(`Styles loaded for: ${module.name}`);
147147

148148
await mObj.loadTranslations();
149-
Log.log("Translations loaded for: " + module.name);
149+
Log.log(`Translations loaded for: ${module.name}`);
150150

151151
moduleObjects.push(mObj);
152152
};
@@ -164,7 +164,7 @@ const Loader = (function () {
164164
switch (extension.toLowerCase()) {
165165
case "js":
166166
return new Promise((resolve) => {
167-
Log.log("Load script: " + fileName);
167+
Log.log(`Load script: ${fileName}`);
168168
script = document.createElement("script");
169169
script.type = "text/javascript";
170170
script.src = fileName;
@@ -179,7 +179,7 @@ const Loader = (function () {
179179
});
180180
case "css":
181181
return new Promise((resolve) => {
182-
Log.log("Load stylesheet: " + fileName);
182+
Log.log(`Load stylesheet: ${fileName}`);
183183

184184
stylesheet = document.createElement("link");
185185
stylesheet.rel = "stylesheet";
@@ -236,7 +236,7 @@ const Loader = (function () {
236236
*/
237237
loadFileForModule: async function (fileName, module) {
238238
if (loadedFiles.indexOf(fileName.toLowerCase()) !== -1) {
239-
Log.log("File already loaded: " + fileName);
239+
Log.log(`File already loaded: ${fileName}`);
240240
return;
241241
}
242242

@@ -251,7 +251,7 @@ const Loader = (function () {
251251
// This file is available in the vendor folder.
252252
// Load it from this vendor folder.
253253
loadedFiles.push(fileName.toLowerCase());
254-
return loadFile(config.paths.vendor + "/" + vendor[fileName]);
254+
return loadFile(`${config.paths.vendor}/${vendor[fileName]}`);
255255
}
256256

257257
// File not loaded yet.

js/main.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const MM = (function () {
2929
dom.className = module.name;
3030

3131
if (typeof module.data.classes === "string") {
32-
dom.className = "module " + dom.className + " " + module.data.classes;
32+
dom.className = `module ${dom.className} ${module.data.classes}`;
3333
}
3434

3535
dom.opacity = 0;
@@ -243,7 +243,7 @@ const MM = (function () {
243243

244244
const moduleWrapper = document.getElementById(module.identifier);
245245
if (moduleWrapper !== null) {
246-
moduleWrapper.style.transition = "opacity " + speed / 1000 + "s";
246+
moduleWrapper.style.transition = `opacity ${speed / 1000}s`;
247247
moduleWrapper.style.opacity = 0;
248248
moduleWrapper.classList.add("hidden");
249249

@@ -291,7 +291,7 @@ const MM = (function () {
291291
// Check if there are no more lockstrings set, or the force option is set.
292292
// Otherwise cancel show action.
293293
if (module.lockStrings.length !== 0 && options.force !== true) {
294-
Log.log("Will not show " + module.name + ". LockStrings active: " + module.lockStrings.join(","));
294+
Log.log(`Will not show ${module.name}. LockStrings active: ${module.lockStrings.join(",")}`);
295295
if (typeof options.onError === "function") {
296296
options.onError(new Error("LOCK_STRING_ACTIVE"));
297297
}
@@ -302,13 +302,13 @@ const MM = (function () {
302302

303303
// If forced show, clean current lockstrings.
304304
if (module.lockStrings.length !== 0 && options.force === true) {
305-
Log.log("Force show of module: " + module.name);
305+
Log.log(`Force show of module: ${module.name}`);
306306
module.lockStrings = [];
307307
}
308308

309309
const moduleWrapper = document.getElementById(module.identifier);
310310
if (moduleWrapper !== null) {
311-
moduleWrapper.style.transition = "opacity " + speed / 1000 + "s";
311+
moduleWrapper.style.transition = `opacity ${speed / 1000}s`;
312312
// Restore the position. See hideModule() for more info.
313313
moduleWrapper.style.position = "static";
314314
moduleWrapper.classList.remove("hidden");

js/module.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const Module = Class.extend({
4141
* Called when the module is started.
4242
*/
4343
start: async function () {
44-
Log.info("Starting module: " + this.name);
44+
Log.info(`Starting module: ${this.name}`);
4545
},
4646

4747
/**
@@ -127,7 +127,7 @@ const Module = Class.extend({
127127
* @returns {string} The template string of filename.
128128
*/
129129
getTemplate: function () {
130-
return '<div class="normal">' + this.name + '</div><div class="small dimmed">' + this.identifier + "</div>";
130+
return `<div class="normal">${this.name}</div><div class="small dimmed">${this.identifier}</div>`;
131131
},
132132

133133
/**
@@ -185,21 +185,21 @@ const Module = Class.extend({
185185
* @param {*} payload The payload of the notification.
186186
*/
187187
socketNotificationReceived: function (notification, payload) {
188-
Log.log(this.name + " received a socket notification: " + notification + " - Payload: " + payload);
188+
Log.log(`${this.name} received a socket notification: ${notification} - Payload: ${payload}`);
189189
},
190190

191191
/**
192192
* Called when the module is hidden.
193193
*/
194194
suspend: function () {
195-
Log.log(this.name + " is suspended.");
195+
Log.log(`${this.name} is suspended.`);
196196
},
197197

198198
/**
199199
* Called when the module is shown.
200200
*/
201201
resume: function () {
202-
Log.log(this.name + " is resumed.");
202+
Log.log(`${this.name} is resumed.`);
203203
},
204204

205205
/*********************************************
@@ -255,7 +255,7 @@ const Module = Class.extend({
255255
* @returns {string} the file path
256256
*/
257257
file: function (file) {
258-
return (this.data.path + "/" + file).replace("//", "/");
258+
return `${this.data.path}/${file}`.replace("//", "/");
259259
},
260260

261261
/**
@@ -491,15 +491,15 @@ Module.create = function (name) {
491491

492492
Module.register = function (name, moduleDefinition) {
493493
if (moduleDefinition.requiresVersion) {
494-
Log.log("Check MagicMirror² version for module '" + name + "' - Minimum version: " + moduleDefinition.requiresVersion + " - Current version: " + window.mmVersion);
494+
Log.log(`Check MagicMirror² version for module '${name}' - Minimum version: ${moduleDefinition.requiresVersion} - Current version: ${window.mmVersion}`);
495495
if (cmpVersions(window.mmVersion, moduleDefinition.requiresVersion) >= 0) {
496496
Log.log("Version is ok!");
497497
} else {
498-
Log.warn("Version is incorrect. Skip module: '" + name + "'");
498+
Log.warn(`Version is incorrect. Skip module: '${name}'`);
499499
return;
500500
}
501501
}
502-
Log.log("Module registered: " + name);
502+
Log.log(`Module registered: ${name}`);
503503
Module.definitions[name] = moduleDefinition;
504504
};
505505

js/server_functions.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ async function cors(req, res) {
3030

3131
const match = new RegExp(urlRegEx, "g").exec(req.url);
3232
if (!match) {
33-
url = "invalid url: " + req.url;
33+
url = `invalid url: ${req.url}`;
3434
Log.error(url);
3535
res.send(url);
3636
} else {
@@ -39,7 +39,7 @@ async function cors(req, res) {
3939
const headersToSend = getHeadersToSend(req.url);
4040
const expectedRecievedHeaders = geExpectedRecievedHeaders(req.url);
4141

42-
Log.log("cors url: " + url);
42+
Log.log(`cors url: ${url}`);
4343
const response = await fetch(url, { headers: headersToSend });
4444

4545
for (const header of expectedRecievedHeaders) {
@@ -62,7 +62,7 @@ async function cors(req, res) {
6262
* @returns {object} An object specifying name and value of the headers.
6363
*/
6464
function getHeadersToSend(url) {
65-
const headersToSend = { "User-Agent": "Mozilla/5.0 MagicMirror/" + global.version };
65+
const headersToSend = { "User-Agent": `Mozilla/5.0 MagicMirror/${global.version}` };
6666
const headersToSendMatch = new RegExp("sendheaders=(.+?)(&|$)", "g").exec(url);
6767
if (headersToSendMatch) {
6868
const headers = headersToSendMatch[1].split(",");

js/socketclient.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ const MMSocket = function (moduleName) {
1818
if (typeof config !== "undefined" && typeof config.basePath !== "undefined") {
1919
base = config.basePath;
2020
}
21-
this.socket = io("/" + this.moduleName, {
22-
path: base + "socket.io"
21+
this.socket = io(`/${this.moduleName}`, {
22+
path: `${base}socket.io`
2323
});
2424

2525
let notificationCallback = function () {};

js/translator.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const Translator = (function () {
2626
fileinfo = JSON.parse(xhr.responseText);
2727
} catch (exception) {
2828
// nothing here, but don't die
29-
Log.error(" loading json file =" + file + " failed");
29+
Log.error(` loading json file =${file} failed`);
3030
}
3131
resolve(fileinfo);
3232
}
@@ -70,7 +70,7 @@ const Translator = (function () {
7070
template = variables.fallback;
7171
}
7272
return template.replace(new RegExp("{([^}]+)}", "g"), function (_unused, varName) {
73-
return varName in variables ? variables[varName] : "{" + varName + "}";
73+
return varName in variables ? variables[varName] : `{${varName}}`;
7474
});
7575
}
7676

@@ -123,7 +123,7 @@ const Translator = (function () {
123123
*/
124124
loadCoreTranslations: async function (lang) {
125125
if (lang in translations) {
126-
Log.log("Loading core translation file: " + translations[lang]);
126+
Log.log(`Loading core translation file: ${translations[lang]}`);
127127
this.coreTranslations = await loadJSON(translations[lang]);
128128
} else {
129129
Log.log("Configured language not found in core translations.");
@@ -139,7 +139,7 @@ const Translator = (function () {
139139
loadCoreTranslationsFallback: async function () {
140140
let first = Object.keys(translations)[0];
141141
if (first) {
142-
Log.log("Loading core translation fallback file: " + translations[first]);
142+
Log.log(`Loading core translation fallback file: ${translations[first]}`);
143143
this.coreTranslationsFallback = await loadJSON(translations[first]);
144144
}
145145
}

modules/default/alert/notificationFx.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
NotificationFx.prototype._init = function () {
8181
// create HTML structure
8282
this.ntf = document.createElement("div");
83-
this.ntf.className = this.options.al_no + " ns-" + this.options.layout + " ns-effect-" + this.options.effect + " ns-type-" + this.options.type;
83+
this.ntf.className = `${this.options.al_no} ns-${this.options.layout} ns-effect-${this.options.effect} ns-type-${this.options.type}`;
8484
let strinner = '<div class="ns-box-inner">';
8585
strinner += this.options.message;
8686
strinner += "</div>";

0 commit comments

Comments
 (0)