Compare commits

...

50 Commits

Author SHA1 Message Date
Michael Teeuw
30d5bfe59e Merge pull request #2873 from MichMich/develop
v2.20.0
2022-07-02 13:07:02 +02:00
Michael Teeuw
b716ec33d9 Release v2.20.0 2022-07-02 13:00:01 +02:00
Michael Teeuw
e25209d9f9 Merge pull request #2871 from sdetweil/fix_maxEntries
Fix maximumEntries regression
2022-06-28 15:26:31 +02:00
Sam Detweiler
1f4ac82495 add changelog for #2868 2022-06-28 08:05:13 -05:00
Sam Detweiler
0baf58f3fd fix regression calendar.maximumEntries not used 2022-06-28 08:01:28 -05:00
Michael Teeuw
9a769203e3 Merge pull request #2870 from khassel/update_deps 2022-06-25 10:33:18 +02:00
Karsten Hassel
1435efaea7 update depencies (before upcoming new release) 2022-06-24 23:44:17 +02:00
Michael Teeuw
c411ac821e Merge pull request #2864 from KristjanESPERANTO/develop
Use .yaml instead of .yml
2022-06-17 15:34:21 +02:00
Michael Teeuw
da0489fc0c Merge pull request #2866 from kolbyjack/broadcast-duplicate-events
Include duplicate events in broadcasts
2022-06-17 15:32:17 +02:00
Jonathan Kolb
c82de1e314 Group filters that only apply when limiting for display 2022-06-09 09:21:00 -04:00
Jonathan Kolb
604a555e14 Include duplicate events in broadcasts 2022-06-09 07:52:29 -04:00
Kristjan SCHMIDT
87e011ff96 Add entry for YAML file extention 2022-06-07 00:07:56 +02:00
Kristjan SCHMIDT
9b2051827c Use .yaml instead of .yml
This is the recommended file extension: https://yaml.org/faq.html
2022-06-06 23:57:52 +02:00
Michael Teeuw
47aefb0c82 Merge pull request #2858 from turrisxyz/Pinned-Dependencies-GitHub
chore: Set permissions for GitHub actions
2022-06-04 14:59:28 +02:00
Michael Teeuw
70da1d6f5c Merge pull request #2861 from turrisxyz/Dependabot-GitHub-Actions
chore: Included githubactions in the dependabot config
2022-06-04 14:59:14 +02:00
Michael Teeuw
c0743ce9de Merge pull request #2857 from khassel/fetch 2022-06-04 14:14:52 +02:00
naveen
fe7b4044e0 chore: Included githubactions in the dependabot config
This should help with keeping the GitHub actions updated on new releases. This will also help with keeping it secure.

Dependabot helps in keeping the supply chain secure https://docs.github.com/en/code-security/dependabot

GitHub actions up to date https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot

https://github.com/ossf/scorecard/blob/main/docs/checks.md#dependency-update-tool
Signed-off-by: naveen <172697+naveensrinivasan@users.noreply.github.com>
2022-06-02 01:29:42 +00:00
nathannaveen
701ce8ad47 chore: Set permissions for GitHub actions
Restrict the GitHub token permissions only to the required ones; this way, even if the attackers will succeed in compromising your workflow, they won’t be able to do much.

- Included permissions for the action. https://github.com/ossf/scorecard/blob/main/docs/checks.md#token-permissions

https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions

https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs

[Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/)

