Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,8 @@ Temporary Items
.directory
.Trash-*

# Ignore all modules except the default modules.
# Ignore all modules
/modules/*
!/modules/default

# Ignore changes to the custom css files but keep the sample and main.
/css/*
Expand Down
10 changes: 5 additions & 5 deletions cspell.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -343,11 +343,11 @@
"ignorePaths": [
"css/roboto.css",
"node_modules/**",
"modules/!(default)/**",
"modules/default/**/translations/!(en).json",
"modules/default/calendar/windowsZones.json",
"modules/default/clock/faces/*.svg",
"modules/default/weather/providers/yr.js",
"modules/**",
"defaultmodules/**/translations/!(en).json",
"defaultmodules/calendar/windowsZones.json",
"defaultmodules/clock/faces/*.svg",
"defaultmodules/weather/providers/yr.js",
"tests/mocks/**",
"tests/e2e/modules/clock_es_spec.js",
"translations/**"
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* of starting the MagicMirror² core. Adjust the values below to your desire.
*/
// Load internal alias resolver
require("../../../js/alias-resolver");
require("../../js/alias-resolver");
const Log = require("logger");

const CalendarFetcher = require("./calendarfetcher");
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const fs = require("node:fs");
const path = require("node:path");
const NodeHelper = require("node_helper");

const defaultModules = require(`${global.root_path}/modules/default/defaultmodules`);
const defaultModules = require(`${global.root_path}/${global.defaultModulesDir}/defaultmodules`);
const GitHelper = require("./git_helper");
const UpdateHelper = require("./update_helper");

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import stylistic from "@stylistic/eslint-plugin";
import vitest from "@vitest/eslint-plugin";

