Merge pull request #22 from MichMich/v2-beta

Update from Master
This commit is contained in:
Paul-Vincent Roll
2016-05-06 16:55:09 +02:00
27 changed files with 240 additions and 80 deletions

7
.eslintignore Normal file
View File

@@ -0,0 +1,7 @@
vendor/
!/vendor/vendor.js
/modules/**
!/modules/default/**
!/modules/node_helper
!/modules/node_helper/**
!/modules/default/defaultmodules.js

14
.eslintrc.json Normal file
View File

@@ -0,0 +1,14 @@
{
"rules": {
"indent": ["error", "tab"],
"quotes": ["error", "double"],
"max-len": ["error", 250],
"curly": "error",
"camelcase": ["error", {"properties": "never"}]
},
"env": {
"browser": true,
"node": true,
"es6": true
}
}

View File

@@ -1,9 +0,0 @@
{
"preset": "google",
"validateIndentation": "\t",
"validateQuoteMarks": "\"",
"maximumLineLength": 250,
"requireCurlyBraces": [],
"requireCamelCaseOrUpperCaseIdentifiers": false,
"excludeFiles": [".jscsrc"],
}

9
.travis.yml Normal file
View File

@@ -0,0 +1,9 @@
language: node_js
node_js:
- "6"
- "5.1"
- "4"
- "0.12"
before_script:
- npm install grunt-cli -g
script: grunt

28
Gruntfile.js Normal file
View File

@@ -0,0 +1,28 @@
module.exports = function(grunt) {
require("time-grunt")(grunt);
grunt.initConfig({
pkg: grunt.file.readJSON("package.json"),
eslint: {
options: {
configFile: ".eslintrc.json"
},
target: ["js/*.js", "modules/default/*.js", "serveronly/*.js", "*.js"]
},
postcss: {
lint: {
options: {
processors: [
require("stylelint")({"extends": "stylelint-config-standard", "font-family-name-quotes": "double-where-recommended"}),
require("postcss-reporter")({ clearMessages: true })
]
},
dist: {
src: "**/**/**/**/**/**/**/**.css"
}
}
}
});
grunt.loadNpmTasks("grunt-eslint");
grunt.loadNpmTasks("grunt-postcss");
grunt.registerTask("default", ["eslint", "postcss:lint"]);
};

View File