Signed-off-by: nathannaveen <42319948+nathannaveen@users.noreply.github.com>
2022-05-30 00:58:20 +00:00
Karsten Hassel
591f907134 fix newsfeedfetcher using correct stream version (changed with node-18-fetch) 2022-05-28 22:28:37 +02:00
Michael Teeuw
4f1db749c0 Merge pull request #2855 from khassel/fetch 2022-05-28 06:38:52 +02:00
Karsten Hassel
ae72ed8c67 improve startApplication 2022-05-27 21:49:29 +02:00
Karsten Hassel
ab7934fa98 Merge branch 'develop' into fetch
# Conflicts:
#	CHANGELOG.md
2022-05-27 21:04:07 +02:00
Michael Teeuw
a4c77f0c9e Merge pull request #2853 from khassel/update_deps 2022-05-27 20:32:45 +02:00
Karsten Hassel
0023c64d59 use internal fetch function of node instead external node-fetch library if node version >= v18 2022-05-27 19:46:28 +02:00
Karsten Hassel
b55b3bd63b update dependencies including electron to v19 2022-05-24 23:50:33 +02:00
Michael Teeuw
cbda20f67e Merge pull request #2850 from khassel/iframe
added a new config option `httpHeaders` used by helmet
2022-05-18 09:15:32 +02:00
Michael Teeuw
e598dbb206 Merge branch 'develop' into iframe 2022-05-18 09:15:16 +02:00
Michael Teeuw
094881fc5c Merge pull request #2848 from rejas/issue_2192
Show endDate for calendar events when using dateHeaders
2022-05-18 09:14:36 +02:00
Michael Teeuw
b13414cab8 Merge branch 'develop' into issue_2192 2022-05-18 09:14:29 +02:00
Michael Teeuw
3e65ac653b Merge pull request #2844 from rejas/actions
Update github actions
2022-05-18 09:13:40 +02:00
Michael Teeuw
05621c9876 Merge branch 'develop' into actions 2022-05-18 09:13:31 +02:00
Michael Teeuw
938619ce0c Merge pull request #2843 from khassel/update-deps
update dependencies
2022-05-18 09:12:59 +02:00
Michael Teeuw
8e5267d44f Merge pull request #2842 from MMRIZE/weather
Added outgoing notification of the weather module
2022-05-18 09:12:48 +02:00
Karsten Hassel
3b55886c45 added a new config option httpHeaders used by helmet 2022-05-13 22:29:43 +02:00
rejas
ed3aceb427 Update CHANGELOG 2022-05-10 21:44:46 +02:00
rejas
c3b2aaec69 Show endDate for calendar events
when dateHeader is enabled and showEnd is set to true
2022-05-10 21:44:39 +02:00
veeck
bb1d3431cc Update node test matrix for real 2022-05-02 22:35:03 +02:00
veeck
fe83fe338a Update CHANGELOG 2022-05-02 22:02:20 +02:00
veeck
6504b5e818 Update github actions and tested node versions 2022-05-02 22:01:26 +02:00
Karsten Hassel
8578900bfb update deps 2022-05-02 21:50:16 +02:00
Michael Teeuw
d730dd04bf Merge pull request #2839 from rohitdharavath/patch-1 2022-04-26 20:46:38 +02:00
eouia
1d90c5e1fe Add JSDoc description 2022-04-26 17:37:23 +02:00
eouia
0f39b7733c fix typo jsdom tag returns 2022-04-26 14:57:47 +02:00
eouia
038b6765e7 Change property name clearly 2022-04-26 14:52:05 +02:00
eouia
58569a648c Added ECMA Version of lint to 2020 2022-04-26 14:51:12 +02:00
eouia
df0f048ecc Added outgoing notification 2022-04-26 13:55:39 +02:00
Rohith Dharavath
288a008e72 Update electron.js
corrected spelling mistake
2022-04-21 01:53:22 +05:30
Michael Teeuw
439690b981 Merge pull request #2836 from khassel/fix-non-latin 2022-04-09 19:18:17 +02:00
Karsten Hassel
b4e75f6844 fix problems with non latin fonds caused by updating to fontsource (fixes #2835). 2022-04-05 20:58:48 +02:00
Michael Teeuw
3f6a5a7772 Prepare 2.20.0-develop 2022-04-01 20:49:47 +02:00
43 changed files with 2472 additions and 3072 deletions

View File

@@ -16,7 +16,7 @@
},
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2018,
"ecmaVersion": 2020,
"ecmaFeatures": {
"globalReturn": true
}

6
.github/dependabot.yaml vendored Normal file
View File

@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

View File

@@ -9,16 +9,19 @@ on:
pull_request:
branches: [master, develop]
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
matrix:
node-version: [14.x, 16.x, 17.x]
node-version: [14.x, 16.x, 18.x]
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:

View File

@@ -1,4 +1,5 @@
# This workflow runs the automated test and uploads the coverage results to codecov.io
# For more information see: https://github.com/codecov/codecov-action
name: "Run Codecov Tests"
@@ -8,13 +9,16 @@ on:
pull_request:
branches: [master, develop]
permissions:
contents: read
jobs:
run-and-upload-coverage-report:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Install dependencies and run coverage
run: |
Xvfb :99 -screen 0 1024x768x16 &

View File

@@ -1,4 +1,5 @@
# This workflow enforces the update of a changelog file on every pull request
# For more information see: https://github.com/dangoslen/changelog-enforcer
name: "Enforce Changelog"
@@ -11,10 +12,8 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Enforce changelog
uses: dangoslen/changelog-enforcer@v2
uses: dangoslen/changelog-enforcer@v3
with:
changeLogPath: "CHANGELOG.md"
skipLabels: "Skip Changelog"