export default defineConfig([
globalIgnores(["config/**", "modules/**/*", "!modules/default/**", "js/positions.js"]),
globalIgnores(["config/**", "modules/**/*", "js/positions.js"]),
{
files: ["**/*.js"],
languageOptions: {
Expand Down
4 changes: 2 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@
<script type="text/javascript" src="js/defaults.js"></script>
<script type="text/javascript" src="#CONFIG_FILE#"></script>
<script type="text/javascript" src="js/vendor.js"></script>
<script type="text/javascript" src="modules/default/defaultmodules.js"></script>
<script type="text/javascript" src="modules/default/utils.js"></script>
<script type="text/javascript" src="defaultmodules/defaultmodules.js"></script>
<script type="text/javascript" src="defaultmodules/utils.js"></script>
<script type="text/javascript" src="js/logger.js"></script>
<script type="text/javascript" src="translations/translations.js"></script>
<script type="text/javascript" src="js/translator.js"></script>
Expand Down
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const config = {
collectCoverageFrom: [
"<rootDir>/clientonly/**/*.js",
"<rootDir>/js/**/*.js",
"<rootDir>/modules/default/**/*.js",
"<rootDir>/defaultmodules/**/*.js",
"<rootDir>/serveronly/**/*.js"
],
coverageReporters: ["lcov", "text"],
Expand Down
7 changes: 5 additions & 2 deletions js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ global.root_path = path.resolve(`${__dirname}/../`);
const Server = require(`${__dirname}/server`);
const Utils = require(`${__dirname}/utils`);

const defaultModules = require(`${global.root_path}/modules/default/defaultmodules`);
// used to control fetch timeout for node_helpers
const { setGlobalDispatcher, Agent } = require("undici");
const { getEnvVarsAsObj, getConfigFilePath } = require("#server_functions");
Expand Down Expand Up @@ -57,6 +56,7 @@ process.on("uncaughtException", function (err) {
function App () {
let nodeHelpers = [];
let httpServer;
let defaultModules;

/**
* Loads the config file. Combines it with the defaults and returns the config
Expand Down Expand Up @@ -185,7 +185,7 @@ function App () {
let moduleFolder = path.resolve(`${global.root_path}/${env.modulesDir}`, module);

if (defaultModules.includes(moduleName)) {
const defaultModuleFolder = path.resolve(`${global.root_path}/modules/default/`, module);
const defaultModuleFolder = path.resolve(`${global.root_path}/${global.defaultModulesDir}/`, module);
if (!global.mmTestMode) {
moduleFolder = defaultModuleFolder;
} else {
Expand Down Expand Up @@ -291,6 +291,9 @@ function App () {
this.start = async function () {
config = await loadConfig();

global.defaultModulesDir = config.defaultModulesDir;
defaultModules = require(`${global.root_path}/${global.defaultModulesDir}/defaultmodules`);

Log.setLogLevel(config.logLevel);

// get the used module positions
Expand Down
1 change: 1 addition & 0 deletions js/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const defaults = {
zoom: 1,
customCss: "css/custom.css",
foreignModulesDir: "modules",
defaultModulesDir: "defaultmodules",
// httpHeaders used by helmet, see https://helmetjs.github.io/. You can add other/more object values by overriding this in config.js,
// e.g. you need to add `frameguard: false` for embedding MagicMirror in another website, see https://github.com/MagicMirrorOrg/MagicMirror/issues/2847
httpHeaders: { contentSecurityPolicy: false, crossOriginOpenerPolicy: false, crossOriginEmbedderPolicy: false, crossOriginResourcePolicy: false, originAgentCluster: false },
Expand Down
3 changes: 2 additions & 1 deletion js/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const Loader = (function () {
const getEnvVarsFromConfig = function () {
return {
modulesDir: config.foreignModulesDir || "modules",
defaultModulesDir: config.defaultModulesDir || "defaultmodules",
customCss: config.customCss || "css/custom.css"
};
};
Expand Down Expand Up @@ -103,7 +104,7 @@ const Loader = (function () {
let moduleFolder = `${envVars.modulesDir}/${module}`;

if (defaultModules.indexOf(moduleName) !== -1) {
const defaultModuleFolder = `modules/default/${module}`;
const defaultModuleFolder = `${envVars.defaultModulesDir}/${module}`;
if (window.name !== "jsdom") {
moduleFolder = defaultModuleFolder;
} else {
Expand Down
2 changes: 1 addition & 1 deletion js/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ function Server (config) {
app.use(helmet(config.httpHeaders));
app.use("/js", express.static(__dirname));

let directories = ["/config", "/css", "/favicon.svg", "/modules", "/node_modules/animate.css", "/node_modules/@fontsource", "/node_modules/@fortawesome", "/translations", "/tests/configs", "/tests/mocks"];
let directories = ["/config", "/css", "/favicon.svg", "/defaultmodules", "/modules", "/node_modules/animate.css", "/node_modules/@fontsource", "/node_modules/@fortawesome", "/translations", "/tests/configs", "/tests/mocks"];
for (const [key, value] of Object.entries(vendor)) {
const dirArr = value.split("/");
if (dirArr[0] === "node_modules") directories.push(`/${dirArr[0]}/${dirArr[1]}`);
Expand Down
2 changes: 1 addition & 1 deletion js/server_functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ function getUserAgent () {
* @returns {object} environment variables key: values
*/
function getEnvVarsAsObj () {
const obj = { modulesDir: `${config.foreignModulesDir}`, customCss: `${config.customCss}` };
const obj = { modulesDir: `${config.foreignModulesDir}`, defaultModulesDir: `${config.defaultModulesDir}`, customCss: `${config.customCss}` };
if (process.env.MM_MODULES_DIR) {
obj.modulesDir = process.env.MM_MODULES_DIR.replace(`${global.root_path}/`, "");
}
Expand Down
Empty file added modules/.gitkeep
Empty file.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@
"main": "js/electron.js",
"scripts": {
"config:check": "node js/check_config.js",
"postinstall": "git clean -df fonts vendor",
"postinstall": "git clean -df fonts vendor modules/default",
"install-mm": "npm install --no-audit --no-fund --no-update-notifier --only=prod --omit=dev",
"install-mm:dev": "npm install --no-audit --no-fund --no-update-notifier && npx playwright install chromium",
"lint:css": "stylelint 'css/main.css' 'css/roboto.css' 'css/font-awesome.css' 'modules/default/**/*.css' --fix",
"lint:css": "stylelint 'css/main.css' 'css/roboto.css' 'css/font-awesome.css' 'defaultmodules/**/*.css' --fix",
"lint:js": "eslint --fix",
"lint:markdown": "markdownlint-cli2 . --fix",
"lint:prettier": "prettier . --write",
Expand All @@ -59,9 +59,9 @@
"start:x11": "DISPLAY=\"${DISPLAY:=:0}\" ./node_modules/.bin/electron js/electron.js",
"start:x11:dev": "node --run start:x11 -- dev",
"test": "vitest run",
"test:calendar": "node ./modules/default/calendar/debug.js",
"test:calendar": "node ./defaultmodules/calendar/debug.js",
"test:coverage": "vitest run --coverage",
"test:css": "stylelint 'css/main.css' 'css/roboto.css' 'css/font-awesome.css' 'modules/default/**/*.css'",
"test:css": "stylelint 'css/main.css' 'css/roboto.css' 'css/font-awesome.css' 'defaultmodules/**/*.css'",
"test:e2e": "vitest run tests/e2e",
"test:electron": "vitest run tests/electron",
"test:js": "eslint",
Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/modules/newsfeed_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ describe("Newsfeed module", () => {

describe("Newsfeed module located in config directory", () => {
beforeAll(() => {
fs.cpSync(`${global.root_path}/modules/default/newsfeed`, `${global.root_path}/config/newsfeed`, { recursive: true });
fs.cpSync(`${global.root_path}/${global.defaultModulesDir}/newsfeed`, `${global.root_path}/config/newsfeed`, { recursive: true });
process.env.MM_MODULES_DIR = "config";
});

Expand Down
3 changes: 2 additions & 1 deletion tests/unit/functions/updatenotification_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ async function createGitHelper (fsStatSyncMockRef, loggerMockRef, execShellSpyRe

vi.doMock("logger", () => loggerMockRef.current);

const gitHelperModule = await import("../../../modules/default/updatenotification/git_helper");
const defaults = await import("../../../js/defaults");
const gitHelperModule = await import(`../../../${defaults.defaultModulesDir}/updatenotification/git_helper`);
const GitHelper = gitHelperModule.default || gitHelperModule;
const instance = new GitHelper();
execShellSpyRef.current = vi.spyOn(instance, "execShell");
Expand Down
9 changes: 5 additions & 4 deletions tests/unit/global_vars/defaults_modules_spec.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
const fs = require("node:fs");
const path = require("node:path");
const defaults = require("../../../js/defaults");

const root_path = path.join(__dirname, "../../..");

describe("Default modules set in modules/default/defaultmodules.js", () => {
const expectedDefaultModules = require(`${root_path}/modules/default/defaultmodules`);
describe("Default modules set in defaultmodules/defaultmodules.js", () => {
const expectedDefaultModules = require(`${root_path}/${defaults.defaultModulesDir}/defaultmodules`);

for (const defaultModule of expectedDefaultModules) {
it(`contains a folder for modules/default/${defaultModule}"`, () => {
expect(fs.existsSync(path.join(root_path, "modules/default", defaultModule))).toBe(true);
it(`contains a folder for defaultmodules/${defaultModule}"`, () => {
expect(fs.existsSync(path.join(root_path, "defaultmodules", defaultModule))).toBe(true);
});
}
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
global.moment = require("moment-timezone");

const CalendarFetcherUtils = require("../../../../../modules/default/calendar/calendarfetcherutils");
const defaults = require("../../../js/defaults");

const CalendarFetcherUtils = require(`../../../../../${defaults.defaultModulesDir}/calendar/calendarfetcherutils`);

describe("Calendar fetcher utils test", () => {
const defaultConfig = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ global.moment = require("moment-timezone");

const ical = require("node-ical");
const moment = require("moment-timezone");
const CalendarFetcherUtils = require("../../../../../modules/default/calendar/calendarfetcherutils");
const defaults = require("../../../../../js/defaults");

const CalendarFetcherUtils = require(`../../../../../${defaults.defaultModulesDir}/calendar/calendarfetcherutils`);

describe("Calendar fetcher utils test", () => {
const defaultConfig = {
Expand Down
4 changes: 3 additions & 1 deletion tests/unit/modules/default/calendar/calendar_utils_spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
global.moment = require("moment");

const CalendarUtils = require("../../../../../modules/default/calendar/calendarutils");
const defaults = require("../../../../../js/defaults");

const CalendarUtils = require(`../../../../../${defaults.defaultModulesDir}/calendar/calendarutils`);

describe("Calendar utils tests", () => {
describe("capFirst", () => {
Expand Down
7 changes: 4 additions & 3 deletions tests/unit/modules/default/compliments/compliments_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ describe("Compliments module", () => {
global.Cron = vi.fn();

// Load the module
require("../../../../../modules/default/compliments/compliments");
const defaults = require("../../../../../js/defaults");
require(`../../../../../${defaults.defaultModulesDir}/compliments/compliments`);

// Setup module instance
complimentsModule.config = { ...complimentsModule.defaults };
complimentsModule.name = "compliments";
complimentsModule.file = vi.fn((path) => `http://localhost:8080/modules/default/compliments/${path}`);
complimentsModule.file = vi.fn((path) => `http://localhost:8080/${defaults.defaultModulesDir}/compliments/${path}`);
});

afterEach(() => {
Expand Down Expand Up @@ -144,7 +145,7 @@ describe("Compliments module", () => {
await complimentsModule.loadComplimentFile();

const calledUrl = fetch.mock.calls[0][0];
expect(calledUrl).toBe("http://localhost:8080/modules/default/compliments/compliments.json");
expect(calledUrl).toBe("http://localhost:8080/defaultmodules/compliments/compliments.json");
expect(calledUrl).not.toContain("dummy=");
});
});
Expand Down
4 changes: 3 additions & 1 deletion tests/unit/modules/default/utils_spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
global.moment = require("moment-timezone");
const { performWebRequest, formatTime } = require("../../../../modules/default/utils");
const defaults = require("../../../../js/defaults");

const { performWebRequest, formatTime } = require(`../../../../${defaults.defaultModulesDir}/utils`);

describe("Default modules utils tests", () => {
describe("performWebRequest", () => {
Expand Down
4 changes: 3 additions & 1 deletion tests/unit/modules/default/weather/weather_object_spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const WeatherObject = require("../../../../../modules/default/weather/weatherobject");
const defaults = require("../../../../../js/defaults");

const WeatherObject = require(`../../../../../${defaults.defaultModulesDir}/weather/weatherobject`);

global.moment = require("moment-timezone");
global.SunCalc = require("suncalc");
Expand Down
6 changes: 4 additions & 2 deletions tests/unit/modules/default/weather/weather_utils_spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
const weather = require("../../../../../modules/default/weather/weatherutils");
const WeatherUtils = require("../../../../../modules/default/weather/weatherutils");
const defaults = require("../../../../../js/defaults");

const weather = require(`../../../../../${defaults.defaultModulesDir}/weather/weatherutils`);
const WeatherUtils = require(`../../../../../${defaults.defaultModulesDir}/weather/weatherutils`);

describe("Weather utils tests", () => {
describe("temperature conversion to imperial", () => {
Expand Down
4 changes: 2 additions & 2 deletions vitest.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export default defineConfig({
setupFiles: ["./tests/utils/vitest-setup.js"],
include: [
"tests/unit/**/*_spec.js",
"tests/unit/modules/default/calendar/calendar_fetcher_utils_bad_rrule.js"
"tests/unit/defaultmodules/calendar/calendar_fetcher_utils_bad_rrule.js"
],
testTimeout: 20000,
hookTimeout: 10000
Expand Down Expand Up @@ -82,7 +82,7 @@ export default defineConfig({
include: [
"clientonly/**/*.js",
"js/**/*.js",
"modules/default/**/*.js",
"defaultmodules/**/*.js",
"serveronly/**/*.js"
],
exclude: [
Expand Down