diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 1166747bd5..1f897d047e 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -6,22 +6,28 @@ We hold our code to standard, and these standards are documented below.
## Linters
-We use prettier for automatic linting of all our files: `npm run lint:prettier`.
+We use [prettier](https://prettier.io/) for automatic formatting a lot all our files. The configuration is in our `prettier.config.mjs` file.
-### JavaScript: Run ESLint
+To run prettier, use `npm run lint:prettier`.
-We use [ESLint](https://eslint.org) on our JavaScript files.
+### JavaScript: Run ESLint
-The ESLint configuration is in our `eslint.config.mjs` file.
+We use [ESLint](https://eslint.org) to lint our JavaScript files. The configuration is in our `eslint.config.mjs` file.
To run ESLint, use `npm run lint:js`.
### CSS: Run StyleLint
-We use [StyleLint](https://stylelint.io) to lint our CSS. Our configuration is in our `.stylelintrc` file.
+We use [StyleLint](https://stylelint.io) to lint our CSS. The configuration is in our `.stylelintrc.json` file.
To run StyleLint, use `npm run lint:css`.
+### Markdown: Run markdownlint
+
+We use [markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2) to lint our markdown files. The configuration is in our `.markdownlint.json` file.
+
+To run markdownlint, use `npm run markdownlint:css`.
+
## Testing
We use [Jest](https://jestjs.io) for JavaScript testing.
diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml
index 1c64d3a727..cf083cbf46 100644
--- a/.github/workflows/automated-tests.yaml
+++ b/.github/workflows/automated-tests.yaml
@@ -39,4 +39,5 @@ jobs:
npm run test:prettier
npm run test:js
npm run test:css
+ npm run test:markdown
npm run test
diff --git a/.markdownlint.json b/.markdownlint.json
new file mode 100644
index 0000000000..f5202cdfe0
--- /dev/null
+++ b/.markdownlint.json
@@ -0,0 +1,6 @@
+{
+ "line_length": false,
+ "no-duplicate-heading": false,
+ "no-inline-html": false,
+ "no-trailing-punctuation": false
+}
diff --git a/.prettierrc.json b/.prettierrc.json
deleted file mode 100644
index 1518304d4c..0000000000
--- a/.prettierrc.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "trailingComma": "none"
-}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e3cef7e281..af4a01a28f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,11 +16,12 @@ _This release is scheduled to be released on 2025-01-01._
- [core] Add wayland and windows start options to `package.json` (#3594)
- [docs] Add step for npm publishing in release process (#3595)
- [core] Add GitHub workflow to run spellcheck a few days before each release (#3623)
-- [core] Add intest flag to index.html to pass to module js for test mode detection (needed by #3630)
-- [compliments] add support for refreshing remote compliments file, and testcases (#3630)
+- [core] Add test flag to index.html to pass to module js for test mode detection (needed by #3630)
+- [core] Add export on animation names (#3644)
+- [compliments] add support for refreshing remote compliments file, and test cases (#3630)
- [linter] Re-add `eslint-plugin-import`now that it supports ESLint v9 (#3586)
-- [linter] Re-activate `eslint-plugin-package-json` to lint `package.json`
-- [core] Add export on animation names
+- [linter] Re-activate `eslint-plugin-package-json` to lint `package.json` (#3643)
+- [linter] Add linting for markdown files.
- [calendar] - added ability to display end date for full date events, where end is not same day (showEnd=true)
### Removed
diff --git a/Collaboration.md b/Collaboration.md
index b61ca52826..52b4f80755 100644
--- a/Collaboration.md
+++ b/Collaboration.md
@@ -1,3 +1,5 @@
+# Collaboration
+
This document describes how collaborators of this repository should work together.
## Pull Requests
diff --git a/README.md b/README.md
index 751637ca8b..7bc585c9c4 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,14 @@
-![MagicMirror²: The open source modular smart mirror platform. ](.github/header.png)
+# ![MagicMirror²: The open source modular smart mirror platform.](.github/header.png)
-
-
-
-
-
-
-
+
+
+
+
+
+
+
**MagicMirror²** is an open source modular smart mirror platform. With a growing list of installable modules, the **MagicMirror²** allows you to convert your hallway or bathroom mirror into your personal assistant. **MagicMirror²** is built by the creator of [the original MagicMirror](https://michaelteeuw.nl/tagged/magicmirror) with the incredible help of a [growing community of contributors](https://github.com/MagicMirrorOrg/MagicMirror/graphs/contributors).
@@ -24,7 +24,7 @@ For the full documentation including **[installation instructions](https://docs.
- Website: [https://magicmirror.builders](https://magicmirror.builders)
- Documentation: [https://docs.magicmirror.builders](https://docs.magicmirror.builders)
- Forum: [https://forum.magicmirror.builders](https://forum.magicmirror.builders)
- - Technical discussions: https://forum.magicmirror.builders/category/11/core-system
+ - Technical discussions:
- Discord: [https://discord.gg/J5BAtvx](https://discord.gg/J5BAtvx)
- Blog: [https://michaelteeuw.nl/tagged/magicmirror](https://michaelteeuw.nl/tagged/magicmirror)
- Donations: [https://magicmirror.builders/#donate](https://magicmirror.builders/#donate)
@@ -49,5 +49,5 @@ If we receive enough donations we might even be able to free up some working hou
To donate, please follow [this](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=G5D8E9MR5DTD2&source=url) link.
-
+
diff --git a/cspell.config.json b/cspell.config.json
index ba8aa98e14..5a27b4121a 100644
--- a/cspell.config.json
+++ b/cspell.config.json
@@ -198,6 +198,7 @@
"tada",
"taglist",
"Teeuw",
+ "TESTMODE",
"thomasrockhu",
"tomzt",
"ukmetoffice",
diff --git a/package-lock.json b/package-lock.json
index 4c2a3adb81..312e72de94 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -41,6 +41,7 @@
"jest": "^29.7.0",
"jsdom": "^25.0.1",
"lint-staged": "^15.2.10",
+ "markdownlint-cli2": "^0.15.0",
"playwright": "^1.48.2",
"prettier": "^3.3.3",
"sinon": "^19.0.2",
@@ -2482,6 +2483,19 @@
"url": "https://github.com/sindresorhus/is?sponsor=1"
}
},
+ "node_modules/@sindresorhus/merge-streams": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz",
+ "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/@sinonjs/commons": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
@@ -8499,6 +8513,13 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/jsonc-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz",
+ "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
@@ -8613,6 +8634,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/linkify-it": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
+ "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "uc.micro": "^2.0.0"
+ }
+ },
"node_modules/lint-staged": {
"version": "15.2.10",
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz",
@@ -8985,6 +9016,138 @@
"tmpl": "1.0.5"
}
},
+ "node_modules/markdown-it": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
+ "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1",
+ "entities": "^4.4.0",
+ "linkify-it": "^5.0.0",
+ "mdurl": "^2.0.0",
+ "punycode.js": "^2.3.1",
+ "uc.micro": "^2.1.0"
+ },
+ "bin": {
+ "markdown-it": "bin/markdown-it.mjs"
+ }
+ },
+ "node_modules/markdownlint": {
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.36.1.tgz",
+ "integrity": "sha512-s73fU2CQN7WCgjhaQUQ8wYESQNzGRNOKDd+3xgVqu8kuTEhmwepd/mxOv1LR2oV046ONrTLBFsM7IoKWNvmy5g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "markdown-it": "14.1.0",
+ "markdownlint-micromark": "0.1.12"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/DavidAnson"
+ }
+ },
+ "node_modules/markdownlint-cli2": {
+ "version": "0.15.0",
+ "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.15.0.tgz",
+ "integrity": "sha512-4P/lnxQxU2R5lywRJs4b2ajm8z65CW8qqR1bTIcdQ5EG+nZpC6HJlJUnmIR5ee+uecUkoMroazxWcLB7etSmrg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "globby": "14.0.2",
+ "js-yaml": "4.1.0",
+ "jsonc-parser": "3.3.1",
+ "markdownlint": "0.36.1",
+ "markdownlint-cli2-formatter-default": "0.0.5",
+ "micromatch": "4.0.8"
+ },
+ "bin": {
+ "markdownlint-cli2": "markdownlint-cli2.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/DavidAnson"
+ }
+ },
+ "node_modules/markdownlint-cli2-formatter-default": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/markdownlint-cli2-formatter-default/-/markdownlint-cli2-formatter-default-0.0.5.tgz",
+ "integrity": "sha512-4XKTwQ5m1+Txo2kuQ3Jgpo/KmnG+X90dWt4acufg6HVGadTUG5hzHF/wssp9b5MBYOMCnZ9RMPaU//uHsszF8Q==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/DavidAnson"
+ },
+ "peerDependencies": {
+ "markdownlint-cli2": ">=0.0.4"
+ }
+ },
+ "node_modules/markdownlint-cli2/node_modules/globby": {
+ "version": "14.0.2",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz",
+ "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@sindresorhus/merge-streams": "^2.1.0",
+ "fast-glob": "^3.3.2",
+ "ignore": "^5.2.4",
+ "path-type": "^5.0.0",
+ "slash": "^5.1.0",
+ "unicorn-magic": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/markdownlint-cli2/node_modules/path-type": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz",
+ "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/markdownlint-cli2/node_modules/slash": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz",
+ "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/markdownlint-micromark": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/markdownlint-micromark/-/markdownlint-micromark-0.1.12.tgz",
+ "integrity": "sha512-RlB6EwMGgc0sxcIhOQ2+aq7Zw1V2fBnzbXKGgYK/mVWdT7cz34fteKSwfYeo4rL6+L/q2tyC9QtD/PgZbkdyJQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/DavidAnson"
+ }
+ },
"node_modules/matcher": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz",
@@ -9016,6 +9179,13 @@
"dev": true,
"license": "CC0-1.0"
},
+ "node_modules/mdurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
+ "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@@ -10442,6 +10612,16 @@
"node": ">=6"
}
},
+ "node_modules/punycode.js": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
+ "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/pure-rand": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
@@ -12512,6 +12692,13 @@
"node": ">=14.17"
}
},
+ "node_modules/uc.micro": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
+ "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/uglify-js": {
"version": "3.19.3",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
@@ -12546,6 +12733,19 @@
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
"license": "MIT"
},
+ "node_modules/unicorn-magic": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz",
+ "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
diff --git a/package.json b/package.json
index 8e6f4108a7..d2200a6149 100644
--- a/package.json
+++ b/package.json
@@ -31,6 +31,7 @@
"install-vendor": "echo \"Installing vendor files ...\n\" && cd vendor && npm install --loglevel=error --no-audit --no-fund --no-update-notifier",
"lint:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --config .stylelintrc.json --fix",
"lint:js": "eslint . --fix",
+ "lint:markdown": "markdownlint-cli2 . --fix",
"lint:prettier": "prettier . --write",
"lint:staged": "lint-staged",
"postinstall": "npm run install-vendor && npm run install-fonts && echo \"MagicMirror² installation finished successfully! \n\"",
@@ -51,6 +52,7 @@
"test:e2e": "NODE_ENV=test jest --selectProjects e2e -i --forceExit",
"test:electron": "NODE_ENV=test jest --selectProjects electron -i --forceExit",
"test:js": "eslint .",
+ "test:markdown": "markdownlint-cli2 .",
"test:prettier": "prettier . --check",
"test:spelling": "cspell . --gitignore",
"test:unit": "NODE_ENV=test jest --selectProjects unit"
@@ -92,6 +94,7 @@
"jest": "^29.7.0",
"jsdom": "^25.0.1",
"lint-staged": "^15.2.10",
+ "markdownlint-cli2": "^0.15.0",
"playwright": "^1.48.2",
"prettier": "^3.3.3",
"sinon": "^19.0.2",
diff --git a/prettier.config.mjs b/prettier.config.mjs
new file mode 100644
index 0000000000..7ec216b40b
--- /dev/null
+++ b/prettier.config.mjs
@@ -0,0 +1,13 @@
+const config = {
+ overrides: [
+ {
+ files: "*.md",
+ options: {
+ parser: "markdown"
+ }
+ }
+ ],
+ trailingComma: "none"
+};
+
+export default config;