View File

@@ -5,6 +5,28 @@ This project adheres to [Semantic Versioning](https://semver.org/).
❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/donate) With your help we can continue to improve the MagicMirror².
## [2.20.0] - 2022-07-02
Special thanks to the following contributors: @eouia, @khassel, @kolbyjack, @KristjanESPERANTO, @nathannaveen, @naveensrinivasan, @rejas, @rohitdharavath and @sdetweil.
### Added
- Added a new config option `httpHeaders` used by helmet (see https://helmetjs.github.io/). You can now set own httpHeaders which will override the defaults in `js/defauls.js` which is useful e.g. if you want to embed MagicMirror into annother website (solves #2847).
- Show endDate for calendar events when dateHeader is enabled and showEnd is set to true (#2192).
- Added the notification emitting from the weather module on infromation updated.
- Use recommended file extention for YAML files (#2864).
### Updated
- Use latest node 18 when running tests on github actions.
- Update `electron` to v19 and other dependencies.
- Use internal fetch function of node instead external `node-fetch` library if used node version >= `v18`.
- Include duplicate events in broadcasts.
### Fixed
- Fix problems with non latin fonds caused by updating to fontsource (fixes #2835).
## [2.19.0] - 2022-04-01
Special thanks to the following contributors: @10bias, @CFenner, @JHWelch, @k1rd3rf, @khassel, @kolbyjack, @krekos, @KristjanESPERANTO, @Nerfzooka, @oraclesean, @oscarb, @philnagel, @rejas, @sdetweil, @shin10, @SiderealArt and @Tom-Hirschberger.
@@ -12,9 +34,9 @@ Special thanks to the following contributors: @10bias, @CFenner, @JHWelch, @k1rd
### Added
- Added a config option under the weather module, `absoluteDates`, providing an option to format weather forecast date output with either absolute or relative dates.
- Added test for new weather forecast `absoluteDates` porperty.
- Added test for new weather forecast `absoluteDates` property.
- The modules get a class hidden added/removed if they get hidden/shown which will also toggle pointer-events.
- Added new config option `showTitleAsUrl` to newsfeed module. If set, the diplayed title is a link to the article which is useful when running in a browser and you want to read this article.
- Added new config option `showTitleAsUrl` to newsfeed module. If set, the displayed title is a link to the article which is useful when running in a browser and you want to read this article.
- Added internal cors proxy to get weather providers working without public proxies (fixes #2714). The new url `http(s)://address:port/cors?url=https://whatever-to-proxy` can be used in other modules too.
- Added a WeatherProvider for Weatherflow.
- Added new env var `ELECTRON_DISABLE_GPU` which disable gpu under electron if set (fixes #2831).
@@ -39,6 +61,7 @@ Special thanks to the following contributors: @10bias, @CFenner, @JHWelch, @k1rd
- Don't adjust startDate for full day events if endDate is in the past.
- Fix windspeed conversion error in openweathermap provider. (#2812)
- Fix conflicting parms turning off showEnd for full day events. (#2629)
- Fix regression, calendar.maximumEntries not used to filter calendar level entries (#2868)
## [2.18.0] - 2022-01-01

View File

@@ -7,31 +7,31 @@
"name": "magicmirror-fonts",
"license": "MIT",
"dependencies": {
"@fontsource/roboto": "^4.5.5",
"@fontsource/roboto-condensed": "^4.5.6"
"@fontsource/roboto": "^4.5.7",
"@fontsource/roboto-condensed": "^4.5.8"
}
},
"node_modules/@fontsource/roboto": {
"version": "4.5.5",
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.5.tgz",
"integrity": "sha512-Pe1p+gAO6K0aLxBXlLoJRHVx352tVc/v/7DOnvM3t+FYXb+KUga9aCD1NpnDfd0kKnWXqrZyAXguyyFWDDuphw=="
"version": "4.5.7",
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.7.tgz",
"integrity": "sha512-m57UMER23Mk6Drg9OjtHW1Y+0KPGyZfE5XJoPTOsLARLar6013kJj4X2HICt+iFLJqIgTahA/QAvSn9lwF1EEw=="
},
"node_modules/@fontsource/roboto-condensed": {
"version": "4.5.6",
"resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-4.5.6.tgz",
"integrity": "sha512-WDN0RlwXa3ADUDJxrB9HEIhrwYdJFLTNw4YemEYSeIPURU5DAHSx2VFXFv69PbM7kV8At5yMTp8bQkL5TBUP3w=="
"version": "4.5.8",
"resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-4.5.8.tgz",
"integrity": "sha512-HCuf1rVSOsXnl/KgHNRLCr8XS/Dunzn10BjhliJiEZ5qPynXCWH4RRBFupIODHamhj2Uyp/iZkSQp574luKp6A=="
}
},
"dependencies": {
"@fontsource/roboto": {
"version": "4.5.5",
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.5.tgz",
"integrity": "sha512-Pe1p+gAO6K0aLxBXlLoJRHVx352tVc/v/7DOnvM3t+FYXb+KUga9aCD1NpnDfd0kKnWXqrZyAXguyyFWDDuphw=="
"version": "4.5.7",
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.7.tgz",
"integrity": "sha512-m57UMER23Mk6Drg9OjtHW1Y+0KPGyZfE5XJoPTOsLARLar6013kJj4X2HICt+iFLJqIgTahA/QAvSn9lwF1EEw=="
},
"@fontsource/roboto-condensed": {
"version": "4.5.6",
"resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-4.5.6.tgz",
"integrity": "sha512-WDN0RlwXa3ADUDJxrB9HEIhrwYdJFLTNw4YemEYSeIPURU5DAHSx2VFXFv69PbM7kV8At5yMTp8bQkL5TBUP3w=="
"version": "4.5.8",
"resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-4.5.8.tgz",
"integrity": "sha512-HCuf1rVSOsXnl/KgHNRLCr8XS/Dunzn10BjhliJiEZ5qPynXCWH4RRBFupIODHamhj2Uyp/iZkSQp574luKp6A=="
}
}
}

View File

@@ -10,7 +10,7 @@
"url": "https://github.com/MichMich/MagicMirror/issues"
},
"dependencies": {
"@fontsource/roboto": "^4.5.5",
"@fontsource/roboto-condensed": "^4.5.6"
"@fontsource/roboto": "^4.5.7",
"@fontsource/roboto-condensed": "^4.5.8"
}
}

View File

@@ -2,57 +2,54 @@
font-family: Roboto;
font-style: normal;
font-weight: 100;
src: local("Roboto Thin"), local("Roboto-Thin"), url("node_modules/@fontsource/roboto/files/roboto-latin-100-normal.woff2") format("woff2"), url("node_modules/@fontsource/roboto/files/roboto-latin-100-normal.woff") format("woff");
src: local("Roboto Thin"), local("Roboto-Thin"), url("node_modules/@fontsource/roboto/files/roboto-all-100-normal.woff") format("woff");
}
@font-face {
font-family: "Roboto Condensed";
font-style: normal;
font-weight: 300;
src: local("Roboto Condensed Light"), local("RobotoCondensed-Light"), url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-300-normal.woff2") format("woff2"),
url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-300-normal.woff") format("woff");
src: local("Roboto Condensed Light"), local("RobotoCondensed-Light"), url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-all-300-normal.woff") format("woff");
}
@font-face {
font-family: "Roboto Condensed";
font-style: normal;
font-weight: 400;
src: local("Roboto Condensed"), local("RobotoCondensed-Regular"), url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-400-normal.woff2") format("woff2"),
url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-400-normal.woff") format("woff");
src: local("Roboto Condensed"), local("RobotoCondensed-Regular"), url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-all-400-normal.woff") format("woff");
}
@font-face {
font-family: "Roboto Condensed";
font-style: normal;
font-weight: 700;
src: local("Roboto Condensed Bold"), local("RobotoCondensed-Bold"), url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-700-normal.woff2") format("woff2"),
url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-700-normal.woff") format("woff");
src: local("Roboto Condensed Bold"), local("RobotoCondensed-Bold"), url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-all-700-normal.woff") format("woff");
}
@font-face {
font-family: Roboto;
font-style: normal;
font-weight: 400;
src: local("Roboto"), local("Roboto-Regular"), url("node_modules/@fontsource/roboto/files/roboto-latin-400-normal.woff2") format("woff2"), url("node_modules/@fontsource/roboto/files/roboto-latin-400-normal.woff") format("woff");
src: local("Roboto"), local("Roboto-Regular"), url("node_modules/@fontsource/roboto/files/roboto-all-400-normal.woff") format("woff");
}
@font-face {
font-family: Roboto;
font-style: normal;
font-weight: 500;
src: local("Roboto Medium"), local("Roboto-Medium"), url("node_modules/@fontsource/roboto/files/roboto-latin-500-normal.woff2") format("woff2"), url("node_modules/@fontsource/roboto/files/roboto-latin-500-normal.woff") format("woff");
src: local("Roboto Medium"), local("Roboto-Medium"), url("node_modules/@fontsource/roboto/files/roboto-all-500-normal.woff") format("woff");
}
@font-face {
font-family: Roboto;
font-style: normal;
font-weight: 700;
src: local("Roboto Bold"), local("Roboto-Bold"), url("node_modules/@fontsource/roboto/files/roboto-latin-700-normal.woff2") format("woff2"), url("node_modules/@fontsource/roboto/files/roboto-latin-700-normal.woff") format("woff");
src: local("Roboto Bold"), local("Roboto-Bold"), url("node_modules/@fontsource/roboto/files/roboto-all-700-normal.woff") format("woff");
}
@font-face {
font-family: Roboto;
font-style: normal;
font-weight: 300;
src: local("Roboto Light"), local("Roboto-Light"), url("node_modules/@fontsource/roboto/files/roboto-latin-300-normal.woff2") format("woff2"), url("node_modules/@fontsource/roboto/files/roboto-latin-300-normal.woff") format("woff");
src: local("Roboto Light"), local("Roboto-Light"), url("node_modules/@fontsource/roboto/files/roboto-all-300-normal.woff") format("woff");
}

View File

@@ -25,6 +25,9 @@ const defaults = {
units: "metric",
zoom: 1,
customCss: "css/custom.css",
// 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/MichMich/MagicMirror/issues/2847
httpHeaders: { contentSecurityPolicy: false, crossOriginOpenerPolicy: false, crossOriginEmbedderPolicy: false, crossOriginResourcePolicy: false, originAgentCluster: false },
modules: [
{

View File

@@ -8,7 +8,7 @@ const Log = require("logger");
let config = process.env.config ? JSON.parse(process.env.config) : {};
// Module to control application life.
const app = electron.app;
// If ELECTRON_DISABLE_GPU is set electron is startet with --disable-gpu flag.
// If ELECTRON_DISABLE_GPU is set electron is started with --disable-gpu flag.
// See https://www.electronjs.org/docs/latest/tutorial/offscreen-rendering for more info.
if (process.env.ELECTRON_DISABLE_GPU !== undefined) {
app.disableHardwareAcceleration();

20
js/fetch.js Normal file
View File

@@ -0,0 +1,20 @@
/**
* fetch
*
* @param {string} url to be fetched
* @param {object} options object e.g. for headers
* @class
*/
async function fetch(url, options) {
const nodeVersion = process.version.match(/^v(\d+)\.*/)[1];
if (nodeVersion >= 18) {
// node version >= 18
return global.fetch(url, options);
} else {
// node version < 18
const nodefetch = require("node-fetch");
return nodefetch(url, options);
}
}
module.exports = fetch;

View File

@@ -10,7 +10,7 @@ const path = require("path");
const ipfilter = require("express-ipfilter").IpFilter;
const fs = require("fs");
const helmet = require("helmet");
const fetch = require("node-fetch");
const fetch = require("fetch");
const Log = require("logger");
const Utils = require("./utils.js");
@@ -69,7 +69,7 @@ function Server(config, callback) {
res.status(403).send("This device is not allowed to access your mirror. <br> Please check your config.js or config.js.sample to change this.");
});
});
app.use(helmet({ contentSecurityPolicy: false, crossOriginOpenerPolicy: false, crossOriginEmbedderPolicy: false, crossOriginResourcePolicy: false, originAgentCluster: false }));
app.use(helmet(config.httpHeaders));
app.use("/js", express.static(__dirname));

View File

@@ -305,6 +305,12 @@ Module.register("calendar", {
timeWrapper.className = "time light align-left " + this.timeClassForUrl(event.url);
timeWrapper.style.paddingLeft = "2px";
timeWrapper.innerHTML = moment(event.startDate, "x").format("LT");
// Add endDate to dataheaders if showEnd is enabled
if (this.config.showEnd) {
timeWrapper.innerHTML += " - " + moment(event.endDate, "x").format("LT");
}
eventWrapper.appendChild(timeWrapper);
titleWrapper.classList.add("align-right");
}
@@ -381,7 +387,7 @@ Module.register("calendar", {
}
}
} else if (event.startDate - now < this.config.getRelative * oneHour) {
// If event is within getRelative hours, display 'in xxx' time format or moment.fromNow()
// If event is within getRelative hours, display 'in xxx' time format or moment.fromNow()
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow());
}
} else {
@@ -490,22 +496,20 @@ Module.register("calendar", {
for (const e in calendar) {
const event = JSON.parse(JSON.stringify(calendar[e])); // clone object
if (event.endDate < now && limitNumberOfEntries) {
if (this.config.hidePrivate && event.class === "PRIVATE") {
// do not add the current event, skip it
continue;
}
if (this.config.hidePrivate) {
if (event.class === "PRIVATE") {
// do not add the current event, skip it
if (limitNumberOfEntries) {
if (event.endDate < now) {
continue;
}
}
if (this.config.hideOngoing && limitNumberOfEntries) {
if (event.startDate < now) {
if (this.config.hideOngoing && event.startDate < now) {
continue;
}
if (this.listContainsEvent(events, event)) {
continue;
}
}
if (this.listContainsEvent(events, event)) {
continue;
}
event.url = calendarUrl;
event.today = event.startDate >= today && event.startDate < today + 24 * 60 * 60 * 1000;

View File

@@ -8,7 +8,7 @@ const CalendarUtils = require("./calendarutils");
const Log = require("logger");
const NodeHelper = require("node_helper");
const ical = require("node-ical");
const fetch = require("node-fetch");
const fetch = require("fetch");
const digest = require("digest-fetch");
const https = require("https");

View File

@@ -498,7 +498,8 @@ const CalendarUtils = {
return a.startDate - b.startDate;
});
return newEvents;
let maxEvents = newEvents.slice(0, config.maximumEntries);
return maxEvents;
},
/**

View File

@@ -7,8 +7,9 @@
const Log = require("logger");
const FeedMe = require("feedme");
const NodeHelper = require("node_helper");
const fetch = require("node-fetch");
const fetch = require("fetch");
const iconv = require("iconv-lite");
const stream = require("stream");
/**
* Responsible for requesting an update on the set interval and broadcasting the data.
@@ -87,7 +88,13 @@ const NewsfeedFetcher = function (url, reloadInterval, encoding, logFeedWarnings
fetch(url, { headers: headers })
.then(NodeHelper.checkFetchStatus)
.then((response) => {
response.body.pipe(iconv.decodeStream(encoding)).pipe(parser);
let nodeStream;
if (response.body instanceof stream.Readable) {
nodeStream = response.body;
} else {
nodeStream = stream.Readable.fromWeb(response.body);
}
nodeStream.pipe(iconv.decodeStream(encoding)).pipe(parser);
})
.catch((error) => {
fetchFailedCallback(this, error);

View File

@@ -154,6 +154,15 @@ Module.register("weather", {
if (this.weatherProvider.currentWeather()) {
this.sendNotification("CURRENTWEATHER_TYPE", { type: this.weatherProvider.currentWeather().weatherType.replace("-", "_") });
}
const notificationPayload = {
currentWeather: this.weatherProvider?.currentWeatherObject?.simpleClone() ?? null,
forecastArray: this.weatherProvider?.weatherForecastArray?.map((ar) => ar.simpleClone()) ?? [],
hourlyArray: this.weatherProvider?.weatherHourlyArray?.map((ar) => ar.simpleClone()) ?? [],
locationName: this.weatherProvider?.fetchedLocationName,
providerName: this.weatherProvider.providerName
};
this.sendNotification("WEATHER_UPDATED", notificationPayload);
},
scheduleUpdate: function (delay = null) {

View File

@@ -146,6 +146,23 @@ class WeatherObject {
this.sunrise = moment(times.sunrise, "X");
this.sunset = moment(times.sunset, "X");
}
/**
* Clone to simple object to prevent mutating and deprecation of legacy library.
*
* Before being handed to other modules, mutable values must be cloned safely.
* Especially 'moment' object is not immutable, so original 'date', 'sunrise', 'sunset' could be corrupted or changed by other modules.
*
* @returns {object} plained object clone of original weatherObject
*/
simpleClone() {
const toFlat = ["date", "sunrise", "sunset"];
let clone = { ...this };
for (const prop of toFlat) {
clone[prop] = clone?.[prop]?.valueOf() ?? clone?.[prop];
}
return clone;
}
}
/*************** DO NOT EDIT THE LINE BELOW ***************/

5197
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "magicmirror",
"version": "2.19.0",
"version": "2.20.0",
"description": "The open source modular smart mirror platform.",
"main": "js/electron.js",
"scripts": {
@@ -48,48 +48,49 @@
"homepage": "https://magicmirror.builders",
"devDependencies": {
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-jest": "^26.1.3",
"eslint-plugin-jsdoc": "^38.1.3",
"eslint-plugin-jest": "^26.5.3",
"eslint-plugin-jsdoc": "^39.3.3",
"eslint-plugin-prettier": "^4.0.0",
"express-basic-auth": "^1.2.1",
"husky": "^7.0.4",
"jest": "^27.5.1",
"jsdom": "^19.0.0",
"husky": "^8.0.1",
"jest": "^28.1.1",
"jsdom": "^20.0.0",
"lodash": "^4.17.21",
"nyc": "^15.1.0",
"playwright": "^1.20.1",
"prettier": "^2.6.1",
"playwright": "^1.22.2",
"prettier": "^2.7.1",
"pretty-quick": "^3.1.3",
"sinon": "^13.0.1",
"stylelint": "^14.6.1",
"sinon": "^14.0.0",
"stylelint": "^14.9.1",
"stylelint-config-prettier": "^9.0.3",
"stylelint-config-standard": "^25.0.0",
"stylelint-config-standard": "^26.0.0",
"stylelint-prettier": "^2.0.0",
"suncalc": "^1.9.0"
},
"optionalDependencies": {
"electron": "^17.2.0"
"electron": "^19.0.6"
},
"dependencies": {
"colors": "^1.4.0",
"console-stamp": "^3.0.4",
"console-stamp": "^3.0.6",
"digest-fetch": "^1.2.1",
"eslint": "^8.12.0",
"express": "^4.17.3",
"eslint": "^8.18.0",
"express": "^4.18.1",
"express-ipfilter": "^1.2.0",
"feedme": "^2.0.2",
"helmet": "^5.0.2",
"helmet": "^5.1.0",
"iconv-lite": "^0.6.3",
"luxon": "^1.21.3",
"luxon": "^1.28.0",
"module-alias": "^2.2.2",
"moment": "^2.29.1",
"moment": "^2.29.3",
"node-fetch": "^2.6.7",
"node-ical": "^0.15.1",
"socket.io": "^4.4.1"
"socket.io": "^4.5.1"
},
"_moduleAliases": {
"node_helper": "js/node_helper.js",
"logger": "js/logger.js"
"logger": "js/logger.js",
"fetch": "js/fetch.js"
},
"engines": {
"node": ">=14"

View File

@@ -1,4 +1,4 @@
const fetch = require("node-fetch");
const fetch = require("fetch");
const helpers = require("./global-setup");
describe("App environment", function () {
@@ -6,8 +6,8 @@ describe("App environment", function () {
helpers.startApplication("tests/configs/default.js");
helpers.getDocument(done);
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
it("get request from http://localhost:8080 should return 200", function (done) {

View File

@@ -1,4 +1,4 @@
const fetch = require("node-fetch");
const fetch = require("fetch");
const helpers = require("./global-setup");
describe("All font files from roboto.css should be downloadable", function () {
@@ -17,8 +17,8 @@ describe("All font files from roboto.css should be downloadable", function () {
beforeAll(function () {
helpers.startApplication("tests/configs/without_modules.js");
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
test.each(fontFiles)("should return 200 HTTP code for file '%s'", (fontFile, done) => {

View File

@@ -2,9 +2,7 @@ const jsdom = require("jsdom");
exports.startApplication = function (configFilename, exec) {
jest.resetModules();
if (global.app) {
global.app.stop();
}
this.stopApplication();
// Set config sample for use in test
if (configFilename === "") {
process.env.MM_CONFIG_FILE = "config/config.js";
@@ -16,10 +14,11 @@ exports.startApplication = function (configFilename, exec) {
global.app.start();
};
exports.stopApplication = function () {
exports.stopApplication = async function () {
if (global.app) {
global.app.stop();
}
await new Promise((resolve) => setTimeout(resolve, 100));
};
exports.getDocument = function (callback) {

View File

@@ -1,4 +1,4 @@
const fetch = require("node-fetch");
const fetch = require("fetch");
const helpers = require("./global-setup");
describe("ipWhitelist directive configuration", function () {
@@ -6,8 +6,8 @@ describe("ipWhitelist directive configuration", function () {
beforeAll(function () {
helpers.startApplication("tests/configs/noIpWhiteList.js");
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
it("should return 403", function (done) {
@@ -22,8 +22,8 @@ describe("ipWhitelist directive configuration", function () {
beforeAll(function () {
helpers.startApplication("tests/configs/empty_ipWhiteList.js");
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
it("should return 200", function (done) {

View File

@@ -5,8 +5,8 @@ describe("Alert module", function () {
helpers.startApplication("tests/configs/modules/alert/default.js");
helpers.getDocument(done);
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
it("should show the welcome message", function () {

View File

@@ -25,8 +25,8 @@ describe("Calendar module", function () {
});
};
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
describe("Default configuration", function () {

View File

@@ -1,8 +1,8 @@
const helpers = require("../global-setup");
describe("Clock set to spanish language module", function () {
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
const testMatch = function (element, regex) {

View File

@@ -2,8 +2,8 @@ const helpers = require("../global-setup");
const moment = require("moment");
describe("Clock module", function () {
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
const testMatch = function (element, regex) {

View File

@@ -16,8 +16,8 @@ function doTest(complimentsArray) {
}
describe("Compliments module", function () {
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
describe("parts of days", function () {

View File

@@ -1,8 +1,8 @@
const helpers = require("../global-setup");
describe("Test helloworld module", function () {
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
describe("helloworld set config text", function () {

View File

@@ -1,8 +1,8 @@
const helpers = require("../global-setup");
describe("Newsfeed module", function () {
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
describe("Default configuration", function () {

View File

@@ -40,8 +40,8 @@ describe("Weather module", function () {
helpers.getDocument(callback);
}
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
describe("Current weather", function () {

View File

@@ -5,8 +5,8 @@ describe("Display of modules", function () {
helpers.startApplication("tests/configs/modules/display.js");
helpers.getDocument(done);
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
it("should show the test header", function () {

View File

@@ -5,8 +5,8 @@ describe("Position of modules", function () {
helpers.startApplication("tests/configs/modules/positions.js");
helpers.getDocument(done);
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
const positions = ["top_bar", "top_left", "top_center", "top_right", "upper_third", "middle_center", "lower_third", "bottom_left", "bottom_center", "bottom_right", "bottom_bar", "fullscreen_above", "fullscreen_below"];

View File

@@ -1,4 +1,4 @@
const fetch = require("node-fetch");
const fetch = require("fetch");
const helpers = require("./global-setup");
describe("port directive configuration", function () {
@@ -6,8 +6,8 @@ describe("port directive configuration", function () {
beforeAll(function () {
helpers.startApplication("tests/configs/port_8090.js");
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
it("should return 200", function (done) {
@@ -22,8 +22,8 @@ describe("port directive configuration", function () {
beforeAll(function () {
helpers.startApplication("tests/configs/port_8090.js", (process.env.MM_PORT = 8100));
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
it("should return 200", function (done) {

View File

@@ -1,12 +1,12 @@
const fetch = require("node-fetch");
const fetch = require("fetch");
const helpers = require("./global-setup");
describe("Vendors", function () {
beforeAll(function () {
helpers.startApplication("tests/configs/default.js");
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
describe("Get list vendors", function () {

View File

@@ -5,8 +5,8 @@ describe("Check configuration without modules", function () {
helpers.startApplication("tests/configs/without_modules.js");
helpers.getDocument(done);
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
it("Show the message MagicMirror² title", function () {

14
vendor/package-lock.json generated vendored
View File

@@ -8,7 +8,7 @@
"license": "MIT",
"dependencies": {
"@fortawesome/fontawesome-free": "^6.1.1",
"moment": "^2.29.1",
"moment": "^2.29.3",
"moment-timezone": "^0.5.34",
"nunjucks": "^3.2.3",
"suncalc": "^1.9.0",
@@ -43,9 +43,9 @@
}
},
"node_modules/moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==",
"version": "2.29.3",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz",
"integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==",
"engines": {
"node": "*"
}
@@ -118,9 +118,9 @@
"integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="
},
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
"version": "2.29.3",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz",
"integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw=="
},
"moment-timezone": {
"version": "0.5.34",

2
vendor/package.json vendored
View File

@@ -11,7 +11,7 @@
},
"dependencies": {
"@fortawesome/fontawesome-free": "^6.1.1",
"moment": "^2.29.1",
"moment": "^2.29.3",
"moment-timezone": "^0.5.34",
"nunjucks": "^3.2.3",
"suncalc": "^1.9.0",