Release 2.27.0 (#3410)

## [2.27.0] - 2024-04-01

Thanks to: @bugsounet, @crazyscot, @illimarkangur, @jkriegshauser,
@khassel, @KristjanESPERANTO, @Paranoid93, @rejas, @sdetweil and
@vppencilsharpener.

This release marks the first release without Michael Teeuw (@michmich).
A very special thanks to him for creating MagicMirror and leading the
project for so many years.

For more info, please read the following post: [A New Chapter for
MagicMirror: The Community Takes the
Lead](https://forum.magicmirror.builders/topic/18329/a-new-chapter-for-magicmirror-the-community-takes-the-lead).

### Added

- Output of system information to the console for troubleshooting (#3328
and #3337), ignore errors under aarch64 (#3349)
- [chore] Add `eslint-plugin-package-json` to lint the `package.json`
files (#3368)
- [weather] `showHumidity` config is now a string describing where to
show this element. Supported values: "wind", "temp", "feelslike",
"below", "none". (#3330)
- electron-rebuild test suite for electron and 3rd party modules
compatibility (#3392)
- Create MM² icon and attach it to electron process (#3407)

### Updated

- Update updatenotification (update_helper.js): Recode with pm2 library
(#3332)
- Removing lodash dependency by replacing merge by spread operator
(#3339)
- Use node prefix for build-in modules (#3340)
- Rework logging colors (#3350)
- Update pm2 to v5.3.1 with no allow-ghsas (#3364)
- [chore] Update husky and let lint-staged fix ESLint issues
- [chore] Update dependencies including electron to v29 (#3357) and
node-ical
- Update translations for estonian (#3371)
- Update electron to v29 and update other dependencies
- [calendar] fullDay events over several days now show the left days
from the first day on and 'today' on the last day
- Update layout of current weather indoor values

### Fixed

- Correct apibase of weathergov weatherprovider to match documentation
(#2926)
- Worked around several issues in the RRULE library that were causing
deleted calender events to still show, some
initial and recurring events to not show, and some event times to be off
an hour. (#3291)
- Skip changelog requirement when running tests for dependency updates
(#3320)
- Display precipitation probability when it is 0% instead of blank/empty
(#3345)
- [newsfeed] Suppress unsightly animation cases when there are 0 or 1
active news items (#3336)
- [newsfeed] Always compute the feed item URL using the same helper
function (#3336)
- Ignore all custom css files (#3359)
- [newsfeed] Fix newsfeed stall issue introduced by #3336 (#3361)
- Changed `log.debug` to `log.log` in `app.js` where logLevel is not set
because config is not loaded at this time (#3353)
- [calendar] deny fetch interval < 60000 and set 60000 in this case
(prevent fetch loop failed) (#3382)
- added message in case where config.js is missing the module.export
line PR #3383
- Fixed an issue where recurring events could extend past their
recurrence end date (#3393)
- Don't display any `npm WARN <....>` on install (#3399)
- Fixed move suncalc dependency to production from dev, as it is used by
clock module
- [compliments] Fix mirror not responding anymore when no compliments
are to be shown (#3385)

### Deleted

- Unneeded file headers (#3358)

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Michael Teeuw <michael@xonaymedia.nl>
Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Karsten Hassel <hassel@gmx.de>
Co-authored-by: Ross Younger <crazyscot@gmail.com>
Co-authored-by: Bugsounet - Cédric <github@bugsounet.fr>
Co-authored-by: jkriegshauser <joshuakr@nvidia.com>
Co-authored-by: illimarkangur <116028111+illimarkangur@users.noreply.github.com>
Co-authored-by: sam detweiler <sdetweil@gmail.com>
Co-authored-by: vppencilsharpener <tim.pray@gmail.com>
Co-authored-by: Paranoid93 <6515818+Paranoid93@users.noreply.github.com>
This commit is contained in:
Veeck 2024-04-01 22:03:20 +02:00 committed by GitHub
parent 118e21238c
commit 5ea8a3469a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
173 changed files with 4025 additions and 2474 deletions

View file

@ -1 +1,2 @@
modules/default/calendar/vendor/*
modules/*
!modules/default/

View file

@ -1,9 +1,9 @@
{
"extends": ["eslint:recommended", "plugin:@stylistic/all-extends", "plugin:import/recommended", "plugin:jest/recommended", "plugin:jsdoc/recommended"],
"plugins": [],
"plugins": ["unicorn"],
"env": {
"browser": true,
"es2023": true,
"es2024": true,
"jest/globals": true,
"node": true
},
@ -16,7 +16,7 @@
},
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2023,
"ecmaVersion": "latest",
"ecmaFeatures": {
"globalReturn": true
}
@ -62,7 +62,8 @@
"@stylistic/indent": ["error", "tab"],
"@stylistic/semi": ["error", "always"],
"@stylistic/space-before-function-paren": ["error", "always"],
"@stylistic/spaced-comment": "off"
"@stylistic/spaced-comment": "off",
"unicorn/prefer-node-protocol": "error"
},
"overrides": [
{
@ -78,6 +79,15 @@
"rules": {
"@stylistic/quotes": "off"
}
},
{
"extends": ["plugin:package-json/recommended"],
"files": ["package.json"],
"parser": "jsonc-eslint-parser",
"plugins": ["package-json"],
"rules": {
"package-json/sort-collections": ["error", ["devDependencies", "dependencies", "peerDependencies", "config"]]
}
}
]
}

10
.github/codecov.yaml vendored
View file

@ -1,10 +0,0 @@
coverage:
status:
project:
default:
# advanced settings
informational: true
patch:
default:
threshold: 0%
target: 0

View file

@ -5,21 +5,36 @@ updates:
schedule:
interval: "weekly"
target-branch: "develop"
labels:
- "Skip Changelog"
- "dependencies"
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "monthly"
target-branch: "develop"
labels:
- "Skip Changelog"
- "dependencies"
- "javascript"
- package-ecosystem: "npm"
directory: "/vendor"
schedule:
interval: "monthly"
target-branch: "develop"
labels:
- "Skip Changelog"
- "dependencies"
- "javascript"
- package-ecosystem: "npm"
directory: "/fonts"
schedule:
interval: "monthly"
target-branch: "develop"
labels:
- "Skip Changelog"
- "dependencies"
- "javascript"

View file

@ -15,4 +15,4 @@ jobs:
- name: "Checkout code"
uses: actions/checkout@v4
- name: "Dependency Review"
uses: actions/dependency-review-action@v3
uses: actions/dependency-review-action@v4

20
.github/workflows/electronRebuild.yaml vendored Normal file
View file

@ -0,0 +1,20 @@
name: "Electron Rebuild Testing"
on: [pull_request]
jobs:
rebuild:
name: Run electron-rebuild
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install MagicMirror
run: npm run install-mm
- name: Install @electron/rebuild
run: npm install @electron/rebuild
- name: Install some test library to be rebuilded
run: npm install onoff node-pty drivelist
- name: Run electron-rebuild
run: npx electron-rebuild
continue-on-error: false

View file

@ -19,7 +19,7 @@ jobs:
changeLogPath: "CHANGELOG.md"
skipLabels: "Skip Changelog"
- name: "Enforce develop branch"
if: ${{ github.base_ref == 'master' && !contains(github.event.pull_request.labels.*.name, 'mastermerge') }}
if: ${{ github.event.pull_request.base.ref == 'master' && !contains(github.event.pull_request.labels.*.name, 'mastermerge') }}
run: |
echo "This PR is based against the master branch and not a release or hotfix."
echo "Please don't do this. Switch the branch to 'develop'."

6
.gitignore vendored
View file

@ -63,8 +63,10 @@ Temporary Items
!/modules/default/**
!/modules/README.md**
# Ignore changes to the custom css files.
/css/custom.css
# Ignore changes to the custom css files but keep the sample and main.
/css/*
!/css/custom.css.sample
!/css/main.css
# Ignore users config file but keep the sample.
/config/*

View file

@ -1,7 +1,5 @@
#!/bin/sh
[ -f "$(dirname "$0")/_/husky.sh" ] && . "$(dirname "$0")/_/husky.sh"
if command -v npm &> /dev/null; then
npm run lint:staged
fi

1
.npmrc
View file

@ -1,2 +1,3 @@
engine-strict=true
audit=false
loglevel="error"

View file

@ -1,4 +1,6 @@
*.js
.eslintignore
.husky/pre-commit
.prettierignore
/config
/coverage

View file

@ -3,9 +3,64 @@
All notable changes to this project will be documented in this file.
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².
❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/#donate) With your help we can continue to improve the MagicMirror².
## [2.26.0] - 01-01-2024
## [2.27.0] - 2024-04-01
Thanks to: @bugsounet, @crazyscot, @illimarkangur, @jkriegshauser, @khassel, @KristjanESPERANTO, @Paranoid93, @rejas, @sdetweil and @vppencilsharpener.
This release marks the first release without Michael Teeuw (@michmich). A very special thanks to him for creating MagicMirror and leading the project for so many years.
For more info, please read the following post: [A New Chapter for MagicMirror: The Community Takes the Lead](https://forum.magicmirror.builders/topic/18329/a-new-chapter-for-magicmirror-the-community-takes-the-lead).
### Added
- Output of system information to the console for troubleshooting (#3328 and #3337), ignore errors under aarch64 (#3349)
- [chore] Add `eslint-plugin-package-json` to lint the `package.json` files (#3368)
- [weather] `showHumidity` config is now a string describing where to show this element. Supported values: "wind", "temp", "feelslike", "below", "none". (#3330)
- electron-rebuild test suite for electron and 3rd party modules compatibility (#3392)
- Create MM² icon and attach it to electron process (#3407)
### Updated
- Update updatenotification (update_helper.js): Recode with pm2 library (#3332)
- Removing lodash dependency by replacing merge by spread operator (#3339)
- Use node prefix for build-in modules (#3340)
- Rework logging colors (#3350)
- Update pm2 to v5.3.1 with no allow-ghsas (#3364)
- [chore] Update husky and let lint-staged fix ESLint issues
- [chore] Update dependencies including electron to v29 (#3357) and node-ical
- Update translations for estonian (#3371)
- Update electron to v29 and update other dependencies
- [calendar] fullDay events over several days now show the left days from the first day on and 'today' on the last day
- Update layout of current weather indoor values
### Fixed
- Correct apibase of weathergov weatherprovider to match documentation (#2926)
- Worked around several issues in the RRULE library that were causing deleted calender events to still show, some
initial and recurring events to not show, and some event times to be off an hour. (#3291)
- Skip changelog requirement when running tests for dependency updates (#3320)
- Display precipitation probability when it is 0% instead of blank/empty (#3345)
- [newsfeed] Suppress unsightly animation cases when there are 0 or 1 active news items (#3336)
- [newsfeed] Always compute the feed item URL using the same helper function (#3336)
- Ignore all custom css files (#3359)
- [newsfeed] Fix newsfeed stall issue introduced by #3336 (#3361)
- Changed `log.debug` to `log.log` in `app.js` where logLevel is not set because config is not loaded at this time (#3353)
- [calendar] deny fetch interval < 60000 and set 60000 in this case (prevent fetch loop failed) (#3382)
- added message in case where config.js is missing the module.export line PR #3383
- Fixed an issue where recurring events could extend past their recurrence end date (#3393)
- Don't display any `npm WARN <....>` on install (#3399)
- Fixed move suncalc dependency to production from dev, as it is used by clock module
- [compliments] Fix mirror not responding anymore when no compliments are to be shown (#3385)
- [chore] Fixed mastermerge workflow (#3415)
### Deleted
- Unneeded file headers (#3358)
- Removed codecov.yaml
## [2.26.0] - 2024-01-01
Thanks to: @bnitkin, @bugsounet, @dependabot, @jkriegshauser, @kaennchenstruggle, @KristjanESPERANTO and @Ybbet.
@ -49,7 +104,7 @@ This release also marks the latest release by Michael Teeuw. For more info, plea
- Fix #3256 filter out bad results from rrule.between
- Fix calendar events sometimes not respecting deleted events (#3250)
- Fix electron loadurl locally on Windows when address "0.0.0.0" (#2550)
- Fix updatanotification (update_helper.js): catch error if reponse is not an JSON format (check PM2)
- Fix updatanotification (update_helper.js): catch error if response is not an JSON format (check PM2)
- Fix missing typeof in calendar module
- Fix style issues after prettier update
- Fix calendar test (#3291) by moving "Exdate check" from e2e to electron to run on a Thursday
@ -124,8 +179,8 @@ Special thanks to @khassel, @rejas and @sdetweil for taking over most (if not al
- Added tests for serveronly
- Set Timezone `Europe/Berlin` in unit tests (needed for new formatTime tests)
- Added no-param-reassign eslint rule and fix warnings
- updatenotification: Added `sendUpdatesNotifications` feature. Broadcast update with `UPDATES` notification to other modules
- updatenotification: allow force scanning with `SCAN_UPDATES` notification from other modules
- [updatenotification] Added `sendUpdatesNotifications` feature. Broadcast update with `UPDATES` notification to other modules
- [updatenotification] Allow force scanning with `SCAN_UPDATES` notification from other modules
- Added per-calendar fetchInterval
### Removed
@ -652,12 +707,12 @@ Special thanks to the following contributors: @bryanzzhu, @bugsounet, @chamakura
### Fixed
- Fix backward compatibility issues for Safari < 11.
- Fix the use of "maxNumberOfDays" in the module "weatherforecast depending on the endpoint (forecast/daily or forecast)". [#2018](https://github.com/MichMich/MagicMirror/issues/2018)
- Fix calendar display. Account for current timezone. [#2068](https://github.com/MichMich/MagicMirror/issues/2068)
- Fix the use of "maxNumberOfDays" in the module "weatherforecast depending on the endpoint (forecast/daily or forecast)". [#2018](https://github.com/MagicMirrorOrg/MagicMirror/issues/2018)
- Fix calendar display. Account for current timezone. [#2068](https://github.com/MagicMirrorOrg/MagicMirror/issues/2068)
- Fix logLevel being set before loading config.
- Fix incorrect namespace links in svg clockfaces. [#2072](https://github.com/MichMich/MagicMirror/issues/2072)
- Fix weather/providers/weathergov for API guidelines. [#2045](https://github.com/MichMich/MagicMirror/issues/2045)
- Fix "undefined" in weather modules header. [#1985](https://github.com/MichMich/MagicMirror/issues/1985)
- Fix incorrect namespace links in svg clockfaces. [#2072](https://github.com/MagicMirrorOrg/MagicMirror/issues/2072)
- Fix weather/providers/weathergov for API guidelines. [#2045](https://github.com/MagicMirrorOrg/MagicMirror/issues/2045)
- Fix "undefined" in weather modules header. [#1985](https://github.com/MagicMirrorOrg/MagicMirror/issues/1985)
- Fix #2110, #2111, #2118: Recurring full day events should not use timezone adjustment. Just compare month/day.
## [2.12.0] - 2020-07-01
@ -691,14 +746,14 @@ Special thanks to the following contributors: @AndreKoepke, @andrezibaia, @bryan
### Fixed
- The broken modules due to Socket.io change from last release. [#1973](https://github.com/MichMich/MagicMirror/issues/1973)
- Add backward compatibility for old module code in socketclient.js. [#1973](https://github.com/MichMich/MagicMirror/issues/1973)
- Support multiple instances of calendar module with different config. [#1109](https://github.com/MichMich/MagicMirror/issues/1109)
- Fix the use of "maxNumberOfDays" in the module "weatherforecast". [#2018](https://github.com/MichMich/MagicMirror/issues/2018)
- Throw error when check_config fails. [#1928](https://github.com/MichMich/MagicMirror/issues/1928)
- Bug fix related to 'maxEntries' not displaying Calendar events. [#2050](https://github.com/MichMich/MagicMirror/issues/2050)
- Updated ical library to the latest version. [#1926](https://github.com/MichMich/MagicMirror/issues/1926)
- Fix config check after merge of prettier [#2109](https://github.com/MichMich/MagicMirror/issues/2109)
- The broken modules due to Socket.io change from last release. [#1973](https://github.com/MagicMirrorOrg/MagicMirror/issues/1973)
- Add backward compatibility for old module code in socketclient.js. [#1973](https://github.com/MagicMirrorOrg/MagicMirror/issues/1973)
- Support multiple instances of calendar module with different config. [#1109](https://github.com/MagicMirrorOrg/MagicMirror/issues/1109)
- Fix the use of "maxNumberOfDays" in the module "weatherforecast". [#2018](https://github.com/MagicMirrorOrg/MagicMirror/issues/2018)
- Throw error when check_config fails. [#1928](https://github.com/MagicMirrorOrg/MagicMirror/issues/1928)
- Bug fix related to 'maxEntries' not displaying Calendar events. [#2050](https://github.com/MagicMirrorOrg/MagicMirror/issues/2050)
- Updated ical library to the latest version. [#1926](https://github.com/MagicMirrorOrg/MagicMirror/issues/1926)
- Fix config check after merge of prettier [#2109](https://github.com/MagicMirrorOrg/MagicMirror/issues/2109)
## [2.11.0] - 2020-04-01
@ -706,7 +761,7 @@ Special thanks to the following contributors: @AndreKoepke, @andrezibaia, @bryan
In the past years the project has grown a lot. This came with a huge downside: poor maintainability. If I let the project continue the way it was, it would eventually crash and burn. More important: I would completely lose the drive and interest to continue the project. Because of this the decision was made to simplify the core by removing all side features like automatic installers and support for exotic platforms. This release (2.11.0) is the first real release that will reflect (parts) of these changes. As a result of this, some things might break. So before you continue make sure to backup your installation. Your config, your modules or better yet: your full MagicMirror² folder. In other words: update at your own risk.
For more information regarding this major change, please check issue [#1860](https://github.com/MichMich/MagicMirror/issues/1860).
For more information regarding this major change, please check issue [#1860](https://github.com/MagicMirrorOrg/MagicMirror/issues/1860).
### Deleted
@ -736,8 +791,8 @@ For more information regarding this major change, please check issue [#1860](htt
- Fix calendar time offset for recurring events crossing Daylight Savings Time (ISSUE #1798)
- Fix regression in currentweather module causing 'undefined' to show up when config.hideTemp is false
- Fix FEELS translation for Croatian
- Fixed weather tests [#1840](https://github.com/MichMich/MagicMirror/issues/1840)
- Fixed Socket.io can't be used with Reverse Proxy in serveronly mode [#1934](https://github.com/MichMich/MagicMirror/issues/1934)
- Fixed weather tests [#1840](https://github.com/MagicMirrorOrg/MagicMirror/issues/1840)
- Fixed Socket.io can't be used with Reverse Proxy in serveronly mode [#1934](https://github.com/MagicMirrorOrg/MagicMirror/issues/1934)
- Fix update checking skipping 3rd party modules the first time
### Changed
@ -805,14 +860,14 @@ Special thanks to @sdetweil for all his great contributions!
- Updatenotification module: Display update notification for a limited (configurable) time.
- Enabled e2e/vendor_spec.js tests.
- The css/custom.css will be renamed after the next release. We've added into `run-start.sh` an instruction by GIT to ignore with `--skip-worktree` and `rm --cached`. [#1540](https://github.com/MichMich/MagicMirror/issues/1540)
- The css/custom.css will be renamed after the next release. We've added into `run-start.sh` an instruction by GIT to ignore with `--skip-worktree` and `rm --cached`. [#1540](https://github.com/MagicMirrorOrg/MagicMirror/issues/1540)
- Disable sending of notification CLOCK_SECOND when displaySeconds is false.
### Fixed
- Updatenotification module: Properly handle race conditions, prevent crash.
- Send `NEWS_FEED` notification also for the first news messages which are shown.
- Fixed issue where weather module would not refresh data after a network or API outage. [#1722](https://github.com/MichMich/MagicMirror/issues/1722)
- Fixed issue where weather module would not refresh data after a network or API outage. [#1722](https://github.com/MagicMirrorOrg/MagicMirror/issues/1722)
- Fixed weatherforecast module not displaying rain amount on fallback endpoint.
- Notifications CLOCK_SECOND & CLOCK_MINUTE being from startup instead of matched against the clock and avoid drifting.
@ -827,7 +882,7 @@ Special thanks to @sdetweil for all his great contributions!
- Russian translation for “Feels”
- Calendar module: added `nextDaysRelative` config option
- Add `broadcastPastEvents` config option for calendars to include events from the past `maximumNumberOfDays` in event broadcasts
- Added feature to broadcast news feed items `NEWS_FEED` and updated news items `NEWS_FEED_UPDATED` in default [newsfeed](https://github.com/MichMich/MagicMirror/tree/develop/modules/default/newsfeed) module (when news is updated) with documented default and `config.js` options in [README.md](https://github.com/MichMich/MagicMirror/blob/develop/modules/default/newsfeed/README.md)
- Added feature to broadcast news feed items `NEWS_FEED` and updated news items `NEWS_FEED_UPDATED` in default [newsfeed](https://github.com/MagicMirrorOrg/MagicMirror/tree/develop/modules/default/newsfeed) module (when news is updated) with documented default and `config.js` options in [README.md](https://github.com/MagicMirrorOrg/MagicMirror/blob/develop/modules/default/newsfeed/README.md)
- Added notifications to default `clock` module broadcasting `CLOCK_SECOND` and `CLOCK_MINUTE` for the respective time elapsed.
- Added UK Met Office Datapoint feed as a provider in the default weather module.
- Added new provider class
@ -836,7 +891,7 @@ Special thanks to @sdetweil for all his great contributions!
- Use Feels Like temp from feed if present
- Optionally display probability of precipitation (PoP) in current weather (UK Met Office data)
- Automatically try to fix eslint errors by passing `--fix` option to it
- Added sunrise and sunset times to weathergov weather-provider [#1705](https://github.com/MichMich/MagicMirror/issues/1705)
- Added sunrise and sunset times to weathergov weather-provider [#1705](https://github.com/MagicMirrorOrg/MagicMirror/issues/1705)
- Added "useLocationAsHeader" to display "location" in `config.js` as header when location name is not returned
- Added to `newsfeed.js`: in order to design the news article better with css, three more class-names were introduced: newsfeed-desc, newsfeed-desc, newsfeed-desc
@ -845,18 +900,18 @@ Special thanks to @sdetweil for all his great contributions!
- English translation for "Feels" to "Feels like"
- Fixed the example calendar url in `config.js.sample`
- Updated `ical.js` to solve various calendar issues.
- Updated weather city list url [#1676](https://github.com/MichMich/MagicMirror/issues/1676)
- Updated weather city list url [#1676](https://github.com/MagicMirrorOrg/MagicMirror/issues/1676)
- Only update clock once per minute when seconds aren't shown
- Updated weather-provider documentation.
### Fixed
- Fixed uncaught exception, race condition on module update
- Fixed issue [#1696](https://github.com/MichMich/MagicMirror/issues/1696), some ical files start date to not parse to date type
- Fixed issue [#1696](https://github.com/MagicMirrorOrg/MagicMirror/issues/1696), some ical files start date to not parse to date type
- Allowance HTML5 autoplay-policy (policy is changed from Chrome 66 updates)
- Handle SIGTERM messages
- Fixes sliceMultiDayEvents so it respects maximumNumberOfDays
- Minor types in default NewsFeed [README.md](https://github.com/MichMich/MagicMirror/blob/develop/modules/default/newsfeed/README.md)
- Minor types in default NewsFeed [README.md](https://github.com/MagicMirrorOrg/MagicMirror/blob/develop/modules/default/newsfeed/README.md)
- Fix typos and small syntax errors, cleanup dependencies, remove multiple-empty-lines, add semi-rule
- Fixed issues with calendar not displaying one-time changes to repeating events
- Updated the fetchedLocationName variable in currentweather.js so that city shows up in the header
@ -894,41 +949,41 @@ Fixed `package.json` version number.
### Updated
- Bumped the Electron dependency to v3.0.13 to support the most recent Raspbian. [#1500](https://github.com/MichMich/MagicMirror/issues/1500)
- Bumped the Electron dependency to v3.0.13 to support the most recent Raspbian. [#1500](https://github.com/MagicMirrorOrg/MagicMirror/issues/1500)
- Updated modernizr code in alert module, fixed a small typo there too
- More verbose error message on console if the config is malformed
- Updated installer script to install Node.js version 10.x
### Fixed
- Fixed temperature displays in currentweather and weatherforecast modules [#1503](https://github.com/MichMich/MagicMirror/issues/1503), [#1511](https://github.com/MichMich/MagicMirror/issues/1511).
- Fixed unhandled error on bad git data in updatenotification module [#1285](https://github.com/MichMich/MagicMirror/issues/1285).
- Weather forecast now works with openweathermap in new weather module. Daily data are displayed, see issue [#1504](https://github.com/MichMich/MagicMirror/issues/1504).
- Fixed temperature displays in currentweather and weatherforecast modules [#1503](https://github.com/MagicMirrorOrg/MagicMirror/issues/1503), [#1511](https://github.com/MagicMirrorOrg/MagicMirror/issues/1511).
- Fixed unhandled error on bad git data in updatenotification module [#1285](https://github.com/MagicMirrorOrg/MagicMirror/issues/1285).
- Weather forecast now works with openweathermap in new weather module. Daily data are displayed, see issue [#1504](https://github.com/MagicMirrorOrg/MagicMirror/issues/1504).
- Fixed analogue clock border display issue where non-black backgrounds used (previous fix for issue 611)
- Fixed compatibility issues caused when modules request different versions of Font Awesome, see issue [#1522](https://github.com/MichMich/MagicMirror/issues/1522). MagicMirror² now uses [Font Awesome 5 with v4 shims included for backwards compatibility](https://fontawesome.com/how-to-use/on-the-web/setup/upgrading-from-version-4#shims).
- Fixed compatibility issues caused when modules request different versions of Font Awesome, see issue [#1522](https://github.com/MagicMirrorOrg/MagicMirror/issues/1522). MagicMirror² now uses [Font Awesome 5 with v4 shims included for backwards compatibility](https://fontawesome.com/how-to-use/on-the-web/setup/upgrading-from-version-4#shims).
- Installation script problems with raspbian
- Calendar: only show repeating count if the event is actually repeating [#1534](https://github.com/MichMich/MagicMirror/pull/1534)
- Calendar: only show repeating count if the event is actually repeating [#1534](https://github.com/MagicMirrorOrg/MagicMirror/pull/1534)
- Calendar: Fix exdate handling when multiple values are specified (comma separated)
- Calendar: Fix relative date handling for fulldate events, calculate difference always from start of day [#1572](https://github.com/MichMich/MagicMirror/issues/1572)
- Calendar: Fix relative date handling for fulldate events, calculate difference always from start of day [#1572](https://github.com/MagicMirrorOrg/MagicMirror/issues/1572)
- Fix null dereference in moduleNeedsUpdate when the module isn't visible
- Calendar: Fixed event end times by setting default calendarEndTime to "LT" (Local time format). [#1479]
- Calendar: Fixed missing calendar fetchers after server process restarts [#1589](https://github.com/MichMich/MagicMirror/issues/1589)
- Calendar: Fixed missing calendar fetchers after server process restarts [#1589](https://github.com/MagicMirrorOrg/MagicMirror/issues/1589)
- Notification: fixed background color (was white text on white background)
- Use getHeader instead of data.header when creating the DOM so overwriting the function also propagates into it
- Fix documentation of `useKMPHwind` option in currentweather
### New weather module
- Fixed weather forecast table display [#1499](https://github.com/MichMich/MagicMirror/issues/1499).
- Fixed weather forecast table display [#1499](https://github.com/MagicMirrorOrg/MagicMirror/issues/1499).
- Dimmed loading indicator for weather forecast.
- Implemented config option `decimalSymbol` [#1499](https://github.com/MichMich/MagicMirror/issues/1499).
- Aligned indoor values in current weather vertical [#1499](https://github.com/MichMich/MagicMirror/issues/1499).
- Implemented config option `decimalSymbol` [#1499](https://github.com/MagicMirrorOrg/MagicMirror/issues/1499).
- Aligned indoor values in current weather vertical [#1499](https://github.com/MagicMirrorOrg/MagicMirror/issues/1499).
- Added humidity support to nunjuck unit filter.
- Do not display degree symbol for temperature in Kelvin [#1503](https://github.com/MichMich/MagicMirror/issues/1503).
- Weather forecast now works with openweathermap for both, `/forecast` and `/forecast/daily`, in new weather module. If you use the `/forecast`-weatherEndpoint, the hourly data are converted to daily data, see issues [#1504](https://github.com/MichMich/MagicMirror/issues/1504), [#1513](https://github.com/MichMich/MagicMirror/issues/1513).
- Added fade, fadePoint and maxNumberOfDays properties to the forecast mode [#1516](https://github.com/MichMich/MagicMirror/issues/1516)
- Fixed Loading string and decimalSymbol string replace [#1538](https://github.com/MichMich/MagicMirror/issues/1538)
- Show Snow amounts in new weather module [#1545](https://github.com/MichMich/MagicMirror/issues/1545)
- Do not display degree symbol for temperature in Kelvin [#1503](https://github.com/MagicMirrorOrg/MagicMirror/issues/1503).
- Weather forecast now works with openweathermap for both, `/forecast` and `/forecast/daily`, in new weather module. If you use the `/forecast`-weatherEndpoint, the hourly data are converted to daily data, see issues [#1504](https://github.com/MagicMirrorOrg/MagicMirror/issues/1504), [#1513](https://github.com/MagicMirrorOrg/MagicMirror/issues/1513).
- Added fade, fadePoint and maxNumberOfDays properties to the forecast mode [#1516](https://github.com/MagicMirrorOrg/MagicMirror/issues/1516)
- Fixed Loading string and decimalSymbol string replace [#1538](https://github.com/MagicMirrorOrg/MagicMirror/issues/1538)
- Show Snow amounts in new weather module [#1545](https://github.com/MagicMirrorOrg/MagicMirror/issues/1545)
- Added weather.gov as a new weather-provider for US locations
## [2.6.0] - 2019-01-01
@ -953,7 +1008,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
- Screenshot for the weather forecast module
- Portuguese translation for "Feels"
- Croatian translation
- Fading for dateheaders timeFormat in Calendar [#1464](https://github.com/MichMich/MagicMirror/issues/1464)
- Fading for dateheaders timeFormat in Calendar [#1464](https://github.com/MagicMirrorOrg/MagicMirror/issues/1464)
- Documentation for the existing `scale` option in the Weather Forecast module.
### Fixed
@ -962,7 +1017,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
- Fixed Polish translation for Single Update Info
- Ignore entries with unparseable details in the calendar module
- Bug showing FullDayEvents one day too long in calendar fixed
- Bug in newsfeed when `removeStartTags` is used on the description [#1478](https://github.com/MichMich/MagicMirror/issues/1478)
- Bug in newsfeed when `removeStartTags` is used on the description [#1478](https://github.com/MagicMirrorOrg/MagicMirror/issues/1478)
### Updated
@ -995,7 +1050,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
- Fixed mixup between german and spanish translation for newsfeed.
- Fixed close dates to be absolute, if no configured in the config.js - module Calendar
- Fixed the updatenotification module message about new commits in the repository, so they can be correctly localized in singular and plural form.
- Fix for weatherforecast rainfall rounding [#1374](https://github.com/MichMich/MagicMirror/issues/1374)
- Fix for weatherforecast rainfall rounding [#1374](https://github.com/MagicMirrorOrg/MagicMirror/issues/1374)
- Fix calendar parsing issue for Midori on RasperryPi Zero w, related to issue #694.
- Fix weather city ID link in sample config
- Fixed issue with clientonly not updating with IP address and port provided on command line.
@ -1017,7 +1072,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
## [2.4.0] - 2018-07-01
⚠️ **Warning:** This release includes an updated version of Electron. This requires a Raspberry Pi configuration change to allow the best performance and prevent the CPU from overheating. Please read the information on the [MagicMirror² Wiki](https://github.com/michmich/magicmirror/wiki/configuring-the-raspberry-pi#enable-the-open-gl-driver-to-decrease-electrons-cpu-usage).
⚠️ **Warning:** This release includes an updated version of Electron. This requires a Raspberry Pi configuration change to allow the best performance and prevent the CPU from overheating. Please read the information on the [MagicMirror² Wiki](https://github.com/MagicMirrorOrg/MagicMirror/wiki/configuring-the-raspberry-pi#enable-the-open-gl-driver-to-decrease-electrons-cpu-usage).
**Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`
@ -1039,20 +1094,20 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
- Upgrade to Electron 2.0.0.
- Remove yarn-or-npm which breaks production builds.
- Invoke module suspend even if no dom content. [#1308](https://github.com/MichMich/MagicMirror/issues/1308)
- Invoke module suspend even if no dom content. [#1308](https://github.com/MagicMirrorOrg/MagicMirror/issues/1308)
### Fixed
- Fixed issue where wind chill could not be displayed in Fahrenheit. [#1247](https://github.com/MichMich/MagicMirror/issues/1247)
- Fixed issues where a module crashes when it tries to dismiss a non existing alert. [#1240](https://github.com/MichMich/MagicMirror/issues/1240)
- Fixed issue where wind chill could not be displayed in Fahrenheit. [#1247](https://github.com/MagicMirrorOrg/MagicMirror/issues/1247)
- Fixed issues where a module crashes when it tries to dismiss a non existing alert. [#1240](https://github.com/MagicMirrorOrg/MagicMirror/issues/1240)
- In default module currentWeather/currentWeather.js line 296, 300, self.config.animationSpeed can not be found because the notificationReceived function does not have "self" variable.
- Fixed browser-side code to work on the Midori browser.
- Fixed issue where heat index was reporting incorrect values in Celsius and Fahrenheit. [#1263](https://github.com/MichMich/MagicMirror/issues/1263)
- Fixed issue where heat index was reporting incorrect values in Celsius and Fahrenheit. [#1263](https://github.com/MagicMirrorOrg/MagicMirror/issues/1263)
- Fixed weatherforecast to use dt_txt field instead of dt to handle timezones better
- Newsfeed now remembers to show the description when `"ARTICLE_LESS_DETAILS"` is called if the user wants to always show the description. [#1282](https://github.com/MichMich/MagicMirror/issues/1282)
- Newsfeed now remembers to show the description when `"ARTICLE_LESS_DETAILS"` is called if the user wants to always show the description. [#1282](https://github.com/MagicMirrorOrg/MagicMirror/issues/1282)
- `clientonly/*.js` is now linted, and one linting error is fixed
- Fix issue #1196 by changing underscore to hyphen in locale id, in align with momentjs.
- Fixed issue where heat index and wind chill were reporting incorrect values in Kelvin. [#1263](https://github.com/MichMich/MagicMirror/issues/1263)
- Fixed issue where heat index and wind chill were reporting incorrect values in Kelvin. [#1263](https://github.com/MagicMirrorOrg/MagicMirror/issues/1263)
### Updated
@ -1064,7 +1119,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
### Fixed
- Downgrade electron to 1.4.15 to solve the black screen issue.[#1243](https://github.com/MichMich/MagicMirror/issues/1243)
- Downgrade electron to 1.4.15 to solve the black screen issue.[#1243](https://github.com/MagicMirrorOrg/MagicMirror/issues/1243)
## [2.3.0] - 2018-04-01
@ -1190,8 +1245,8 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
### Changed
- Revert Docker related changes in favor of [docker-MagicMirror](https://github.com/bastilimbach/docker-MagicMirror). All Docker images are outsourced. ([#856](https://github.com/MichMich/MagicMirror/pull/856))
- Change Docker base image (Debian + Node) to an arm based distro (AlpineARM + Node) ([#846](https://github.com/MichMich/MagicMirror/pull/846))
- Revert Docker related changes in favor of [docker-MagicMirror](https://github.com/bastilimbach/docker-MagicMirror). All Docker images are outsourced. ([#856](https://github.com/MagicMirrorOrg/MagicMirror/pull/856))
- Change Docker base image (Debian + Node) to an arm based distro (AlpineARM + Node) ([#846](https://github.com/MagicMirrorOrg/MagicMirror/pull/846))
- Fix the dockerfile to have it running from the first time.
### Added
@ -1238,7 +1293,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
- Add `anytime` group for Compliments module.
- Compliments module can use remoteFile without default daytime arrays defined.
- Installer: Use init config.js from config.js.sample.
- Switched out `rrule` package for `rrule-alt` and fixes in `ical.js` in order to fix calendar issues. ([#565](https://github.com/MichMich/MagicMirror/issues/565))
- Switched out `rrule` package for `rrule-alt` and fixes in `ical.js` in order to fix calendar issues. ([#565](https://github.com/MagicMirrorOrg/MagicMirror/issues/565))
- Make mouse events pass through the region fullscreen_above to modules below.
- Scaled the splash screen down to make it a bit more subtle.
- Replace HTML tables with markdown tables in README files.
@ -1251,7 +1306,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
### Added
- Added Docker support (Pull Request [#673](https://github.com/MichMich/MagicMirror/pull/673)).
- Added Docker support (Pull Request [#673](https://github.com/MagicMirrorOrg/MagicMirror/pull/673)).
- Calendar-specific support for `maximumEntries`, and `maximumNumberOfDays`.
- Add loaded function to modules, providing an async callback.
- Made default newsfeed module aware of gesture events from [MMM-Gestures](https://github.com/thobach/MMM-Gestures)
@ -1297,7 +1352,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
- Updated .gitignore to not ignore default modules folder.
- Remove white flash on boot up.
- Added `update` in Raspberry Pi installation script.
- Fix an issue where the analog clock looked scrambled. ([#611](https://github.com/MichMich/MagicMirror/issues/611))
- Fix an issue where the analog clock looked scrambled. ([#611](https://github.com/MagicMirrorOrg/MagicMirror/issues/611))
- If units are set to imperial, the showRainAmount option of weatherforecast will show the correct unit.
- Module currentWeather: check if temperature received from api is defined.
- Fix an issue with module hidden status changing to `true` although lock string prevented showing it.
@ -1314,18 +1369,18 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
- Finnish translation.
- Danish translation.
- Turkish translation.
- Option to limit access to certain IP addresses based on the value of `ipWhitelist` in the `config.js`, default is access from localhost only (Issue [#456](https://github.com/MichMich/MagicMirror/issues/456)).
- Option to limit access to certain IP addresses based on the value of `ipWhitelist` in the `config.js`, default is access from localhost only (Issue [#456](https://github.com/MagicMirrorOrg/MagicMirror/issues/456)).
- Added ability to change the point of time when calendar events get relative.
- Add Splash screen on boot.
- Add option to show humidity in currentWeather module.
- Add VSCode IntelliSense support.
- Module API: Add Visibility locking to module system. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#visibility-locking) for more information.
- Module API: Method to overwrite the module's header. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#getheader) for more information.
- Module API: Option to define the minimum MagicMirror² version to run a module. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules#requiresversion) for more information.
- Calendar module now broadcasts the event list to all other modules using the notification system. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules/default/calendar) for more information.
- Possibility to use the calendar feed as the source for the weather (currentweather & weatherforecast) location data. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules/default/weatherforecast) for more information.
- Module API: Add Visibility locking to module system. [See documentation](https://github.com/MagicMirrorOrg/MagicMirror/tree/develop/modules#visibility-locking) for more information.
- Module API: Method to overwrite the module's header. [See documentation](https://github.com/MagicMirrorOrg/MagicMirror/tree/develop/modules#getheader) for more information.
- Module API: Option to define the minimum MagicMirror² version to run a module. [See documentation](https://github.com/MagicMirrorOrg/MagicMirror/tree/develop/modules#requiresversion) for more information.
- Calendar module now broadcasts the event list to all other modules using the notification system. [See documentation](https://github.com/MagicMirrorOrg/MagicMirror/tree/develop/modules/default/calendar) for more information.
- Possibility to use the calendar feed as the source for the weather (currentweather & weatherforecast) location data. [See documentation](https://github.com/MagicMirrorOrg/MagicMirror/tree/develop/modules/default/weatherforecast) for more information.
- Added option to show rain amount in the weatherforecast default module
- Add module `updatenotification` to get an update whenever a new version is available. [See documentation](https://github.com/MichMich/MagicMirror/tree/develop/modules/default/updatenotification) for more information.
- Add module `updatenotification` to get an update whenever a new version is available. [See documentation](https://github.com/MagicMirrorOrg/MagicMirror/tree/develop/modules/default/updatenotification) for more information.
- Add the ability to set timezone on the date display in the Clock Module
- Ability to set date format in calendar module
- Possibility to use currentweather for the compliments
@ -1395,11 +1450,11 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
### Fixed
- Prevent `getModules()` selectors from returning duplicate entries.
- Append endpoints of weather modules with `/` to retrieve the correct data. (Issue [#337](https://github.com/MichMich/MagicMirror/issues/337))
- Append endpoints of weather modules with `/` to retrieve the correct data. (Issue [#337](https://github.com/MagicMirrorOrg/MagicMirror/issues/337))
- Corrected grammar in `module.js` from 'suspend' to 'suspended'.
- Fixed openweathermap.org URL in config sample.
- Prevent currentweather module from crashing when received data object is incorrect.
- Fix issue where translation loading prevented the UI start-up when the language was set to 'en'. (Issue [#388](https://github.com/MichMich/MagicMirror/issues/388))
- Fix issue where translation loading prevented the UI start-up when the language was set to 'en'. (Issue [#388](https://github.com/MagicMirrorOrg/MagicMirror/issues/388))
### Updated
@ -1419,8 +1474,8 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
### Fixed
- Edit Alert Module to display title & message if they are provided in the notification (Issue [#300](https://github.com/MichMich/MagicMirror/issues/300))
- Removed 'null' reference from updateModuleContent(). This fixes recent Edge and Internet Explorer browser displays (Issue [#319](https://github.com/MichMich/MagicMirror/issues/319))
- Edit Alert Module to display title & message if they are provided in the notification (Issue [#300](https://github.com/MagicMirrorOrg/MagicMirror/issues/300))
- Removed 'null' reference from updateModuleContent(). This fixes recent Edge and Internet Explorer browser displays (Issue [#319](https://github.com/MagicMirrorOrg/MagicMirror/issues/319))
### Changed
@ -1437,7 +1492,7 @@ A huge, huge, huge thanks to user @fewieden for all his hard work on the new `we
### Fixed
- Added reference to Italian Translation.
- Added the missing NE translation to all languages. [#344](https://github.com/MichMich/MagicMirror/issues/344)
- Added the missing NE translation to all languages. [#344](https://github.com/MagicMirrorOrg/MagicMirror/issues/344)
- Added proper User-Agent string to calendar call.
### Changed

View file

@ -5,7 +5,7 @@ This document describes how collaborators of this repository should work togethe
- never merge your own PR's
- never merge without someone having approved (approving and merging from same person is allowed)
- wait for all approvals requested (or the author decides something different in the comments)
- never merge to `master`, except for releases (because of update notification)
- merge to `master` only for releases or other urgent issues (update notification is only triggered by tags)
- merges to master should be tagged with the "mastermerge" label so that the test runs through
## Issues
@ -15,4 +15,24 @@ This document describes how collaborators of this repository should work togethe
## Releases
- are done by @MichMich only
Are done by @rejas or @khassel.
### Deployment steps
- pull latest `develop` branch
- update `package.json` to reflect correct version number
- run `npm install` to generate new `package-lock.json`
- test `develop` branch
- update `CHANGELOG.md` (don't forget to add all contributor names)
- commit and push all changes
- after successful test run via github actions: create pull request to `master` branch
- after PR tests run without issues, merge PR
- create new release with corresponding version tag
- publish release notes with link to github release on forum in new locked topic
### Draft new development release
- checkout `develop` branch
- update `package.json` to reflect correct version number `2.xx.0-develop`
- draft new section in `CHANGELOG.md`
- commit and publish `develop` branch

View file

@ -1,6 +1,6 @@
# The MIT License (MIT)
Copyright © 2016-2022 Michael Teeuw
Copyright © 2016-2024 Michael Teeuw
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation

View file

@ -4,14 +4,14 @@
<a href="https://choosealicense.com/licenses/mit">
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License">
</a>
<img src="https://img.shields.io/github/actions/workflow/status/michmich/magicmirror/automated-tests.yaml" alt="GitHub Actions">
<img src="https://img.shields.io/github/checks-status/michmich/magicmirror/master" alt="Build Status">
<a href="https://github.com/MichMich/MagicMirror">
<img src="https://img.shields.io/github/stars/michmich/magicmirror?style=social">
<img src="https://img.shields.io/github/actions/workflow/status/magicmirrororg/magicmirror/automated-tests.yaml" alt="GitHub Actions">
<img src="https://img.shields.io/github/checks-status/magicmirrororg/magicmirror/master" alt="Build Status">
<a href="https://github.com/MagicMirrorOrg/MagicMirror">
<img src="https://img.shields.io/github/stars/magicmirrororg/magicmirror?style=social">
</a>
</p>
**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/MichMich/MagicMirror/graphs/contributors).
**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).
MagicMirror² focuses on a modular plugin system and uses [Electron](https://www.electronjs.org/) as an application wrapper. So no more web server or browser installs necessary!

View file

@ -40,7 +40,7 @@
// Return new pending promise
return new Promise((resolve, reject) => {
// Select http or https module, depending on requested url
const lib = url.startsWith("https") ? require("https") : require("http");
const lib = url.startsWith("https") ? require("node:https") : require("node:http");
const request = lib.get(url, (response) => {
let configData = "";
@ -94,7 +94,7 @@
// Spawn electron application
const electron = require("electron");
const child = require("child_process").spawn(electron, ["js/electron.js"], options);
const child = require("node:child_process").spawn(electron, ["js/electron.js"], options);
// Pipe all child process output to current stdout
child.stdout.on("data", function (buf) {

View file

@ -1,7 +1,4 @@
/* MagicMirror² Config Sample
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
/* Config Sample
*
* For more information on how you can configure this file
* see https://docs.magicmirror.builders/configuration/introduction.html

View file

@ -1,10 +1,8 @@
/* MagicMirror² Custom CSS Sample
/* Custom CSS Sample
*
* Change color and fonts here.
*
* Beware that properties cannot be unitless, so for example write '--gap-body: 0px;' instead of just '--gap-body: 0;'
*
* MIT Licensed.
*/
/* Uncomment and adjust accordingly if you want to import another font from the google-fonts-api: */
@ -18,7 +16,7 @@
--font-primary: "Roboto Condensed";
--font-secondary: "Roboto";
--font-size: 20px;
--font-size-small: 0.75rem;
@ -26,6 +24,6 @@
--gap-body-right: 60px;
--gap-body-bottom: 60px;
--gap-body-left: 60px;
--gap-modules: 30px;
}

View file

@ -1,25 +1,27 @@
{
"name": "magicmirror-fonts",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "magicmirror-fonts",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"@fontsource/roboto": "^5.0.8",
"@fontsource/roboto-condensed": "^5.0.14"
"@fontsource/roboto": "^5.0.12",
"@fontsource/roboto-condensed": "^5.0.15"
}
},
"node_modules/@fontsource/roboto": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.0.8.tgz",
"integrity": "sha512-XxPltXs5R31D6UZeLIV1td3wTXU3jzd3f2DLsXI8tytMGBkIsGcc9sIyiupRtA8y73HAhuSCeweOoBqf6DbWCA=="
"version": "5.0.12",
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.0.12.tgz",
"integrity": "sha512-x0o17jvgoSSbS9OZnUX2+xJmVRvVCfeaYJjkS7w62iN7CuJWtMf5vJj8LqgC7ibqIkitOHVW+XssRjgrcHn62g=="
},
"node_modules/@fontsource/roboto-condensed": {
"version": "5.0.14",
"resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.0.14.tgz",
"integrity": "sha512-ZNBHUhE5/3z9efMIjpBblFsfLHgGotJjlzKd5Q8DODbkRRWy6Yh+JnbiaJZ8zwQyHyYBNOolk57BG4BcjSzrRg=="
"version": "5.0.15",
"resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.0.15.tgz",
"integrity": "sha512-0AFvcI/8JQ5+FZE12hdaE1W/1ooJUzd5XP7jD74+SP+PArsswJ+6OV/oKTasgeQeZlvGrcD3chO6yr5K4JGwzA=="
}
}
}

View file

@ -1,16 +1,17 @@
{
"name": "magicmirror-fonts",
"description": "Package for fonts use by MagicMirror² Core.",
"version": "1.0.0",
"description": "Package for fonts use by MagicMirror² core.",
"repository": {
"type": "git",
"url": "git+https://github.com/MichMich/MagicMirror.git"
"url": "https://github.com/MagicMirrorOrg/MagicMirror"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/MichMich/MagicMirror/issues"
"url": "https://github.com/MagicMirrorOrg/MagicMirror/issues"
},
"dependencies": {
"@fontsource/roboto": "^5.0.8",
"@fontsource/roboto-condensed": "^5.0.14"
"@fontsource/roboto": "^5.0.12",
"@fontsource/roboto-condensed": "^5.0.15"
}
}

View file

@ -1,10 +1,3 @@
/* MagicMirror²
* AnimateCSS System from https://animate.style/
* by @bugsounet
* for Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
/* enumeration of animations in Array **/
const AnimateCSSIn = [
// Attention seekers

View file

@ -1,15 +1,8 @@
/* MagicMirror²
* The Core App (Server)
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
// Alias modules mentioned in package.js under _moduleAliases.
require("module-alias/register");
const fs = require("fs");
const path = require("path");
const fs = require("node:fs");
const path = require("node:path");
const envsub = require("envsub");
const Log = require("logger");
@ -21,6 +14,9 @@ const defaultModules = require(`${__dirname}/../modules/default/defaultmodules`)
global.version = require(`${__dirname}/../package.json`).version;
Log.log(`Starting MagicMirror: v${global.version}`);
// Log system information.
Utils.logSystemInformation();
// global absolute root path
global.root_path = path.resolve(`${__dirname}/../`);
@ -29,7 +25,7 @@ if (process.env.MM_CONFIG_FILE) {
}
// FIXME: Hotfix Pull Request
// https://github.com/MichMich/MagicMirror/pull/673
// https://github.com/MagicMirrorOrg/MagicMirror/pull/673
if (process.env.MM_PORT) {
global.mmPort = process.env.MM_PORT;
}
@ -37,10 +33,13 @@ if (process.env.MM_PORT) {
// The next part is here to prevent a major exception when there
// is no internet connection. This could probable be solved better.
process.on("uncaughtException", function (err) {
Log.error("Whoops! There was an uncaught exception...");
Log.error(err);
Log.error("MagicMirror² will not quit, but it might be a good idea to check why this happened. Maybe no internet connection?");
Log.error("If you think this really is an issue, please open an issue on GitHub: https://github.com/MichMich/MagicMirror/issues");
// ignore strange exceptions under aarch64 coming from systeminformation:
if (!err.stack.includes("node_modules/systeminformation")) {
Log.error("Whoops! There was an uncaught exception...");
Log.error(err);
Log.error("MagicMirror² will not quit, but it might be a good idea to check why this happened. Maybe no internet connection?");
Log.error("If you think this really is an issue, please open an issue on GitHub: https://github.com/MagicMirrorOrg/MagicMirror/issues");
}
});
/**
@ -70,7 +69,7 @@ function App () {
fs.accessSync(templateFile, fs.F_OK);
} catch (err) {
templateFile = null;
Log.debug("config template file not exists, no envsubst");
Log.log("config template file not exists, no envsubst");
}
if (templateFile) {
@ -91,7 +90,7 @@ function App () {
envFiles.push(configEnvFile);
}
} catch (err) {
Log.debug(`${configEnvFile} does not exist. ${err.message}`);
Log.log(`${configEnvFile} does not exist. ${err.message}`);
}
let options = {
@ -116,15 +115,18 @@ function App () {
try {
fs.accessSync(configFilename, fs.F_OK);
const c = require(configFilename);
if (Object.keys(c).length === 0) {
Log.error("WARNING! Config file appears empty, maybe missing module.exports last line?");
}
checkDeprecatedOptions(c);
return Object.assign(defaults, c);
} catch (e) {
if (e.code === "ENOENT") {
Log.error(Utils.colors.error("WARNING! Could not find config file. Please create one. Starting with default configuration."));
Log.error("WARNING! Could not find config file. Please create one. Starting with default configuration.");
} else if (e instanceof ReferenceError || e instanceof SyntaxError) {
Log.error(Utils.colors.error(`WARNING! Could not validate config file. Starting with default configuration. Please correct syntax errors at or above this line: ${e.stack}`));
Log.error(`WARNING! Could not validate config file. Starting with default configuration. Please correct syntax errors at or above this line: ${e.stack}`);
} else {
Log.error(Utils.colors.error(`WARNING! Could not load config file. Starting with default configuration. Error found: ${e}`));
Log.error(`WARNING! Could not load config file. Starting with default configuration. Error found: ${e}`);
}
}
@ -142,7 +144,7 @@ function App () {
const usedDeprecated = deprecatedOptions.filter((option) => userConfig.hasOwnProperty(option));
if (usedDeprecated.length > 0) {
Log.warn(Utils.colors.warn(`WARNING! Your config is using deprecated options: ${usedDeprecated.join(", ")}. Check README and CHANGELOG for more up-to-date ways of getting the same functionality.`));
Log.warn(`WARNING! Your config is using deprecated options: ${usedDeprecated.join(", ")}. Check README and CHANGELOG for more up-to-date ways of getting the same functionality.`);
}
}

View file

@ -1,19 +1,12 @@
/* MagicMirror²
*
* Check the configuration file for errors
*
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
* MIT Licensed.
*/
const path = require("path");
const fs = require("fs");
const path = require("node:path");
const fs = require("node:fs");
const colors = require("ansis");
const { Linter } = require("eslint");
const linter = new Linter();
const rootPath = path.resolve(`${__dirname}/../`);
const Log = require(`${rootPath}/js/logger.js`);
const Utils = require(`${rootPath}/js/utils.js`);
/**
* Returns a string with path of configuration file.
@ -33,7 +26,7 @@ function checkConfigFile () {
// Check if file is present
if (fs.existsSync(configFileName) === false) {
Log.error(Utils.colors.error("File not found: "), configFileName);
Log.error(`File not found: ${configFileName}`);
throw new Error("No config file present!");
}
@ -41,12 +34,12 @@ function checkConfigFile () {
try {
fs.accessSync(configFileName, fs.F_OK);
} catch (e) {
Log.error(Utils.colors.error(e));
Log.error(e);
throw new Error("No permission to access config file!");
}
// Validate syntax of the configuration file.
Log.info(Utils.colors.info("Checking file... "), configFileName);
Log.info("Checking file... ", configFileName);
// I'm not sure if all ever is utf-8
const configFile = fs.readFileSync(configFileName, "utf-8");
@ -59,9 +52,9 @@ function checkConfigFile () {
});
if (errors.length === 0) {
Log.info(Utils.colors.pass("Your configuration file doesn't contain syntax errors :)"));
Log.info(colors.green("Your configuration file doesn't contain syntax errors :)"));
} else {
Log.error(Utils.colors.error("Your configuration file contains syntax errors :("));
Log.error(colors.red("Your configuration file contains syntax errors :("));
for (const error of errors) {
Log.error(`Line ${error.line} column ${error.column}: ${error.message}`);

View file

@ -1,11 +1,5 @@
/* global mmPort */
/* MagicMirror²
* Config Defaults
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
const address = "localhost";
let port = 8080;
if (typeof mmPort !== "undefined") {
@ -26,7 +20,7 @@ const defaults = {
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
// 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 },
// properties for checking if server is alive and has same startup-timestamp, the check is per default enabled

View file

@ -1,11 +1,3 @@
/* MagicMirror² Deprecated Config Options List
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*
* Olex S. original idea this deprecated option
*/
module.exports = {
configs: ["kioskmode"]
};

View file

@ -40,6 +40,7 @@ function createWindow () {
let electronOptionsDefaults = {
width: electronSize.width,
height: electronSize.height,
icon: "mm2.png",
x: 0,
y: 0,
darkTheme: true,

View file

@ -1,11 +1,5 @@
/* global defaultModules, vendor */
/* MagicMirror²
* Module and File loaders.
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
const Loader = (function () {
/* Create helper variables */

View file

@ -1,19 +1,40 @@
/* MagicMirror²
* Log
*
* This logger is very simple, but needs to be extended.
* This system can eventually be used to push the log messages to an external target.
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
// This logger is very simple, but needs to be extended.
(function (root, factory) {
if (typeof exports === "object") {
if (process.env.JEST_WORKER_ID === undefined) {
const colors = require("ansis");
// add timestamps in front of log messages
require("console-stamp")(console, {
pattern: "yyyy-mm-dd HH:MM:ss.l",
include: ["debug", "log", "info", "warn", "error"]
format: ":date(yyyy-mm-dd HH:MM:ss.l) :label(7) :msg",
tokens: {
label: (arg) => {
const { method, defaultTokens } = arg;
let label = defaultTokens.label(arg);
if (method === "error") {
label = colors.red(label);
} else if (method === "warn") {
label = colors.yellow(label);
} else if (method === "debug") {
label = colors.bgBlue(label);
} else if (method === "info") {
label = colors.blue(label);
}
return label;
},
msg: (arg) => {
const { method, defaultTokens } = arg;
let msg = defaultTokens.msg(arg);
if (method === "error") {
msg = colors.red(msg);
} else if (method === "warn") {
msg = colors.yellow(msg);
} else if (method === "info") {
msg = colors.blue(msg);
}
return msg;
}
}
});
}
// Node, CommonJS-like

View file

@ -1,11 +1,5 @@
/* global Loader, defaults, Translator, addAnimateCSS, removeAnimateCSS, AnimateCSSIn, AnimateCSSOut */
/* MagicMirror²
* Main System
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
const MM = (function () {
let modules = [];

View file

@ -1,11 +1,7 @@
/* global Class, cloneObject, Loader, MMSocket, nunjucks, Translator */
/* MagicMirror²
* Module Blueprint.
/* Module Blueprint.
* @typedef {Object} Module
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
const Module = Class.extend({

View file

@ -1,9 +1,3 @@
/* MagicMirror²
* Node Helper Superclass
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
const express = require("express");
const Log = require("logger");
const Class = require("./class");

View file

@ -1,13 +1,7 @@
/* MagicMirror²
* Server
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
const fs = require("fs");
const http = require("http");
const https = require("https");
const path = require("path");
const fs = require("node:fs");
const http = require("node:http");
const https = require("node:https");
const path = require("node:path");
const express = require("express");
const ipfilter = require("express-ipfilter").IpFilter;
const helmet = require("helmet");
@ -62,7 +56,7 @@ function Server (config) {
server.listen(port, config.address || "localhost");
if (config.ipWhitelist instanceof Array && config.ipWhitelist.length === 0) {
Log.warn(Utils.colors.warn("You're using a full whitelist configuration to allow for all IPs"));
Log.warn("You're using a full whitelist configuration to allow for all IPs");
}
app.use(function (req, res, next) {

View file

@ -1,5 +1,5 @@
const fs = require("fs");
const path = require("path");
const fs = require("node:fs");
const path = require("node:path");
const Log = require("logger");
const startUp = new Date();

View file

@ -1,11 +1,5 @@
/* global io */
/* MagicMirror²
* TODO add description
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
const MMSocket = function (moduleName) {
if (typeof moduleName !== "string") {
throw new Error("Please set the module name for the MMSocket.");

View file

@ -1,11 +1,5 @@
/* global translations */
/* MagicMirror²
* Translator (l10n)
*
* By Christopher Fenner https://github.com/CFenner
* MIT Licensed.
*/
const Translator = (function () {
/**

View file

@ -1,16 +1,29 @@
/* MagicMirror²
* Utils
*
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
* MIT Licensed.
*/
const colors = require("colors/safe");
const execSync = require("node:child_process").execSync;
const Log = require("logger");
const si = require("systeminformation");
module.exports = {
colors: {
warn: colors.yellow,
error: colors.red,
info: colors.blue,
pass: colors.green
async logSystemInformation () {
try {
let installedNodeVersion = execSync("node -v", { encoding: "utf-8" }).replace("v", "").replace(/(?:\r\n|\r|\n)/g, "");
const staticData = await si.get({
system: "manufacturer, model, raspberry, virtual",
osInfo: "platform, distro, release, arch",
versions: "kernel, node, npm, pm2"
});
let systemDataString = "System information:";
systemDataString += `\n### SYSTEM: manufacturer: ${staticData["system"]["manufacturer"]}; model: ${staticData["system"]["model"]}; raspberry: ${staticData["system"]["raspberry"]}; virtual: ${staticData["system"]["virtual"]}`;
systemDataString += `\n### OS: platform: ${staticData["osInfo"]["platform"]}; distro: ${staticData["osInfo"]["distro"]}; release: ${staticData["osInfo"]["release"]}; arch: ${staticData["osInfo"]["arch"]}; kernel: ${staticData["versions"]["kernel"]}`;
systemDataString += `\n### VERSIONS: electron: ${process.versions.electron}; used node: ${staticData["versions"]["node"]}; installed node: ${installedNodeVersion}; npm: ${staticData["versions"]["npm"]}; pm2: ${staticData["versions"]["pm2"]}`;
systemDataString += `\n### OTHER: timeZone: ${Intl.DateTimeFormat().resolvedOptions().timeZone}; ELECTRON_ENABLE_GPU: ${process.env.ELECTRON_ENABLE_GPU}`;
Log.info(systemDataString);
// Return is currently only for jest
return systemDataString;
} catch (e) {
Log.error(e);
}
}
};

BIN
mm2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

View file

@ -1,11 +1,5 @@
/* global NotificationFx */
/* MagicMirror²
* Module: alert
*
* By Paul-Vincent Roll https://paulvincentroll.com/
* MIT Licensed.
*/
Module.register("alert", {
alerts: {},

View file

@ -1,11 +1,5 @@
/* global CalendarUtils */
/* MagicMirror²
* Module: Calendar
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
Module.register("calendar", {
// Define module defaults
defaults: {
@ -42,6 +36,7 @@ Module.register("calendar", {
hideDuplicates: true,
showTimeToday: false,
colored: false,
forceUseCurrentTime: false,
tableClass: "small",
calendars: [
{
@ -97,12 +92,12 @@ Module.register("calendar", {
Log.info(`Starting module: ${this.name}`);
if (this.config.colored) {
Log.warn("Your are using the deprecated config values 'colored'. Please switch to 'coloredSymbol' & 'coloredText'!");
Log.warn("Your are using the deprecated config values 'colored'. Please switch to 'coloredSymbol' & 'coloredText'!");
this.config.coloredText = true;
this.config.coloredSymbol = true;
}
if (this.config.coloredSymbolOnly) {
Log.warn("Your are using the deprecated config values 'coloredSymbolOnly'. Please switch to 'coloredSymbol' & 'coloredText'!");
Log.warn("Your are using the deprecated config values 'coloredSymbolOnly'. Please switch to 'coloredSymbol' & 'coloredText'!");
this.config.coloredText = false;
this.config.coloredSymbol = true;
}
@ -209,6 +204,11 @@ Module.register("calendar", {
this.updateDom(this.config.animationSpeed);
},
eventEndingWithinNextFullTimeUnit (event, ONE_DAY) {
const now = new Date();
return event.endDate - now <= ONE_DAY;
},
// Override dom generator.
getDom () {
const ONE_SECOND = 1000; // 1,000 milliseconds
@ -443,7 +443,7 @@ Module.register("calendar", {
}
} else {
// Show relative times
if (event.startDate >= now || (event.fullDayEvent && event.today)) {
if (event.startDate >= now || (event.fullDayEvent && this.eventEndingWithinNextFullTimeUnit(event, ONE_DAY))) {
// Use relative time
if (!this.config.hideTime && !event.fullDayEvent) {
timeWrapper.innerHTML = CalendarUtils.capFirst(moment(event.startDate, "x").calendar(null, { sameElse: this.config.dateFormat }));
@ -459,7 +459,7 @@ Module.register("calendar", {
}
if (event.fullDayEvent) {
// Full days events within the next two days
if (event.today) {
if (event.today || (event.fullDayEvent && this.eventEndingWithinNextFullTimeUnit(event, ONE_DAY))) {
timeWrapper.innerHTML = CalendarUtils.capFirst(this.translate("TODAY"));
} else if (event.dayBeforeYesterday) {
if (this.translate("DAYBEFOREYESTERDAY") !== "DAYBEFOREYESTERDAY") {
@ -573,9 +573,16 @@ Module.register("calendar", {
const ONE_HOUR = ONE_MINUTE * 60;
const ONE_DAY = ONE_HOUR * 24;
const now = new Date();
const today = moment().startOf("day");
const future = moment().startOf("day").add(this.config.maximumNumberOfDays, "days").toDate();
let now, today, future;
if (this.config.forceUseCurrentTime || this.defaults.forceUseCurrentTime) {
now = new Date();
today = moment().startOf("day");
future = moment().startOf("day").add(this.config.maximumNumberOfDays, "days").toDate();
} else {
now = new Date(Date.now()); // Can use overridden time
today = moment(now).startOf("day");
future = moment(now).startOf("day").add(this.config.maximumNumberOfDays, "days").toDate();
}
let events = [];
for (const calendarUrl in this.calendarData) {

View file

@ -1,11 +1,4 @@
/* MagicMirror²
* Node Helper: Calendar - CalendarFetcher
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
const https = require("https");
const https = require("node:https");
const ical = require("node-ical");
const Log = require("logger");
const NodeHelper = require("node_helper");

View file

@ -1,14 +1,7 @@
/* MagicMirror²
* Calendar Fetcher Util Methods
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
/**
* @external Moment
*/
const path = require("path");
const path = require("node:path");
const moment = require("moment");
const zoneTable = require(path.join(__dirname, "windowsZones.json"));
@ -63,7 +56,7 @@ const CalendarFetcherUtils = {
event.start.tz = "";
Log.debug(`ical offset=${current_offset} date=${date}`);
mm = moment(date);
let x = parseInt(moment(new Date()).utcOffset());
let x = moment(new Date()).utcOffset();
Log.debug(`net mins=${current_offset * 60 - x}`);
mm = mm.add(x - current_offset * 60, "minutes");
@ -135,24 +128,26 @@ const CalendarFetcherUtils = {
};
const eventDate = function (event, time) {
return CalendarFetcherUtils.isFullDayEvent(event) ? moment(event[time], "YYYYMMDD") : moment(new Date(event[time]));
return CalendarFetcherUtils.isFullDayEvent(event) ? moment(event[time]).startOf("day") : moment(event[time]);
};
Log.debug(`There are ${Object.entries(data).length} calendar entries.`);
const now = new Date(Date.now());
const todayLocal = moment(now).startOf("day").toDate();
const futureLocalDate
= moment(now)
.startOf("day")
.add(config.maximumNumberOfDays, "days")
.subtract(1, "seconds") // Subtract 1 second so that events that start on the middle of the night will not repeat.
.toDate();
Object.entries(data).forEach(([key, event]) => {
Log.debug("Processing entry...");
const now = new Date();
const today = moment().startOf("day").toDate();
const future
= moment()
.startOf("day")
.add(config.maximumNumberOfDays, "days")
.subtract(1, "seconds") // Subtract 1 second so that events that start on the middle of the night will not repeat.
.toDate();
let past = today;
let pastLocalDate = todayLocal;
if (config.includePastEvents) {
past = moment().startOf("day").subtract(config.maximumNumberOfDays, "days").toDate();
pastLocalDate = moment(now).startOf("day").subtract(config.maximumNumberOfDays, "days").toDate();
}
// FIXME: Ugly fix to solve the facebook birthday issue.
@ -166,33 +161,33 @@ const CalendarFetcherUtils = {
if (event.type === "VEVENT") {
Log.debug(`Event:\n${JSON.stringify(event)}`);
let startDate = eventDate(event, "start");
let endDate;
let startMoment = eventDate(event, "start");
let endMoment;
if (typeof event.end !== "undefined") {
endDate = eventDate(event, "end");
endMoment = eventDate(event, "end");
} else if (typeof event.duration !== "undefined") {
endDate = startDate.clone().add(moment.duration(event.duration));
endMoment = startMoment.clone().add(moment.duration(event.duration));
} else {
if (!isFacebookBirthday) {
// make copy of start date, separate storage area
endDate = moment(startDate.format("x"), "x");
endMoment = moment(startMoment.valueOf());
} else {
endDate = moment(startDate).add(1, "days");
endMoment = moment(startMoment).add(1, "days");
}
}
Log.debug(`start: ${startDate.toDate()}`);
Log.debug(`end:: ${endDate.toDate()}`);
Log.debug(`start: ${startMoment.toDate()}`);
Log.debug(`end:: ${endMoment.toDate()}`);
// Calculate the duration of the event for use with recurring events.
let duration = parseInt(endDate.format("x")) - parseInt(startDate.format("x"));
Log.debug(`duration: ${duration}`);
const durationMs = endMoment.valueOf() - startMoment.valueOf();
Log.debug(`duration: ${durationMs}`);
// FIXME: Since the parsed json object from node-ical comes with time information
// this check could be removed (?)
if (event.start.length === 8) {
startDate = startDate.startOf("day");
startMoment = startMoment.startOf("day");
}
const title = CalendarFetcherUtils.getTitleFromEvent(event);
@ -252,11 +247,11 @@ const CalendarFetcherUtils = {
const geo = event.geo || false;
const description = event.description || false;
if (typeof event.rrule !== "undefined" && event.rrule !== null && !isFacebookBirthday) {
if (event.rrule && typeof event.rrule !== "undefined" && !isFacebookBirthday) {
const rule = event.rrule;
const pastMoment = moment(past);
const futureMoment = moment(future);
const pastMoment = moment(pastLocalDate);
const futureMoment = moment(futureLocalDate);
// can cause problems with e.g. birthdays before 1900
if ((rule.options && rule.origOptions && rule.origOptions.dtstart && rule.origOptions.dtstart.getFullYear() < 1900) || (rule.options && rule.options.dtstart && rule.options.dtstart.getFullYear() < 1900)) {
@ -267,8 +262,8 @@ const CalendarFetcherUtils = {
// For recurring events, get the set of start dates that fall within the range
// of dates we're looking for.
// kblankenship1989 - to fix issue #1798, converting all dates to locale time first, then converting back to UTC time
let pastLocal = 0;
let futureLocal = 0;
let pastLocal;
let futureLocal;
if (CalendarFetcherUtils.isFullDayEvent(event)) {
Log.debug("fullday");
// if full day event, only use the date part of the ranges
@ -284,17 +279,57 @@ const CalendarFetcherUtils = {
pastLocal = pastMoment.toDate();
} else {
// otherwise use NOW.. cause we shouldn't use any before now
pastLocal = moment().toDate(); //now
pastLocal = moment(now).toDate(); //now
}
futureLocal = futureMoment.toDate(); // future
}
Log.debug(`Search for recurring events between: ${pastLocal} and ${futureLocal}`);
let dates = rule.between(pastLocal, futureLocal, true, limitFunction);
const hasByWeekdayRule = rule.options.byweekday !== undefined && rule.options.byweekday !== null;
const oneDayInMs = 24 * 60 * 60 * 1000;
Log.debug(`RRule: ${rule.toString()}`);
rule.options.tzid = null; // RRule gets *very* confused with timezones
let dates = rule.between(new Date(pastLocal.valueOf() - oneDayInMs), new Date(futureLocal.valueOf() + oneDayInMs), true, () => { return true; });
Log.debug(`Title: ${event.summary}, with dates: ${JSON.stringify(dates)}`);
dates = dates.filter((d) => {
if (JSON.stringify(d) === "null") return false;
else return true;
});
// RRule can generate dates with an incorrect recurrence date. Process the array here and apply date correction.
if (hasByWeekdayRule) {
Log.debug("Rule has byweekday, checking for correction");
dates.forEach((date, index, arr) => {
// NOTE: getTimezoneOffset() is negative of the expected value. For America/Los_Angeles under DST (GMT-7),
// this value is +420. For Australia/Sydney under DST (GMT+11), this value is -660.
const tzOffset = date.getTimezoneOffset() / 60;
const hour = date.getHours();
if ((tzOffset < 0) && (hour < -tzOffset)) { // east of GMT
Log.debug(`East of GMT (tzOffset: ${tzOffset}) and hour=${hour} < ${-tzOffset}, Subtracting 1 day from ${date}`);
arr[index] = new Date(date.valueOf() - oneDayInMs);
} else if ((tzOffset > 0) && (hour >= (24 - tzOffset))) { // west of GMT
Log.debug(`West of GMT (tzOffset: ${tzOffset}) and hour=${hour} >= 24-${tzOffset}, Adding 1 day to ${date}`);
arr[index] = new Date(date.valueOf() + oneDayInMs);
}
});
// Adjusting the dates could push it beyond the 'until' date, so filter those out here.
if (rule.options.until !== null) {
dates = dates.filter((date) => {
return date.valueOf() <= rule.options.until.valueOf();
});
}
}
// The dates array from rrule can be confused by DST. If the event was created during DST and we
// are querying a date range during non-DST, rrule can have the incorrect time for the date range.
// Reprocess the array here computing and applying the time offset.
dates.forEach((date, index, arr) => {
let adjustHours = CalendarFetcherUtils.calculateTimezoneAdjustment(event, date);
if (adjustHours !== 0) {
Log.debug(`Applying timezone adjustment hours=${adjustHours} to ${date}`);
arr[index] = new Date(date.valueOf() + (adjustHours * 60 * 60 * 1000));
}
});
// The "dates" array contains the set of dates within our desired date range range that are valid
// for the recurrence rule. *However*, it's possible for us to have a specific recurrence that
// had its date changed from outside the range to inside the range. For the time being,
@ -304,108 +339,35 @@ const CalendarFetcherUtils = {
// Would be great if there was a better way to handle this.
Log.debug(`event.recurrences: ${event.recurrences}`);
if (event.recurrences !== undefined) {
for (let r in event.recurrences) {
for (let dateKey in event.recurrences) {
// Only add dates that weren't already in the range we added from the rrule so that
// we don"t double-add those events.
if (moment(new Date(r)).isBetween(pastMoment, futureMoment) !== true) {
dates.push(new Date(r));
// we don't double-add those events.
let d = new Date(dateKey);
if (!moment(d).isBetween(pastMoment, futureMoment)) {
dates.push(d);
}
}
}
// Lastly, sometimes rrule doesn't include the event.start even if it is in the requested range. Ensure
// inclusion here. Unfortunately dates.includes() doesn't find it so we have to do forEach().
{
let found = false;
dates.forEach((d) => { if (d.valueOf() === event.start.valueOf()) found = true; });
if (!found) {
Log.debug(`event.start=${event.start} was not included in results from rrule; adding`);
dates.splice(0, 0, event.start);
}
}
// Loop through the set of date entries to see which recurrences should be added to our event list.
for (let d in dates) {
let date = dates[d];
let curEvent = event;
let curDurationMs = durationMs;
let showRecurrence = true;
// set the time information in the date to equal the time information in the event
date.setUTCHours(curEvent.start.getUTCHours(), curEvent.start.getUTCMinutes(), curEvent.start.getUTCSeconds(), curEvent.start.getUTCMilliseconds());
// Get the offset of today where we are processing
// This will be the correction, we need to apply.
let nowOffset = new Date().getTimezoneOffset();
// For full day events, the time might be off from RRULE/Luxon problem
// Get time zone offset of the rule calculated event
let dateoffset = date.getTimezoneOffset();
// Reduce the time by the following offset.
Log.debug(` recurring date is ${date} offset is ${dateoffset}`);
let dh = moment(date).format("HH");
Log.debug(` recurring date is ${date} offset is ${dateoffset / 60} Hour is ${dh}`);
if (CalendarFetcherUtils.isFullDayEvent(event)) {
Log.debug("Fullday");
// If the offset is negative (east of GMT), where the problem is
if (dateoffset < 0) {
if (dh < Math.abs(dateoffset / 60)) {
// if the rrule byweekday WAS explicitly set , correct it
// reduce the time by the offset
if (curEvent.rrule.origOptions.byweekday !== undefined) {
// Apply the correction to the date/time to get it UTC relative
date = new Date(date.getTime() - Math.abs(24 * 60) * 60000);
}
// the duration was calculated way back at the top before we could correct the start time..
// fix it for this event entry
//duration = 24 * 60 * 60 * 1000;
Log.debug(`new recurring date1 fulldate is ${date}`);
}
} else {
// if the timezones are the same, correct date if needed
//if (event.start.tz === moment.tz.guess()) {
// if the date hour is less than the offset
if (24 - dh <= Math.abs(dateoffset / 60)) {
// if the rrule byweekday WAS explicitly set , correct it
if (curEvent.rrule.origOptions.byweekday !== undefined) {
// apply the correction to the date/time back to right day
date = new Date(date.getTime() + Math.abs(24 * 60) * 60000);
}
// the duration was calculated way back at the top before we could correct the start time..
// fix it for this event entry
//duration = 24 * 60 * 60 * 1000;
Log.debug(`new recurring date2 fulldate is ${date}`);
}
//}
}
} else {
// not full day, but luxon can still screw up the date on the rule processing
// we need to correct the date to get back to the right event for
if (dateoffset < 0) {
// if the date hour is less than the offset
if (dh <= Math.abs(dateoffset / 60)) {
// if the rrule byweekday WAS explicitly set , correct it
if (curEvent.rrule.origOptions.byweekday !== undefined) {
// Reduce the time by t:
// Apply the correction to the date/time to get it UTC relative
date = new Date(date.getTime() - Math.abs(24 * 60) * 60000);
}
// the duration was calculated way back at the top before we could correct the start time..
// fix it for this event entry
//duration = 24 * 60 * 60 * 1000;
Log.debug(`new recurring date1 is ${date}`);
}
} else {
// if the timezones are the same, correct date if needed
//if (event.start.tz === moment.tz.guess()) {
// if the date hour is less than the offset
if (24 - dh <= Math.abs(dateoffset / 60)) {
// if the rrule byweekday WAS explicitly set , correct it
if (curEvent.rrule.origOptions.byweekday !== undefined) {
// apply the correction to the date/time back to right day
date = new Date(date.getTime() + Math.abs(24 * 60) * 60000);
}
// the duration was calculated way back at the top before we could correct the start time..
// fix it for this event entry
//duration = 24 * 60 * 60 * 1000;
Log.debug(`new recurring date2 is ${date}`);
}
//}
}
}
startDate = moment(date);
Log.debug(`Corrected startDate: ${startDate.toDate()}`);
let adjustDays = CalendarFetcherUtils.calculateTimezoneAdjustment(event, date);
startMoment = moment(date);
// Remove the time information of each date by using its substring, using the following method:
// .toISOString().substring(0,10).
@ -418,30 +380,30 @@ const CalendarFetcherUtils = {
if (curEvent.recurrences !== undefined && curEvent.recurrences[dateKey] !== undefined) {
// We found an override, so for this recurrence, use a potentially different title, start date, and duration.
curEvent = curEvent.recurrences[dateKey];
startDate = moment(curEvent.start);
duration = parseInt(moment(curEvent.end).format("x")) - parseInt(startDate.format("x"));
startMoment = moment(curEvent.start);
curDurationMs = curEvent.end.valueOf() - startMoment.valueOf();
}
// If there's no recurrence override, check for an exception date. Exception dates represent exceptions to the rule.
else if (curEvent.exdate !== undefined && curEvent.exdate[dateKey] !== undefined) {
// This date is an exception date, which means we should skip it in the recurrence pattern.
showRecurrence = false;
}
Log.debug(`duration: ${duration}`);
Log.debug(`duration: ${curDurationMs}`);
endDate = moment(parseInt(startDate.format("x")) + duration, "x");
if (startDate.format("x") === endDate.format("x")) {
endDate = endDate.endOf("day");
endMoment = moment(startMoment.valueOf() + curDurationMs);
if (startMoment.valueOf() === endMoment.valueOf()) {
endMoment = endMoment.endOf("day");
}
const recurrenceTitle = CalendarFetcherUtils.getTitleFromEvent(curEvent);
// If this recurrence ends before the start of the date range, or starts after the end of the date range, don"t add
// it to the event list.
if (endDate.isBefore(past) || startDate.isAfter(future)) {
if (endMoment.isBefore(pastLocal) || startMoment.isAfter(futureLocal)) {
showRecurrence = false;
}
if (CalendarFetcherUtils.timeFilterApplies(now, endDate, dateFilter)) {
if (CalendarFetcherUtils.timeFilterApplies(now, endMoment, dateFilter)) {
showRecurrence = false;
}
@ -449,8 +411,8 @@ const CalendarFetcherUtils = {
Log.debug(`saving event: ${description}`);
newEvents.push({
title: recurrenceTitle,
startDate: (adjustDays ? (adjustDays > 0 ? startDate.add(adjustDays, "hours") : startDate.subtract(Math.abs(adjustDays), "hours")) : startDate).format("x"),
endDate: (adjustDays ? (adjustDays > 0 ? endDate.add(adjustDays, "hours") : endDate.subtract(Math.abs(adjustDays), "hours")) : endDate).format("x"),
startDate: startMoment.format("x"),
endDate: endMoment.format("x"),
fullDayEvent: CalendarFetcherUtils.isFullDayEvent(event),
recurringEvent: true,
class: event.class,
@ -468,43 +430,47 @@ const CalendarFetcherUtils = {
// Log.debug("full day event")
// if the start and end are the same, then make end the 'end of day' value (start is at 00:00:00)
if (fullDayEvent && startDate.format("x") === endDate.format("x")) {
endDate = endDate.endOf("day");
if (fullDayEvent && startMoment.valueOf() === endMoment.valueOf()) {
endMoment = endMoment.endOf("day");
}
if (config.includePastEvents) {
// Past event is too far in the past, so skip.
if (endDate < past) {
if (endMoment < pastLocalDate) {
return;
}
} else {
// It's not a fullday event, and it is in the past, so skip.
if (!fullDayEvent && endDate < new Date()) {
if (!fullDayEvent && endMoment < now) {
return;
}
// It's a fullday event, and it is before today, So skip.
if (fullDayEvent && endDate <= today) {
if (fullDayEvent && endMoment <= todayLocal) {
return;
}
}
// It exceeds the maximumNumberOfDays limit, so skip.
if (startDate > future) {
if (startMoment > futureLocalDate) {
return;
}
if (CalendarFetcherUtils.timeFilterApplies(now, endDate, dateFilter)) {
if (CalendarFetcherUtils.timeFilterApplies(now, endMoment, dateFilter)) {
return;
}
// get correction for date saving and dst change between now and then
let adjustDays = CalendarFetcherUtils.calculateTimezoneAdjustment(event, startDate.toDate());
let adjustHours = CalendarFetcherUtils.calculateTimezoneAdjustment(event, startMoment.toDate());
// This shouldn't happen
if (adjustHours) {
Log.warn(`Unexpected timezone adjustment of ${adjustHours} hours on non-recurring event`);
}
// Every thing is good. Add it to the list.
newEvents.push({
title: title,
startDate: (adjustDays ? (adjustDays > 0 ? startDate.add(adjustDays, "hours") : startDate.subtract(Math.abs(adjustDays), "hours")) : startDate).format("x"),
endDate: (adjustDays ? (adjustDays > 0 ? endDate.add(adjustDays, "hours") : endDate.subtract(Math.abs(adjustDays), "hours")) : endDate).format("x"),
startDate: startMoment.add(adjustHours, "hours").format("x"),
endDate: endMoment.add(adjustHours, "hours").format("x"),
fullDayEvent: fullDayEvent,
class: event.class,
location: location,
@ -585,7 +551,7 @@ const CalendarFetcherUtils = {
increment = until[1].slice(-1) === "s" ? until[1] : `${until[1]}s`, // Massage the data for moment js
filterUntil = moment(endDate.format()).subtract(value, increment);
return now < filterUntil.format("x");
return now < filterUntil.toDate();
}
return false;

View file

@ -1,9 +1,3 @@
/* MagicMirror²
* Calendar Util Methods
*
* By Rejas
* MIT Licensed.
*/
const CalendarUtils = {
/**

View file

@ -1,9 +1,6 @@
/* CalendarFetcher Tester
* use this script with `node debug.js` to test the fetcher without the need
* of starting the MagicMirror² core. Adjust the values below to your desire.
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
// Alias modules mentioned in package.js under _moduleAliases.
require("module-alias/register");

View file

@ -1,9 +1,3 @@
/* MagicMirror²
* Node Helper: Calendar
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
const NodeHelper = require("node_helper");
const Log = require("logger");
const CalendarFetcher = require("./calendarfetcher");
@ -53,9 +47,14 @@ module.exports = NodeHelper.create({
}
let fetcher;
let fetchIntervalCorrected;
if (typeof this.fetchers[identifier + url] === "undefined") {
Log.log(`Create new calendarfetcher for url: ${url} - Interval: ${fetchInterval}`);
fetcher = new CalendarFetcher(url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, broadcastPastEvents, selfSignedCert);
if (fetchInterval < 60000) {
Log.warn(`fetchInterval for url ${url} must be >= 60000`);
fetchIntervalCorrected = 60000;
}
Log.log(`Create new calendarfetcher for url: ${url} - Interval: ${fetchIntervalCorrected || fetchInterval}`);
fetcher = new CalendarFetcher(url, fetchIntervalCorrected || fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, broadcastPastEvents, selfSignedCert);
fetcher.onReceive((fetcher) => {
this.broadcastEvents(fetcher, identifier);

View file

@ -1,11 +1,5 @@
/* global SunCalc, formatTime */
/* MagicMirror²
* Module: Clock
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
Module.register("clock", {
// Module config defaults.
defaults: {
@ -105,7 +99,6 @@ Module.register("clock", {
analogWrapper.className = "clock-circle";
const digitalWrapper = document.createElement("div");
digitalWrapper.className = "digital";
digitalWrapper.style.gridArea = "center";
/************************************
* Create wrappers for DIGITAL clock
@ -129,7 +122,7 @@ Module.register("clock", {
// Set content of wrappers.
// The moment().format("h") method has a bug on the Raspberry Pi.
// So we need to generate the timestring manually.
// See issue: https://github.com/MichMich/MagicMirror/issues/181
// See issue: https://github.com/MagicMirrorOrg/MagicMirror/issues/181
let timeString;
const now = moment();
if (this.config.timezone) {
@ -247,7 +240,7 @@ Module.register("clock", {
analogWrapper.style.background = `url(${this.data.path}faces/${this.config.analogFace}.svg)`;
analogWrapper.style.backgroundSize = "100%";
// The following line solves issue: https://github.com/MichMich/MagicMirror/issues/611
// The following line solves issue: https://github.com/MagicMirrorOrg/MagicMirror/issues/611
// analogWrapper.style.border = "1px solid black";
analogWrapper.style.border = "rgba(0, 0, 0, 0.1)"; //Updated fix for Issue 611 where non-black backgrounds are used
} else if (this.config.analogFace !== "none") {

View file

@ -1,9 +1,3 @@
/* MagicMirror²
* Module: Compliments
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
Module.register("compliments", {
// Module config defaults.
defaults: {
@ -56,7 +50,7 @@ Module.register("compliments", {
* @returns {number} a random index of given array
*/
randomIndex (compliments) {
if (compliments.length === 1) {
if (compliments.length <= 1) {
return 0;
}

View file

@ -1,8 +1,5 @@
/* MagicMirror² Default Modules List
/* Default Modules List
* Modules listed below can be loaded without the 'default/' prefix. Omitting the default folder name.
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
const defaultModules = ["alert", "calendar", "clock", "compliments", "helloworld", "newsfeed", "updatenotification", "weather"];

View file

@ -1,9 +1,3 @@
/* MagicMirror²
* Module: HelloWorld
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
Module.register("helloworld", {
// Default module config.
defaults: {

View file

@ -1,9 +1,3 @@
/* MagicMirror²
* Module: NewsFeed
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
Module.register("newsfeed", {
// Default module config.
defaults: {
@ -118,27 +112,33 @@ Module.register("newsfeed", {
//Override template data and return whats used for the current template
getTemplateData () {
if (this.activeItem >= this.newsItems.length) {
this.activeItem = 0;
}
this.activeItemCount = this.newsItems.length;
// this.config.showFullArticle is a run-time configuration, triggered by optional notifications
if (this.config.showFullArticle) {
this.activeItemHash = this.newsItems[this.activeItem]?.hash;
return {
url: this.getActiveItemURL()
};
}
if (this.error) {
this.activeItemHash = undefined;
return {
error: this.error
};
}
if (this.newsItems.length === 0) {
this.activeItemHash = undefined;
return {
empty: true
};
}
if (this.activeItem >= this.newsItems.length) {
this.activeItem = 0;
}
const item = this.newsItems[this.activeItem];
this.activeItemHash = item.hash;
const items = this.newsItems.map(function (item) {
item.publishDate = moment(new Date(item.pubdate)).fromNow();
return item;
@ -150,7 +150,7 @@ Module.register("newsfeed", {
sourceTitle: item.sourceTitle,
publishDate: moment(new Date(item.pubdate)).fromNow(),
title: item.title,
url: this.getUrlPrefix(item) + item.url,
url: this.getActiveItemURL(),
description: item.description,
items: items
};
@ -312,8 +312,27 @@ Module.register("newsfeed", {
if (this.timer) clearInterval(this.timer);
this.timer = setInterval(() => {
this.activeItem++;
this.updateDom(this.config.animationSpeed);
/*
* When animations are enabled, don't update the DOM unless we are actually changing what we are displaying.
* (Animating from a headline to itself is unsightly.)
* Cases:
*
* Number of items | Number of items | Display
* at last update | right now | Behaviour
* ----------------------------------------------------
* 0 | 0 | do not update
* 0 | >0 | update
* 1 | 0 or >1 | update
* 1 | 1 | update only if item details (hash value) changed
* >1 | any | update
*
* (N.B. We set activeItemCount and activeItemHash in getTemplateData().)
*/
if (this.newsItems.length > 1 || this.newsItems.length !== this.activeItemCount || this.activeItemHash !== this.newsItems[0]?.hash) {
this.activeItem++; // this is OK if newsItems.Length==1; getTemplateData will wrap it around
this.updateDom(this.config.animationSpeed);
}
// Broadcast NewsFeed if needed
if (this.config.broadcastNewsFeeds) {

View file

@ -1,11 +1,5 @@
/* MagicMirror²
* Node Helper: Newsfeed - NewsfeedFetcher
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
const stream = require("stream");
const crypto = require("node:crypto");
const stream = require("node:stream");
const FeedMe = require("feedme");
const iconv = require("iconv-lite");
const { htmlToText } = require("html-to-text");
@ -67,7 +61,8 @@ const NewsfeedFetcher = function (url, reloadInterval, encoding, logFeedWarnings
description: description,
pubdate: pubdate,
url: url,
useCorsProxy: useCorsProxy
useCorsProxy: useCorsProxy,
hash: crypto.createHash("sha256").update(`${pubdate} :: ${title} :: ${url}`).digest("hex")
});
} else if (logFeedWarnings) {
Log.warn("Can't parse feed item:");

View file

@ -1,10 +1,3 @@
/* MagicMirror²
* Node Helper: Newsfeed
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
const NodeHelper = require("node_helper");
const Log = require("logger");
const NewsfeedFetcher = require("./newsfeedfetcher");

View file

@ -1,7 +1,7 @@
const util = require("util");
const exec = util.promisify(require("child_process").exec);
const fs = require("fs");
const path = require("path");
const util = require("node:util");
const exec = util.promisify(require("node:child_process").exec);
const fs = require("node:fs");
const path = require("node:path");
const Log = require("logger");
const BASE_DIR = path.normalize(`${__dirname}/../../../`);
@ -128,7 +128,7 @@ class GitHelper {
const { stderr } = await this.execShell(`cd ${repo.folder} && git fetch -n --dry-run`);
// example output:
// From https://github.com/MichMich/MagicMirror
// From https://github.com/MagicMirrorOrg/MagicMirror
// e40ddd4..06389e3 develop -> origin/develop
// here the result is in stderr (this is a git default, don't ask why ...)
const matches = stderr.match(this.getRefRegex(gitInfo.current));

View file

@ -1,6 +1,7 @@
const Exec = require("child_process").exec;
const Spawn = require("child_process").spawn;
const commandExists = require("command-exists");
const Exec = require("node:child_process").exec;
const Spawn = require("node:child_process").spawn;
const pm2 = require("pm2");
const Log = require("logger");
/* class Updater
@ -138,7 +139,7 @@ class Updater {
// restart MagicMiror with "pm2"
pm2Restart () {
Log.info("updatenotification: PM2 will restarting MagicMirror...");
Exec(`pm2 restart ${this.PM2}`, (err, std, sde) => {
pm2.restart(this.PM2, (err, proc) => {
if (err) {
Log.error("updatenotification:[PM2] restart Error", err);
}
@ -159,53 +160,35 @@ class Updater {
check_PM2_Process () {
Log.info("updatenotification: Checking PM2 using...");
return new Promise((resolve) => {
commandExists("pm2")
.then(async () => {
var PM2_List = await this.PM2_GetList();
if (!PM2_List) {
pm2.connect((err) => {
if (err) {
Log.error("updatenotification: [PM2]", err);
this.usePM2 = false;
resolve(false);
return;
}
pm2.list((err, list) => {
if (err) {
Log.error("updatenotification: [PM2] Can't get process List!");
this.usePM2 = false;
resolve(false);
return;
}
PM2_List.forEach((pm) => {
if (pm.pm2_env.version === this.version && pm.pm2_env.status === "online" && pm.pm2_env.PWD.includes(this.root_path)) {
list.forEach((pm) => {
if (pm.pm2_env.version === this.version && pm.pm2_env.status === "online" && pm.pm2_env.pm_cwd.includes(`${this.root_path}/`)) {
this.PM2 = pm.name;
this.usePM2 = true;
Log.info("updatenotification: You are using pm2 with", this.PM2);
Log.info("updatenotification: [PM2] You are using pm2 with", this.PM2);
resolve(true);
}
});
pm2.disconnect();
if (!this.PM2) {
Log.info("updatenotification: You are not using pm2");
Log.info("updatenotification: [PM2] You are not using pm2");
this.usePM2 = false;
resolve(false);
}
})
.catch(() => {
Log.info("updatenotification: You are not using pm2");
this.usePM2 = false;
resolve(false);
});
});
}
// Get the list of pm2 process
PM2_GetList () {
return new Promise((resolve) => {
Exec("pm2 jlist", (err, std, sde) => {
if (err) {
resolve(null);
return;
}
try {
let result = JSON.parse(std);
resolve(result);
} catch (e) {
Log.error("updatenotification: [PM2] can't GetList!");
Log.debug("updatenotification: [PM2] GetList is not an JSON format", e);
resolve(null);
}
});
});
}
@ -218,7 +201,7 @@ class Updater {
// search update module command
applyCommand (module) {
if (this.isMagicMirror(module.module)) return null;
if (this.isMagicMirror(module.module) || !this.updates.length) return null;
let command = null;
this.updates.forEach((updater) => {
if (updater[module]) command = updater[module];

View file

@ -1,9 +1,3 @@
/* MagicMirror²
* Module: UpdateNotification
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
Module.register("updatenotification", {
defaults: {
updateInterval: 10 * 60 * 1000, // every 10 minutes
@ -18,7 +12,7 @@ Module.register("updatenotification", {
suspended: false,
moduleList: {},
needRestart: false,
updates: {},
updates: [],
start () {
Log.info(`Starting module: ${this.name}`);
@ -102,7 +96,7 @@ Module.register("updatenotification", {
const localRef = status.hash;
const remoteRef = status.tracking.replace(/.*\//, "");
return `<a href="https://github.com/MichMich/MagicMirror/compare/${localRef}...${remoteRef}" class="xsmall dimmed difflink" target="_blank">${text}</a>`;
return `<a href="https://github.com/MagicMirrorOrg/MagicMirror/compare/${localRef}...${remoteRef}" class="xsmall dimmed difflink" target="_blank">${text}</a>`;
});
},

View file

@ -1,3 +1,8 @@
{% macro humidity() %}
{% if current.humidity %}
<span class="humidity"><span>{{ current.humidity | decimalSymbol }}</span><sup>&nbsp;<i class="wi wi-humidity humidity-icon"></i></sup></span>
{% endif %}
{% endmacro %}
{% if current %}
{% if not config.onlyTemp %}
<div class="normal medium">
@ -7,8 +12,7 @@
{% if config.showWindDirection %}
<sup>
{% if config.showWindDirectionAsArrow %}
<i class="fas fa-long-arrow-alt-down"
style="transform:rotate({{ current.windFromDirection }}deg)"></i>
<i class="fas fa-long-arrow-alt-down" style="transform:rotate({{ current.windFromDirection }}deg)"></i>
{% else %}
{{ current.cardinalWindDirection() | translate }}
{% endif %}
@ -16,8 +20,8 @@
</sup>
{% endif %}
</span>
{% if config.showHumidity and current.humidity %}
<span>{{ current.humidity | decimalSymbol }}</span><sup>&nbsp;<i class="wi wi-humidity humidity-icon"></i></sup>
{% if config.showHumidity === "wind" %}
{{ humidity() }}
{% endif %}
{% if config.showSun %}
<span class="wi dimmed wi-{{ current.nextSunAction() }}"></span>
@ -37,28 +41,39 @@
{% endif %}
</div>
{% endif %}
<div class="large light">
<span class="wi weathericon wi-{{ current.weatherType }}"></span>
<span class="bright">{{ current.temperature | roundValue | unit("temperature") | decimalSymbol }}</span>
</div>
<div class="normal light indoor">
{% if config.showIndoorTemperature and indoor.temperature %}
<div>
<span class="fas fa-home"></span>
<span class="bright">{{ indoor.temperature | roundValue | unit("temperature") | decimalSymbol }}</span>
</div>
<div class="large">
{% if config.showIndoorTemperature and indoor.temperature or config.showIndoorHumidity and indoor.humidity %}
<span class="medium fas fa-home"></span>
<span style="display: inline-block">
{% if config.showIndoorTemperature and indoor.temperature %}
<sup class="small" style="position: relative; display: block; text-align: left;">
<span>
{{ indoor.temperature | roundValue | unit("temperature") | decimalSymbol }}
</span>
</sup>
{% endif %}
{% if config.showIndoorHumidity and indoor.humidity %}
<sub class="small" style="position: relative; display: block; text-align: left;">
<span>
{{ indoor.humidity | roundValue | unit("humidity") | decimalSymbol }}
</span>
</sub>
{% endif %}
</span>
{% endif %}
{% if config.showIndoorHumidity and indoor.humidity %}
<div>
<span class="fas fa-tint"></span>
<span class="bright">{{ indoor.humidity | roundValue | unit("humidity") | decimalSymbol }}</span>
</div>
<span class="light wi weathericon wi-{{ current.weatherType }}"></span>
<span class="light bright">{{ current.temperature | roundValue | unit("temperature") | decimalSymbol }}</span>
{% if config.showHumidity === "temp" %}
<span class="medium bright">{{ humidity() }}</span>
{% endif %}
</div>
{% if (config.showFeelsLike or config.showPrecipitationAmount or config.showPrecipitationProbability) and not config.onlyTemp %}
<div class="normal medium feelslike">
{% if config.showFeelsLike %}
<span class="dimmed">
{% if config.showHumidity === "feelslike" %}
{{ humidity() }}
{% endif %}
{{ "FEELS" | translate({DEGREE: current.feelsLike() | roundValue | unit("temperature") | decimalSymbol }) }}
</span>
<br />
@ -76,6 +91,9 @@
{% endif %}
</div>
{% endif %}
{% if config.showHumidity === "below" %}
<span class="medium dimmed">{{ humidity() }}</span>
{% endif %}
{% else %}
<div class="dimmed light small">{{ "LOADING" | translate }}</div>
{% endif %}

View file

@ -1,10 +1,6 @@
/* global WeatherProvider, WeatherObject, WeatherUtils */
/* MagicMirror²
* Module: Weather
* Provider: Environment Canada (EC)
*
* This class is a provider for Environment Canada MSC Datamart
/* This class is a provider for Environment Canada MSC Datamart
* Note that this is only for Canadian locations and does not require an API key (access is anonymous)
*
* EC Documentation at following links:
@ -27,8 +23,6 @@
* with locations you can search under column B (English Names), with the corresponding siteCode under
* column A (Codes) and provCode under column C (Province).
*
* Original by Kevin Godin
*
* License to use Environment Canada (EC) data is detailed here:
* https://eccc-msc.github.io/open-data/licence/readme_en/
*

View file

@ -1,15 +1,9 @@
/* global WeatherProvider, WeatherObject */
/* MagicMirror²
* Module: Weather
* Provider: Open-Meteo
*
* By Andrés Vanegas
* MIT Licensed
*
* This class is a provider for Open-Meteo, based on Andrew Pometti's class
* for Weatherbit.
/* This class is a provider for Open-Meteo,
* see https://open-meteo.com/
*/
// https://www.bigdatacloud.com/docs/api/free-reverse-geocode-to-city-api
const GEOCODE_BASE = "https://api.bigdatacloud.net/data/reverse-geocode-client";
const OPEN_METEO_BASE = "https://api.open-meteo.com/v1";

View file

@ -1,12 +1,7 @@
/* global WeatherProvider, WeatherObject */
/* MagicMirror²
* Module: Weather
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*
* This class is the blueprint for a weather provider.
/* This class is a provider for Openweathermap,
* see https://openweathermap.org/
*/
WeatherProvider.register("openweathermap", {
// Set the name of the provider.

View file

@ -1,14 +1,7 @@
/* global WeatherProvider, WeatherObject */
/* MagicMirror²
* Module: Weather
* Provider: Pirate Weather
*
* Written by Nicholas Hubbard https://github.com/nhubbard for formerly Dark Sky Provider
* Modified by Karsten Hassel for Pirate Weather
* MIT Licensed
*
* This class is a provider for Pirate Weather, it is a replacement for Dark Sky (same api).
/* This class is a provider for Pirate Weather, it is a replacement for Dark Sky (same api),
* see http://pirateweather.net/en/latest/
*/
WeatherProvider.register("pirateweather", {
// Set the name of the provider.

View file

@ -1,14 +1,8 @@
/* global WeatherProvider, WeatherObject */
/* MagicMirror²
* Module: Weather
* Provider: SMHI
*
* By BuXXi https://github.com/buxxi
* MIT Licensed
*
* This class is a provider for SMHI (Sweden only). Metric system is the only
* supported unit.
/* This class is a provider for SMHI (Sweden only).
* Metric system is the only supported unit,
* see https://www.smhi.se/
*/
WeatherProvider.register("smhi", {
providerName: "SMHI",

View file

@ -1,12 +1,7 @@
/* global WeatherProvider, WeatherObject, WeatherUtils */
/* MagicMirror²
* Module: Weather
*
* By Malcolm Oakes https://github.com/maloakes
* MIT Licensed.
*
* This class is a provider for UK Met Office Datapoint.
/* This class is a provider for UK Met Office Datapoint,
* see https://www.metoffice.gov.uk/
*/
WeatherProvider.register("ukmetoffice", {
// Set the name of the provider.

View file

@ -1,13 +1,6 @@
/* global WeatherProvider, WeatherObject */
/* MagicMirror²
* Module: Weather
*
* By Malcolm Oakes https://github.com/maloakes
* Existing Met Office provider edited for new MetOffice Data Hub by CreepinJesus http://github.com/XBCreepinJesus
* MIT Licensed.
*
* This class is a provider for UK Met Office Data Hub (the replacement for their Data Point services).
/* This class is a provider for UK Met Office Data Hub (the replacement for their Data Point services).
* For more information on Data Hub, see https://www.metoffice.gov.uk/services/data/datapoint/notifications/weather-datahub
* Data available:
* Hourly data for next 2 days ("hourly") - https://www.metoffice.gov.uk/binaries/content/assets/metofficegovuk/pdf/data/global-spot-data-hourly.pdf

View file

@ -1,14 +1,7 @@
/* global WeatherProvider, WeatherObject */
/* MagicMirror²
* Module: Weather
* Provider: Weatherbit
*
* By Andrew Pometti
* MIT Licensed
*
* This class is a provider for Weatherbit, based on Nicholas Hubbard's class
* for Dark Sky & Vince Peri's class for Weather.gov.
/* This class is a provider for Weatherbit,
* see https://www.weatherbit.io/
*/
WeatherProvider.register("weatherbit", {
// Set the name of the provider.

View file

@ -1,16 +1,8 @@
/* global WeatherProvider, WeatherObject, WeatherUtils */
/* MagicMirror²
* Module: Weather
* Provider: Weatherflow
*
* By Tobias Dreyem https://github.com/10bias
* MIT Licensed
*
* This class is a provider for Weatherflow.
/* This class is a provider for Weatherflow.
* Note that the Weatherflow API does not provide snowfall.
*/
WeatherProvider.register("weatherflow", {
// Set the name of the provider.
// Not strictly required, but helps for debugging

View file

@ -1,13 +1,8 @@
/* global WeatherProvider, WeatherObject, WeatherUtils */
/* MagicMirror²
* Module: Weather
* Provider: weather.gov
/* Provider: weather.gov
* https://weather-gov.github.io/api/general-faqs
*
* Original by Vince Peri
* MIT Licensed.
*
* This class is a provider for weather.gov.
* Note that this is only for US locations (lat and lon) and does not require an API key
* Since it is free, there are some items missing - like sunrise, sunset
@ -39,7 +34,6 @@ WeatherProvider.register("weathergov", {
// Called to set the config, this config is the same as the weather module's config.
setConfig (config) {
this.config = config;
this.config.apiBase = "https://api.weather.gov";
this.fetchWxGovURLs(this.config);
},
@ -123,7 +117,7 @@ WeatherProvider.register("weathergov", {
* Get specific URLs
*/
fetchWxGovURLs (config) {
this.fetchData(`${config.apiBase}/points/${config.lat},${config.lon}`)
this.fetchData(`${config.apiBase}/${config.lat},${config.lon}`)
.then((data) => {
if (!data || !data.properties) {
// points URL did not respond with usable data.

View file

@ -1,14 +1,6 @@
/* global WeatherProvider, WeatherObject */
/* MagicMirror²
* Module: Weather
* Provider: Yr.no
*
* By Magnus Marthinsen
* MIT Licensed
*
* This class is a provider for Yr.no, a norwegian weather service.
*
/* This class is a provider for Yr.no, a norwegian weather service.
* Terms of service: https://developer.yr.no/doc/TermsOfService/
*/
WeatherProvider.register("yr", {

View file

@ -1,11 +1,5 @@
/* global WeatherProvider, WeatherUtils, formatTime */
/* MagicMirror²
* Module: Weather
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*/
Module.register("weather", {
// Default module config.
defaults: {
@ -20,7 +14,7 @@ Module.register("weather", {
updateInterval: 10 * 60 * 1000, // every 10 minutes
animationSpeed: 1000,
showFeelsLike: true,
showHumidity: false,
showHumidity: "none", // this is now a string; see current.njk
showIndoorHumidity: false,
showIndoorTemperature: false,
allowOverrideNotification: false,
@ -86,6 +80,10 @@ Module.register("weather", {
Log.warn("Your are using the deprecated config values 'useBeaufort'. Please switch to windUnits!");
this.windUnits = "beaufort";
}
if (typeof this.config.showHumidity === "boolean") {
Log.warn("[weather] Deprecation warning: Please consider updating showHumidity to the new style (config string).");
this.config.showHumidity = this.config.showHumidity ? "wind" : "none";
}
// Initialize the weather provider.
this.weatherProvider = WeatherProvider.initialize(this.config.weatherProvider, this);
@ -235,7 +233,7 @@ Module.register("weather", {
}
}
} else if (type === "precip") {
if (value === null || isNaN(value) || value === 0 || value.toFixed(2) === "0.00") {
if (value === null || isNaN(value)) {
formattedValue = "";
} else {
formattedValue = WeatherUtils.convertPrecipitationUnit(value, valueUnit, this.config.units);

View file

@ -1,17 +1,5 @@
/* global SunCalc, WeatherUtils */
/* MagicMirror²
* Module: Weather
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*
* This class is the blueprint for a day which includes weather information.
*
* Currently this is focused on the information which is necessary for the current weather.
* As soon as we start implementing the forecast, mode properties will be added.
*/
/**
* @external Moment
*/

View file

@ -1,13 +1,6 @@
/* global Class, performWebRequest, OverrideWrapper */
/* MagicMirror²
* Module: Weather
*
* By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed.
*
* This class is the blueprint for a weather provider.
*/
// This class is the blueprint for a weather provider.
const WeatherProvider = Class.extend({
// Weather Provider Properties
providerName: null,

View file

@ -1,9 +1,3 @@
/* MagicMirror²
* Weather Util Methods
*
* By Rejas
* MIT Licensed.
*/
const WeatherUtils = {
/**

4014
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "magicmirror",
"version": "2.26.0",
"version": "2.27.0",
"description": "The open source modular smart mirror platform.",
"main": "js/electron.js",
"scripts": {
@ -18,19 +18,19 @@
"test:e2e": "NODE_ENV=test jest --selectProjects e2e -i --forceExit",
"test:unit": "NODE_ENV=test jest --selectProjects unit",
"test:prettier": "prettier . --check",
"test:js": "eslint 'js/**/*.js' 'modules/default/**/*.js' 'clientonly/*.js' 'serveronly/*.js' 'translations/*.js' 'vendor/*.js' 'tests/**/*.js' 'config/*'",
"test:js": "eslint .",
"test:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --config .stylelintrc.json",
"test:calendar": "node ./modules/default/calendar/debug.js",
"config:check": "node js/check_config.js",
"lint:prettier": "prettier . --write",
"lint:js": "eslint 'js/**/*.js' 'modules/default/**/*.js' 'clientonly/*.js' 'serveronly/*.js' 'translations/*.js' 'vendor/*.js' 'tests/**/*.js' 'config/*' --fix",
"lint:js": "eslint . --fix",
"lint:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --config .stylelintrc.json --fix",
"lint:staged": "lint-staged",
"prepare": "[ -f node_modules/.bin/husky ] && husky install || echo no husky installed."
"prepare": "[ -f node_modules/.bin/husky ] && husky || echo no husky installed."
},
"repository": {
"type": "git",
"url": "git+https://github.com/MichMich/MagicMirror.git"
"url": "https://github.com/MagicMirrorOrg/MagicMirror"
},
"keywords": [
"magic mirror",
@ -41,56 +41,58 @@
],
"author": "Michael Teeuw",
"contributors": [
"https://github.com/MichMich/MagicMirror/graphs/contributors"
"https://github.com/MagicMirrorOrg/MagicMirror/graphs/contributors"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/MichMich/MagicMirror/issues"
"url": "https://github.com/MagicMirrorOrg/MagicMirror/issues"
},
"homepage": "https://magicmirror.builders",
"devDependencies": {
"@stylistic/eslint-plugin": "^1.5.1",
"@stylistic/eslint-plugin": "^1.7.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jest": "^27.6.0",
"eslint-plugin-jsdoc": "^46.9.1",
"eslint-plugin-jest": "^27.9.0",
"eslint-plugin-jsdoc": "^48.2.2",
"eslint-plugin-package-json": "^0.12.1",
"eslint-plugin-unicorn": "^51.0.1",
"express-basic-auth": "^1.2.1",
"husky": "^8.0.3",
"husky": "^9.0.11",
"jest": "^29.7.0",
"jsdom": "^23.0.1",
"lint-staged": "^15.2.0",
"lodash": "^4.17.21",
"playwright": "^1.40.1",
"prettier": "^3.1.1",
"jsdom": "^24.0.0",
"lint-staged": "^15.2.2",
"playwright": "^1.42.1",
"prettier": "^3.2.5",
"sinon": "^17.0.1",
"stylelint": "^16.1.0",
"stylelint": "^16.3.1",
"stylelint-config-standard": "^36.0.0",
"stylelint-prettier": "^5.0.0",
"suncalc": "^1.9.0"
"stylelint-prettier": "^5.0.0"
},
"optionalDependencies": {
"electron": "^27.2.0"
"electron": "^29.1.6"
},
"dependencies": {
"colors": "^1.4.0",
"command-exists": "^1.2.9",
"ansis": "^2.3.0",
"console-stamp": "^3.1.2",
"envsub": "^4.1.0",
"eslint": "^8.56.0",
"express": "^4.18.2",
"express-ipfilter": "^1.3.1",
"eslint": "^8.57.0",
"express": "^4.19.2",
"express-ipfilter": "^1.3.2",
"feedme": "^2.0.2",
"helmet": "^7.1.0",
"html-to-text": "^9.0.5",
"iconv-lite": "^0.6.3",
"module-alias": "^2.2.3",
"moment": "^2.30.1",
"node-ical": "^0.17.1",
"socket.io": "^4.7.2"
"node-ical": "^0.18.0",
"pm2": "^5.3.1",
"socket.io": "^4.7.5",
"suncalc": "^1.9.0",
"systeminformation": "^5.22.6"
},
"lint-staged": {
"*": "prettier --write",
"*.js": "eslint",
"*.css": "stylelint"
"*.js": "eslint --fix",
"*.css": "stylelint --fix"
},
"_moduleAliases": {
"node_helper": "js/node_helper.js",

View file

@ -4,5 +4,5 @@ const Log = require("../js/logger");
app.start().then((config) => {
const bindAddress = config.address ? config.address : "localhost";
const httpType = config.useHttps ? "https" : "http";
Log.log(`\nReady to go! Please point your browser to: ${httpType}://${bindAddress}:${config.port}`);
Log.info(`\n>>> Ready to go! Please point your browser to: ${httpType}://${bindAddress}:${config.port} <<<`);
});

View file

@ -1,8 +1,3 @@
/* MagicMirror² Test default config for modules
*
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
* MIT Licensed.
*/
exports.configFactory = (options) => {
return Object.assign(
{

View file

@ -1,8 +1,3 @@
/* MagicMirror² Test config sample ipWhitelist
*
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
* MIT Licensed.
*/
let config = require(`${process.cwd()}/tests/configs/default.js`).configFactory({
ipWhitelist: [],
port: 8282

View file

@ -1,8 +1,3 @@
/* MagicMirror² Test config sample module alert
*
* By rejas
* MIT Licensed.
*/
let config = {
modules: [
{

View file

@ -1,8 +1,3 @@
/* MagicMirror² Test config default calendar with auth by default
*
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
* MIT Licensed.
*/
let config = {
timeFormat: 12,

View file

@ -1,8 +1,3 @@
/* MagicMirror² Test ics with out of date event causing bad return from rrule.between
*
* By Sam Detweiler
* MIT Licensed.
*/
let config = {
timeFormat: 12,
logLevel: ["INFO", "LOG", "WARN", "ERROR", "DEBUG"],

View file

@ -1,8 +1,3 @@
/* MagicMirror² Test config default calendar
*
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
* MIT Licensed.
*/
let config = {
timeFormat: 12,

View file

@ -1,8 +1,3 @@
/* MagicMirror² Test config default calendar with auth by default
*
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
* MIT Licensed.
*/
let config = {
timeFormat: 12,

View file

@ -1,8 +1,3 @@
/* MagicMirror² Test config custom calendar
*
* By Rejas
* MIT Licensed.
*/
let config = {
timeFormat: 12,
@ -12,6 +7,7 @@ let config = {
position: "bottom_bar",
config: {
customEvents: [{ keyword: "CustomEvent", symbol: "dice", eventClass: "undo" }],
forceUseCurrentTime: true,
calendars: [
{
maximumEntries: 5,

View file

@ -1,8 +1,3 @@
/* MagicMirror² Test config default calendar
*
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
* MIT Licensed.
*/
let config = {
timeFormat: 12,

View file

@ -3,11 +3,8 @@
* By jkriegshauser
* MIT Licensed.
*
* NOTE: calendar_test_exdate.ics has exdate entries for the next 20 years, but without some
* way to set a debug date for tests, this test may become flaky on specific days (i.e. could
* not test easily on leap-years, the BYDAY specified in exdate, etc.) or when the 20 years
* elapses if this project is still in active development ;)
* See issue #3250
* See tests/electron/modules/calendar_spec.js
*/
let config = {
timeFormat: 12,
@ -21,8 +18,8 @@ let config = {
calendars: [
{
maximumEntries: 100,
maximumNumberOfDays: 364,
url: "http://localhost:8080/tests/mocks/calendar_test_exdate.ics"
maximumNumberOfDays: 28, // 4 weeks, 2 of which are skipped
url: "http://localhost:8080/tests/mocks/exdate_la_at_midnight_dst.ics"
}
]
}
@ -30,6 +27,10 @@ let config = {
]
};
Date.now = () => {
return new Date("19 Oct 2023 12:30:00 GMT-07:00").valueOf();
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;

View file

@ -0,0 +1,37 @@
/* MagicMirror² Test calendar exdate
*
* By jkriegshauser
* MIT Licensed.
*
* See issue #3250
* See tests/electron/modules/calendar_spec.js
*/
let config = {
timeFormat: 12,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
maximumEntries: 100,
calendars: [
{
maximumEntries: 100,
maximumNumberOfDays: 28, // 4 weeks, 2 of which are skipped
url: "http://localhost:8080/tests/mocks/exdate_la_at_midnight_std.ics"
}
]
}
}
]
};
Date.now = () => {
return new Date("19 Oct 2023 12:30:00 GMT-07:00").valueOf();
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View file

@ -0,0 +1,37 @@
/* MagicMirror² Test calendar exdate
*
* By jkriegshauser
* MIT Licensed.
*
* See issue #3250
* See tests/electron/modules/calendar_spec.js
*/
let config = {
timeFormat: 12,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
maximumEntries: 100,
calendars: [
{
maximumEntries: 100,
maximumNumberOfDays: 28, // 4 weeks, 2 of which are skipped
url: "http://localhost:8080/tests/mocks/exdate_la_before_midnight.ics"
}
]
}
}
]
};
Date.now = () => {
return new Date("19 Oct 2023 12:30:00 GMT-07:00").valueOf();
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View file

@ -0,0 +1,37 @@
/* MagicMirror² Test calendar exdate
*
* By jkriegshauser
* MIT Licensed.
*
* See issue #3250
* See tests/electron/modules/calendar_spec.js
*/
let config = {
timeFormat: 12,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
maximumEntries: 100,
calendars: [
{
maximumEntries: 100,
maximumNumberOfDays: 28, // 4 weeks, 2 of which are skipped
url: "http://localhost:8080/tests/mocks/exdate_syd_at_midnight_dst.ics"
}
]
}
}
]
};
Date.now = () => {
return new Date("14 Sep 2023 12:30:00 GMT+10:00").valueOf();
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View file

@ -0,0 +1,37 @@
/* MagicMirror² Test calendar exdate
*
* By jkriegshauser
* MIT Licensed.
*
* See issue #3250
* See tests/electron/modules/calendar_spec.js
*/
let config = {
timeFormat: 12,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
maximumEntries: 100,
calendars: [
{
maximumEntries: 100,
maximumNumberOfDays: 28, // 4 weeks, 2 of which are skipped
url: "http://localhost:8080/tests/mocks/exdate_syd_at_midnight_std.ics"
}
]
}
}
]
};
Date.now = () => {
return new Date("14 Sep 2023 12:30:00 GMT+10:00").valueOf();
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View file

@ -0,0 +1,37 @@
/* MagicMirror² Test calendar exdate
*
* By jkriegshauser
* MIT Licensed.
*
* See issue #3250
* See tests/electron/modules/calendar_spec.js
*/
let config = {
timeFormat: 12,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
maximumEntries: 100,
calendars: [
{
maximumEntries: 100,
maximumNumberOfDays: 28, // 4 weeks, 2 of which are skipped
url: "http://localhost:8080/tests/mocks/exdate_syd_before_midnight.ics"
}
]
}
}
]
};
Date.now = () => {
return new Date("14 Sep 2023 12:30:00 GMT+10:00").valueOf();
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View file

@ -1,10 +1,3 @@
/* MagicMirror² Test calendar calendar
*
* This configuration is a wrong authentication
*
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
* MIT Licensed.
*/
let config = {
timeFormat: 12,

View file

@ -0,0 +1,28 @@
/* MagicMirror² Test config for fullday calendar entries over multiple days
*
* By Paranoid93 https://github.com/Paranoid93/
* MIT Licensed.
*/
let config = {
timeFormat: 12,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
calendars: [
{
maximumNumberOfDays: 2,
url: "http://localhost:8080/tests/mocks/calendar_test_multi_day_starting_today.ics"
}
]
}
}
]
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View file

@ -1,8 +1,3 @@
/* MagicMirror² Test config default calendar
* with authentication old config
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
* MIT Licensed.
*/
let config = {
timeFormat: 12,

View file

@ -1,8 +1,3 @@
/* MagicMirror² Test config custom calendar
*
* By Rejas
* MIT Licensed.
*/
let config = {
timeFormat: 12,

View file

@ -0,0 +1,30 @@
let config = {
timeFormat: 12,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
hideDuplicates: false,
maximumEntries: 100,
calendars: [
{
maximumEntries: 100,
maximumNumberOfDays: 1, // Just today
url: "http://localhost:8080/tests/mocks/rrule_until.ics"
}
]
}
}
]
};
Date.now = () => {
return new Date("07 Mar 2024 10:38:00 GMT-07:00").valueOf();
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View file

@ -1,8 +1,3 @@
/* MagicMirror² Test config for multiple calendar events having the same name and start date/time
*
* By Paranoid93 https://github.com/Paranoid93/
* MIT Licensed.
*/
let config = {
timeFormat: 12,

View file

@ -0,0 +1,28 @@
/* MagicMirror² Test config for fullday calendar entries over multiple days
*
* By Paranoid93 https://github.com/Paranoid93/
* MIT Licensed.
*/
let config = {
timeFormat: 12,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
calendars: [
{
maximumNumberOfDays: 2,
url: "http://localhost:8080/tests/mocks/calendar_test_full_day_events.ics"
}
]
}
}
]
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View file

@ -1,8 +1,3 @@
/* MagicMirror² Test config for default clock module
*
* By Sergey Morozov
* MIT Licensed.
*/
let config = {
timeFormat: 12,

View file

@ -1,8 +1,3 @@
/* MagicMirror² Test config for default clock module
*
* By Sergey Morozov
* MIT Licensed.
*/
let config = {
modules: [
{

View file

@ -1,7 +1,3 @@
/* MagicMirror² Test config for analog clock face
*
* MIT Licensed.
*/
let config = {
modules: [
{

View file

@ -1,8 +1,3 @@
/* MagicMirror² Test config for default clock module
*
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
* MIT Licensed.
*/
let config = {
timeFormat: 12,

View file

@ -1,8 +1,3 @@
/* MagicMirror² Test config for default clock module
*
* By Johan Hammar
* MIT Licensed.
*/
let config = {
timeFormat: 12,

Some files were not shown because too many files have changed in this diff Show more