@@ -104,7 +104,7 @@ The following modules are installed by default.
- [**Hello World**](modules/default/helloworld) - [**Hello World**](modules/default/helloworld)
- [**Alert**](modules/default/alert) - [**Alert**](modules/default/alert)
For more available modules, check out out the wiki page: [MagicMirror² Modules](https://github.com/MichMich/MagicMirror/wiki/MagicMirror²-Modules). If you want to build your own modules, check out the [MagicMirror² Module Development Documentation](modules). For more available modules, check out out the wiki page: [MagicMirror² Modules](https://github.com/MichMich/MagicMirror/wiki/MagicMirror²-Modules). If you want to build your own modules, check out the [MagicMirror² Module Development Documentation](modules) and don't forget to add it to the wiki and the [forum](https://forum.magicmirror.builders/category/7/showcase)!
## Known issues ## Known issues
@@ -127,3 +127,4 @@ Please keep the following in mind:
- **New Features**: please please discuss in a GitHub issue before you start to alter a big part of the code. Without discussion upfront, the pull request will not be accepted / merged. - **New Features**: please please discuss in a GitHub issue before you start to alter a big part of the code. Without discussion upfront, the pull request will not be accepted / merged.
Thanks for your help in making MagicMirror² better! Thanks for your help in making MagicMirror² better!

View File

@@ -6,8 +6,8 @@
<meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<link rel="icon" href="data:;base64,iVBORw0KGgo="> <link rel="icon" href="data:;base64,iVBORw0KGgo=">
<link rel="stylesheet" type="text/css" href="css/main.css"> <link rel="stylesheet" type="text/css" href="css/main.css">
<link rel="stylesheet" type="text/css" href="css/custom.css">
<link rel="stylesheet" type="text/css" href="fonts/roboto.css"> <link rel="stylesheet" type="text/css" href="fonts/roboto.css">
<!-- custom.css is loaded by the loader.js to make sure it's loaded after the module css files. -->
</head> </head>
<body> <body>
<div class="region fullscreen below"><div class="container"></div></div> <div class="region fullscreen below"><div class="container"></div></div>

View File

@@ -18,7 +18,7 @@
echo "Installing helper tools ..." echo "Installing helper tools ..."
sudo apt-get install curl wget build-essential unzip || exit sudo apt-get install curl wget build-essential unzip || exit
ARM=$(uname -m) # Determine which Pi is running. ARM=$(uname -m) # Determine which Pi is running.
NODE_LATEST="v6.0.0" # Set the latest version here. NODE_LATEST=$(curl -l http://api.jordidepoortere.com/nodejs-latest/) # Fetch the latest version of Node.js.
DOWNLOAD_URL="https://nodejs.org/dist/latest/node-$NODE_LATEST-linux-$ARM.tar.gz" # Construct the download URL. DOWNLOAD_URL="https://nodejs.org/dist/latest/node-$NODE_LATEST-linux-$ARM.tar.gz" # Construct the download URL.
echo "Installing Latest Node.js ..." echo "Installing Latest Node.js ..."

View File

@@ -12,11 +12,11 @@ var path = require("path");
// The next part is here to prevent a major exception when there // The next part is here to prevent a major exception when there
// is no internet connection. This could probable be solved better. // is no internet connection. This could probable be solved better.
process.on('uncaughtException', function (err) { process.on("uncaughtException", function (err) {
console.log("Whoops! There was an uncaught exception..."); console.log("Whoops! There was an uncaught exception...");
console.error(err); console.error(err);
console.log("MagicMirror will not quit, but it might be a good idea to check why this happened. Maybe no internet connection?"); console.log("MagicMirror will not quit, but it might be a good idea to check why this happened. Maybe no internet connection?");
console.log("If you think this really is an issue, please open an issue on GitHub: https://github.com/MichMich/MagicMirror/issues"); console.log("If you think this really is an issue, please open an issue on GitHub: https://github.com/MichMich/MagicMirror/issues");
}); });
/* App - The core app. /* App - The core app.
@@ -41,7 +41,7 @@ var App = function() {
var config = Object.assign(defaults, c); var config = Object.assign(defaults, c);
callback(config); callback(config);
} catch (e) { } catch (e) {
console.error('WARNING! Could not find config. Please create one.'); console.error("WARNING! Could not find config. Please create one.");
callback(defaults); callback(defaults);
} }
}; };
@@ -98,7 +98,7 @@ var App = function() {
/* start(callback) /* start(callback)
* This methods starts the core app. * This methods starts the core app.
* It loads the config, then it loads all modules. * It loads the config, then it loads all modules.
* When it's done it executs the callback with the config as argument. * When it"s done it executs the callback with the config as argument.
* *
* argument callback function - The callback function. * argument callback function - The callback function.
*/ */
@@ -130,7 +130,7 @@ var App = function() {
console.log("Sockets connected & modules started ..."); console.log("Sockets connected & modules started ...");
if (typeof callback === 'function') { if (typeof callback === "function") {
callback(config); callback(config);
} }

View File

@@ -48,8 +48,9 @@
// The dummy class constructor // The dummy class constructor
function Class() { function Class() {
// All construction is actually done in the init method // All construction is actually done in the init method
if (!initializing && this.init) if (!initializing && this.init) {
this.init.apply(this, arguments); this.init.apply(this, arguments);
}
} }
// Populate our constructed prototype object // Populate our constructed prototype object

View File

@@ -38,6 +38,14 @@ var defaults = {
text: "See README for more information." text: "See README for more information."
} }
}, },
{
module: "helloworld",
position: "middle_center",
classes: "xsmall",
config: {
text: "If you get this message while your config file is already<br>created, your config file probably contains an error.<br>Use a JavaScript linter to validate your file."
}
},
{ {
module: "helloworld", module: "helloworld",
position: "bottom_bar", position: "bottom_bar",

View File

@@ -1,7 +1,4 @@
/* global config, vendor, MM, Log, Module */ /* global config, vendor, MM, Log, Module */
/* jshint unused:false */
/* jshint -W061 */
/* Magic Mirror /* Magic Mirror
* Module and File loaders. * Module and File loaders.
* *
@@ -34,7 +31,15 @@ var Loader = (function() {
loadNextModule(); loadNextModule();
}); });
} else { } else {
startModules(); // All modules loaded. Load custom.css
// This is done after all the moduels so we can
// overwrite all the defined styls.
loadFile('css/custom.css', function() {
// custom.css loaded. Start all modules.
startModules();
});
} }
}; };
@@ -165,31 +170,26 @@ var Loader = (function() {
var extension = fileName.slice((Math.max(0, fileName.lastIndexOf(".")) || Infinity) + 1); var extension = fileName.slice((Math.max(0, fileName.lastIndexOf(".")) || Infinity) + 1);
switch (extension.toLowerCase()) { switch (extension.toLowerCase()) {
case "js": case "js":
Log.log("Load script: " + fileName); Log.log("Load script: " + fileName);
var script = document.createElement("script");
var script = document.createElement("script"); script.type = "text/javascript";
script.type = "text/javascript"; script.src = fileName;
script.src = fileName; script.onload = function() {
script.onload = function() { if (typeof callback === "function") {callback();}
if (typeof callback === "function") {callback();} };
}; document.getElementsByTagName("body")[0].appendChild(script);
document.getElementsByTagName("body")[0].appendChild(script);
break; break;
case "css":
case "css": Log.log("Load stylesheet: " + fileName);
Log.log("Load stylesheet: " + fileName); var stylesheet = document.createElement("link");
stylesheet.rel = "stylesheet";
var stylesheet = document.createElement("link"); stylesheet.type = "text/css";
stylesheet.rel = "stylesheet"; stylesheet.href = fileName;
stylesheet.type = "text/css"; stylesheet.onload = function() {
stylesheet.href = fileName; if (typeof callback === "function") {callback();}
stylesheet.onload = function() { };
if (typeof callback === "function") {callback();} document.getElementsByTagName("head")[0].appendChild(stylesheet);
};
document.getElementsByTagName("head")[0].appendChild(stylesheet);
break; break;
} }

View File

@@ -1,5 +1,4 @@
/* global Log, Loader, Module, config, defaults */ /* global Log, Loader, Module, config, defaults */
/* jshint -W020 */
/* Magic Mirror /* Magic Mirror
* Main System * Main System
@@ -165,7 +164,7 @@ var MM = (function() {
clearTimeout(module.showHideTimer); clearTimeout(module.showHideTimer);
module.showHideTimer = setTimeout(function() { module.showHideTimer = setTimeout(function() {
// To not take up any space, we just make the position absolute. // To not take up any space, we just make the position absolute.
// since it's fade out anyway, we can see it lay above or // since it"s fade out anyway, we can see it lay above or
// below other modules. This works way better than adjusting // below other modules. This works way better than adjusting
// the .display property. // the .display property.
moduleWrapper.style.position = "absolute"; moduleWrapper.style.position = "absolute";
@@ -434,7 +433,27 @@ var MM = (function() {
})(); })();
// Add polyfill for Object.assign. // Add polyfill for Object.assign.
if (typeof Object.assign != 'function') { (function () { Object.assign = function (target) { 'use strict'; if (target === undefined || target === null) { throw new TypeError('Cannot convert undefined or null to object'); } var output = Object(target); for (var index = 1; index < arguments.length; index++) { var source = arguments[index]; if (source !== undefined && source !== null) { for (var nextKey in source) { if (source.hasOwnProperty(nextKey)) { output[nextKey] = source[nextKey]; } } } } return output; }; })(); } if (typeof Object.assign != "function") {
(function() {
Object.assign = function(target) {
"use strict";
if (target === undefined || target === null) {
throw new TypeError("Cannot convert undefined or null to object");
}
var output = Object(target);
for (var index = 1; index < arguments.length; index++) {
var source = arguments[index];
if (source !== undefined && source !== null) {
for (var nextKey in source) {
if (source.hasOwnProperty(nextKey)) {
output[nextKey] = source[nextKey];
}
}
}
}
return output;
};
})();
}
MM.init(); MM.init();

View File

@@ -111,7 +111,7 @@ var Module = Class.extend({
}, },
/********************************************* /*********************************************
* The methods below don't need subclassing. * * The methods below don"t need subclassing. *
*********************************************/ *********************************************/
/* setData(data) /* setData(data)
@@ -138,7 +138,7 @@ var Module = Class.extend({
}, },
/* socket() /* socket()
* Returns a socket object. If it doesn't exsist, it's created. * Returns a socket object. If it doesn"t exsist, it"s created.
* It also registers the notification callback. * It also registers the notification callback.
*/ */
socket: function() { socket: function() {
@@ -223,9 +223,9 @@ var Module = Class.extend({
var translations = this.getTranslations(); var translations = this.getTranslations();
var translationFile = translations && (translations[config.language.toLowerCase()] || translations.en) || undefined; var translationFile = translations && (translations[config.language.toLowerCase()] || translations.en) || undefined;
if(translationFile) { if(translationFile) {
Translator.load(this, translationFile, callback); Translator.load(this, translationFile, callback);
} else { } else {
callback(); callback();
} }
}, },
@@ -236,7 +236,7 @@ var Module = Class.extend({
* argument defaultValue string - The default value if no translation was found. (Optional) * argument defaultValue string - The default value if no translation was found. (Optional)
*/ */
translate: function(key, defaultValue) { translate: function(key, defaultValue) {
return Translator.translate(this, key) || defaultValue || ''; return Translator.translate(this, key) || defaultValue || "";
}, },
/* updateDom(speed) /* updateDom(speed)
@@ -299,7 +299,7 @@ Module.create = function(name) {
return obj; return obj;
} }
var temp = obj.constructor(); // give temp the original obj's constructor var temp = obj.constructor(); // give temp the original obj"s constructor
for (var key in obj) { for (var key in obj) {
temp[key] = cloneObject(obj[key]); temp[key] = cloneObject(obj[key]);
} }

View File

@@ -47,7 +47,7 @@ var Translator = (function() {
_loadJSON: function(file, callback) { _loadJSON: function(file, callback) {
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
xhr.overrideMimeType("application/json"); xhr.overrideMimeType("application/json");
xhr.open('GET', file, true); xhr.open("GET", file, true);
xhr.onreadystatechange = function () { xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == "200") { if (xhr.readyState == 4 && xhr.status == "200") {
callback(JSON.parse(xhr.responseText)); callback(JSON.parse(xhr.responseText));

View File

@@ -18,7 +18,7 @@ Module.register("alert",{
//Position //Position
position: "center", position: "center",
//shown at startup //shown at startup
welcome_message: true, welcome_message: false,
}, },
getScripts: function() { getScripts: function() {
return ["classie.js", "modernizr.custom.js", "notificationFx.js"]; return ["classie.js", "modernizr.custom.js", "notificationFx.js"];

View File

@@ -144,7 +144,10 @@
if (ev.target !== self.ntf) return false; if (ev.target !== self.ntf) return false;
this.removeEventListener(animEndEventName, onEndAnimationFn); this.removeEventListener(animEndEventName, onEndAnimationFn);
} }
self.options.wrapper.removeChild(this);
if (this.parentNode === self.options.wrapper) {
self.options.wrapper.removeChild(this);
}
}; };
if (support.animations) { if (support.animations) {

View File

@@ -112,6 +112,14 @@ The following properties can be configured:
</code> </code>
</td> </td>
</tr> </tr>
<tr>
<td><code>displayRepeatingCountTitle</code></td>
<td>Show count title for yearly repeating events (e.g. "X. Birthday", "X. Anniversary")<br>
<br><b>Possible values:</b> <code>true</code> or <code>false</code>
<br><b>Default value:</b> <code>false</code>
</td>
</tr>
</tbody> </tbody>
</table> </table>
@@ -154,5 +162,12 @@ config: {
<br><b>Possible values:</b> See <a href="http://fontawesome.io/icons/" target="_blank">Font Awsome</a> website. <br><b>Possible values:</b> See <a href="http://fontawesome.io/icons/" target="_blank">Font Awsome</a> website.
</td> </td>
</tr> </tr>
<tr>
<td><code> repeatingCountTitle </code></td>
<td>The count title for yearly repating events in this calendar. <br>
<br><b>Example:</b> <br>
<code>'Birthday'</code>
</td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@@ -15,6 +15,8 @@ Module.register("calendar",{
maximumNumberOfDays: 365, maximumNumberOfDays: 365,
displaySymbol: true, displaySymbol: true,
defaultSymbol: "calendar", // Fontawsome Symbol see http://fontawesome.io/cheatsheet/ defaultSymbol: "calendar", // Fontawsome Symbol see http://fontawesome.io/cheatsheet/
displayRepeatingCountTitle: false,
defaultRepeatingCountTitle: '',
maxTitleLength: 25, maxTitleLength: 25,
fetchInterval: 5 * 60 * 1000, // Update every 5 minutes. fetchInterval: 5 * 60 * 1000, // Update every 5 minutes.
animationSpeed: 2000, animationSpeed: 2000,
@@ -46,7 +48,8 @@ Module.register("calendar",{
return { return {
en: "translations/en.json", en: "translations/en.json",
de: "translations/de.json", de: "translations/de.json",
nl: "translations/nl.json" nl: "translations/nl.json",
fr: "translations/fr.json"
}; };
}, },
@@ -113,8 +116,23 @@ Module.register("calendar",{
eventWrapper.appendChild(symbolWrapper); eventWrapper.appendChild(symbolWrapper);
} }
var titleWrapper = document.createElement("td"); var titleWrapper = document.createElement("td"),
titleWrapper.innerHTML = this.titleTransform(event.title); repeatingCountTitle = '';
if (this.config.displayRepeatingCountTitle) {
repeatingCountTitle = this.countTitleForUrl(event.url);
if(repeatingCountTitle !== '') {
var thisYear = new Date().getFullYear(),
yearDiff = thisYear - event.firstYear;
repeatingCountTitle = ', '+ yearDiff + '. ' + repeatingCountTitle;
}
}
titleWrapper.innerHTML = this.titleTransform(event.title) + repeatingCountTitle;
titleWrapper.className = "title bright"; titleWrapper.className = "title bright";
eventWrapper.appendChild(titleWrapper); eventWrapper.appendChild(titleWrapper);
@@ -239,6 +257,23 @@ Module.register("calendar",{
return this.config.defaultSymbol; return this.config.defaultSymbol;
}, },
/* countTitleForUrl(url)
* Retrieves the name for a specific url.
*
* argument url sting - Url to look for.
*
* return string - The Symbol
*/
countTitleForUrl: function(url) {
for (var c in this.config.calendars) {
var calendar = this.config.calendars[c];
if (calendar.url === url && typeof calendar.repeatingCountTitle === "string") {
return calendar.repeatingCountTitle;
}
}
return this.config.defaultRepeatingCountTitle;
},
/* shorten(string, maxLength) /* shorten(string, maxLength)
* Shortens a sting if it's longer than maxLenthg. * Shortens a sting if it's longer than maxLenthg.

View File

@@ -55,14 +55,16 @@ var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumbe
if (event.type === "VEVENT") { if (event.type === "VEVENT") {
//console.log(event);
var startDate = (event.start.length === 8) ? moment(event.start, "YYYYMMDD") : moment(new Date(event.start)); var startDate = (event.start.length === 8) ? moment(event.start, "YYYYMMDD") : moment(new Date(event.start));
var endDate; var endDate;
if (typeof event.end !== "undefined") { if (typeof event.end !== "undefined") {
endDate = (event.end.length === 8) ? moment(event.end, "YYYYMMDD") : moment(new Date(event.end)); endDate = (event.end.length === 8) ? moment(event.end, "YYYYMMDD") : moment(new Date(event.end));
} else { } else {
endDate = startDate; if (!isFacebookBirthday) {
endDate = startDate;
} else {
endDate = moment(startDate).add(1, 'days');
}
} }
// calculate the duration f the event for use with recurring events. // calculate the duration f the event for use with recurring events.
@@ -84,14 +86,15 @@ var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumbe
title: (typeof event.summary.val !== "undefined") ? event.summary.val : event.summary, title: (typeof event.summary.val !== "undefined") ? event.summary.val : event.summary,
startDate: startDate.format("x"), startDate: startDate.format("x"),
endDate: endDate.format("x"), endDate: endDate.format("x"),
fullDayEvent: isFullDayEvent(event) fullDayEvent: isFullDayEvent(event),
firstYear: event.start.getFullYear()
}); });
} }
} }
} else { } else {
// console.log("Single event ..."); // console.log("Single event ...");
// Single event. // Single event.
var fullDayEvent = isFullDayEvent(event); var fullDayEvent = (isFacebookBirthday) ? true : isFullDayEvent(event);
var title = (typeof event.summary.val !== "undefined") ? event.summary.val : event.summary; var title = (typeof event.summary.val !== "undefined") ? event.summary.val : event.summary;
if (!fullDayEvent && endDate < new Date()) { if (!fullDayEvent && endDate < new Date()) {

View File

@@ -0,0 +1,7 @@
{
"TODAY": "Aujourd'hui"
, "TOMORROW": "Demain"
, "RUNNING": "Se termine dans"
, "LOADING": "Chargement des RDV &hellip;"
, "EMPTY": "Aucun RDV."
}

View File

@@ -32,7 +32,7 @@ ical.objectHandlers['END'] = function(val, params, curr, stack){
if (curr.start.length === 8) { if (curr.start.length === 8) {
var comps = /^(\d{4})(\d{2})(\d{2})$/.exec(curr.start); var comps = /^(\d{4})(\d{2})(\d{2})$/.exec(curr.start);
if (comps) { if (comps) {
curr.start = new Date (comps[1], comps[2], comps[3]); curr.start = new Date (comps[1], comps[2] - 1, comps[3]);
} }
} }

View File

@@ -97,6 +97,13 @@ The following properties can be configured:
<br><b>Default value:</b> <code>false</code> <br><b>Default value:</b> <code>false</code>
</td> </td>
</tr> </tr>
<tr>
<td><code>useBeaufort</code></td>
<td>Pick between using the Beaufort scale for wind speed or using the default units.<br>
<br><b>Possible values:</b> <code>true</code> or <code>false</code>
<br><b>Default value:</b> <code>true</code>
</td>
</tr>
<tr> <tr>
<td><code>lang</code></td> <td><code>lang</code></td>
<td>The language of the days.<br> <td>The language of the days.<br>

View File

@@ -20,6 +20,7 @@ Module.register("currentweather",{
showPeriod: true, showPeriod: true,
showPeriodUpper: false, showPeriodUpper: false,
showWindDirection: false, showWindDirection: false,
useBeaufort: true,
lang: config.language, lang: config.language,
initialLoadDelay: 0, // 0 seconds delay initialLoadDelay: 0, // 0 seconds delay
@@ -204,7 +205,14 @@ Module.register("currentweather",{
*/ */
processWeather: function(data) { processWeather: function(data) {
this.temperature = this.roundValue(data.main.temp); this.temperature = this.roundValue(data.main.temp);
this.windSpeed = this.ms2Beaufort(this.roundValue(data.wind.speed));
if (this.config.useBeaufort){
this.windSpeed = this.ms2Beaufort(this.roundValue(data.wind.speed));
}else {
this.windSpeed = parseFloat(data.wind.speed).toFixed(0);
}
this.windDirection = this.deg2Cardinal(data.wind.deg); this.windDirection = this.deg2Cardinal(data.wind.deg);
this.weatherType = this.config.iconTable[data.weather[0].icon]; this.weatherType = this.config.iconTable[data.weather[0].icon];

View File

@@ -21,8 +21,7 @@ modules: [
url: "http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml", url: "http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml",
}, },
{ {
title: "BBC title: "BBC",
",
url: "http://feeds.bbci.co.uk/news/video_and_audio/news_front_page/rss.xml?edition=uk", url: "http://feeds.bbci.co.uk/news/video_and_audio/news_front_page/rss.xml?edition=uk",
}, },
] ]

View File

@@ -29,8 +29,13 @@
"homepage": "https://github.com/MichMich/MagicMirror#readme", "homepage": "https://github.com/MichMich/MagicMirror#readme",
"devDependencies": { "devDependencies": {
"electron-prebuilt": "latest", "electron-prebuilt": "latest",
"grunt": "latest",
"grunt-eslint": "latest",
"grunt-postcss": "latest",
"postcss-reporter": "latest",
"stylelint": "latest", "stylelint": "latest",
"stylelint-config-standard": "latest" "stylelint-config-standard": "latest",
"time-grunt": "latest"
}, },
"dependencies": { "dependencies": {
"express": "latest", "express": "latest",
@@ -38,7 +43,7 @@
"iconv-lite": "latest", "iconv-lite": "latest",
"moment": "latest", "moment": "latest",
"request": "latest", "request": "latest",
"snyk": "^1.13.2", "snyk": "latest",
"socket.io": "latest", "socket.io": "latest",
"valid-url": "latest", "valid-url": "latest",
"walk": "latest", "walk": "latest",

View File

@@ -1,5 +1,5 @@
var app = require('../js/app.js'); var app = require("../js/app.js");
app.start(function(config) { app.start(function(config) {
console.log(''); console.log("");
console.log('Ready to go! Please point your browser to: http://localhost:' + config.port); console.log("Ready to go! Please point your browser to: http://localhost:" + config.port);
}); });