37
CHANGELOG.md
@ -4,9 +4,46 @@ All notable changes to this project will be documented in this file.
|
|||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## [2.6.0] - 2019-01-01
|
||||||
|
|
||||||
|
ℹ️ **Note:** This update uses new dependencies. Please update using the following command: `git pull && npm install`. If you are having issues updating, make sure you are running the latest version of Node.
|
||||||
|
|
||||||
|
### ✨ Experimental ✨
|
||||||
|
- New default [module weather](modules/default/weather). This module will eventually replace the current `currentweather` and `weatherforecast` modules. The new module is still pretty experimental, but it's included so you can give it a try and help us improve this module. Please give us you feedback using [this forum post](https://forum.magicmirror.builders/topic/9335/default-weather-module-refactoring).
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Possibility to add classes to the cell of symbol, title and time of the events of calendar.
|
||||||
|
- Font-awesome 5, still has 4 for backwards compatibility.
|
||||||
|
- Missing `showEnd` in calendar documentation
|
||||||
|
- Screenshot for the new feed module
|
||||||
|
- Screenshot for the compliments module
|
||||||
|
- Screenshot for the clock module
|
||||||
|
- Screenshot for the current weather
|
||||||
|
- 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)
|
||||||
|
- Documentation for the existing `scale` option in the Weather Forecast module.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Allow to parse recurring calendar events where the start date is before 1900
|
||||||
|
- 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)
|
||||||
|
|
||||||
|
### Updated
|
||||||
|
- The default calendar setting `showEnd` is changed to `false`.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- The Weather Forecast module by default displays the ° symbol after every numeric value to be consistent with the Current Weather module.
|
||||||
|
|
||||||
|
|
||||||
## [2.5.0] - 2018-10-01
|
## [2.5.0] - 2018-10-01
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
- Romanian translation for "Feels"
|
||||||
- Support multi-line compliments
|
- Support multi-line compliments
|
||||||
- Simplified Chinese translation for "Feels"
|
- Simplified Chinese translation for "Feels"
|
||||||
- Polish translate for "Feels"
|
- Polish translate for "Feels"
|
||||||
|
@ -38,7 +38,7 @@ MagicMirror² focuses on a modular plugin system and uses [Electron](http://elec
|
|||||||
|
|
||||||
*Electron*, the app wrapper around MagicMirror², only supports the Raspberry Pi 2/3. The Raspberry Pi 0/1 is currently **not** supported. If you want to run this on a Raspberry Pi 1, use the [server only](#server-only) feature and setup a fullscreen browser yourself. (Yes, people have managed to run MM² also on a Pi0, so if you insist, search in the forums.)
|
*Electron*, the app wrapper around MagicMirror², only supports the Raspberry Pi 2/3. The Raspberry Pi 0/1 is currently **not** supported. If you want to run this on a Raspberry Pi 1, use the [server only](#server-only) feature and setup a fullscreen browser yourself. (Yes, people have managed to run MM² also on a Pi0, so if you insist, search in the forums.)
|
||||||
|
|
||||||
Note that you will need to install the lastest full version of Raspbian, **don't use the Lite version**.
|
Note that you will need to install the latest full version of Raspbian, **don't use the Lite version**.
|
||||||
|
|
||||||
Execute the following command on your Raspberry Pi to install MagicMirror²:
|
Execute the following command on your Raspberry Pi to install MagicMirror²:
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ The following properties can be configured:
|
|||||||
| `timeFormat` | The form of time notation that will be used. Possible values are `12` or `24`. The default is `24`. |
|
| `timeFormat` | The form of time notation that will be used. Possible values are `12` or `24`. The default is `24`. |
|
||||||
| `units` | The units that will be used in the default weather modules. Possible values are `metric` or `imperial`. The default is `metric`. |
|
| `units` | The units that will be used in the default weather modules. Possible values are `metric` or `imperial`. The default is `metric`. |
|
||||||
| `modules` | An array of active modules. **The array must contain objects. See the next table below for more information.** |
|
| `modules` | An array of active modules. **The array must contain objects. See the next table below for more information.** |
|
||||||
| `electronOptions` | An optional array of Electron (browser) options. This allows configuration of e.g. the browser screen size and position (example: `electronOptions: { fullscreen: false, width: 800, height: 600 }`). Kiosk mode can be enabled by setting `kiosk = true`, `autoHideMenuBar = false` and `fullscreen = false`. More options can be found [here](https://github.com/electron/electron/blob/master/docs/api/browser-window.md). |
|
| `electronOptions` | An optional array of Electron (browser) options. This allows configuration of e.g. the browser screen size and position (example: `electronOptions: { fullscreen: false, width: 800, height: 600 }`). Kiosk mode can be enabled by setting `kiosk: true`, `autoHideMenuBar: false` and `fullscreen: false`. More options can be found [here](https://github.com/electron/electron/blob/master/docs/api/browser-window.md). |
|
||||||
| `customCss` | The path of the `custom.css` stylesheet. The default is `css/custom.css`. |
|
| `customCss` | The path of the `custom.css` stylesheet. The default is `css/custom.css`. |
|
||||||
|
|
||||||
Module configuration:
|
Module configuration:
|
||||||
|
@ -44,7 +44,7 @@ var config = {
|
|||||||
config: {
|
config: {
|
||||||
calendars: [
|
calendars: [
|
||||||
{
|
{
|
||||||
symbol: "calendar-check-o ",
|
symbol: "calendar-check",
|
||||||
url: "webcal://www.calendarlabs.com/templates/ical/US-Holidays.ics"
|
url: "webcal://www.calendarlabs.com/templates/ical/US-Holidays.ics"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -69,7 +69,7 @@ var config = {
|
|||||||
header: "Weather Forecast",
|
header: "Weather Forecast",
|
||||||
config: {
|
config: {
|
||||||
location: "New York",
|
location: "New York",
|
||||||
locationID: "5128581", //ID from http://www.openweathermap.org/help/city_list.txt
|
locationID: "5128581", //ID from https://openweathermap.org/city
|
||||||
appid: "YOUR_OPENWEATHER_API_KEY"
|
appid: "YOUR_OPENWEATHER_API_KEY"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
# Module: Calendar
|
# Module: Calendar
|
||||||
The `calendar` module is one of the default modules of the MagicMirror.
|
The `calendar` module is one of the default modules of the MagicMirror.
|
||||||
This module displays events from a public .ical calendar. It can combine multiple calendars.
|
This module displays events from a public .ical calendar. It can combine multiple calendars.
|
||||||
Note that calendars may not contain any entry before 1st January 1970, otherwise the calendar won't be displayed and the module will crash.
|
|
||||||
|
|
||||||
## Using the module
|
## Using the module
|
||||||
|
|
||||||
@ -42,8 +41,11 @@ The following properties can be configured:
|
|||||||
| `titleReplace` | An object of textual replacements applied to the tile of the event. This allow to remove or replace certains words in the title. <br><br> **Example:** `{'Birthday of ' : '', 'foo':'bar'}` <br> **Default value:** `{ "De verjaardag van ": "", "'s birthday": "" }`
|
| `titleReplace` | An object of textual replacements applied to the tile of the event. This allow to remove or replace certains words in the title. <br><br> **Example:** `{'Birthday of ' : '', 'foo':'bar'}` <br> **Default value:** `{ "De verjaardag van ": "", "'s birthday": "" }`
|
||||||
| `displayRepeatingCountTitle` | Show count title for yearly repeating events (e.g. "X. Birthday", "X. Anniversary") <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
|
| `displayRepeatingCountTitle` | Show count title for yearly repeating events (e.g. "X. Birthday", "X. Anniversary") <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
|
||||||
| `dateFormat` | Format to use for the date of events (when using absolute dates) <br><br> **Possible values:** See [Moment.js formats](http://momentjs.com/docs/#/parsing/string-format/) <br> **Default value:** `MMM Do` (e.g. Jan 18th)
|
| `dateFormat` | Format to use for the date of events (when using absolute dates) <br><br> **Possible values:** See [Moment.js formats](http://momentjs.com/docs/#/parsing/string-format/) <br> **Default value:** `MMM Do` (e.g. Jan 18th)
|
||||||
|
| `dateEndFormat` | Format to use for the end time of events <br><br> **Possible values:** See [Moment.js formats](http://momentjs.com/docs/#/parsing/string-format/) <br> **Default value:** `HH:mm` (e.g. 16:30)
|
||||||
|
| `showEnd` | Show end time of events <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||||
| `fullDayEventDateFormat` | Format to use for the date of full day events (when using absolute dates) <br><br> **Possible values:** See [Moment.js formats](http://momentjs.com/docs/#/parsing/string-format/) <br> **Default value:** `MMM Do` (e.g. Jan 18th)
|
| `fullDayEventDateFormat` | Format to use for the date of full day events (when using absolute dates) <br><br> **Possible values:** See [Moment.js formats](http://momentjs.com/docs/#/parsing/string-format/) <br> **Default value:** `MMM Do` (e.g. Jan 18th)
|
||||||
| `timeFormat` | Display event times as absolute dates, or relative time, or using absolute date headers with times for each event next to it <br><br> **Possible values:** `absolute` or `relative` or `dateheaders` <br> **Default value:** `relative`
|
| `timeFormat` | Display event times as absolute dates, or relative time, or using absolute date headers with times for each event next to it <br><br> **Possible values:** `absolute` or `relative` or `dateheaders` <br> **Default value:** `relative`
|
||||||
|
| `showEnd` | Display the end of a date as well <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||||
| `getRelative` | How much time (in hours) should be left until calendar events start getting relative? <br><br> **Possible values:** `0` (events stay absolute) - `48` (48 hours before the event starts) <br> **Default value:** `6`
|
| `getRelative` | How much time (in hours) should be left until calendar events start getting relative? <br><br> **Possible values:** `0` (events stay absolute) - `48` (48 hours before the event starts) <br> **Default value:** `6`
|
||||||
| `urgency` | When using a timeFormat of `absolute`, the `urgency` setting allows you to display events within a specific time frame as `relative`. This allows events within a certain time frame to be displayed as relative (in xx days) while others are displayed as absolute dates <br><br> **Possible values:** a positive integer representing the number of days for which you want a relative date, for example `7` (for 7 days) <br><br> **Default value:** `7`
|
| `urgency` | When using a timeFormat of `absolute`, the `urgency` setting allows you to display events within a specific time frame as `relative`. This allows events within a certain time frame to be displayed as relative (in xx days) while others are displayed as absolute dates <br><br> **Possible values:** a positive integer representing the number of days for which you want a relative date, for example `7` (for 7 days) <br><br> **Default value:** `7`
|
||||||
| `broadcastEvents` | If this property is set to true, the calendar will broadcast all the events to all other modules with the notification message: `CALENDAR_EVENTS`. The event objects are stored in an array and contain the following fields: `title`, `startDate`, `endDate`, `fullDayEvent`, `location` and `geo`. <br><br> **Possible values:** `true`, `false` <br><br> **Default value:** `true`
|
| `broadcastEvents` | If this property is set to true, the calendar will broadcast all the events to all other modules with the notification message: `CALENDAR_EVENTS`. The event objects are stored in an array and contain the following fields: `title`, `startDate`, `endDate`, `fullDayEvent`, `location` and `geo`. <br><br> **Possible values:** `true`, `false` <br><br> **Default value:** `true`
|
||||||
@ -86,6 +88,9 @@ config: {
|
|||||||
| `maximumEntries` | The maximum number of events shown. Overrides global setting. **Possible values:** `0` - `100`
|
| `maximumEntries` | The maximum number of events shown. Overrides global setting. **Possible values:** `0` - `100`
|
||||||
| `maximumNumberOfDays` | The maximum number of days in the future. Overrides global setting
|
| `maximumNumberOfDays` | The maximum number of days in the future. Overrides global setting
|
||||||
| `auth` | The object containing options for authentication against the calendar.
|
| `auth` | The object containing options for authentication against the calendar.
|
||||||
|
| `symbolClass` | Add a class to the cell of symbol.
|
||||||
|
| `titleClass` | Add a class to the title's cell.
|
||||||
|
| `timeClass` | Add a class to the time's cell.
|
||||||
|
|
||||||
|
|
||||||
#### Calendar authentication options:
|
#### Calendar authentication options:
|
||||||
|
@ -27,7 +27,7 @@ Module.register("calendar", {
|
|||||||
dateFormat: "MMM Do",
|
dateFormat: "MMM Do",
|
||||||
dateEndFormat: "HH:mm",
|
dateEndFormat: "HH:mm",
|
||||||
fullDayEventDateFormat: "MMM Do",
|
fullDayEventDateFormat: "MMM Do",
|
||||||
showEnd: true,
|
showEnd: false,
|
||||||
getRelative: 6,
|
getRelative: 6,
|
||||||
fadePoint: 0.25, // Start on 1/4th of the list.
|
fadePoint: 0.25, // Start on 1/4th of the list.
|
||||||
hidePrivate: false,
|
hidePrivate: false,
|
||||||
@ -51,7 +51,7 @@ Module.register("calendar", {
|
|||||||
|
|
||||||
// Define required scripts.
|
// Define required scripts.
|
||||||
getStyles: function () {
|
getStyles: function () {
|
||||||
return ["calendar.css", "font-awesome.css"];
|
return ["calendar.css", "font-awesome5.css", "font-awesome5.v4shims.css"];
|
||||||
},
|
},
|
||||||
|
|
||||||
// Define required scripts.
|
// Define required scripts.
|
||||||
@ -82,6 +82,15 @@ Module.register("calendar", {
|
|||||||
maximumEntries: calendar.maximumEntries,
|
maximumEntries: calendar.maximumEntries,
|
||||||
maximumNumberOfDays: calendar.maximumNumberOfDays
|
maximumNumberOfDays: calendar.maximumNumberOfDays
|
||||||
};
|
};
|
||||||
|
if (calendar.symbolClass === "undefined" || calendar.symbolClass === null) {
|
||||||
|
calendarConfig.symbolClass = "";
|
||||||
|
}
|
||||||
|
if (calendar.titleClass === "undefined" || calendar.titleClass === null) {
|
||||||
|
calendarConfig.titleClass = "";
|
||||||
|
}
|
||||||
|
if (calendar.timeClass === "undefined" || calendar.timeClass === null) {
|
||||||
|
calendarConfig.timeClass = "";
|
||||||
|
}
|
||||||
|
|
||||||
// we check user and password here for backwards compatibility with old configs
|
// we check user and password here for backwards compatibility with old configs
|
||||||
if(calendar.user && calendar.pass) {
|
if(calendar.user && calendar.pass) {
|
||||||
@ -135,6 +144,15 @@ Module.register("calendar", {
|
|||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.config.fade && this.config.fadePoint < 1) {
|
||||||
|
if (this.config.fadePoint < 0) {
|
||||||
|
this.config.fadePoint = 0;
|
||||||
|
}
|
||||||
|
var startFade = events.length * this.config.fadePoint;
|
||||||
|
var fadeSteps = events.length - startFade;
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentFadeStep = 0;
|
||||||
var lastSeenDate = "";
|
var lastSeenDate = "";
|
||||||
|
|
||||||
for (var e in events) {
|
for (var e in events) {
|
||||||
@ -143,7 +161,7 @@ Module.register("calendar", {
|
|||||||
if(this.config.timeFormat === "dateheaders"){
|
if(this.config.timeFormat === "dateheaders"){
|
||||||
if(lastSeenDate !== dateAsString){
|
if(lastSeenDate !== dateAsString){
|
||||||
var dateRow = document.createElement("tr");
|
var dateRow = document.createElement("tr");
|
||||||
dateRow.className = "normal"
|
dateRow.className = "normal";
|
||||||
var dateCell = document.createElement("td");
|
var dateCell = document.createElement("td");
|
||||||
|
|
||||||
dateCell.colSpan = "3";
|
dateCell.colSpan = "3";
|
||||||
@ -151,6 +169,10 @@ Module.register("calendar", {
|
|||||||
dateRow.appendChild(dateCell);
|
dateRow.appendChild(dateCell);
|
||||||
wrapper.appendChild(dateRow);
|
wrapper.appendChild(dateRow);
|
||||||
|
|
||||||
|
if (e >= startFade) { //fading
|
||||||
|
currentFadeStep = e - startFade;
|
||||||
|
dateRow.style.opacity = 1 - (1 / fadeSteps * currentFadeStep);
|
||||||
|
}
|
||||||
|
|
||||||
lastSeenDate = dateAsString;
|
lastSeenDate = dateAsString;
|
||||||
}
|
}
|
||||||
@ -172,7 +194,9 @@ Module.register("calendar", {
|
|||||||
symbolWrapper.style.cssText = "color:" + this.colorForUrl(event.url);
|
symbolWrapper.style.cssText = "color:" + this.colorForUrl(event.url);
|
||||||
}
|
}
|
||||||
|
|
||||||
symbolWrapper.className = "symbol align-right";
|
var symbolClass = this.symbolClassForUrl(event.url);
|
||||||
|
symbolWrapper.className = "symbol align-right " + symbolClass;
|
||||||
|
|
||||||
var symbols = this.symbolsForUrl(event.url);
|
var symbols = this.symbolsForUrl(event.url);
|
||||||
if(typeof symbols === "string") {
|
if(typeof symbols === "string") {
|
||||||
symbols = [symbols];
|
symbols = [symbols];
|
||||||
@ -189,7 +213,7 @@ Module.register("calendar", {
|
|||||||
eventWrapper.appendChild(symbolWrapper);
|
eventWrapper.appendChild(symbolWrapper);
|
||||||
}else if(this.config.timeFormat === "dateheaders"){
|
}else if(this.config.timeFormat === "dateheaders"){
|
||||||
var blankCell = document.createElement("td");
|
var blankCell = document.createElement("td");
|
||||||
blankCell.innerHTML = " "
|
blankCell.innerHTML = " ";
|
||||||
eventWrapper.appendChild(blankCell);
|
eventWrapper.appendChild(blankCell);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,10 +234,12 @@ Module.register("calendar", {
|
|||||||
|
|
||||||
titleWrapper.innerHTML = this.titleTransform(event.title) + repeatingCountTitle;
|
titleWrapper.innerHTML = this.titleTransform(event.title) + repeatingCountTitle;
|
||||||
|
|
||||||
|
var titleClass = this.titleClassForUrl(event.url);
|
||||||
|
|
||||||
if (!this.config.colored) {
|
if (!this.config.colored) {
|
||||||
titleWrapper.className = "title bright";
|
titleWrapper.className = "title bright " + titleClass;
|
||||||
} else {
|
} else {
|
||||||
titleWrapper.className = "title";
|
titleWrapper.className = "title " + titleClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.config.timeFormat === "dateheaders"){
|
if(this.config.timeFormat === "dateheaders"){
|
||||||
@ -223,26 +249,13 @@ Module.register("calendar", {
|
|||||||
titleWrapper.align = "left";
|
titleWrapper.align = "left";
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
|
|
||||||
|
var timeClass = this.timeClassForUrl(event.url);
|
||||||
var timeWrapper = document.createElement("td");
|
var timeWrapper = document.createElement("td");
|
||||||
timeWrapper.className = "time light";
|
timeWrapper.className = "time light " + timeClass;
|
||||||
timeWrapper.align = "left";
|
timeWrapper.align = "left";
|
||||||
timeWrapper.style.paddingLeft = "2px";
|
timeWrapper.style.paddingLeft = "2px";
|
||||||
var timeFormatString = "";
|
timeWrapper.innerHTML = moment(event.startDate, "x").format("LT");
|
||||||
switch (config.timeFormat) {
|
|
||||||
case 12: {
|
|
||||||
timeFormatString = "h:mm A";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 24: {
|
|
||||||
timeFormatString = "HH:mm";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
timeFormatString = "HH:mm";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
timeWrapper.innerHTML = moment(event.startDate, "x").format(timeFormatString);
|
|
||||||
eventWrapper.appendChild(timeWrapper);
|
eventWrapper.appendChild(timeWrapper);
|
||||||
titleWrapper.align = "right";
|
titleWrapper.align = "right";
|
||||||
}
|
}
|
||||||
@ -260,6 +273,8 @@ Module.register("calendar", {
|
|||||||
var oneHour = oneMinute * 60;
|
var oneHour = oneMinute * 60;
|
||||||
var oneDay = oneHour * 24;
|
var oneDay = oneHour * 24;
|
||||||
if (event.fullDayEvent) {
|
if (event.fullDayEvent) {
|
||||||
|
//subtract one second so that fullDayEvents end at 23:59:59, and not at 0:00:00 one the next day
|
||||||
|
event.endDate -= oneSecond;
|
||||||
if (event.today) {
|
if (event.today) {
|
||||||
timeWrapper.innerHTML = this.capFirst(this.translate("TODAY"));
|
timeWrapper.innerHTML = this.capFirst(this.translate("TODAY"));
|
||||||
} else if (event.startDate - now < oneDay && event.startDate - now > 0) {
|
} else if (event.startDate - now < oneDay && event.startDate - now > 0) {
|
||||||
@ -343,23 +358,17 @@ Module.register("calendar", {
|
|||||||
}
|
}
|
||||||
//timeWrapper.innerHTML += ' - '+ moment(event.startDate,'x').format('lll');
|
//timeWrapper.innerHTML += ' - '+ moment(event.startDate,'x').format('lll');
|
||||||
//console.log(event);
|
//console.log(event);
|
||||||
timeWrapper.className = "time light";
|
var timeClass = this.timeClassForUrl(event.url);
|
||||||
|
timeWrapper.className = "time light " + timeClass;
|
||||||
eventWrapper.appendChild(timeWrapper);
|
eventWrapper.appendChild(timeWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
wrapper.appendChild(eventWrapper);
|
wrapper.appendChild(eventWrapper);
|
||||||
|
|
||||||
// Create fade effect.
|
// Create fade effect.
|
||||||
if (this.config.fade && this.config.fadePoint < 1) {
|
if (e >= startFade) {
|
||||||
if (this.config.fadePoint < 0) {
|
currentFadeStep = e - startFade;
|
||||||
this.config.fadePoint = 0;
|
eventWrapper.style.opacity = 1 - (1 / fadeSteps * currentFadeStep);
|
||||||
}
|
|
||||||
var startingPoint = events.length * this.config.fadePoint;
|
|
||||||
var steps = events.length - startingPoint;
|
|
||||||
if (e >= startingPoint) {
|
|
||||||
var currentStep = e - startingPoint;
|
|
||||||
eventWrapper.style.opacity = 1 - (1 / steps * currentStep);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,11 +481,15 @@ Module.register("calendar", {
|
|||||||
maximumEntries: calendarConfig.maximumEntries || this.config.maximumEntries,
|
maximumEntries: calendarConfig.maximumEntries || this.config.maximumEntries,
|
||||||
maximumNumberOfDays: calendarConfig.maximumNumberOfDays || this.config.maximumNumberOfDays,
|
maximumNumberOfDays: calendarConfig.maximumNumberOfDays || this.config.maximumNumberOfDays,
|
||||||
fetchInterval: this.config.fetchInterval,
|
fetchInterval: this.config.fetchInterval,
|
||||||
|
symbolClass: calendarConfig.symbolClass,
|
||||||
|
titleClass: calendarConfig.titleClass,
|
||||||
|
timeClass: calendarConfig.timeClass,
|
||||||
auth: auth
|
auth: auth
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/* symbolsForUrl(url)
|
/**
|
||||||
|
* symbolsForUrl(url)
|
||||||
* Retrieves the symbols for a specific url.
|
* Retrieves the symbols for a specific url.
|
||||||
*
|
*
|
||||||
* argument url string - Url to look for.
|
* argument url string - Url to look for.
|
||||||
@ -487,6 +500,42 @@ Module.register("calendar", {
|
|||||||
return this.getCalendarProperty(url, "symbol", this.config.defaultSymbol);
|
return this.getCalendarProperty(url, "symbol", this.config.defaultSymbol);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* symbolClassForUrl(url)
|
||||||
|
* Retrieves the symbolClass for a specific url.
|
||||||
|
*
|
||||||
|
* @param url string - Url to look for.
|
||||||
|
*
|
||||||
|
* @returns string
|
||||||
|
*/
|
||||||
|
symbolClassForUrl: function (url) {
|
||||||
|
return this.getCalendarProperty(url, "symbolClass", "");
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* titleClassForUrl(url)
|
||||||
|
* Retrieves the titleClass for a specific url.
|
||||||
|
*
|
||||||
|
* @param url string - Url to look for.
|
||||||
|
*
|
||||||
|
* @returns string
|
||||||
|
*/
|
||||||
|
titleClassForUrl: function (url) {
|
||||||
|
return this.getCalendarProperty(url, "titleClass", "");
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* timeClassForUrl(url)
|
||||||
|
* Retrieves the timeClass for a specific url.
|
||||||
|
*
|
||||||
|
* @param url string - Url to look for.
|
||||||
|
*
|
||||||
|
* @returns string
|
||||||
|
*/
|
||||||
|
timeClassForUrl: function (url) {
|
||||||
|
return this.getCalendarProperty(url, "timeClass", "");
|
||||||
|
},
|
||||||
|
|
||||||
/* colorForUrl(url)
|
/* colorForUrl(url)
|
||||||
* Retrieves the color for a specific url.
|
* Retrieves the color for a specific url.
|
||||||
*
|
*
|
||||||
|
@ -171,8 +171,16 @@ var CalendarFetcher = function(url, reloadInterval, excludedEvents, maximumEntri
|
|||||||
var geo = event.geo || false;
|
var geo = event.geo || false;
|
||||||
var description = event.description || false;
|
var description = event.description || false;
|
||||||
|
|
||||||
if (typeof event.rrule != "undefined" && !isFacebookBirthday) {
|
if (typeof event.rrule != "undefined" && event.rrule != null && !isFacebookBirthday) {
|
||||||
var rule = event.rrule;
|
var rule = event.rrule;
|
||||||
|
|
||||||
|
// can cause problems with e.g. birthdays before 1900
|
||||||
|
if(rule.origOptions && rule.origOptions.dtstart && rule.origOptions.dtstart.getFullYear() < 1900 ||
|
||||||
|
rule.options && rule.options.dtstart && rule.options.dtstart.getFullYear() < 1900){
|
||||||
|
rule.origOptions.dtstart.setYear(1900);
|
||||||
|
rule.options.dtstart.setYear(1900);
|
||||||
|
}
|
||||||
|
|
||||||
var dates = rule.between(today, future, true, limitFunction);
|
var dates = rule.between(today, future, true, limitFunction);
|
||||||
|
|
||||||
for (var d in dates) {
|
for (var d in dates) {
|
||||||
|
@ -44,7 +44,13 @@ ical.objectHandlers['END'] = function(val, params, curr, stack){
|
|||||||
rule += ' EXDATE:' + curr.exdates[i].toISOString().replace(/[-:]/g, '');
|
rule += ' EXDATE:' + curr.exdates[i].toISOString().replace(/[-:]/g, '');
|
||||||
rule = rule.replace(/\.[0-9]{3}/, '');
|
rule = rule.replace(/\.[0-9]{3}/, '');
|
||||||
}
|
}
|
||||||
curr.rrule = rrulestr(rule);
|
try {
|
||||||
|
curr.rrule = rrulestr(rule);
|
||||||
|
}
|
||||||
|
catch(err) {
|
||||||
|
console.log("Unrecognised element in calendar feed, ignoring: " + rule);
|
||||||
|
curr.rrule = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return originalEnd.call(this, val, params, curr, stack);
|
return originalEnd.call(this, val, params, curr, stack);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,11 @@
|
|||||||
The `clock` module is one of the default modules of the MagicMirror.
|
The `clock` module is one of the default modules of the MagicMirror.
|
||||||
This module displays the current date and time. The information will be updated realtime.
|
This module displays the current date and time. The information will be updated realtime.
|
||||||
|
|
||||||
|
## Screenshot
|
||||||
|
|
||||||
|
- Current time
|
||||||
|

|
||||||
|
|
||||||
## Using the module
|
## Using the module
|
||||||
|
|
||||||
To use this module, add it to the modules array in the `config/config.js` file:
|
To use this module, add it to the modules array in the `config/config.js` file:
|
||||||
|
BIN
modules/default/clock/clock_screenshot.png
Normal file
After Width: | Height: | Size: 30 KiB |
@ -2,6 +2,10 @@
|
|||||||
The `compliments` module is one of the default modules of the MagicMirror.
|
The `compliments` module is one of the default modules of the MagicMirror.
|
||||||
This module displays a random compliment.
|
This module displays a random compliment.
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
- Compliments Screenshot
|
||||||
|

|
||||||
|
|
||||||
## Using the module
|
## Using the module
|
||||||
|
|
||||||
To use this module, add it to the modules array in the `config/config.js` file:
|
To use this module, add it to the modules array in the `config/config.js` file:
|
||||||
@ -45,22 +49,22 @@ The `compliments` property contains an object with four arrays: <code>morning</c
|
|||||||
|
|
||||||
|
|
||||||
If use the currentweather is possible use a actual weather for set compliments. The availables properties are:
|
If use the currentweather is possible use a actual weather for set compliments. The availables properties are:
|
||||||
* `day_sunny`
|
- `day_sunny`
|
||||||
* `day_cloudy`
|
- `day_cloudy`
|
||||||
* `cloudy`
|
- `cloudy`
|
||||||
* `cloudy_windy`
|
- `cloudy_windy`
|
||||||
* `showers`
|
- `showers`
|
||||||
* `rain`
|
- `rain`
|
||||||
* `thunderstorm`
|
- `thunderstorm`
|
||||||
* `snow`
|
- `snow`
|
||||||
* `fog`
|
- `fog`
|
||||||
* `night_clear`
|
- `night_clear`
|
||||||
* `night_cloudy`
|
- `night_cloudy`
|
||||||
* `night_showers`
|
- `night_showers`
|
||||||
* `night_rain`
|
- `night_rain`
|
||||||
* `night_thunderstorm`
|
- `night_thunderstorm`
|
||||||
* `night_snow`
|
- `night_snow`
|
||||||
* `night_alt_cloudy_windy`
|
- `night_alt_cloudy_windy`
|
||||||
|
|
||||||
#### Example use with currentweather module
|
#### Example use with currentweather module
|
||||||
````javascript
|
````javascript
|
||||||
|
BIN
modules/default/compliments/compliments_screenshot.png
Normal file
After Width: | Height: | Size: 26 KiB |
@ -2,6 +2,11 @@
|
|||||||
The `currentweather` module is one of the default modules of the MagicMirror.
|
The `currentweather` module is one of the default modules of the MagicMirror.
|
||||||
This module displays the current weather, including the windspeed, the sunset or sunrise time, the temperature and an icon to display the current conditions.
|
This module displays the current weather, including the windspeed, the sunset or sunrise time, the temperature and an icon to display the current conditions.
|
||||||
|
|
||||||
|
## Screenshot
|
||||||
|
|
||||||
|
- Current weather screenshot
|
||||||
|

|
||||||
|
|
||||||
## Using the module
|
## Using the module
|
||||||
|
|
||||||
To use this module, add it to the modules array in the `config/config.js` file:
|
To use this module, add it to the modules array in the `config/config.js` file:
|
||||||
@ -29,7 +34,7 @@ The following properties can be configured:
|
|||||||
| Option | Description
|
| Option | Description
|
||||||
| ---------------------------- | -----------
|
| ---------------------------- | -----------
|
||||||
| `location` | The location used for weather information. <br><br> **Example:** `'Amsterdam,Netherlands'` <br> **Default value:** `false` <br><br> **Note:** When the `location` and `locationID` are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used.
|
| `location` | The location used for weather information. <br><br> **Example:** `'Amsterdam,Netherlands'` <br> **Default value:** `false` <br><br> **Note:** When the `location` and `locationID` are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used.
|
||||||
| `locationID` | Location ID from [OpenWeatherMap](http://openweathermap.org/help/city_list.txt) **This will override anything you put in location.** <br> Leave blank if you want to use location. <br> **Example:** `1234567` <br> **Default value:** `false` <br><br> **Note:** When the `location` and `locationID` are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used.
|
| `locationID` | Location ID from [OpenWeatherMap](https://openweathermap.org/find) **This will override anything you put in location.** <br> Leave blank if you want to use location. <br> **Example:** `1234567` <br> **Default value:** `false` <br><br> **Note:** When the `location` and `locationID` are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used.
|
||||||
| `appid` | The [OpenWeatherMap](https://home.openweathermap.org) API key, which can be obtained by creating an OpenWeatherMap account. <br><br> This value is **REQUIRED**
|
| `appid` | The [OpenWeatherMap](https://home.openweathermap.org) API key, which can be obtained by creating an OpenWeatherMap account. <br><br> This value is **REQUIRED**
|
||||||
| `units` | What units to use. Specified by config.js <br><br> **Possible values:** `config.units` = Specified by config.js, `default` = Kelvin, `metric` = Celsius, `imperial` =Fahrenheit <br> **Default value:** `config.units`
|
| `units` | What units to use. Specified by config.js <br><br> **Possible values:** `config.units` = Specified by config.js, `default` = Kelvin, `metric` = Celsius, `imperial` =Fahrenheit <br> **Default value:** `config.units`
|
||||||
| `roundTemp` | Round temperature value to nearest integer. <br><br> **Possible values:** `true` (round to integer) or `false` (display exact value with decimal point) <br> **Default value:** `false`
|
| `roundTemp` | Round temperature value to nearest integer. <br><br> **Possible values:** `true` (round to integer) or `false` (display exact value with decimal point) <br> **Default value:** `false`
|
||||||
|
BIN
modules/default/currentweather/weather_screenshot.png
Normal file
After Width: | Height: | Size: 38 KiB |
@ -16,7 +16,8 @@ var defaultModules = [
|
|||||||
"helloworld",
|
"helloworld",
|
||||||
"newsfeed",
|
"newsfeed",
|
||||||
"weatherforecast",
|
"weatherforecast",
|
||||||
"updatenotification"
|
"updatenotification",
|
||||||
|
"weather"
|
||||||
];
|
];
|
||||||
|
|
||||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
The `newsfeed ` module is one of the default modules of the MagicMirror.
|
The `newsfeed ` module is one of the default modules of the MagicMirror.
|
||||||
This module displays news headlines based on an RSS feed. Scrolling through news headlines happens time-based (````updateInterval````), but can also be controlled by sending news feed specific notifications to the module.
|
This module displays news headlines based on an RSS feed. Scrolling through news headlines happens time-based (````updateInterval````), but can also be controlled by sending news feed specific notifications to the module.
|
||||||
|
|
||||||
|
## Screenshot
|
||||||
|
- News Feed Screenshot using the NYT
|
||||||
|

|
||||||
|
|
||||||
## Using the module
|
## Using the module
|
||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
|
@ -138,7 +138,7 @@ Module.register("newsfeed",{
|
|||||||
if (this.isShowingDescription) {
|
if (this.isShowingDescription) {
|
||||||
for (f=0; f<this.config.startTags.length;f++) {
|
for (f=0; f<this.config.startTags.length;f++) {
|
||||||
if (this.newsItems[this.activeItem].description.slice(0,this.config.startTags[f].length) === this.config.startTags[f]) {
|
if (this.newsItems[this.activeItem].description.slice(0,this.config.startTags[f].length) === this.config.startTags[f]) {
|
||||||
this.newsItems[this.activeItem].title = this.newsItems[this.activeItem].description.slice(this.config.startTags[f].length,this.newsItems[this.activeItem].description.length);
|
this.newsItems[this.activeItem].description = this.newsItems[this.activeItem].description.slice(this.config.startTags[f].length,this.newsItems[this.activeItem].description.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
modules/default/newsfeed/newsfeed_screenshot.png
Normal file
After Width: | Height: | Size: 44 KiB |
98
modules/default/weather/README.md
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
# Weather Module
|
||||||
|
|
||||||
|
This module is aimed to be the replacement for the current `currentweather` and `weatherforcast` modules. The module will be configurable to be used as a current weather view, or to show the forecast. This way the module can be used twice to fullfil both purposes.
|
||||||
|
|
||||||
|
The biggest cange is the use of weather providers. This way we are not bound to one API source. And users can choose which API they want to use as their source.
|
||||||
|
|
||||||
|
The module is in a very early stage, and needs a lot of work. It's API isn't set in stone, so keep that in mind when you want to contribute.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
 
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
To use this module, add it to the modules array in the `config/config.js` file:
|
||||||
|
|
||||||
|
````javascript
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
module: "weather",
|
||||||
|
position: "top_right",
|
||||||
|
config: {
|
||||||
|
// See 'Configuration options' for more information.
|
||||||
|
type: 'current'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
````
|
||||||
|
|
||||||
|
## Configuration options
|
||||||
|
|
||||||
|
The following properties can be configured:
|
||||||
|
|
||||||
|
### General options
|
||||||
|
|
||||||
|
| Option | Description
|
||||||
|
| ---------------------------- | -----------
|
||||||
|
| `weatherProvider` | Which weather provider should be used. <br><br> **Possible values:** `openweathermap` and `darksky` <br> **Default value:** `openweathermap`
|
||||||
|
| `type` | Which type of weather data should be displayed. <br><br> **Possible values:** `current` and `forecast` <br> **Default value:** `current`
|
||||||
|
| `units` | What units to use. Specified by config.js <br><br> **Possible values:** `config.units` = Specified by config.js, `default` = Kelvin, `metric` = Celsius, `imperial` =Fahrenheit <br> **Default value:** `config.units`
|
||||||
|
| `roundTemp` | Round temperature value to nearest integer. <br><br> **Possible values:** `true` (round to integer) or `false` (display exact value with decimal point) <br> **Default value:** `false`
|
||||||
|
| `degreeLabel` | Show the degree label for your chosen units (Metric = C, Imperial = F, Kelvins = K). <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
|
||||||
|
| `updateInterval` | How often does the content needs to be fetched? (Milliseconds) <br><br> **Possible values:** `1000` - `86400000` <br> **Default value:** `600000` (10 minutes)
|
||||||
|
| `animationSpeed` | Speed of the update animation. (Milliseconds) <br><br> **Possible values:**`0` - `5000` <br> **Default value:** `1000` (1 second)
|
||||||
|
| `timeFormat` | Use 12 or 24 hour format. <br><br> **Possible values:** `12` or `24` <br> **Default value:** uses value of _config.timeFormat_
|
||||||
|
| `showPeriod` | Show the period (am/pm) with 12 hour format <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||||
|
| `showPeriodUpper` | Show the period (AM/PM) with 12 hour format as uppercase <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
|
||||||
|
| `lang` | The language of the days. <br><br> **Possible values:** `en`, `nl`, `ru`, etc ... <br> **Default value:** uses value of _config.language_
|
||||||
|
| `decimalSymbol` | The decimal symbol to use.<br><br> **Possible values:** `.`, `,` or any other symbol.<br> **Default value:** `.`
|
||||||
|
| `initialLoadDelay` | The initial delay before loading. If you have multiple modules that use the same API key, you might want to delay one of the requests. (Milliseconds) <br><br> **Possible values:** `1000` - `5000` <br> **Default value:** `0`
|
||||||
|
| `appendLocationNameToHeader` | If set to `true`, the returned location name will be appended to the header of the module, if the header is enabled. This is mainly intresting when using calender based weather. <br><br> **Default value:** `true`
|
||||||
|
| `calendarClass` | The class for the calender module to base the event based weather information on. <br><br> **Default value:** `'calendar'`
|
||||||
|
|
||||||
|
#### Current weather options
|
||||||
|
|
||||||
|
| Option | Description
|
||||||
|
| ---------------------------- | -----------
|
||||||
|
| `onlyTemp` | Show only current Temperature and weather icon without windspeed, sunset, sunrise time and feels like. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
|
||||||
|
| `useBeaufort` | Pick between using the Beaufort scale for wind speed or using the default units. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||||
|
| `showWindDirection` | Show the wind direction next to the wind speed. <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||||
|
| `showWindDirectionAsArrow` | Show the wind direction as an arrow instead of abbreviation <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
|
||||||
|
| `showHumidity` | Show the current humidity <br><br> **Possible values:** `true` or `false` <br> **Default value:** `false`
|
||||||
|
| `showIndoorTemperature` | If you have another module that emits the `INDOOR_TEMPERATURE` notification, the indoor temperature will be displayed <br> **Default value:** `false`
|
||||||
|
| `showIndoorHumidity` | If you have another module that emits the `INDOOR_HUMIDITY` notification, the indoor humidity will be displayed <br> **Default value:** `false`
|
||||||
|
| `showFeelsLike` | Shows the Feels like temperature weather. <br><br> **Possible values:**`true` or `false`<br>**Default value:** `true`
|
||||||
|
|
||||||
|
#### Weather forecast options
|
||||||
|
|
||||||
|
| Option | Description
|
||||||
|
| ---------------------------- | -----------
|
||||||
|
| `tableClass` | The class for the forecast table. <br><br> **Default value:** `'small'`
|
||||||
|
| `colored` | If set to `true`, the min and max temperature are color coded. <br><br> **Default value:** `false`
|
||||||
|
| `showRainAmount` | Show the amount of rain in the forecast <br><br> **Possible values:** `true` or `false` <br> **Default value:** `true`
|
||||||
|
|
||||||
|
### Openweathermap options
|
||||||
|
|
||||||
|
| Option | Description
|
||||||
|
| ---------------------------- | -----------
|
||||||
|
| `apiVersion` | The OpenWeatherMap API version to use. <br><br> **Default value:** `2.5`
|
||||||
|
| `apiBase` | The OpenWeatherMap base URL. <br><br> **Default value:** `'http://api.openweathermap.org/data/'`
|
||||||
|
| `weatherEndpoint` | The OpenWeatherMap API endPoint. <br><br> **Possible values:** `/weather` or `/forecast/daily` <br> **Default value:** `'/weather'`
|
||||||
|
| `locationID` | Location ID from [OpenWeatherMap](https://openweathermap.org/find) **This will override anything you put in location.** <br> Leave blank if you want to use location. <br> **Example:** `1234567` <br> **Default value:** `false` <br><br> **Note:** When the `location` and `locationID` are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used.
|
||||||
|
| `location` | The location used for weather information. <br><br> **Example:** `'Amsterdam,Netherlands'` <br> **Default value:** `false` <br><br> **Note:** When the `location` and `locationID` are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used.
|
||||||
|
| `apiKey` | The [OpenWeatherMap](https://home.openweathermap.org) API key, which can be obtained by creating an OpenWeatherMap account. <br><br> This value is **REQUIRED**
|
||||||
|
|
||||||
|
### Darksky options
|
||||||
|
|
||||||
|
| Option | Description
|
||||||
|
| ---------------------------- | -----------
|
||||||
|
| `apiBase` | The DarkSky base URL. The darksky api has disabled [cors](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS), therefore a proxy is required. <br><br> **Possible value:** `'https://cors-anywhere.herokuapp.com/https://api.darksky.net'` <br> This value is **REQUIRED**
|
||||||
|
| `weatherEndpoint` | The DarkSky API endPoint. <br><br> **Possible values:** `/forecast` <br> This value is **REQUIRED**
|
||||||
|
| `apiKey` | The [DarkSky](https://darksky.net/dev/register) API key, which can be obtained by creating an DarkSky account. <br><br> This value is **REQUIRED**
|
||||||
|
| `lat` | The geo coordinate latitude. <br><br> This value is **REQUIRED**
|
||||||
|
| `lon` | The geo coordinate longitude. <br><br> This value is **REQUIRED**
|
||||||
|
|
||||||
|
## API Provider Development
|
||||||
|
|
||||||
|
If you want to add another API provider checkout the [Guide](providers).
|
68
modules/default/weather/current.njk
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
{% if current %}
|
||||||
|
{% if not config.onlyTemp %}
|
||||||
|
<div class="normal medium">
|
||||||
|
<span class="wi wi-strong-wind dimmed"></span>
|
||||||
|
<span>
|
||||||
|
{% if config.useBeaufort %}
|
||||||
|
{{current.beaufortWindSpeed() | round}}
|
||||||
|
{% else %}
|
||||||
|
{{current.windSpeed | round}}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if config.showWindDirection %}
|
||||||
|
<sup>
|
||||||
|
{% if config.showWindDirectionAsArrow %}
|
||||||
|
<i class="fa fa-long-arrow-up" style="transform:rotate({{current.windDirection}}deg);"></i>
|
||||||
|
{% else %}
|
||||||
|
{{current.cardinalWindDirection() | translate}}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</sup>
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
{% if config.showHumidity and current.humidity %}
|
||||||
|
<span>{{ current.humidity }}</span><sup> <i class="wi wi-humidity humidityIcon"></i></sup>
|
||||||
|
{% endif %}
|
||||||
|
<span class="wi dimmed wi-{{current.nextSunAction()}}"></span>
|
||||||
|
<span>
|
||||||
|
{% if current.nextSunAction() == "sunset" %}
|
||||||
|
{{current.sunset | formatTime}}
|
||||||
|
{% else %}
|
||||||
|
{{current.sunrise | formatTime}}
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="large light">
|
||||||
|
<span class="wi weathericon wi-{{current.weatherType}}"></span>
|
||||||
|
<span class="bright">
|
||||||
|
{{current.temperature | roundValue | unit("temperature")}}
|
||||||
|
</span>
|
||||||
|
{% if config.showIndoorTemperature and indoor.temperature %}
|
||||||
|
<span class="fa fa-home"></span>
|
||||||
|
<span class="bright">
|
||||||
|
{{indoor.temperature | roundValue | unit("temperature")}}
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
{% if config.showIndoorHumidity and indoor.humidity %}
|
||||||
|
<span class="fa fa-tint"></span>
|
||||||
|
<span class="bright">
|
||||||
|
{{indoor.humidity | roundValue}}%
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% if config.showFeelsLike and not config.onlyTemp %}
|
||||||
|
<div class="normal medium">
|
||||||
|
<span class="dimmed">
|
||||||
|
{{ "FEELS" | translate }} {{ current.feelsLike() | roundValue | unit("temperature") }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<div class="dimmed light small">
|
||||||
|
{{"LOADING" | translate}}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- Unclomment the line below to see the contents of the `current` object. -->
|
||||||
|
<!-- <div style="word-wrap:break-word" class="xsmall dimmed">{{current | dump}}</div> -->
|
BIN
modules/default/weather/current.png
Normal file
After Width: | Height: | Size: 8.0 KiB |
26
modules/default/weather/forecast.njk
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{% if forecast %}
|
||||||
|
<table class="{{config.tableClass}}">
|
||||||
|
{% for f in forecast %}
|
||||||
|
<tr {% if config.colored %}class="colored"{% endif %}>
|
||||||
|
<td class="day">{{f.date.format('ddd')}}</td>
|
||||||
|
<td class="bright weather-icon"><span class="wi weathericon wi-{{f.weatherType}}"></span></td>
|
||||||
|
<td class="align-right bright max-temp">
|
||||||
|
{{f.maxTemperature | roundValue | unit("temperature")}}
|
||||||
|
</td>
|
||||||
|
<td class="align-right min-temp">
|
||||||
|
{{f.minTemperature | roundValue | unit("temperature")}}
|
||||||
|
</td>
|
||||||
|
{% if config.showRainAmount %}
|
||||||
|
<td class="align-right bright rain">
|
||||||
|
{{f.rain | unit("rain")}}
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
{% else %}
|
||||||
|
{{"LOADING" | translate}}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- Unclomment the line below to see the contents of the `current` object. -->
|
||||||
|
<!-- <div style="word-wrap:break-word" class="xsmall dimmed">{{forecast | dump}}</div> -->
|
BIN
modules/default/weather/forecast.png
Normal file
After Width: | Height: | Size: 16 KiB |
129
modules/default/weather/providers/README.md
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
# MagicMirror² Weather Module Weather Provider Development Documentation
|
||||||
|
|
||||||
|
This document describes the way to develop your own MagicMirror² weather module weather provider.
|
||||||
|
|
||||||
|
Table of Contents:
|
||||||
|
|
||||||
|
- The weather provider file: yourprovider.js
|
||||||
|
- [Weather provider methods to implement](#weather-provider-methods-to-implement)
|
||||||
|
- [Weather Provider instance methods](#weather-provider-instance-methods)
|
||||||
|
- [WeatherObject](#weatherobject)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## The weather provider file: yourprovider.js
|
||||||
|
|
||||||
|
This is the script in which the weather provider will be defined. In it's most simple form, the weather provider must implement the following:
|
||||||
|
|
||||||
|
````javascript
|
||||||
|
WeatherProvider.register("yourprovider", {
|
||||||
|
providerName: "YourProvider",
|
||||||
|
|
||||||
|
fetchCurrentWeather() {},
|
||||||
|
|
||||||
|
fetchWeatherForecast() {}
|
||||||
|
});
|
||||||
|
````
|
||||||
|
|
||||||
|
### Weather provider methods to implement
|
||||||
|
|
||||||
|
#### `fetchCurrentWeather()`
|
||||||
|
|
||||||
|
This method is called when the weather module tries to fetch the current weather of your provider. The implementation of this method is required.
|
||||||
|
The implementation can make use of the already implemented function `this.fetchData(url, method, data);`, which is returning a promise.
|
||||||
|
After the response is processed, the current weather information (as a [WeatherObject](#weatherobject)) needs to be set with `this.setCurrentWeather(currentWeather);`.
|
||||||
|
It will then automatically refresh the module DOM with the new data.
|
||||||
|
|
||||||
|
#### `fetchWeatherForecast()`
|
||||||
|
|
||||||
|
This method is called when the weather module tries to fetch the weather weather of your provider. The implementation of this method is required.
|
||||||
|
The implementation can make use of the already implemented function `this.fetchData(url, method, data);`, which is returning a promise.
|
||||||
|
After the response is processed, the weather forecast information (as an array of [WeatherObject](#weatherobject)s) needs to be set with `this.setCurrentWeather(forecast);`.
|
||||||
|
It will then automatically refresh the module DOM with the new data.
|
||||||
|
|
||||||
|
### Weather Provider instance methods
|
||||||
|
|
||||||
|
#### `init()`
|
||||||
|
|
||||||
|
Called when a weather provider is initialized.
|
||||||
|
|
||||||
|
#### `setConfig(config)`
|
||||||
|
|
||||||
|
Called to set the config, this config is the same as the weather module's config.
|
||||||
|
|
||||||
|
#### `start()`
|
||||||
|
|
||||||
|
Called when the weather provider is about to start.
|
||||||
|
|
||||||
|
#### `currentWeather()`
|
||||||
|
|
||||||
|
This returns a WeatherDay object for the current weather.
|
||||||
|
|
||||||
|
#### `weatherForecast()`
|
||||||
|
|
||||||
|
This returns an array of WeatherDay objects for the weather forecast.
|
||||||
|
|
||||||
|
#### `fetchedLocation()`
|
||||||
|
|
||||||
|
This returns the name of the fetched location or an empty string.
|
||||||
|
|
||||||
|
#### `setCurrentWeather(currentWeatherObject)`
|
||||||
|
|
||||||
|
Set the currentWeather and notify the delegate that new information is available.
|
||||||
|
|
||||||
|
#### `setWeatherForecast(weatherForecastArray)`
|
||||||
|
|
||||||
|
Set the weatherForecastArray and notify the delegate that new information is available.
|
||||||
|
|
||||||
|
#### `setFetchedLocation(name)`
|
||||||
|
|
||||||
|
Set the fetched location name.
|
||||||
|
|
||||||
|
#### `updateAvailable()`
|
||||||
|
|
||||||
|
Notify the delegate that new weather is available.
|
||||||
|
|
||||||
|
#### `fetchData(url, method, data)`
|
||||||
|
|
||||||
|
A convinience function to make requests. It returns a promise.
|
||||||
|
|
||||||
|
### WeatherObject
|
||||||
|
|
||||||
|
| Property | Type | Value/Unit |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| units | `string` | Gets initialized with the constructor. <br> Possible values: `metric` and `imperial` |
|
||||||
|
| date | `object` | [Moment.js](https://momentjs.com/) object of the time/date. |
|
||||||
|
| windSpeed |`number` | Metric: `meter/second` <br> Imperial: `miles/hour` |
|
||||||
|
| windDirection |`number` | Direction of the wind in degrees. |
|
||||||
|
| sunrise |`object` | [Moment.js](https://momentjs.com/) object of sunrise. |
|
||||||
|
| sunset |`object` | [Moment.js](https://momentjs.com/) object of sunset. |
|
||||||
|
| temperature | `number` | Current temperature |
|
||||||
|
| minTemperature | `number` | Lowest temperature of the day. |
|
||||||
|
| maxTemperature | `number` | Highest temperature of the day. |
|
||||||
|
| weatherType | `string` | Icon name of the weather type. <br> Possible values: [WeatherIcons](https://www.npmjs.com/package/weathericons) |
|
||||||
|
| humidity | `number` | Percentage of humidity |
|
||||||
|
| rain | `number` | Metric: `millimeters` <br> Imperial: `inches` |
|
||||||
|
|
||||||
|
#### Current weather
|
||||||
|
|
||||||
|
For the current weather object the following properties are required:
|
||||||
|
|
||||||
|
- humidity
|
||||||
|
- sunrise
|
||||||
|
- sunset
|
||||||
|
- temperature
|
||||||
|
- units
|
||||||
|
- weatherType
|
||||||
|
- windDirection
|
||||||
|
- windSpeed
|
||||||
|
|
||||||
|
#### Weather forecast
|
||||||
|
|
||||||
|
For the forecast weather object the following properties are required:
|
||||||
|
|
||||||
|
- date
|
||||||
|
- maxTemperature
|
||||||
|
- minTemperature
|
||||||
|
- rain
|
||||||
|
- units
|
||||||
|
- weatherType
|
113
modules/default/weather/providers/darksky.js
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/* global WeatherProvider, WeatherDay */
|
||||||
|
|
||||||
|
/* Magic Mirror
|
||||||
|
* Module: Weather
|
||||||
|
* Provider: Dark Sky
|
||||||
|
*
|
||||||
|
* By Nicholas Hubbard https://github.com/nhubbard
|
||||||
|
* MIT Licensed
|
||||||
|
*
|
||||||
|
* This class is a provider for Dark Sky.
|
||||||
|
*/
|
||||||
|
WeatherProvider.register("darksky", {
|
||||||
|
// Set the name of the provider.
|
||||||
|
// Not strictly required, but helps for debugging.
|
||||||
|
providerName: "Dark Sky",
|
||||||
|
|
||||||
|
units: {
|
||||||
|
imperial: 'us',
|
||||||
|
metric: 'si'
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchCurrentWeather() {
|
||||||
|
this.fetchData(this.getUrl())
|
||||||
|
.then(data => {
|
||||||
|
if(!data || !data.currently || typeof data.currently.temperature === "undefined") {
|
||||||
|
// No usable data?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentWeather = this.generateWeatherDayFromCurrentWeather(data);
|
||||||
|
this.setCurrentWeather(currentWeather);
|
||||||
|
}).catch(function(request) {
|
||||||
|
Log.error("Could not load data ... ", request);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchWeatherForecast() {
|
||||||
|
this.fetchData(this.getUrl())
|
||||||
|
.then(data => {
|
||||||
|
if(!data || !data.daily || !data.daily.data.length) {
|
||||||
|
// No usable data?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const forecast = this.generateWeatherObjectsFromForecast(data.daily.data);
|
||||||
|
this.setWeatherForecast(forecast);
|
||||||
|
}).catch(function(request) {
|
||||||
|
Log.error("Could not load data ... ", request);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// Create a URL from the config and base URL.
|
||||||
|
getUrl() {
|
||||||
|
const units = this.units[this.config.units] || "auto";
|
||||||
|
return `${this.config.apiBase}${this.config.weatherEndpoint}/${this.config.apiKey}/${this.config.lat},${this.config.lon}?units=${units}&lang=${this.config.lang}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Implement WeatherDay generator.
|
||||||
|
generateWeatherDayFromCurrentWeather(currentWeatherData) {
|
||||||
|
const currentWeather = new WeatherObject(this.config.units);
|
||||||
|
|
||||||
|
currentWeather.date = moment();
|
||||||
|
currentWeather.humidity = parseFloat(currentWeatherData.currently.humidity);
|
||||||
|
currentWeather.temperature = parseFloat(currentWeatherData.currently.temperature);
|
||||||
|
currentWeather.windSpeed = parseFloat(currentWeatherData.currently.windSpeed);
|
||||||
|
currentWeather.windDirection = currentWeatherData.currently.windBearing;
|
||||||
|
currentWeather.weatherType = this.convertWeatherType(currentWeatherData.currently.icon);
|
||||||
|
currentWeather.sunrise = moment(currentWeatherData.daily.data[0].sunriseTime, "X");
|
||||||
|
currentWeather.sunset = moment(currentWeatherData.daily.data[0].sunsetTime, "X");
|
||||||
|
|
||||||
|
return currentWeather;
|
||||||
|
},
|
||||||
|
|
||||||
|
generateWeatherObjectsFromForecast(forecasts) {
|
||||||
|
const days = [];
|
||||||
|
|
||||||
|
for (const forecast of forecasts) {
|
||||||
|
const weather = new WeatherObject(this.config.units);
|
||||||
|
|
||||||
|
weather.date = moment(forecast.time, "X");
|
||||||
|
weather.minTemperature = forecast.temperatureMin;
|
||||||
|
weather.maxTemperature = forecast.temperatureMax;
|
||||||
|
weather.weatherType = this.convertWeatherType(forecast.icon);
|
||||||
|
if (this.config.units === "metric" && !isNaN(forecast.precipAccumulation)) {
|
||||||
|
weather.rain = forecast.precipAccumulation * 10;
|
||||||
|
} else {
|
||||||
|
weather.rain = forecast.precipAccumulation;
|
||||||
|
}
|
||||||
|
|
||||||
|
days.push(weather);
|
||||||
|
}
|
||||||
|
|
||||||
|
return days;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Map icons from Dark Sky to our icons.
|
||||||
|
convertWeatherType(weatherType) {
|
||||||
|
const weatherTypes = {
|
||||||
|
"clear-day": "day-sunny",
|
||||||
|
"clear-night": "night-clear",
|
||||||
|
"rain": "rain",
|
||||||
|
"snow": "snow",
|
||||||
|
"sleet": "snow",
|
||||||
|
"wind": "wind",
|
||||||
|
"fog": "fog",
|
||||||
|
"cloudy": "cloudy",
|
||||||
|
"partly-cloudy-day": "day-cloudy",
|
||||||
|
"partly-cloudy-night": "night-cloudy"
|
||||||
|
};
|
||||||
|
|
||||||
|
return weatherTypes.hasOwnProperty(weatherType) ? weatherTypes[weatherType] : null;
|
||||||
|
}
|
||||||
|
});
|
165
modules/default/weather/providers/openweathermap.js
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
/* global WeatherProvider, WeatherObject */
|
||||||
|
|
||||||
|
/* Magic Mirror
|
||||||
|
* Module: Weather
|
||||||
|
*
|
||||||
|
* By Michael Teeuw http://michaelteeuw.nl
|
||||||
|
* MIT Licensed.
|
||||||
|
*
|
||||||
|
* This class is the blueprint for a weather provider.
|
||||||
|
*/
|
||||||
|
|
||||||
|
WeatherProvider.register("openweathermap", {
|
||||||
|
|
||||||
|
// Set the name of the provider.
|
||||||
|
// This isn't strictly necessary, since it will fallback to the provider identifier
|
||||||
|
// But for debugging (and future alerts) it would be nice to have the real name.
|
||||||
|
providerName: "OpenWeatherMap",
|
||||||
|
|
||||||
|
// Overwrite the fetchCurrentWeather method.
|
||||||
|
fetchCurrentWeather() {
|
||||||
|
this.fetchData(this.getUrl())
|
||||||
|
.then(data => {
|
||||||
|
if (!data || !data.main || typeof data.main.temp === "undefined") {
|
||||||
|
// Did not receive usable new data.
|
||||||
|
// Maybe this needs a better check?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setFetchedLocation(`${data.name}, ${data.sys.country}`);
|
||||||
|
|
||||||
|
const currentWeather = this.generateWeatherObjectFromCurrentWeather(data);
|
||||||
|
this.setCurrentWeather(currentWeather);
|
||||||
|
})
|
||||||
|
.catch(function(request) {
|
||||||
|
Log.error("Could not load data ... ", request);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// Overwrite the fetchCurrentWeather method.
|
||||||
|
fetchWeatherForecast() {
|
||||||
|
this.fetchData(this.getUrl())
|
||||||
|
.then(data => {
|
||||||
|
if (!data || !data.list || !data.list.length) {
|
||||||
|
// Did not receive usable new data.
|
||||||
|
// Maybe this needs a better check?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setFetchedLocation(`${data.city.name}, ${data.city.country}`);
|
||||||
|
|
||||||
|
const forecast = this.generateWeatherObjectsFromForecast(data.list);
|
||||||
|
this.setWeatherForecast(forecast);
|
||||||
|
})
|
||||||
|
.catch(function(request) {
|
||||||
|
Log.error("Could not load data ... ", request);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** OpenWeatherMap Specific Methods - These are not part of the default provider methods */
|
||||||
|
/*
|
||||||
|
* Gets the complete url for the request
|
||||||
|
*/
|
||||||
|
getUrl() {
|
||||||
|
return this.config.apiBase + this.config.apiVersion + this.config.weatherEndpoint + this.getParams();
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate a WeatherObject based on currentWeatherInformation
|
||||||
|
*/
|
||||||
|
generateWeatherObjectFromCurrentWeather(currentWeatherData) {
|
||||||
|
const currentWeather = new WeatherObject(this.config.units);
|
||||||
|
|
||||||
|
currentWeather.humidity = currentWeatherData.main.humidity;
|
||||||
|
currentWeather.temperature = currentWeatherData.main.temp;
|
||||||
|
currentWeather.windSpeed = currentWeatherData.wind.speed;
|
||||||
|
currentWeather.windDirection = currentWeatherData.wind.deg;
|
||||||
|
currentWeather.weatherType = this.convertWeatherType(currentWeatherData.weather[0].icon);
|
||||||
|
currentWeather.sunrise = moment(currentWeatherData.sys.sunrise, "X");
|
||||||
|
currentWeather.sunset = moment(currentWeatherData.sys.sunset, "X");
|
||||||
|
|
||||||
|
return currentWeather;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate WeatherObjects based on forecast information
|
||||||
|
*/
|
||||||
|
generateWeatherObjectsFromForecast(forecasts) {
|
||||||
|
const days = [];
|
||||||
|
|
||||||
|
for (const forecast of forecasts) {
|
||||||
|
const weather = new WeatherObject(this.config.units);
|
||||||
|
|
||||||
|
weather.date = moment(forecast.dt, "X");
|
||||||
|
weather.minTemperature = forecast.temp.min;
|
||||||
|
weather.maxTemperature = forecast.temp.max;
|
||||||
|
weather.weatherType = this.convertWeatherType(forecast.weather[0].icon);
|
||||||
|
if (this.config.units === "imperial" && !isNaN(forecast.rain)) {
|
||||||
|
weather.rain = forecast.rain / 25.4
|
||||||
|
} else {
|
||||||
|
weather.rain = forecast.rain;
|
||||||
|
}
|
||||||
|
|
||||||
|
days.push(weather);
|
||||||
|
}
|
||||||
|
|
||||||
|
return days;
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert the OpenWeatherMap icons to a more usable name.
|
||||||
|
*/
|
||||||
|
convertWeatherType(weatherType) {
|
||||||
|
const weatherTypes = {
|
||||||
|
"01d": "day-sunny",
|
||||||
|
"02d": "day-cloudy",
|
||||||
|
"03d": "cloudy",
|
||||||
|
"04d": "cloudy-windy",
|
||||||
|
"09d": "showers",
|
||||||
|
"10d": "rain",
|
||||||
|
"11d": "thunderstorm",
|
||||||
|
"13d": "snow",
|
||||||
|
"50d": "fog",
|
||||||
|
"01n": "night-clear",
|
||||||
|
"02n": "night-cloudy",
|
||||||
|
"03n": "night-cloudy",
|
||||||
|
"04n": "night-cloudy",
|
||||||
|
"09n": "night-showers",
|
||||||
|
"10n": "night-rain",
|
||||||
|
"11n": "night-thunderstorm",
|
||||||
|
"13n": "night-snow",
|
||||||
|
"50n": "night-alt-cloudy-windy"
|
||||||
|
};
|
||||||
|
|
||||||
|
return weatherTypes.hasOwnProperty(weatherType) ? weatherTypes[weatherType] : null;
|
||||||
|
},
|
||||||
|
|
||||||
|
/* getParams(compliments)
|
||||||
|
* Generates an url with api parameters based on the config.
|
||||||
|
*
|
||||||
|
* return String - URL params.
|
||||||
|
*/
|
||||||
|
getParams() {
|
||||||
|
let params = "?";
|
||||||
|
if(this.config.locationID) {
|
||||||
|
params += "id=" + this.config.locationID;
|
||||||
|
} else if(this.config.location) {
|
||||||
|
params += "q=" + this.config.location;
|
||||||
|
} else if (this.firstEvent && this.firstEvent.geo) {
|
||||||
|
params += "lat=" + this.firstEvent.geo.lat + "&lon=" + this.firstEvent.geo.lon;
|
||||||
|
} else if (this.firstEvent && this.firstEvent.location) {
|
||||||
|
params += "q=" + this.firstEvent.location;
|
||||||
|
} else {
|
||||||
|
this.hide(this.config.animationSpeed, {lockString:this.identifier});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
params += "&units=" + this.config.units;
|
||||||
|
params += "&lang=" + this.config.lang;
|
||||||
|
params += "&APPID=" + this.config.apiKey;
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
});
|
45
modules/default/weather/weather.css
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
.weather .weathericon,
|
||||||
|
.weather .fa-home {
|
||||||
|
font-size: 75%;
|
||||||
|
line-height: 65px;
|
||||||
|
display: inline-block;
|
||||||
|
-ms-transform: translate(0, -3px); /* IE 9 */
|
||||||
|
-webkit-transform: translate(0, -3px); /* Safari */
|
||||||
|
transform: translate(0, -3px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather .humidityIcon {
|
||||||
|
padding-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather .humidity-padding {
|
||||||
|
padding-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather .day {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather .weather-icon {
|
||||||
|
padding-right: 30px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather .min-temp {
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather .rain {
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather tr.colored .min-temp {
|
||||||
|
color: #bcddff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather tr.colored .max-temp {
|
||||||
|
color: #ff8e99;
|
||||||
|
}
|
212
modules/default/weather/weather.js
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
/* global Module, WeatherProvider */
|
||||||
|
|
||||||
|
/* Magic Mirror
|
||||||
|
* Module: Weather
|
||||||
|
*
|
||||||
|
* By Michael Teeuw http://michaelteeuw.nl
|
||||||
|
* MIT Licensed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Module.register("weather",{
|
||||||
|
// Default module config.
|
||||||
|
defaults: {
|
||||||
|
updateInterval: 10 * 60 * 1000,
|
||||||
|
weatherProvider: "openweathermap",
|
||||||
|
roundTemp: false,
|
||||||
|
type: "current", //current, forecast
|
||||||
|
|
||||||
|
location: false,
|
||||||
|
locationID: false,
|
||||||
|
appid: "",
|
||||||
|
units: config.units,
|
||||||
|
updateInterval: 10 * 60 * 1000, // every 10 minutes
|
||||||
|
animationSpeed: 1000,
|
||||||
|
timeFormat: config.timeFormat,
|
||||||
|
showPeriod: true,
|
||||||
|
showPeriodUpper: false,
|
||||||
|
showWindDirection: true,
|
||||||
|
showWindDirectionAsArrow: false,
|
||||||
|
useBeaufort: true,
|
||||||
|
lang: config.language,
|
||||||
|
showHumidity: false,
|
||||||
|
degreeLabel: false,
|
||||||
|
showIndoorTemperature: false,
|
||||||
|
showIndoorHumidity: false,
|
||||||
|
|
||||||
|
initialLoadDelay: 0, // 0 seconds delay
|
||||||
|
retryDelay: 2500,
|
||||||
|
|
||||||
|
apiVersion: "2.5",
|
||||||
|
apiBase: "http://api.openweathermap.org/data/",
|
||||||
|
weatherEndpoint: "/weather",
|
||||||
|
|
||||||
|
appendLocationNameToHeader: true,
|
||||||
|
calendarClass: "calendar",
|
||||||
|
tableClass: "small",
|
||||||
|
|
||||||
|
onlyTemp: false,
|
||||||
|
showRainAmount: true,
|
||||||
|
colored: false,
|
||||||
|
showFeelsLike: true
|
||||||
|
},
|
||||||
|
|
||||||
|
// Module properties.
|
||||||
|
weatherProvider: null,
|
||||||
|
|
||||||
|
// Define required scripts.
|
||||||
|
getStyles: function() {
|
||||||
|
return ["font-awesome.css", "weather-icons.css", "weather.css"];
|
||||||
|
},
|
||||||
|
|
||||||
|
// Return the scripts that are nessecery for the weather module.
|
||||||
|
getScripts: function () {
|
||||||
|
return [
|
||||||
|
"moment.js",
|
||||||
|
"weatherprovider.js",
|
||||||
|
"weatherobject.js",
|
||||||
|
this.file("providers/" + this.config.weatherProvider.toLowerCase() + ".js")
|
||||||
|
];
|
||||||
|
},
|
||||||
|
|
||||||
|
// Override getHeader method.
|
||||||
|
getHeader: function() {
|
||||||
|
if (this.config.appendLocationNameToHeader && this.weatherProvider) {
|
||||||
|
return this.data.header + " " + this.weatherProvider.fetchedLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.data.header;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Start the weather module.
|
||||||
|
start: function () {
|
||||||
|
moment.locale(this.config.lang);
|
||||||
|
// Initialize the weather provider.
|
||||||
|
this.weatherProvider = WeatherProvider.initialize(this.config.weatherProvider, this);
|
||||||
|
|
||||||
|
// Let the weather provider know we are starting.
|
||||||
|
this.weatherProvider.start();
|
||||||
|
|
||||||
|
// Add custom filters
|
||||||
|
this.addFilters();
|
||||||
|
|
||||||
|
// Schedule the first update.
|
||||||
|
this.scheduleUpdate(this.config.initialLoadDelay);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Override notification handler.
|
||||||
|
notificationReceived: function(notification, payload, sender) {
|
||||||
|
if (notification === "CALENDAR_EVENTS") {
|
||||||
|
var senderClasses = sender.data.classes.toLowerCase().split(" ");
|
||||||
|
if (senderClasses.indexOf(this.config.calendarClass.toLowerCase()) !== -1) {
|
||||||
|
this.firstEvent = false;
|
||||||
|
|
||||||
|
for (var e in payload) {
|
||||||
|
var event = payload[e];
|
||||||
|
if (event.location || event.geo) {
|
||||||
|
this.firstEvent = event;
|
||||||
|
//Log.log("First upcoming event with location: ", event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (notification === "INDOOR_TEMPERATURE") {
|
||||||
|
this.indoorTemperature = this.roundValue(payload);
|
||||||
|
this.updateDom(300);
|
||||||
|
} else if (notification === "INDOOR_HUMIDITY") {
|
||||||
|
this.indoorHumidity = this.roundValue(payload);
|
||||||
|
this.updateDom(300);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Select the template depending on the display type.
|
||||||
|
getTemplate: function () {
|
||||||
|
return `${this.config.type.toLowerCase()}.njk`;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Add all the data to the template.
|
||||||
|
getTemplateData: function () {
|
||||||
|
return {
|
||||||
|
config: this.config,
|
||||||
|
current: this.weatherProvider.currentWeather(),
|
||||||
|
forecast: this.weatherProvider.weatherForecast(),
|
||||||
|
indoor: {
|
||||||
|
humidity: this.indoorHumidity,
|
||||||
|
temperature: this.indoorTemperature
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// What to do when the weather provider has new information available?
|
||||||
|
updateAvailable: function() {
|
||||||
|
Log.log("New weather information available.");
|
||||||
|
this.updateDom(0);
|
||||||
|
this.scheduleUpdate();
|
||||||
|
},
|
||||||
|
|
||||||
|
scheduleUpdate: function(delay = null) {
|
||||||
|
var nextLoad = this.config.updateInterval;
|
||||||
|
if (delay !== null && delay >= 0) {
|
||||||
|
nextLoad = delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
if (this.config.type === "forecast") {
|
||||||
|
this.weatherProvider.fetchWeatherForecast();
|
||||||
|
} else {
|
||||||
|
this.weatherProvider.fetchCurrentWeather();
|
||||||
|
}
|
||||||
|
}, nextLoad);
|
||||||
|
},
|
||||||
|
|
||||||
|
roundValue: function(temperature) {
|
||||||
|
var decimals = this.config.roundTemp ? 0 : 1;
|
||||||
|
return parseFloat(temperature).toFixed(decimals);
|
||||||
|
},
|
||||||
|
|
||||||
|
addFilters() {
|
||||||
|
this.nunjucksEnvironment().addFilter("formatTime", function(date) {
|
||||||
|
date = moment(date);
|
||||||
|
|
||||||
|
if (this.config.timeFormat !== 24) {
|
||||||
|
if (this.config.showPeriod) {
|
||||||
|
if (this.config.showPeriodUpper) {
|
||||||
|
return date.format("h:mm A");
|
||||||
|
} else {
|
||||||
|
return date.format("h:mm a");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return date.format("h:mm");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return date.format("HH:mm");
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
this.nunjucksEnvironment().addFilter("unit", function (value, type) {
|
||||||
|
if (type === "temperature") {
|
||||||
|
value += "°";
|
||||||
|
if (this.config.degreeLabel) {
|
||||||
|
if (this.config.units === "metric") {
|
||||||
|
value += "C";
|
||||||
|
} else if (this.config.units === "imperial") {
|
||||||
|
value += "F";
|
||||||
|
} else {
|
||||||
|
value += "K";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (type === "rain") {
|
||||||
|
if (isNaN(value)) {
|
||||||
|
value = "";
|
||||||
|
} else {
|
||||||
|
value = `${value.toFixed(2)} ${this.config.units === "imperial" ? "in" : "mm"}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
|
this.nunjucksEnvironment().addFilter("roundValue", function(value) {
|
||||||
|
return this.roundValue(value);
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
});
|
100
modules/default/weather/weatherobject.js
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/* global Class */
|
||||||
|
|
||||||
|
/* Magic Mirror
|
||||||
|
* Module: Weather
|
||||||
|
*
|
||||||
|
* By Michael Teeuw http://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.
|
||||||
|
|
||||||
|
class WeatherObject {
|
||||||
|
constructor(units) {
|
||||||
|
this.units = units;
|
||||||
|
this.date = null;
|
||||||
|
this.windSpeed = null;
|
||||||
|
this.windDirection = null;
|
||||||
|
this.sunrise = null;
|
||||||
|
this.sunset = null;
|
||||||
|
this.temperature = null;
|
||||||
|
this.minTemperature = null;
|
||||||
|
this.maxTemperature = null;
|
||||||
|
this.weatherType = null;
|
||||||
|
this.humidity = null;
|
||||||
|
this.rain = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
cardinalWindDirection() {
|
||||||
|
if (this.windDirection > 11.25 && this.windDirection <= 33.75){
|
||||||
|
return "NNE";
|
||||||
|
} else if (this.windDirection > 33.75 && this.windDirection <= 56.25) {
|
||||||
|
return "NE";
|
||||||
|
} else if (this.windDirection > 56.25 && this.windDirection <= 78.75) {
|
||||||
|
return "ENE";
|
||||||
|
} else if (this.windDirection > 78.75 && this.windDirection <= 101.25) {
|
||||||
|
return "E";
|
||||||
|
} else if (this.windDirection > 101.25 && this.windDirection <= 123.75) {
|
||||||
|
return "ESE";
|
||||||
|
} else if (this.windDirection > 123.75 && this.windDirection <= 146.25) {
|
||||||
|
return "SE";
|
||||||
|
} else if (this.windDirection > 146.25 && this.windDirection <= 168.75) {
|
||||||
|
return "SSE";
|
||||||
|
} else if (this.windDirection > 168.75 && this.windDirection <= 191.25) {
|
||||||
|
return "S";
|
||||||
|
} else if (this.windDirection > 191.25 && this.windDirection <= 213.75) {
|
||||||
|
return "SSW";
|
||||||
|
} else if (this.windDirection > 213.75 && this.windDirection <= 236.25) {
|
||||||
|
return "SW";
|
||||||
|
} else if (this.windDirection > 236.25 && this.windDirection <= 258.75) {
|
||||||
|
return "WSW";
|
||||||
|
} else if (this.windDirection > 258.75 && this.windDirection <= 281.25) {
|
||||||
|
return "W";
|
||||||
|
} else if (this.windDirection > 281.25 && this.windDirection <= 303.75) {
|
||||||
|
return "WNW";
|
||||||
|
} else if (this.windDirection > 303.75 && this.windDirection <= 326.25) {
|
||||||
|
return "NW";
|
||||||
|
} else if (this.windDirection > 326.25 && this.windDirection <= 348.75) {
|
||||||
|
return "NNW";
|
||||||
|
} else {
|
||||||
|
return "N";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
beaufortWindSpeed() {
|
||||||
|
const windInKmh = this.units === "imperial" ? this.windSpeed * 1.609344 : this.windSpeed * 60 * 60 / 1000;
|
||||||
|
const speeds = [1, 5, 11, 19, 28, 38, 49, 61, 74, 88, 102, 117, 1000];
|
||||||
|
for (const [index, speed] of speeds.entries()) {
|
||||||
|
if (speed > windInKmh) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
nextSunAction() {
|
||||||
|
return moment().isBetween(this.sunrise, this.sunset) ? "sunset" : "sunrise";
|
||||||
|
}
|
||||||
|
|
||||||
|
feelsLike() {
|
||||||
|
const windInMph = this.units === "imperial" ? this.windSpeed : this.windSpeed * 2.23694;
|
||||||
|
const tempInF = this.units === "imperial" ? this.temperature : this.temperature * 9 / 5 + 32;
|
||||||
|
let feelsLike = tempInF;
|
||||||
|
|
||||||
|
if (windInMph > 3 && tempInF < 50) {
|
||||||
|
feelsLike = Math.round(35.74 + 0.6215 * tempInF - 35.75 * Math.pow(windInMph, 0.16) + 0.4275 * tempInF * Math.pow(windInMph, 0.16));
|
||||||
|
} else if (tempInF > 80 && this.humidity > 40) {
|
||||||
|
feelsLike = -42.379 + 2.04901523 * tempInF + 10.14333127 * this.humidity
|
||||||
|
- 0.22475541 * tempInF * this.humidity - 6.83783 * Math.pow(10, -3) * tempInF * tempInF
|
||||||
|
- 5.481717 * Math.pow(10, -2) * this.humidity * this.humidity
|
||||||
|
+ 1.22874 * Math.pow(10, -3) * tempInF * tempInF * this.humidity
|
||||||
|
+ 8.5282 * Math.pow(10, -4) * tempInF * this.humidity * this.humidity
|
||||||
|
- 1.99 * Math.pow(10, -6) * tempInF * tempInF * this.humidity * this.humidity;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.units === "imperial" ? feelsLike : (feelsLike - 32) * 5 / 9;
|
||||||
|
}
|
||||||
|
}
|
154
modules/default/weather/weatherprovider.js
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/* global Class */
|
||||||
|
|
||||||
|
/* Magic Mirror
|
||||||
|
* Module: Weather
|
||||||
|
*
|
||||||
|
* By Michael Teeuw http://michaelteeuw.nl
|
||||||
|
* MIT Licensed.
|
||||||
|
*
|
||||||
|
* This class is the blueprint for a weather provider.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base BluePrint for the WeatherProvider
|
||||||
|
*/
|
||||||
|
var WeatherProvider = Class.extend({
|
||||||
|
// Weather Provider Properties
|
||||||
|
providerName: null,
|
||||||
|
|
||||||
|
// The following properties have accestor methods.
|
||||||
|
// Try to not access them directly.
|
||||||
|
currentWeatherObject: null,
|
||||||
|
weatherForecastArray: null,
|
||||||
|
fetchedLocationName: null,
|
||||||
|
|
||||||
|
// The following properties will be set automaticly.
|
||||||
|
// You do not need to overwrite these properties.
|
||||||
|
config: null,
|
||||||
|
delegate: null,
|
||||||
|
providerIdentifier: null,
|
||||||
|
|
||||||
|
|
||||||
|
// Weather Provider Methods
|
||||||
|
// All the following methods can be overwrited, although most are good as they are.
|
||||||
|
|
||||||
|
// Called when a weather provider is initialized.
|
||||||
|
init: function(config) {
|
||||||
|
this.config = config;
|
||||||
|
Log.info(`Weather provider: ${this.providerName} initialized.`);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Called to set the config, this config is the same as the weather module's config.
|
||||||
|
setConfig: function(config) {
|
||||||
|
this.config = config;
|
||||||
|
Log.info(`Weather provider: ${this.providerName} config set.`, this.config);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Called when the weather provider is about to start.
|
||||||
|
start: function() {
|
||||||
|
Log.info(`Weather provider: ${this.providerName} started.`);
|
||||||
|
},
|
||||||
|
|
||||||
|
// This method should start the API request to fetch the current weather.
|
||||||
|
// This method should definetly be overwritten in the provider.
|
||||||
|
fetchCurrentWeather: function() {
|
||||||
|
Log.warn(`Weather provider: ${this.providerName} does not subclass the fetchCurrentWeather method.`);
|
||||||
|
},
|
||||||
|
|
||||||
|
// This method should start the API request to fetch the weather forecast.
|
||||||
|
// This method should definetly be overwritten in the provider.
|
||||||
|
fetchWeatherForecast: function() {
|
||||||
|
Log.warn(`Weather provider: ${this.providerName} does not subclass the fetchWeatherForecast method.`);
|
||||||
|
},
|
||||||
|
|
||||||
|
// This returns a WeatherDay object for the current weather.
|
||||||
|
currentWeather: function() {
|
||||||
|
return this.currentWeatherObject;
|
||||||
|
},
|
||||||
|
|
||||||
|
// This returns an array of WeatherDay objects for the weather forecast.
|
||||||
|
weatherForecast: function() {
|
||||||
|
return this.weatherForecastArray;
|
||||||
|
},
|
||||||
|
|
||||||
|
// This returns the name of the fetched location or an empty string.
|
||||||
|
fetchedLocation: function() {
|
||||||
|
return this.fetchedLocationName || "";
|
||||||
|
},
|
||||||
|
|
||||||
|
// Set the currentWeather and notify the delegate that new information is available.
|
||||||
|
setCurrentWeather: function(currentWeatherObject) {
|
||||||
|
// We should check here if we are passing a WeatherDay
|
||||||
|
this.currentWeatherObject = currentWeatherObject;
|
||||||
|
|
||||||
|
this.updateAvailable();
|
||||||
|
},
|
||||||
|
|
||||||
|
// Set the weatherForecastArray and notify the delegate that new information is available.
|
||||||
|
setWeatherForecast: function(weatherForecastArray) {
|
||||||
|
// We should check here if we are passing a WeatherDay
|
||||||
|
this.weatherForecastArray = weatherForecastArray;
|
||||||
|
|
||||||
|
this.updateAvailable();
|
||||||
|
},
|
||||||
|
|
||||||
|
// Set the fetched location name.
|
||||||
|
setFetchedLocation: function(name) {
|
||||||
|
this.fetchedLocationName = name;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Notify the delegate that new weather is available.
|
||||||
|
updateAvailable: function() {
|
||||||
|
this.delegate.updateAvailable(this);
|
||||||
|
},
|
||||||
|
|
||||||
|
// A convinience function to make requests. It returns a promise.
|
||||||
|
fetchData: function(url, method = "GET", data = null) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
request.open(method, url, true);
|
||||||
|
request.onreadystatechange = function() {
|
||||||
|
if (this.readyState === 4) {
|
||||||
|
if (this.status === 200) {
|
||||||
|
resolve(JSON.parse(this.response));
|
||||||
|
} else {
|
||||||
|
reject(request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
request.send();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection of registered weather providers.
|
||||||
|
*/
|
||||||
|
WeatherProvider.providers = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static method to register a new weather provider.
|
||||||
|
*/
|
||||||
|
WeatherProvider.register = function(providerIdentifier, providerDetails) {
|
||||||
|
WeatherProvider.providers[providerIdentifier.toLowerCase()] = WeatherProvider.extend(providerDetails);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static method to initialize a new weather provider.
|
||||||
|
*/
|
||||||
|
WeatherProvider.initialize = function(providerIdentifier, delegate) {
|
||||||
|
providerIdentifier = providerIdentifier.toLowerCase();
|
||||||
|
|
||||||
|
var provider = new WeatherProvider.providers[providerIdentifier]();
|
||||||
|
|
||||||
|
provider.delegate = delegate;
|
||||||
|
provider.setConfig(delegate.config);
|
||||||
|
|
||||||
|
provider.providerIdentifier = providerIdentifier;
|
||||||
|
if (!provider.providerName) {
|
||||||
|
provider.providerName = providerIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
return provider;
|
||||||
|
};
|
@ -2,6 +2,11 @@
|
|||||||
The `weatherforecast` module is one of the default modules of the MagicMirror.
|
The `weatherforecast` module is one of the default modules of the MagicMirror.
|
||||||
This module displays the weather forecast for the coming week, including an an icon to display the current conditions, the minimum temperature and the maximum temperature.
|
This module displays the weather forecast for the coming week, including an an icon to display the current conditions, the minimum temperature and the maximum temperature.
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|
- 5 day forecast
|
||||||
|

|
||||||
|
|
||||||
## Using the module
|
## Using the module
|
||||||
|
|
||||||
To use this module, add it to the modules array in the `config/config.js` file:
|
To use this module, add it to the modules array in the `config/config.js` file:
|
||||||
@ -28,7 +33,7 @@ The following properties can be configured:
|
|||||||
| Option | Description
|
| Option | Description
|
||||||
| ---------------------------- | -----------
|
| ---------------------------- | -----------
|
||||||
| `location` | The location used for weather information. <br><br> **Example:** `'Amsterdam,Netherlands'` <br> **Default value:** `false` <br><br> **Note:** When the `location` and `locationID` are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used.
|
| `location` | The location used for weather information. <br><br> **Example:** `'Amsterdam,Netherlands'` <br> **Default value:** `false` <br><br> **Note:** When the `location` and `locationID` are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used.
|
||||||
| `locationID` | Location ID from [OpenWeatherMap](http://openweathermap.org/help/city_list.txt) **This will override anything you put in location.** <br> Leave blank if you want to use location. <br> **Example:** `1234567` <br> **Default value:** `false` <br><br> **Note:** When the `location` and `locationID` are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used.
|
| `locationID` | Location ID from [OpenWeatherMap](https://openweathermap.org/find) **This will override anything you put in location.** <br> Leave blank if you want to use location. <br> **Example:** `1234567` <br> **Default value:** `false` <br><br> **Note:** When the `location` and `locationID` are both not set, the location will be based on the information provided by the calendar module. The first upcoming event with location data will be used.
|
||||||
| `appid` | The [OpenWeatherMap](https://home.openweathermap.org) API key, which can be obtained by creating an OpenWeatherMap account. <br><br> This value is **REQUIRED**
|
| `appid` | The [OpenWeatherMap](https://home.openweathermap.org) API key, which can be obtained by creating an OpenWeatherMap account. <br><br> This value is **REQUIRED**
|
||||||
| `units` | What units to use. Specified by config.js <br><br> **Possible values:** `config.units` = Specified by config.js, `default` = Kelvin, `metric` = Celsius, `imperial` =Fahrenheit <br> **Default value:** `config.units`
|
| `units` | What units to use. Specified by config.js <br><br> **Possible values:** `config.units` = Specified by config.js, `default` = Kelvin, `metric` = Celsius, `imperial` =Fahrenheit <br> **Default value:** `config.units`
|
||||||
| `roundTemp` | Round temperature values to nearest integer. <br><br> **Possible values:** `true` (round to integer) or `false` (display exact value with decimal point) <br> **Default value:** `false`
|
| `roundTemp` | Round temperature values to nearest integer. <br><br> **Possible values:** `true` (round to integer) or `false` (display exact value with decimal point) <br> **Default value:** `false`
|
||||||
@ -46,10 +51,11 @@ The following properties can be configured:
|
|||||||
| `apiBase` | The OpenWeatherMap base URL. <br><br> **Default value:** `'http://api.openweathermap.org/data/'`
|
| `apiBase` | The OpenWeatherMap base URL. <br><br> **Default value:** `'http://api.openweathermap.org/data/'`
|
||||||
| `forecastEndpoint` | The OpenWeatherMap API endPoint. <br><br> **Default value:** `'forecast/daily'`
|
| `forecastEndpoint` | The OpenWeatherMap API endPoint. <br><br> **Default value:** `'forecast/daily'`
|
||||||
| `appendLocationNameToHeader` | If set to `true`, the returned location name will be appended to the header of the module, if the header is enabled. This is mainly intresting when using calender based weather. <br><br> **Default value:** `true`
|
| `appendLocationNameToHeader` | If set to `true`, the returned location name will be appended to the header of the module, if the header is enabled. This is mainly intresting when using calender based weather. <br><br> **Default value:** `true`
|
||||||
| `calendarClass` | The class for the calender module to base the event based weather information on. <br><br> **Default value:** `'calendar'`
|
| `calendarClass` | The class for the calendar module to base the event based weather information on. <br><br> **Default value:** `'calendar'`
|
||||||
| `tableClass` | Name of the classes issued from `main.css`. <br><br> **Possible values:** xsmall, small, medium, large, xlarge. <br> **Default value:** _small._
|
| `tableClass` | Name of the classes issued from `main.css`. <br><br> **Possible values:** xsmall, small, medium, large, xlarge. <br> **Default value:** _small._
|
||||||
| `iconTable` | The conversion table to convert the weather conditions to weather-icons. <br><br> **Default value:** view table below
|
| `iconTable` | The conversion table to convert the weather conditions to weather-icons. <br><br> **Default value:** view table below
|
||||||
`colored` | If set 'colored' to true the min-temp get a blue tone and the max-temp get a red tone. <br><br> **Default value:** `'false'`
|
| `colored` | If set `colored` to `true` the min-temp gets a blue tone and the max-temp gets a red tone. <br><br> **Default value:** `'false'`
|
||||||
|
| `scale ` | If set to `true` the module will display `C` for Celsius degrees and `F` for Fahrenheit degrees after the number, based on the value of the `units` option, otherwise only the ° character is displayed. <br><br> **Default value:** `false`
|
||||||
|
|
||||||
#### Default Icon Table
|
#### Default Icon Table
|
||||||
````javascript
|
````javascript
|
||||||
|
BIN
modules/default/weatherforecast/forecast_screenshot.png
Normal file
After Width: | Height: | Size: 84 KiB |
@ -142,14 +142,14 @@ Module.register("weatherforecast",{
|
|||||||
icon.className = "wi weathericon " + forecast.icon;
|
icon.className = "wi weathericon " + forecast.icon;
|
||||||
iconCell.appendChild(icon);
|
iconCell.appendChild(icon);
|
||||||
|
|
||||||
var degreeLabel = "";
|
var degreeLabel = "°";
|
||||||
if(this.config.scale) {
|
if(this.config.scale) {
|
||||||
switch(this.config.units) {
|
switch(this.config.units) {
|
||||||
case "metric":
|
case "metric":
|
||||||
degreeLabel = " °C";
|
degreeLabel += " C";
|
||||||
break;
|
break;
|
||||||
case "imperial":
|
case "imperial":
|
||||||
degreeLabel = " °F";
|
degreeLabel += " F";
|
||||||
break;
|
break;
|
||||||
case "default":
|
case "default":
|
||||||
degreeLabel = "K";
|
degreeLabel = "K";
|
||||||
|
2249
package-lock.json
generated
16
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "magicmirror",
|
"name": "magicmirror",
|
||||||
"version": "2.5.0",
|
"version": "2.6.0",
|
||||||
"description": "The open source modular smart mirror platform.",
|
"description": "The open source modular smart mirror platform.",
|
||||||
"main": "js/electron.js",
|
"main": "js/electron.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -49,26 +49,28 @@
|
|||||||
"jshint": "^2.9.5",
|
"jshint": "^2.9.5",
|
||||||
"mocha": "^4.1.0",
|
"mocha": "^4.1.0",
|
||||||
"mocha-each": "^1.1.0",
|
"mocha-each": "^1.1.0",
|
||||||
"spectron": "3.7.x",
|
"spectron": "^3.8.0",
|
||||||
"stylelint": "^8.4.0",
|
"stylelint": "^8.4.0",
|
||||||
"stylelint-config-standard": "latest",
|
"stylelint-config-standard": "latest",
|
||||||
"time-grunt": "latest"
|
"time-grunt": "latest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"ajv": "6.5.5",
|
||||||
"body-parser": "^1.18.2",
|
"body-parser": "^1.18.2",
|
||||||
"colors": "^1.1.2",
|
"colors": "^1.1.2",
|
||||||
"electron": "^2.0.0",
|
"electron": "^2.0.16",
|
||||||
"express": "^4.16.2",
|
"express": "^4.16.2",
|
||||||
"express-ipfilter": "0.3.1",
|
"express-ipfilter": "0.3.1",
|
||||||
"feedme": "latest",
|
"feedme": "latest",
|
||||||
"helmet": "^3.9.0",
|
"helmet": "^3.9.0",
|
||||||
|
"home-path": "^1.0.6",
|
||||||
"iconv-lite": "latest",
|
"iconv-lite": "latest",
|
||||||
"mocha-logger": "^1.0.5",
|
"mocha-logger": "^1.0.6",
|
||||||
"moment": "latest",
|
"moment": "latest",
|
||||||
"request": "^2.83.0",
|
"request": "^2.87.0",
|
||||||
"rrule-alt": "^2.2.7",
|
"rrule-alt": "^2.2.8",
|
||||||
"simple-git": "^1.85.0",
|
"simple-git": "^1.85.0",
|
||||||
"socket.io": "^2.0.4",
|
"socket.io": "^2.1.1",
|
||||||
"valid-url": "latest",
|
"valid-url": "latest",
|
||||||
"walk": "latest"
|
"walk": "latest"
|
||||||
}
|
}
|
||||||
|
35
translations/hr.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"LOADING": "Učitavanje …",
|
||||||
|
|
||||||
|
"TODAY": "Danas",
|
||||||
|
"TOMORROW": "Sutra",
|
||||||
|
"DAYAFTERTOMORROW": "Prekosutra",
|
||||||
|
"RUNNING": "Završava za",
|
||||||
|
"EMPTY": "Nema nadolazećih događaja.",
|
||||||
|
|
||||||
|
"WEEK": "Tjedan {weekNumber}",
|
||||||
|
|
||||||
|
"N": "N",
|
||||||
|
"NNE": "NNE",
|
||||||
|
"NE": "NE",
|
||||||
|
"ENE": "ENE",
|
||||||
|
"E": "E",
|
||||||
|
"ESE": "ESE",
|
||||||
|
"SE": "SE",
|
||||||
|
"SSE": "SSE",
|
||||||
|
"S": "S",
|
||||||
|
"SSW": "SSW",
|
||||||
|
"SW": "SW",
|
||||||
|
"WSW": "WSW",
|
||||||
|
"W": "W",
|
||||||
|
"WNW": "WNW",
|
||||||
|
"NW": "NW",
|
||||||
|
"NNW": "NNW",
|
||||||
|
|
||||||
|
"UPDATE_NOTIFICATION": "Dostupna je aktualizacija MagicMirror².",
|
||||||
|
"UPDATE_NOTIFICATION_MODULE": "Dostupna je aktualizacija modula {MODULE_NAME}.",
|
||||||
|
"UPDATE_INFO_SINGLE": "Instalirana verzija {COMMIT_COUNT} commit kasni za branch-om {BRANCH_NAME}.",
|
||||||
|
"UPDATE_INFO_MULTIPLE": "Instalirana verzija {COMMIT_COUNT} commit-ova kasni za branch-om {BRANCH_NAME}.",
|
||||||
|
|
||||||
|
"FEELS": "Osjeća"
|
||||||
|
}
|
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
"UPDATE_NOTIFICATION": "Dostępna jest aktualizacja MagicMirror².",
|
"UPDATE_NOTIFICATION": "Dostępna jest aktualizacja MagicMirror².",
|
||||||
"UPDATE_NOTIFICATION_MODULE": "Dostępna jest aktualizacja modułu {MODULE_NAME}.",
|
"UPDATE_NOTIFICATION_MODULE": "Dostępna jest aktualizacja modułu {MODULE_NAME}.",
|
||||||
"UPDATE_INFO_SINGLE": "Zainstalowana wersja odbiega o {COMMIT_COUNT} commitów od gałęzi {BRANCH_NAME}.",
|
"UPDATE_INFO_SINGLE": "Zainstalowana wersja odbiega o {COMMIT_COUNT} commit od gałęzi {BRANCH_NAME}.",
|
||||||
"UPDATE_INFO_MULTIPLE": "Zainstalowana wersja odbiega o {COMMIT_COUNT} commitów od gałęzi {BRANCH_NAME}.",
|
"UPDATE_INFO_MULTIPLE": "Zainstalowana wersja odbiega o {COMMIT_COUNT} commitów od gałęzi {BRANCH_NAME}.",
|
||||||
|
|
||||||
"FEELS": "Odczuwalna"
|
"FEELS": "Odczuwalna"
|
||||||
|
@ -28,5 +28,7 @@
|
|||||||
"UPDATE_NOTIFICATION": "Atualização do MagicMirror² disponível.",
|
"UPDATE_NOTIFICATION": "Atualização do MagicMirror² disponível.",
|
||||||
"UPDATE_NOTIFICATION_MODULE": "Atualização para o módulo {MODULE_NAME} disponível.",
|
"UPDATE_NOTIFICATION_MODULE": "Atualização para o módulo {MODULE_NAME} disponível.",
|
||||||
"UPDATE_INFO_SINGLE": "A instalação atual está {COMMIT_COUNT} commit atrasada no branch {BRANCH_NAME}.",
|
"UPDATE_INFO_SINGLE": "A instalação atual está {COMMIT_COUNT} commit atrasada no branch {BRANCH_NAME}.",
|
||||||
"UPDATE_INFO_MULTIPLE": "A instalação atual está {COMMIT_COUNT} commits atrasada no branch {BRANCH_NAME}."
|
"UPDATE_INFO_MULTIPLE": "A instalação atual está {COMMIT_COUNT} commits atrasada no branch {BRANCH_NAME}.",
|
||||||
|
|
||||||
|
"FEELS": "Sentida"
|
||||||
}
|
}
|
||||||
|
@ -29,5 +29,7 @@
|
|||||||
"UPDATE_NOTIFICATION": "Un update este disponibil pentru MagicMirror².",
|
"UPDATE_NOTIFICATION": "Un update este disponibil pentru MagicMirror².",
|
||||||
"UPDATE_NOTIFICATION_MODULE": "Un update este disponibil pentru modulul {MODULE_NAME}.",
|
"UPDATE_NOTIFICATION_MODULE": "Un update este disponibil pentru modulul {MODULE_NAME}.",
|
||||||
"UPDATE_INFO_SINGLE": "Există {COMMIT_COUNT} commit-uri noi pe branch-ul {BRANCH_NAME}.",
|
"UPDATE_INFO_SINGLE": "Există {COMMIT_COUNT} commit-uri noi pe branch-ul {BRANCH_NAME}.",
|
||||||
"UPDATE_INFO_MULTIPLE": "Există {COMMIT_COUNT} commit-uri noi pe branch-ul {BRANCH_NAME}."
|
"UPDATE_INFO_MULTIPLE": "Există {COMMIT_COUNT} commit-uri noi pe branch-ul {BRANCH_NAME}.",
|
||||||
|
|
||||||
|
"FEELS": "Se simte ca fiind"
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,8 @@ var translations = {
|
|||||||
"ro" : "translations/ro.json", // Romanian
|
"ro" : "translations/ro.json", // Romanian
|
||||||
"cy" : "translations/cy.json", // Welsh (Cymraeg)
|
"cy" : "translations/cy.json", // Welsh (Cymraeg)
|
||||||
"bg" : "translations/bg.json", // Bulgarian
|
"bg" : "translations/bg.json", // Bulgarian
|
||||||
"cs" : "translations/cs.json" // Czech
|
"cs" : "translations/cs.json", // Czech
|
||||||
|
"hr" : "translations/hr.json" // Croatian
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof module !== "undefined") {module.exports = translations;}
|
if (typeof module !== "undefined") {module.exports = translations;}
|
||||||
|
576
vendor/package-lock.json
generated
vendored
@ -3,6 +3,11 @@
|
|||||||
"requires": true,
|
"requires": true,
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-free": {
|
||||||
|
"version": "5.6.3",
|
||||||
|
"resolved": "https://npm.fontawesome.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.6.3.tgz",
|
||||||
|
"integrity": "sha512-s5PLdI9NYgjBvfrv6rhirPHlAHWx+Sfo/IjsAeiXYfmemC/GSjwsyz1wLnGPazbLPXWfk62ks980o9AmsxYUEQ=="
|
||||||
|
},
|
||||||
"a-sync-waterfall": {
|
"a-sync-waterfall": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.0.tgz",
|
||||||
@ -209,35 +214,26 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fsevents": {
|
"fsevents": {
|
||||||
"version": "1.1.2",
|
"version": "1.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz",
|
||||||
"integrity": "sha512-Sn44E5wQW4bTHXvQmvSHwqbuiXtduD6Rrjm2ZtUEGbyrig+nUH3t/QD4M4/ZXViY556TBpRgZkHLDx3JxPwxiw==",
|
"integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"nan": "^2.3.0",
|
"nan": "^2.9.2",
|
||||||
"node-pre-gyp": "^0.6.36"
|
"node-pre-gyp": "^0.10.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"abbrev": {
|
"abbrev": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"ajv": {
|
|
||||||
"version": "4.11.8",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"co": "^4.6.0",
|
|
||||||
"json-stable-stringify": "^1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"bundled": true
|
"bundled": true
|
||||||
},
|
},
|
||||||
"aproba": {
|
"aproba": {
|
||||||
"version": "1.1.1",
|
"version": "1.2.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
@ -250,76 +246,20 @@
|
|||||||
"readable-stream": "^2.0.6"
|
"readable-stream": "^2.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"asn1": {
|
|
||||||
"version": "0.2.3",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"assert-plus": {
|
|
||||||
"version": "0.2.0",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"asynckit": {
|
|
||||||
"version": "0.4.0",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"aws-sign2": {
|
|
||||||
"version": "0.6.0",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"aws4": {
|
|
||||||
"version": "1.6.0",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "0.4.2",
|
|
||||||
"bundled": true
|
|
||||||
},
|
|
||||||
"bcrypt-pbkdf": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"tweetnacl": "^0.14.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"block-stream": {
|
|
||||||
"version": "0.0.9",
|
|
||||||
"bundled": true,
|
|
||||||
"requires": {
|
|
||||||
"inherits": "~2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"boom": {
|
|
||||||
"version": "2.10.1",
|
|
||||||
"bundled": true,
|
|
||||||
"requires": {
|
|
||||||
"hoek": "2.x.x"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"brace-expansion": {
|
|
||||||
"version": "1.1.7",
|
|
||||||
"bundled": true,
|
|
||||||
"requires": {
|
|
||||||
"balanced-match": "^0.4.1",
|
|
||||||
"concat-map": "0.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"buffer-shims": {
|
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true
|
"bundled": true
|
||||||
},
|
},
|
||||||
"caseless": {
|
"brace-expansion": {
|
||||||
"version": "0.12.0",
|
"version": "1.1.11",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true
|
"requires": {
|
||||||
|
"balanced-match": "^1.0.0",
|
||||||
|
"concat-map": "0.0.1"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"co": {
|
"chownr": {
|
||||||
"version": "4.6.0",
|
"version": "1.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
@ -327,13 +267,6 @@
|
|||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true
|
"bundled": true
|
||||||
},
|
},
|
||||||
"combined-stream": {
|
|
||||||
"version": "1.0.5",
|
|
||||||
"bundled": true,
|
|
||||||
"requires": {
|
|
||||||
"delayed-stream": "~1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"bundled": true
|
"bundled": true
|
||||||
@ -344,33 +277,11 @@
|
|||||||
},
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true
|
|
||||||
},
|
|
||||||
"cryptiles": {
|
|
||||||
"version": "2.0.5",
|
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true,
|
"optional": true
|
||||||
"requires": {
|
|
||||||
"boom": "2.x.x"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dashdash": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"assert-plus": "^1.0.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"assert-plus": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "2.6.8",
|
"version": "2.6.9",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
@ -378,74 +289,32 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deep-extend": {
|
"deep-extend": {
|
||||||
"version": "0.4.2",
|
"version": "0.5.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"delayed-stream": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"bundled": true
|
|
||||||
},
|
|
||||||
"delegates": {
|
"delegates": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"ecc-jsbn": {
|
"detect-libc": {
|
||||||
"version": "0.1.1",
|
"version": "1.0.3",
|
||||||
"bundled": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"jsbn": "~0.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"extend": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"extsprintf": {
|
"fs-minipass": {
|
||||||
"version": "1.0.2",
|
"version": "1.2.5",
|
||||||
"bundled": true
|
|
||||||
},
|
|
||||||
"forever-agent": {
|
|
||||||
"version": "0.6.1",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"form-data": {
|
|
||||||
"version": "2.1.4",
|
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"asynckit": "^0.4.0",
|
"minipass": "^2.2.1"
|
||||||
"combined-stream": "^1.0.5",
|
|
||||||
"mime-types": "^2.1.12"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fs.realpath": {
|
"fs.realpath": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true
|
|
||||||
},
|
|
||||||
"fstream": {
|
|
||||||
"version": "1.0.11",
|
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"requires": {
|
"optional": true
|
||||||
"graceful-fs": "^4.1.2",
|
|
||||||
"inherits": "~2.0.0",
|
|
||||||
"mkdirp": ">=0.5 0",
|
|
||||||
"rimraf": "2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"fstream-ignore": {
|
|
||||||
"version": "1.0.5",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"fstream": "^1.0.0",
|
|
||||||
"inherits": "2",
|
|
||||||
"minimatch": "^3.0.0"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"gauge": {
|
"gauge": {
|
||||||
"version": "2.7.4",
|
"version": "2.7.4",
|
||||||
@ -462,24 +331,10 @@
|
|||||||
"wide-align": "^1.1.0"
|
"wide-align": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"getpass": {
|
|
||||||
"version": "0.1.7",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"assert-plus": "^1.0.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"assert-plus": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"glob": {
|
"glob": {
|
||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"fs.realpath": "^1.0.0",
|
"fs.realpath": "^1.0.0",
|
||||||
"inflight": "^1.0.4",
|
"inflight": "^1.0.4",
|
||||||
@ -489,57 +344,31 @@
|
|||||||
"path-is-absolute": "^1.0.0"
|
"path-is-absolute": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"graceful-fs": {
|
|
||||||
"version": "4.1.11",
|
|
||||||
"bundled": true
|
|
||||||
},
|
|
||||||
"har-schema": {
|
|
||||||
"version": "1.0.5",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"har-validator": {
|
|
||||||
"version": "4.2.1",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"ajv": "^4.9.1",
|
|
||||||
"har-schema": "^1.0.5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"has-unicode": {
|
"has-unicode": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"hawk": {
|
"iconv-lite": {
|
||||||
"version": "3.1.3",
|
"version": "0.4.21",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"boom": "2.x.x",
|
"safer-buffer": "^2.1.0"
|
||||||
"cryptiles": "2.x.x",
|
|
||||||
"hoek": "2.x.x",
|
|
||||||
"sntp": "1.x.x"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"hoek": {
|
"ignore-walk": {
|
||||||
"version": "2.16.3",
|
"version": "3.0.1",
|
||||||
"bundled": true
|
|
||||||
},
|
|
||||||
"http-signature": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"assert-plus": "^0.2.0",
|
"minimatch": "^3.0.4"
|
||||||
"jsprim": "^1.2.2",
|
|
||||||
"sshpk": "^1.7.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"inflight": {
|
"inflight": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"once": "^1.3.0",
|
"once": "^1.3.0",
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
@ -550,7 +379,7 @@
|
|||||||
"bundled": true
|
"bundled": true
|
||||||
},
|
},
|
||||||
"ini": {
|
"ini": {
|
||||||
"version": "1.3.4",
|
"version": "1.3.5",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
@ -561,85 +390,11 @@
|
|||||||
"number-is-nan": "^1.0.0"
|
"number-is-nan": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"is-typedarray": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"isarray": {
|
"isarray": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true
|
|
||||||
},
|
|
||||||
"isstream": {
|
|
||||||
"version": "0.1.2",
|
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"jodid25519": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"jsbn": "~0.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"jsbn": {
|
|
||||||
"version": "0.1.1",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"json-schema": {
|
|
||||||
"version": "0.2.3",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"json-stable-stringify": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"jsonify": "~0.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"json-stringify-safe": {
|
|
||||||
"version": "5.0.1",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"jsonify": {
|
|
||||||
"version": "0.0.0",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"jsprim": {
|
|
||||||
"version": "1.4.0",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"assert-plus": "1.0.0",
|
|
||||||
"extsprintf": "1.0.2",
|
|
||||||
"json-schema": "0.2.3",
|
|
||||||
"verror": "1.3.6"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"assert-plus": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mime-db": {
|
|
||||||
"version": "1.27.0",
|
|
||||||
"bundled": true
|
|
||||||
},
|
|
||||||
"mime-types": {
|
|
||||||
"version": "2.1.15",
|
|
||||||
"bundled": true,
|
|
||||||
"requires": {
|
|
||||||
"mime-db": "~1.27.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"minimatch": {
|
"minimatch": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
@ -651,6 +406,22 @@
|
|||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
"bundled": true
|
"bundled": true
|
||||||
},
|
},
|
||||||
|
"minipass": {
|
||||||
|
"version": "2.2.4",
|
||||||
|
"bundled": true,
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "^5.1.1",
|
||||||
|
"yallist": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"minizlib": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"minipass": "^2.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"mkdirp": {
|
"mkdirp": {
|
||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
@ -663,20 +434,31 @@
|
|||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"node-pre-gyp": {
|
"needle": {
|
||||||
"version": "0.6.36",
|
"version": "2.2.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"debug": "^2.1.2",
|
||||||
|
"iconv-lite": "^0.4.4",
|
||||||
|
"sax": "^1.2.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node-pre-gyp": {
|
||||||
|
"version": "0.10.0",
|
||||||
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"detect-libc": "^1.0.2",
|
||||||
"mkdirp": "^0.5.1",
|
"mkdirp": "^0.5.1",
|
||||||
|
"needle": "^2.2.0",
|
||||||
"nopt": "^4.0.1",
|
"nopt": "^4.0.1",
|
||||||
|
"npm-packlist": "^1.1.6",
|
||||||
"npmlog": "^4.0.2",
|
"npmlog": "^4.0.2",
|
||||||
"rc": "^1.1.7",
|
"rc": "^1.1.7",
|
||||||
"request": "^2.81.0",
|
|
||||||
"rimraf": "^2.6.1",
|
"rimraf": "^2.6.1",
|
||||||
"semver": "^5.3.0",
|
"semver": "^5.3.0",
|
||||||
"tar": "^2.2.1",
|
"tar": "^4"
|
||||||
"tar-pack": "^3.4.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nopt": {
|
"nopt": {
|
||||||
@ -688,8 +470,22 @@
|
|||||||
"osenv": "^0.1.4"
|
"osenv": "^0.1.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"npm-bundled": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"npm-packlist": {
|
||||||
|
"version": "1.1.10",
|
||||||
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"ignore-walk": "^3.0.1",
|
||||||
|
"npm-bundled": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"npmlog": {
|
"npmlog": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
@ -703,11 +499,6 @@
|
|||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"bundled": true
|
"bundled": true
|
||||||
},
|
},
|
||||||
"oauth-sign": {
|
|
||||||
"version": "0.8.2",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
@ -731,7 +522,7 @@
|
|||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"osenv": {
|
"osenv": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.5",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
@ -741,33 +532,20 @@
|
|||||||
},
|
},
|
||||||
"path-is-absolute": {
|
"path-is-absolute": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"bundled": true
|
|
||||||
},
|
|
||||||
"performance-now": {
|
|
||||||
"version": "0.2.0",
|
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"process-nextick-args": {
|
"process-nextick-args": {
|
||||||
"version": "1.0.7",
|
"version": "2.0.0",
|
||||||
"bundled": true
|
|
||||||
},
|
|
||||||
"punycode": {
|
|
||||||
"version": "1.4.1",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"qs": {
|
|
||||||
"version": "6.4.0",
|
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"rc": {
|
"rc": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.7",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"deep-extend": "~0.4.0",
|
"deep-extend": "^0.5.1",
|
||||||
"ini": "~1.3.0",
|
"ini": "~1.3.0",
|
||||||
"minimist": "^1.2.0",
|
"minimist": "^1.2.0",
|
||||||
"strip-json-comments": "~2.0.1"
|
"strip-json-comments": "~2.0.1"
|
||||||
@ -781,60 +559,43 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"readable-stream": {
|
"readable-stream": {
|
||||||
"version": "2.2.9",
|
"version": "2.3.6",
|
||||||
"bundled": true,
|
|
||||||
"requires": {
|
|
||||||
"buffer-shims": "~1.0.0",
|
|
||||||
"core-util-is": "~1.0.0",
|
|
||||||
"inherits": "~2.0.1",
|
|
||||||
"isarray": "~1.0.0",
|
|
||||||
"process-nextick-args": "~1.0.6",
|
|
||||||
"string_decoder": "~1.0.0",
|
|
||||||
"util-deprecate": "~1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"request": {
|
|
||||||
"version": "2.81.0",
|
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"aws-sign2": "~0.6.0",
|
"core-util-is": "~1.0.0",
|
||||||
"aws4": "^1.2.1",
|
"inherits": "~2.0.3",
|
||||||
"caseless": "~0.12.0",
|
"isarray": "~1.0.0",
|
||||||
"combined-stream": "~1.0.5",
|
"process-nextick-args": "~2.0.0",
|
||||||
"extend": "~3.0.0",
|
"safe-buffer": "~5.1.1",
|
||||||
"forever-agent": "~0.6.1",
|
"string_decoder": "~1.1.1",
|
||||||
"form-data": "~2.1.1",
|
"util-deprecate": "~1.0.1"
|
||||||
"har-validator": "~4.2.1",
|
|
||||||
"hawk": "~3.1.3",
|
|
||||||
"http-signature": "~1.1.0",
|
|
||||||
"is-typedarray": "~1.0.0",
|
|
||||||
"isstream": "~0.1.2",
|
|
||||||
"json-stringify-safe": "~5.0.1",
|
|
||||||
"mime-types": "~2.1.7",
|
|
||||||
"oauth-sign": "~0.8.1",
|
|
||||||
"performance-now": "^0.2.0",
|
|
||||||
"qs": "~6.4.0",
|
|
||||||
"safe-buffer": "^5.0.1",
|
|
||||||
"stringstream": "~0.0.4",
|
|
||||||
"tough-cookie": "~2.3.0",
|
|
||||||
"tunnel-agent": "^0.6.0",
|
|
||||||
"uuid": "^3.0.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rimraf": {
|
"rimraf": {
|
||||||
"version": "2.6.1",
|
"version": "2.6.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"glob": "^7.0.5"
|
"glob": "^7.0.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.0.1",
|
"version": "5.1.1",
|
||||||
"bundled": true
|
"bundled": true
|
||||||
},
|
},
|
||||||
|
"safer-buffer": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"sax": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"bundled": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "5.3.0",
|
"version": "5.5.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
@ -848,37 +609,6 @@
|
|||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"sntp": {
|
|
||||||
"version": "1.0.9",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"hoek": "2.x.x"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sshpk": {
|
|
||||||
"version": "1.13.0",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"asn1": "~0.2.3",
|
|
||||||
"assert-plus": "^1.0.0",
|
|
||||||
"bcrypt-pbkdf": "^1.0.0",
|
|
||||||
"dashdash": "^1.12.0",
|
|
||||||
"ecc-jsbn": "~0.1.1",
|
|
||||||
"getpass": "^0.1.1",
|
|
||||||
"jodid25519": "^1.0.0",
|
|
||||||
"jsbn": "~0.1.0",
|
|
||||||
"tweetnacl": "~0.14.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"assert-plus": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"string-width": {
|
"string-width": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
@ -889,17 +619,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"string_decoder": {
|
"string_decoder": {
|
||||||
"version": "1.0.1",
|
"version": "1.1.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "^5.0.1"
|
"safe-buffer": "~5.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"stringstream": {
|
|
||||||
"version": "0.0.5",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"strip-ansi": {
|
"strip-ansi": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
@ -913,72 +639,24 @@
|
|||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"tar": {
|
"tar": {
|
||||||
"version": "2.2.1",
|
"version": "4.4.1",
|
||||||
"bundled": true,
|
|
||||||
"requires": {
|
|
||||||
"block-stream": "*",
|
|
||||||
"fstream": "^1.0.2",
|
|
||||||
"inherits": "2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tar-pack": {
|
|
||||||
"version": "3.4.0",
|
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "^2.2.0",
|
"chownr": "^1.0.1",
|
||||||
"fstream": "^1.0.10",
|
"fs-minipass": "^1.2.5",
|
||||||
"fstream-ignore": "^1.0.5",
|
"minipass": "^2.2.4",
|
||||||
"once": "^1.3.3",
|
"minizlib": "^1.1.0",
|
||||||
"readable-stream": "^2.1.4",
|
"mkdirp": "^0.5.0",
|
||||||
"rimraf": "^2.5.1",
|
"safe-buffer": "^5.1.1",
|
||||||
"tar": "^2.2.1",
|
"yallist": "^3.0.2"
|
||||||
"uid-number": "^0.0.6"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tough-cookie": {
|
|
||||||
"version": "2.3.2",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"punycode": "^1.4.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tunnel-agent": {
|
|
||||||
"version": "0.6.0",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"safe-buffer": "^5.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tweetnacl": {
|
|
||||||
"version": "0.14.5",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"uid-number": {
|
|
||||||
"version": "0.0.6",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"util-deprecate": {
|
"util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true
|
|
||||||
},
|
|
||||||
"uuid": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"verror": {
|
|
||||||
"version": "1.3.6",
|
|
||||||
"bundled": true,
|
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
|
||||||
"extsprintf": "1.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"wide-align": {
|
"wide-align": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
@ -990,6 +668,10 @@
|
|||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true
|
"bundled": true
|
||||||
|
},
|
||||||
|
"yallist": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"bundled": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1178,9 +860,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nan": {
|
"nan": {
|
||||||
"version": "2.7.0",
|
"version": "2.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz",
|
||||||
"integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=",
|
"integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"normalize-path": {
|
"normalize-path": {
|
||||||
|
1
vendor/package.json
vendored
@ -10,6 +10,7 @@
|
|||||||
"url": "https://github.com/MichMich/MagicMirror/issues"
|
"url": "https://github.com/MichMich/MagicMirror/issues"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-free": "^5.3.1",
|
||||||
"font-awesome": "^4.7.0",
|
"font-awesome": "^4.7.0",
|
||||||
"moment": "^2.17.1",
|
"moment": "^2.17.1",
|
||||||
"moment-timezone": "^0.5.11",
|
"moment-timezone": "^0.5.11",
|
||||||
|
2
vendor/vendor.js
vendored
@ -13,6 +13,8 @@ var vendor = {
|
|||||||
"weather-icons.css": "node_modules/weathericons/css/weather-icons.css",
|
"weather-icons.css": "node_modules/weathericons/css/weather-icons.css",
|
||||||
"weather-icons-wind.css": "node_modules/weathericons/css/weather-icons-wind.css",
|
"weather-icons-wind.css": "node_modules/weathericons/css/weather-icons-wind.css",
|
||||||
"font-awesome.css": "node_modules/font-awesome/css/font-awesome.min.css",
|
"font-awesome.css": "node_modules/font-awesome/css/font-awesome.min.css",
|
||||||
|
"font-awesome5.css": "node_modules/@fortawesome/fontawesome-free/css/all.min.css",
|
||||||
|
"font-awesome5.v4shims.css": "node_modules/@fortawesome/fontawesome-free/css/v4-shims.min.css",
|
||||||
"nunjucks.js": "node_modules/nunjucks/browser/nunjucks.min.js"
|
"nunjucks.js": "node_modules/nunjucks/browser/nunjucks.min.js"
|
||||||
};
|
};
|
||||||
|
|
||||||
|